Approving a plan from the iOS app sends setMode 'auto', discarding the session's prePlanMode; the rejection path then falls back to 'default'

Status Open
Reported on v2.1.267
Maintainer reply None cached
Activity 0 comments · opened Sep 9, 2026

Summary

Approving an ExitPlanMode request from the iOS app sends updatedPermissions: [{type: "setMode", mode: "auto"}] regardless of the mode the session was in before it entered plan mode. This discards the prePlanMode the CLI had already recorded and restores correctly on its own.

There are two separate defects here, and the second one bites even when the first is refused:

  1. The iOS plan-approval button unconditionally requests auto, rather than the session's prePlanMode.
  2. When that request is rejected, the bridge's fallback is a hardcoded default — not the prePlanMode sitting in the same context.

So a bypassPermissions session approved from iOS lands in auto on a host without disableAutoMode, and in default (manual approval) on a host with it. Neither is the mode the user was in.

The CLI and the Android app both get this right, which is what isolates it to the iOS approval surface.

Environment

  • Claude Code CLI 2.1.267, macOS 15 (Darwin 25.6.0), terminal-hosted session driven from the Claude iOS app
  • ~/.claude/settings.json (abridged):
{
  "permissions": {
    "defaultMode": "bypassPermissions",
    "disableAutoMode": "disable"
  }
}

Steps to reproduce

  1. Start a local session that is in bypassPermissions.
  2. Have it enter plan mode and then call ExitPlanMode.
  3. Approve the plan from the iOS app, using the primary button — which is labelled "Exit and auto mode".

Actual

The session leaves plan mode in default, i.e. manual approval, prompting for every tool call.

Debug log from the reproduction (claude --debug), trimmed to the relevant lines:

21:59:00.603 [INFO]  [prepareContextForPlanMode] plain plan entry, prePlanMode=bypassPermissions
21:59:00.603 [DEBUG] Applying permission update: Setting mode to 'plan'
21:59:13.172 [DEBUG] executePermissionRequestHooks called for tool: ExitPlanMode
21:59:22.660 [DEBUG] bridge setMode 'auto' rejected (Cannot set permission mode to auto: auto mode disabled by settings); falling back to 'default'
21:59:22.682 [INFO]  [Stall] tool_dispatch_start tool=ExitPlanMode permissionDecisionMs=9512

The CLI recorded prePlanMode=bypassPermissions on entry and would have restored it — ExitPlanModeV2Tool sets mode: prePlanMode on exit. The bridge's setMode arrives first and overrides that, and its rejection fallback is a literal 'default' rather than the prePlanMode that is right there in the context.

On a host without disableAutoMode the setMode 'auto' is accepted instead, so the session silently lands in auto mode. Same defect, different landing spot.

Contrast: the other approval surfaces are correct

Same CLI build, same settings, same plan, three approval surfaces:

| Approving from | Sends | Session lands in |
|---|---|---|
| CLI TUI | nothing — the dialog offers "Yes, and bypass permissions" first | bypassPermissions ✅ |
| Android app | nothing — its button is a plain "Approve plan" | bypassPermissions ✅ |
| iOS app | setMode: "auto" | default (or auto without the kill switch) ❌ |

The Android and CLI runs produce no bridge setMode line at all, and the CLI run logs Applying permission update: Setting mode to 'bypassPermissions'.

Expected

The plan-approval path should restore the session's prePlanMode, as the CLI already does unaided.

Concretely, either of:

  • iOS sends no setMode on a plain approval, matching Android, and offers the mode choice only as an explicit opt-in the way the CLI dialog does; or
  • iOS requests prePlanMode rather than a hardcoded auto.

Independently of which, the bridge's rejection fallback should be prePlanMode rather than default — falling back to a mode the user never selected, and never had, is surprising in its own right.

Impact

On iOS there is no permission-mode indicator and no dropdown, so the mode change is both invisible and unrecoverable from the phone. On desktop the dropdown at least lets you pick something else, though bypass is not among the options (see #79990).

For anyone who works in bypassPermissions as their default, approving a plan from the phone silently converts the session into one that prompts for everything, with no signal that it happened.

Related

  • #79990 — mobile/web mode dropdown can knock a session out of bypassPermissions with no way back. Same end state, but that is a manual dropdown tap; this one needs no tap on any mode control, just approving a plan.
  • #80812 — Remote Control offers Auto on a host with disableAutoMode. Related root cause: the app's mode handling does not consult the host's gate.

---

Written by Claude Opus 5 (1M context)

View original on GitHub ↗