docs/permission-resolution.md
This document explains how permission mode is resolved for session messages, depending on current state in the app and CLI.
default | acceptEdits | bypassPermissions | plan | read-only | safe-yolo | yolodefault | acceptEdits | bypassPermissions | planpackages/happy-cli/src/claude/utils/permissionMode.ts:
yolo -> bypassPermissionssafe-yolo -> defaultread-only -> defaultpackages/happy-app/sources/sync/storage.ts
When sessions are merged, the app resolves session.permissionMode using this order:
default)default)default)session.metadata.sandbox.enabled === true: bypassPermissionsdefaultpackages/happy-app/sources/sync/persistence.ts
If draft permission mode is missing:
defaultpackages/happy-app/sources/app/(app)/new/index.tsx
packages/happy-app/sources/components/NewSessionWizard.tsx
Default selection:
defaultIf selected mode is invalid for the currently selected agent, UI resets to agent default above.
packages/happy-app/sources/sync/sync.ts
On send:
session.permissionMode is non-default, send it.session.metadata.sandbox.enabled === true: send bypassPermissionsdefaultThis value is sent in:
meta.permissionModepermissionModepackages/happy-cli/src/claude/runClaude.ts
packages/happy-cli/src/claude/utils/permissionMode.ts
Initial mode comes from:
--dangerously-skip-permissions (highest priority) -> bypassPermissions--permission-mode VALUE or --permission-mode=VALUEoptions.permissionModeThen sandbox policy is applied:
bypassPermissionspackages/happy-cli/src/claude/runClaude.ts
When a user message includes meta.permissionMode:
bypassPermissionspackages/happy-cli/src/claude/claudeLocal.ts
If sandbox is enabled, launcher appends --dangerously-skip-permissions before spawn.
bypassPermissions when session mode is default/missingbypassPermissions in remote flowdefault: that mode is useddefault or missing:
default