bypassPermissions state lost after ExitPlanMode — hardcoded reset to 'default'
Bug Report
Summary
When launching with --dangerously-skip-permissions, entering plan mode and exiting via ExitPlanMode causes the bypassPermissions state to be permanently lost. The permission mode is hardcoded to reset from "plan" to "default", with no mechanism to preserve or restore the original mode.
Steps to Reproduce
- Launch Claude Code with
claude --dangerously-skip-permissions - Enter plan mode (via
/planor automatic skill-triggered plan mode) - Exit plan mode via ExitPlanMode (approve the plan)
- Observe: bypass permissions state is gone — tools now prompt for permission
- Observe: mode picker does not offer
bypassPermissionsas an option
Expected Behavior
After ExitPlanMode, the permission mode should be restored to whatever it was before entering plan mode. If launched with --dangerously-skip-permissions, bypass mode should persist through plan mode transitions.
Actual Behavior
- ExitPlanMode hardcodes the permission mode reset:
"plan"→"default" - The original
bypassPermissionsstate is not saved or consulted - The mode picker UI after ExitPlanMode does not include bypass permissions as a selectable option
- All tools (including those in
permissions.allow) start prompting for approval
Source Code Evidence (v2.1.96)
In the minified cli.js, the plan mode exit logic contains:
permissionMode:O?"plan":"default"
and
"plan"?"default":u
This confirms a hardcoded transition from "plan" to "default" with no reference to the pre-plan permission mode.
Impact
--dangerously-skip-permissionsand plan mode are mutually exclusive in practice- Any workflow using plan mode (including skills that automatically enter plan mode) breaks bypass permissions
- Users must restart the session to recover bypass mode
Environment
- Claude Code version: 2.1.96 (latest)
- Platform: macOS (Darwin 25.2.0, arm64)
- Installation: npm global
- Terminal: CLI
Suggested Fix
Save the current permissionMode before entering plan mode, and restore it when ExitPlanMode is called, instead of hardcoding the reset to "default".
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗