anthropics / anthropics/claude-code
2.1.275: switching a bypassPermissions session to plan mode routes every read-only Bash call to canUseTool (regression from 2.1.246)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 147k
- Forks
- 24k
- PR merge metrics
- PR metrics pending
Description
Summary
Since 2.1.275, a session that starts in bypassPermissions and is later switched to plan (via the Agent SDK's query.setPermissionMode("plan") / the set_permission_mode control request) no longer gets plan mode's automatic allow for read-only Bash. Every Bash call — git status --short, git log --oneline -3, grep … — is routed to canUseTool (i.e. a permission prompt). 2.1.246 does not do this. Starting in acceptEdits and switching to plan is fine on both versions.
Any host that lets the user toggle modes on a live session (Paseo does; Shift+Tab in the CLI presumably too) hits this: plan mode becomes "ask for everything".
Repro (Agent SDK 0.3.246)
import { query } from "@anthropic-ai/claude-agent-sdk";
const startMode = process.argv[2]; // "bypassPermissions" or "acceptEdits"
const calls = [];
const user = (content) => ({ type: "user", message: { role: "user", content }, session_id: "", parent_tool_use_id: null });
let go2, end; const gate2 = new Promise(r => go2 = r); const gateEnd = new Promise(r => end = r);
async function* prompts() {
yield user("Reply 'ok' only. Use no tools.");
await gate2;
yield user("Read-only investigation for a plan: run Bash `git status --short`, then `git log --oneline -3`. Report one line. Don't ask questions or write a plan file.");
await gateEnd;
}
const q = query({ prompt: prompts(), options: {
cwd: process.cwd(), model: "claude-sonnet-5",
permissionMode: startMode, allowDangerouslySkipPermissions: true,
pathToClaudeCodeExecutable: process.env.CLAUDE_BIN, // 2.1.275 vs 2.1.246
canUseTool: async (name, input) => { calls.push(`${name} ${JSON.stringify(input).slice(0, 60)}`); return { behavior: "allow", updatedInput: input }; },
}});
let phase = 1;
for await (const m of q) if (m.type === "result") {
if (phase++ === 1) { await q.setPermissionMode("plan"); go2(); continue; }
console.log(`start=${startMode} -> plan, canUseTool calls: ${calls.length}`); calls.forEach(c => console.log(" " + c)); end(); break;
}
Results
| start mode → plan | CLI 2.1.246 | CLI 2.1.275 |
|---|---|---|
bypassPermissions |
0 canUseTool calls | 3 calls (git status --short, git log --oneline -3, grep …) |
acceptEdits |
0 | 0 |
Plan mode is genuinely active in the failing case (the model refuses Write outside the plan file, ExitPlanMode is offered) — it is only the read-only Bash auto-allow that is lost. Also reproduced with acceptEdits → bypassPermissions → plan, so the trigger is "has been in bypass at any point before plan", not the launch flag alone. The CLI was launched with --permission-mode bypassPermissions --allow-dangerously-skip-permissions --permission-prompt-tool stdio.
Expected
After setPermissionMode("plan"), read-only Bash should be auto-allowed exactly as it is when the session was never in bypass.
Environment
- Claude Code 2.1.275 (native install), Linux x86_64
- @anthropic-ai/claude-agent-sdk 0.3.246
- Same behaviour observed through Paseo 0.8.0, which drives the SDK the same way
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Run the supplied Agent SDK reproduction with CLI 2.1.246 and 2.1.275, starting from query.setPermissionMode("plan") and the set_permission_mode control request. Trace how permission handling reaches canUseTool after a session has used bypassPermissions. Done means read-only Bash calls are automatically allowed after switching to plan, without regressing the acceptEdits path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, typescript
- Domain
- api, authorization, cli
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 66/100