From 3d102819ff741cd56f58a8410556229c935ef0f8 Mon Sep 17 00:00:00 2001 From: Charles Vien Date: Mon, 20 Apr 2026 19:59:40 -0700 Subject: [PATCH 1/2] Add auto permission mode for Claude adapter --- .../message-editor/components/ModeSelector.tsx | 5 +++-- packages/agent/src/adapters/claude/UPSTREAM.md | 3 +-- .../claude/permissions/permission-handlers.ts | 3 ++- .../claude/permissions/permission-options.ts | 5 +++++ packages/agent/src/adapters/claude/tools.ts | 2 +- packages/agent/src/adapters/codex/codex-agent.ts | 1 + packages/agent/src/execution-mode.test.ts | 1 + packages/agent/src/execution-mode.ts | 12 ++++++------ 8 files changed, 20 insertions(+), 12 deletions(-) diff --git a/apps/code/src/renderer/features/message-editor/components/ModeSelector.tsx b/apps/code/src/renderer/features/message-editor/components/ModeSelector.tsx index 7d150c3d6..70fd34e77 100644 --- a/apps/code/src/renderer/features/message-editor/components/ModeSelector.tsx +++ b/apps/code/src/renderer/features/message-editor/components/ModeSelector.tsx @@ -6,6 +6,7 @@ import { LockOpen, Pause, Pencil, + Robot, ShieldCheck, } from "@phosphor-icons/react"; import { @@ -42,8 +43,8 @@ const MODE_STYLES: Record = { className: "text-red-11", }, auto: { - icon: , - className: "text-gray-11", + icon: , + className: "text-blue-11", }, "read-only": { icon: , diff --git a/packages/agent/src/adapters/claude/UPSTREAM.md b/packages/agent/src/adapters/claude/UPSTREAM.md index ef2de941c..d8c410832 100644 --- a/packages/agent/src/adapters/claude/UPSTREAM.md +++ b/packages/agent/src/adapters/claude/UPSTREAM.md @@ -51,7 +51,6 @@ Fork of `@anthropic-ai/claude-agent-acp`. Upstream repo: https://github.com/anth | Session storage | `this.sessions[sessionId]` (multi) | `this.session` (single) | Architectural choice | | bypassPermissions | `updatedPermissions` with `destination: "session"` | No `updatedPermissions` | Different permission persistence | | Auth methods | `claude-ai-login` + `console-login` | Returns empty `authMethods` | Auth handled externally | -| `auto` mode | Model classifier for auto-approval | Not implemented | PostHog uses its own permission model | | Session fingerprinting | Implicit teardown on cwd/mcp change | Explicit `refreshSession()` | Caller-initiated is more predictable | | Shutdown on ACP close | Process exits | No standalone process | Agent is embedded in server | @@ -65,10 +64,10 @@ Fork of `@anthropic-ai/claude-agent-acp`. Upstream repo: https://github.com/anth - **Mid-stream usage updates** (v0.29.1): Fire `usage_update` from `message_start`/`message_delta` stream events - **Raw SDK message relay** (v0.27.0): `emitRawSDKMessages` on `NewSessionMeta` for opt-in diagnostics - **Effort level sync** (v0.25.x): `xhigh` level added, `applyFlagSettings` on effort change +- **Auto permission mode** (v0.25.0): Added to `CODE_EXECUTION_MODES`, available modes, ExitPlanMode options ## Skipped in v0.30.0 Sync -- **`auto` permission mode** (v0.25.0): PostHog has its own permission model - **Separate auth methods** (v0.25.0): PostHog returns empty authMethods - **Session fingerprinting** (v0.25.3): PostHog uses explicit `refreshSession()` instead - **Process exit on ACP close** (v0.27.0): PostHog embeds agent in server diff --git a/packages/agent/src/adapters/claude/permissions/permission-handlers.ts b/packages/agent/src/adapters/claude/permissions/permission-handlers.ts index b97ab8fdb..019a523a2 100644 --- a/packages/agent/src/adapters/claude/permissions/permission-handlers.ts +++ b/packages/agent/src/adapters/claude/permissions/permission-handlers.ts @@ -164,7 +164,8 @@ async function applyPlanApproval( if ( response.outcome?.outcome === "selected" && - (response.outcome.optionId === "default" || + (response.outcome.optionId === "auto" || + response.outcome.optionId === "default" || response.outcome.optionId === "acceptEdits" || response.outcome.optionId === "bypassPermissions") ) { diff --git a/packages/agent/src/adapters/claude/permissions/permission-options.ts b/packages/agent/src/adapters/claude/permissions/permission-options.ts index 551be7c31..e331e6856 100644 --- a/packages/agent/src/adapters/claude/permissions/permission-options.ts +++ b/packages/agent/src/adapters/claude/permissions/permission-options.ts @@ -106,6 +106,11 @@ export function buildExitPlanModePermissionOptions(): PermissionOption[] { } options.push( + { + kind: "allow_always", + name: 'Yes, and use "auto" mode', + optionId: "auto", + }, { kind: "allow_always", name: "Yes, and auto-accept edits", diff --git a/packages/agent/src/adapters/claude/tools.ts b/packages/agent/src/adapters/claude/tools.ts index 1f2621aff..2f847e99c 100644 --- a/packages/agent/src/adapters/claude/tools.ts +++ b/packages/agent/src/adapters/claude/tools.ts @@ -41,10 +41,10 @@ const BASE_ALLOWED_TOOLS = [ ]; const AUTO_ALLOWED_TOOLS: Record> = { + auto: new Set(BASE_ALLOWED_TOOLS), default: new Set(BASE_ALLOWED_TOOLS), acceptEdits: new Set([...BASE_ALLOWED_TOOLS, ...WRITE_TOOLS]), plan: new Set(BASE_ALLOWED_TOOLS), - // dontAsk: new Set(BASE_ALLOWED_TOOLS), }; export function isToolAllowedForMode( diff --git a/packages/agent/src/adapters/codex/codex-agent.ts b/packages/agent/src/adapters/codex/codex-agent.ts index d7a542bd3..7d1a30010 100644 --- a/packages/agent/src/adapters/codex/codex-agent.ts +++ b/packages/agent/src/adapters/codex/codex-agent.ts @@ -124,6 +124,7 @@ function prependPrContext(params: PromptRequest): PromptRequest { } const CODEX_NATIVE_MODE: Record = { + auto: "auto", default: "auto", acceptEdits: "auto", plan: "read-only", diff --git a/packages/agent/src/execution-mode.test.ts b/packages/agent/src/execution-mode.test.ts index 4da924c2c..eb36c58c5 100644 --- a/packages/agent/src/execution-mode.test.ts +++ b/packages/agent/src/execution-mode.test.ts @@ -4,6 +4,7 @@ import { getAvailableCodexModes, getAvailableModes } from "./execution-mode"; describe("execution modes", () => { it("includes auto-accept permissions for claude sessions", () => { expect(getAvailableModes().map((mode) => mode.id)).toEqual([ + "auto", "default", "acceptEdits", "plan", diff --git a/packages/agent/src/execution-mode.ts b/packages/agent/src/execution-mode.ts index 66d3b19d3..bd0544cbf 100644 --- a/packages/agent/src/execution-mode.ts +++ b/packages/agent/src/execution-mode.ts @@ -10,6 +10,11 @@ export interface ModeInfo { const ALLOW_BYPASS = !IS_ROOT; const availableModes: ModeInfo[] = [ + { + id: "auto", + name: "Auto", + description: "Use a model classifier to approve/deny permission prompts", + }, { id: "default", name: "Default", @@ -25,11 +30,6 @@ const availableModes: ModeInfo[] = [ name: "Plan Mode", description: "Planning mode, no actual tool execution", }, - // { - // id: "dontAsk", - // name: "Don't Ask", - // description: "Don't prompt for permissions, deny if not pre-approved", - // }, ]; if (ALLOW_BYPASS) { @@ -42,10 +42,10 @@ if (ALLOW_BYPASS) { // Expose execution mode IDs in type-safe order for type checks export const CODE_EXECUTION_MODES = [ + "auto", "default", "acceptEdits", "plan", - // "dontAsk", "bypassPermissions", ] as const; From d027c20c8d161b330f45f77e66be7286a4b4cc89 Mon Sep 17 00:00:00 2001 From: Charles Vien Date: Mon, 20 Apr 2026 20:19:47 -0700 Subject: [PATCH 2/2] Reorder mode dropdown and rename labels --- .../sections/ClaudeCodeSettings.tsx | 6 ++--- packages/agent/src/execution-mode.test.ts | 2 +- packages/agent/src/execution-mode.ts | 24 ++++++++++--------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/apps/code/src/renderer/features/settings/components/sections/ClaudeCodeSettings.tsx b/apps/code/src/renderer/features/settings/components/sections/ClaudeCodeSettings.tsx index 68753d2d9..c3f1aade3 100644 --- a/apps/code/src/renderer/features/settings/components/sections/ClaudeCodeSettings.tsx +++ b/apps/code/src/renderer/features/settings/components/sections/ClaudeCodeSettings.tsx @@ -196,9 +196,9 @@ export function ClaudeCodeSettings() { - Auto-accept is enabled. All actions (shell commands, file edits, web - requests) run without approval. Pick this mode from the mode menu in - the prompt input per session. + Bypass Permissions is enabled. All actions (shell commands, file + edits, web requests) run without approval. Pick this mode from the + mode menu in the prompt input per session. )} diff --git a/packages/agent/src/execution-mode.test.ts b/packages/agent/src/execution-mode.test.ts index eb36c58c5..be5964906 100644 --- a/packages/agent/src/execution-mode.test.ts +++ b/packages/agent/src/execution-mode.test.ts @@ -4,11 +4,11 @@ import { getAvailableCodexModes, getAvailableModes } from "./execution-mode"; describe("execution modes", () => { it("includes auto-accept permissions for claude sessions", () => { expect(getAvailableModes().map((mode) => mode.id)).toEqual([ - "auto", "default", "acceptEdits", "plan", "bypassPermissions", + "auto", ]); }); diff --git a/packages/agent/src/execution-mode.ts b/packages/agent/src/execution-mode.ts index bd0544cbf..799a9b511 100644 --- a/packages/agent/src/execution-mode.ts +++ b/packages/agent/src/execution-mode.ts @@ -10,11 +10,6 @@ export interface ModeInfo { const ALLOW_BYPASS = !IS_ROOT; const availableModes: ModeInfo[] = [ - { - id: "auto", - name: "Auto", - description: "Use a model classifier to approve/deny permission prompts", - }, { id: "default", name: "Default", @@ -33,20 +28,27 @@ const availableModes: ModeInfo[] = [ ]; if (ALLOW_BYPASS) { - availableModes.push({ - id: "bypassPermissions", - name: "Auto-accept Permissions", - description: "Auto-accept all permission requests", - }); + availableModes.push( + { + id: "bypassPermissions", + name: "Bypass Permissions", + description: "Auto-accept all permission requests", + }, + { + id: "auto", + name: "Auto Mode", + description: "Use a model classifier to approve/deny permission prompts", + }, + ); } // Expose execution mode IDs in type-safe order for type checks export const CODE_EXECUTION_MODES = [ - "auto", "default", "acceptEdits", "plan", "bypassPermissions", + "auto", ] as const; export type CodeExecutionMode = (typeof CODE_EXECUTION_MODES)[number];