Skip to content

feat: support auto (and dontAsk) permission modes from @anthropic-ai/claude-agent-sdk #1156

Description

@fintorq

Summary

The Claude Agent SDK (@anthropic-ai/claude-agent-sdk@^0.2.96, which happy already depends on) supports six PermissionMode values:

// node_modules/@anthropic-ai/claude-agent-sdk/sdk.d.ts:1489
export declare type PermissionMode =
    'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' | 'dontAsk' | 'auto';

Happy currently only plumbs through the first four (plus Codex-specific read-only | safe-yolo | yolo). The newer auto mode (model decides whether to prompt) and dontAsk (SDK auto-approve without prompts) are not reachable from the app.

Side note: dontAsk is already listed in packages/happy-app/sources/components/modelModeOptions.ts:52 and its i18n strings, but the wire enum in packages/happy-wire/src/messageMeta.ts rejects it — so even selecting it in the UI fails validation before reaching the CLI. dontAsk is effectively dead UI today.

User impact

Users on recent Claude Code versions cannot select the auto mode that the CLI natively offers. They are stuck choosing between hard bypass (bypassPermissions) and default prompting, with no middle-ground model-driven behavior. The half-wired dontAsk is also a papercut.

Proposed implementation path

Changes isolated to Happy — no SDK change needed.

  1. packages/happy-wire/src/messageMeta.ts: add 'auto' (and 'dontAsk' if we're also finishing that feature) to the permissionMode zod enum.
  2. packages/happy-cli/src/api/types.ts:35: extend PermissionMode union to include 'auto'. Update doc comment.
  3. packages/happy-cli/src/claude/utils/permissionMode.ts:
    • Add 'auto' to VALID_PERMISSION_MODES.
    • mapToClaudeMode: auto is identity passthrough (SDK native).
  4. packages/happy-cli/src/claude/runClaude.ts:80: ensure dangerouslySkipPermissions is NOT set for auto (should only cover bypassPermissions / yolo / sandbox).
  5. packages/happy-cli/src/claude/utils/permissionHandler.ts: no new branch needed at handleToolCallauto should fall through to the SDK's own gating (i.e. canCallTool runs normally; what matters is the mode value passed to the SDK).
  6. packages/happy-cli/src/codex/executionPolicy.ts: add defensive mapping for Codex fallback (e.g. auto → approvalPolicy: 'on-request', sandbox: 'workspace-write'), or leave on defaults.
  7. packages/happy-app/sources/components/modelModeOptions.ts:48: add { key: 'auto', name: translate('agentInput.permissionMode.auto'), ... } to getClaudePermissionModes.
  8. packages/happy-app/sources/text/_default.ts + all translations/*.ts: add agentInput.permissionMode.auto strings.

Release coordination

happy-wire ships as a separate npm package that happy-server also depends on. Adding values to the permissionMode enum is a coordinated release: clients sending 'auto' to a server with the old enum will be rejected at validation. Sequence: publish wire, upgrade server, then ship CLI + app simultaneously (or gate the UI option behind a feature flag until rollout is complete).

Acceptance criteria

  • User can select auto in the Claude permission-mode selector on mobile/web.
  • Outbound messages carry meta.permissionMode: 'auto'.
  • CLI forwards to the Claude SDK as permissionMode: 'auto' and session behaves as native Claude Code auto mode.
  • --permission-mode auto via claudeArgs is also honored.
  • No regression for the existing 7 modes.

Out of scope

  • Finishing dontAsk end-to-end — can ride with this PR or split; I'd suggest same PR for consistency since the plumbing is identical.
  • Gemini / Codex native auto support — neither agent has it natively; only defensive mapping is required.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions