anthropics / anthropics/claude-code
[BUG] Desktop: Plan mode prompts for every non-read-only Bash command since 2.1.270 (plan+bypass quiet path now requires isInteractive; Desktop sessions get no quiet path)
- Lingua principale
- Python
- Stelle
- 145k
- Fork
- 23.1k
- Metriche di merge delle PR
- Metriche PR in attesa
Descrizione
### Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code (2.1.270, as bundled in Claude Desktop 1.52386.6)
### What's Wrong?
In the Claude Desktop **Code tab** (macOS), switching a session to **Plan** mode now raises a permission card for **every Bash command that isn't in the built-in read-only set**. One session produced 35 Bash permission prompts in a single afternoon (desktop `main.log`: `LocalSessions.setPermissionMode … mode=plan` followed by a stream of `Emitted tool permission request … for Bash`). The same Desktop workflow on the previously bundled CLI (2.1.266, and 2.1.260 before it) produced **zero** Bash prompts in plan mode across several days of use.
Desktop launches the CLI as a non-interactive stream: `--output-format stream-json --input-format stream-json --permission-prompt-tool stdio`, plus `--permission-mode bypassPermissions --allow-dangerously-skip-permissions` when the Desktop setting **Allow bypass permissions mode** is on. Auto mode is available on the account and `useAutoModeDuringPlan` is at its default (on).
Comparing the two bundled binaries (`~/Library/Application Support/Claude/claude-code//claude.app/Contents/MacOS/claude`):
- **2.1.266** — the plan-mode "permissive" check at the permission-context resolver is inline:
`n.mode==="plan" && n.isBypassPermissionsModeAvailable===!0`
- **2.1.270** — the same call sites use a new helper:
`function zj(e,n){return e==="plan"&&n===!0&&!Ae()}` where `Ae()` is
`function Ae(){return!n().host.launchOptions.isInteractive()}`.
Desktop sessions are non-interactive, so the "bypass available → plan mode doesn't prompt" path is now switched off for every Desktop (and SDK / stream-json) session.
- The other quiet path — the auto-mode classifier reviewing commands during planning — is gated as
`e.mode==="auto" || e.mode==="plan" && () && !e.isBypassPermissionsModeAvailable`.
With the Desktop bypass toggle on, `isBypassPermissionsModeAvailable` is true for every session, so this path is off as well.
Net effect: in Desktop with the bypass toggle on, **plan mode has no non-prompting path at all**; every non-read-only shell command asks the user. A terminal session with identical settings is unaffected because `isInteractive()` is true there.
The docs (Permission modes → "Skip all checks with bypassPermissions mode") still state: *"In sessions with bypass permissions available, Claude Code also doesn't enforce plan mode's blocks… a file edit or shell command it attempts during planning runs without prompting."* That no longer holds for Desktop/SDK sessions. Nothing in the 2.1.267–2.1.270 CHANGELOG entries mentions plan mode.
### What Should Happen?
One of the two documented quiet paths should apply to Desktop plan mode:
1. plan mode does not enforce its blocks when bypass permissions are available (behavior through 2.1.266, and what the docs describe), **or**
2. if gating that path on interactive sessions is intentional, non-interactive sessions should fall through to the classifier-during-planning path instead of to a prompt (i.e. `!isBypassPermissionsModeAvailable` should not exclude the classifier path when the bypass path itself is unavailable).
If the change is deliberate (e.g. non-interactive sessions must not run commands silently in plan mode), it should be in the changelog and docs, and the Desktop mode selector should not offer a Plan mode that prompts on everything.
### Error Messages/Logs
Desktop `~/Library/Logs/Claude/main.log` (ids elided):
```
2026-09-14 15:46:12 [info] [CCD] LocalSessions.setPermissionMode: sessionId=local_…, mode=plan
2026-09-14 15:46:12 [info] [CCD] Set permission mode for session local_… to plan
2026-09-14 15:58:19 [info] Emitted tool permission request e89ff78f-… for Bash in session local_…
2026-09-14 15:58:23 [info] LocalSessions.respondToToolPermission: requestId=e89ff78f-…, decision=once, hasUpdatedInput=true
2026-09-14 15:58:23 [info] Received permission response for e89ff78f-…: once (tool: Bash)
… 35 Bash permission requests between 15:58 and 16:15 in that one plan-mode session
```
Plan-mode toggles vs Bash permission prompts, same Desktop app and same workflow, counted from the log:
| date | bundled CLI | plan mode entered | Bash permission prompts |
| --- | --- | --- | --- |
| 2026-09-08 | 2.1.260 | 2× via mode selector | 0 |
| 2026-09-09 | 2.1.260 | 3× via mode selector | 0 |
| 2026-09-13 | 2.1.266 | via EnterPlanMode (ExitPlanMode prompt seen) | 0 |
| 2026-09-14 | 2.1.270 | 3× via mode selector (6 mode changes total) | 35 |
### Steps to Reproduce
1. Claude Desktop for macOS 1.52386.6 with bundled Claude Code 2.1.270. Desktop settings: **Allow bypass permissions mode** ON. Auto mode available (Max plan).
2. Code tab → open a session in any folder; mode selector → **Bypass permissions** (or Auto). Confirm shell commands run without prompts.
3. Switch the mode selector to **Plan**.
4. Ask for research that needs non-read-only shell commands (e.g. "inspect X with `ssh`/`gh`/`python3` and write a plan"; long compound commands that the read-only analysis can't classify also qualify).
5. Every such Bash call raises a permission card ("once" / "always" choices). With the previous bundled CLI (2.1.266) the same steps run the commands without prompting.
Code path: `strings` the 2.1.270 binary for `function zj(e,n){return e==="plan"&&n===!0&&!Ae()}` and `function Ae(){return!n().host.launchOptions.isInteractive()}`; in 2.1.266 the corresponding check is `n.mode==="plan"&&n.isBypassPermissionsModeAvailable===!0`.
### Claude Model
claude-fable-5-1 in the affected session (also seen with claude-opus-4-8). Model-independent.
### Is this a regression?
Yes, this worked in a previous version
### Last Working Version
2.1.266 (Claude Code), bundled in the same Desktop app until 2026-09-14. (2.1.267–2.1.269 not tested.)
### Claude Code Version
2.1.270 (Claude Code), bundled in Claude Desktop 1.52386.6
### Platform
Anthropic API (claude.ai Max subscription through the Desktop app)
### Operating System
macOS (26.6.2)
### Terminal/Shell
Other (Claude Desktop app, Code tab — non-interactive stream-json host)
### Additional Information
Workarounds identified (not a fix):
- Add `"Bash(*)"` to `permissions.allow` in `~/.claude/settings.json`. Per the permissions docs, plan mode sends non-read-only commands through the regular permission flow, which honors allow rules, while edits stay blocked. Not yet verified end to end.
- Turn the Desktop **Allow bypass permissions mode** toggle off. Bypass then stops being "available", so the classifier-during-planning path engages. Costs the Bypass mode entirely.
Possibly related but distinct: #10906 (Plan subagent ignores parent permissions), #89403 (plan mode gating after a rejected ExitPlanMode).
Guida per i contributori
Nessuna guida per i contributori indicizzata per questo repository
Valutazione
Questa issue non è ancora stata valutata.