diff --git a/plugins/provider-claude-code/src/bridge/bridge.ts b/plugins/provider-claude-code/src/bridge/bridge.ts index ed894c471..ffcd8cb9e 100644 --- a/plugins/provider-claude-code/src/bridge/bridge.ts +++ b/plugins/provider-claude-code/src/bridge/bridge.ts @@ -2196,6 +2196,17 @@ async function runTurnStart( params.threadId, withTurnLiveSessionSettings(threadSession.liveSettings, params), ); + // `/plan` on an already-loaded session: the runtime never rebuilds a + // bridge session for an option change, so the mode has to be applied to + // the live SDK session here (#2019). Leaving plan mode is owned by + // restoreApprovedPlanPermissionMode once the plan is approved. + if ( + params.claudeCodePermissionMode === "plan" && + threadSession.permissionMode !== "plan" + ) { + await threadSession.session.setPermissionMode("plan"); + threadSession.permissionMode = "plan"; + } } catch (error) { const message = error instanceof Error ? error.message : String(error); sendError(id, -32000, message); diff --git a/plugins/provider-claude-code/src/bridge/commands.ts b/plugins/provider-claude-code/src/bridge/commands.ts index d049024b8..01c44b635 100644 --- a/plugins/provider-claude-code/src/bridge/commands.ts +++ b/plugins/provider-claude-code/src/bridge/commands.ts @@ -85,6 +85,7 @@ export const claudeTurnStartParamsSchema = z.object({ threadId: z.string(), providerThreadId: z.string().nullable(), input: z.array(z.unknown()), + claudeCodePermissionMode: z.literal("plan").optional(), model: z.string().optional(), reasoningLevel: bridgeReasoningLevelSchema.optional(), workflowsEnabled: z.boolean().optional(), diff --git a/plugins/provider-claude-code/src/session-params.ts b/plugins/provider-claude-code/src/session-params.ts index 6b2f95b7d..bd2362e8e 100644 --- a/plugins/provider-claude-code/src/session-params.ts +++ b/plugins/provider-claude-code/src/session-params.ts @@ -319,6 +319,9 @@ export function buildClaudeTurnParams( input: args.input, claudeCodePermissionMode: providerOptions.claudeCodePermissionMode, }), + ...(providerOptions.claudeCodePermissionMode !== undefined + ? { claudeCodePermissionMode: providerOptions.claudeCodePermissionMode } + : {}), ...(args.options.model ? { model: args.options.model } : {}), ...(args.options.reasoningLevel ? { reasoningLevel: args.options.reasoningLevel }