Skip to content

Add Claude Code auto permission mode as a 4th runtime mode#3628

Open
m4tta wants to merge 2 commits into
pingdotgg:mainfrom
m4tta:claude-auto-runtime-mode
Open

Add Claude Code auto permission mode as a 4th runtime mode#3628
m4tta wants to merge 2 commits into
pingdotgg:mainfrom
m4tta:claude-auto-runtime-mode

Conversation

@m4tta

@m4tta m4tta commented Jul 1, 2026

Copy link
Copy Markdown

What Changed

Adds Claude Code's auto permission mode as a fourth runtime mode option, alongside the existing Supervised / Auto-accept edits / Full access modes.

  • RuntimeMode contract gains an "auto" value.
  • ClaudeAdapter maps it to the Agent SDK's native permissionMode: "auto", and never sets allowDangerouslySkipPermissions for it (that flag stays scoped to bypassPermissions only).
  • A new supportsAutoRuntimeMode provider capability flag gates the option so it only shows up for the Claude provider. Codex defensively maps an incoming "auto" to its existing workspace-write policy instead of falling through to full sandbox bypass.
  • Surfaced in the web composer's runtime mode dropdown/menu and in the mobile runtime option list.

Why

Claude Code's TypeScript Agent SDK supports six PermissionMode values (default | acceptEdits | bypassPermissions | plan | dontAsk | auto), but only two of those were reachable from this app's runtime mode selector. auto mode runs tool calls through a background safety classifier rather than skipping permission checks outright, so it's meaningfully different from bypassPermissions: it does not require allowDangerouslySkipPermissions. That matters for orgs whose managed Claude Code settings disable bypassPermissions/--dangerously-skip-permissions but still allow auto mode — those users currently have no way to reduce prompt fatigue in this app beyond acceptEdits.

UI Changes

New "Auto" option in the runtime mode selector (web composer dropdown + compact menu), visible only when the active provider is Claude.

Screenshot 2026-06-30 at 9 02 27 PM

Checklist

  • This PR is small and focused (11 files, +77/-9)
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Add 'auto' as a fourth runtime mode for Claude Code permission handling

  • Adds 'auto' to the RuntimeMode contract schema and wires it through the server, mobile, and web layers.
  • The Claude provider advertises supportsAutoRuntimeMode: true; UI components (web composer, compact menu, mobile thread composer) conditionally show the 'Auto' option only when the selected provider/model supports it.
  • On the server, 'auto' maps to permissionMode: 'auto' in the Claude adapter and to on-request approval policy with workspace-write sandbox in the Codex session runtime (same behavior as 'auto-accept-edits').
  • Behavioral Change: selecting 'Auto' mode in the Claude provider now sends permissionMode: 'auto' to the Claude API rather than rejecting it as an unknown mode.

Macroscope summarized 45eddfd.


Note

Medium Risk
Changes permission/runtime semantics for agent sessions; impact is mostly gated to Claude UI, but Codex still accepts auto at the API layer with a conservative sandbox mapping.

Overview
Introduces a fourth runtime mode, auto, for Claude Code’s background safety-classifier permission path (distinct from full bypassPermissions).

Contracts & server: RuntimeMode and provider snapshots gain supportsAutoRuntimeMode. Claude declares it; ClaudeAdapter maps auto → SDK permissionMode: "auto". Codex treats an incoming auto like auto-accept-edits (workspace-write / on-request) so it never falls through to full-access sandbox.

Clients: Web ChatComposer / compact menu and mobile new-task / thread composers add an Auto runtime choice only when the selected model’s provider supports it; mobile ModelOption carries the flag from server config.

Reviewed by Cursor Bugbot for commit 45eddfd. Bugbot is set up for automated code reviews on this repo. Configure here.

Claude Code's TypeScript Agent SDK exposes an "auto" PermissionMode
(default | acceptEdits | bypassPermissions | plan | dontAsk | auto)
that runs tool calls through a background safety classifier instead
of skipping permission checks entirely. It's distinct from
bypassPermissions and never requires allowDangerouslySkipPermissions,
so it works in environments where an org policy blocks
--dangerously-skip-permissions but still allows auto mode.

- Add "auto" to the RuntimeMode contract and map it to the SDK's
  permissionMode in ClaudeAdapter.
- Add a supportsAutoRuntimeMode provider capability flag so only
  Claude advertises the option; Codex falls back to its
  workspace-write policy defensively instead of full bypass.
- Surface the option in the web composer menus and mobile runtime
  option lists, gated on that capability flag.
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: c519e087-ddd4-47b9-acae-550eeaf13657

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Jul 1, 2026
@m4tta m4tta marked this pull request as ready for review July 1, 2026 04:11
@@ -117,6 +117,7 @@ export type ModelSelection = typeof ModelSelection.Type;
export const RuntimeMode = Schema.Literals([

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium src/orchestration.ts:117

Adding "auto" to the global RuntimeMode schema makes that value valid in every persisted thread and command, not just Claude. A thread created with runtimeMode: "auto" can later have its modelSelection changed via ThreadMetaUpdateCommand to a non-Claude provider while keeping runtimeMode: "auto". Adapters that don't recognize "auto" silently misresolve it — for example CursorAdapter.resolveRequestedModeId maps any non-"approval-required" value to its implement mode, and buildOpenCodePermissionRules falls back to generic non-full-access rules. The thread then runs with wrong permission behavior instead of a normalization or validation failure. If "auto" is Claude-specific, consider narrowing it to a Claude-only field or adding adapter-level validation that rejects unrecognized modes.

🤖 Copy this AI Prompt to have your agent fix this:
In file @packages/contracts/src/orchestration.ts around line 117:

Adding `"auto"` to the global `RuntimeMode` schema makes that value valid in every persisted thread and command, not just Claude. A thread created with `runtimeMode: "auto"` can later have its `modelSelection` changed via `ThreadMetaUpdateCommand` to a non-Claude provider while keeping `runtimeMode: "auto"`. Adapters that don't recognize `"auto"` silently misresolve it — for example `CursorAdapter.resolveRequestedModeId` maps any non-`"approval-required"` value to its implement mode, and `buildOpenCodePermissionRules` falls back to generic non-full-access rules. The thread then runs with wrong permission behavior instead of a normalization or validation failure. If `"auto"` is Claude-specific, consider narrowing it to a Claude-only field or adding adapter-level validation that rejects unrecognized modes.

Comment thread apps/mobile/src/features/threads/ThreadComposer.tsx Outdated
Comment thread apps/web/src/components/chat/ChatComposer.tsx
@macroscopeapp

macroscopeapp Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

2 blocking correctness issues found. New feature adding a 4th runtime mode with multiple unresolved review comments identifying bugs: runtime mode isn't normalized when switching providers, and non-Claude adapters could silently mishandle the 'auto' value. These issues affect runtime behavior and need resolution.

You can customize Macroscope's approvability policy. Learn more.

Mobile checked providerDriver === "claudeAgent" directly, while the
web composer checks the supportsAutoRuntimeMode flag reported by the
provider snapshot. Those happen to agree today since Claude always
sets the flag to true, but they could silently diverge if the flag
is ever made conditional. Add supportsAutoRuntimeMode to ModelOption
and gate on that instead, matching the web behavior.
@m4tta

m4tta commented Jul 1, 2026

Copy link
Copy Markdown
Author

Mobile gating on providerDriver instead of supportsAutoRuntimeMode (comment on ThreadComposer.tsx:561, also NewTaskDraftScreen.tsx:201). Agreed, this was a real inconsistency. Pushed a fix: added supportsAutoRuntimeMode to the mobile ModelOption type (sourced from the same provider-snapshot flag the web composer already reads) and gated both mobile menus on that instead of the hardcoded driver string, so web and mobile can't silently diverge if the flag is ever made conditional per-instance.

Global RuntimeMode schema / cross-provider persistence (comment on orchestration.ts:117). The underlying scenario is real. ThreadMetaUpdateCommand can change modelSelection independently of runtimeMode, and Claude doesn't set requiresNewThreadForModelChange, so a thread can switch from Claude to Cursor/OpenCode in place while keeping a stored runtimeMode: "auto". However, I don't think this needs adapter-level rejection, because the fallback on both of those adapters for an unrecognized mode is already the most conservative option, not a silent bypass:

  • CursorAdapter's permission-request handler only auto-approves for runtimeMode === "full-access"; anything else (including "auto") prompts for approval every time.
  • buildOpenCodePermissionRules only grants blanket allow for "full-access"; its fallback branch is action: "ask" for everything.

So the worst case is a thread that shows "Auto" in its history while actually behaving like "ask before every action" on a non-Claude provider. That's a UX/labeling nit, not a permissions escalation. Codex is the one adapter where this mattered for real, since its unhandled-mode fallback was danger-full-access, so I added an explicit case "auto" there mapping to the same workspace-write policy as auto-accept-edits. Happy to revisit if you see a path where Cursor/OpenCode's fallback isn't actually safe.

flow.interactionMode,
flow.runtimeMode,
flow.selectedModelOption?.supportsAutoRuntimeMode,
providerOptionDescriptors,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium threads/NewTaskDraftScreen.tsx:241

When the selected model does not support the "auto" runtime mode (flow.selectedModelOption?.supportsAutoRuntimeMode is false), the menu hides the "auto" option but flow.runtimeMode is never normalized back to a supported value. If the user previously selected "auto" with a supporting model and then switches to an unsupported model, the options menu subtitle still labels the runtime as "Auto", and handleStart() submits runtimeMode: "auto" to createProjectThread for a provider that does not expose that mode. Consider resetting flow.runtimeMode whenever supportsAutoRuntimeMode transitions to false so the submitted runtime mode stays within the selected provider's supported set.

Also found in 1 other location(s)

apps/mobile/src/features/threads/ThreadComposer.tsx:555

The runtime menu can still present the current mode as "Auto" after the user switches away from a provider that supports auto mode. handleModelMenuAction only changes modelSelection, so currentRuntimeMode stays "auto"; then the subtitle logic at lines 550-557 still renders "Auto" even when currentModelOption?.supportsAutoRuntimeMode is false and the Auto menu item has been removed. Trigger: pick Claude Auto, switch to another provider, and reopen the composer. The UI now claims the active provider is in Auto mode even though that option is supposed to be hidden for non-Claude providers.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/mobile/src/features/threads/NewTaskDraftScreen.tsx around line 241:

When the selected model does not support the `"auto"` runtime mode (`flow.selectedModelOption?.supportsAutoRuntimeMode` is false), the menu hides the `"auto"` option but `flow.runtimeMode` is never normalized back to a supported value. If the user previously selected `"auto"` with a supporting model and then switches to an unsupported model, the options menu subtitle still labels the runtime as `"Auto"`, and `handleStart()` submits `runtimeMode: "auto"` to `createProjectThread` for a provider that does not expose that mode. Consider resetting `flow.runtimeMode` whenever `supportsAutoRuntimeMode` transitions to false so the submitted runtime mode stays within the selected provider's supported set.

Also found in 1 other location(s):
- apps/mobile/src/features/threads/ThreadComposer.tsx:555 -- The runtime menu can still present the current mode as `"Auto"` after the user switches away from a provider that supports auto mode. `handleModelMenuAction` only changes `modelSelection`, so `currentRuntimeMode` stays `"auto"`; then the subtitle logic at lines 550-557 still renders `"Auto"` even when `currentModelOption?.supportsAutoRuntimeMode` is false and the `Auto` menu item has been removed. Trigger: pick Claude `Auto`, switch to another provider, and reopen the composer. The UI now claims the active provider is in `Auto` mode even though that option is supposed to be hidden for non-Claude providers.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 45eddfd. Configure here.

providerKey: fallbackModelSelection.instanceId,
providerLabel,
providerDriver: fallbackModelSelection.instanceId,
supportsAutoRuntimeMode: false,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fallback options hide Auto mode

Medium Severity

Synthetic ModelOption rows from buildModelOptions always set supportsAutoRuntimeMode to false, even when the matching provider is still present in config.providers (disabled, unauthenticated, or missing from the model list). The runtime menus now gate the Auto entry on that flag instead of providerDriver, so Claude selections in those states lose Auto while drafts can still use runtimeMode "auto".

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 45eddfd. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants