Background sessions (claude agents / fleet) don't honor permissions.defaultMode: bypassPermissions

Open 💬 3 comments Opened May 14, 2026 by sanity

Summary

Background sessions spawned via claude agents (and other fleet/daemon-dispatched bg jobs) do not honor permissions.defaultMode: "bypassPermissions" from ~/.claude/settings.json. They start in default mode and prompt for every Bash/Edit/Write call, even though the user has configured the bypass default. This breaks long-standing yolo-mode workflows for users who rely on defaultMode: bypassPermissions and have now adopted the new claude agents mechanism.

Repro

  1. Set in ~/.claude/settings.json:

``json
{
"permissions": {
"defaultMode": "bypassPermissions",
"disableAutoMode": "disable"
}
}
`
(The
disableAutoMode is included to rule out the auto-mode policy overriding defaultMode` — see "Auto mode overlap" below.)

  1. Run claude daemon stop --any --keep-workers to clear any stale spare pool.
  2. Run claude agents and create a new agent.
  3. Ask the agent to run a Bash command (e.g. env | grep PATH).

Expected: Bash runs without a prompt — defaultMode: bypassPermissions is honored.

Actual: The agent prompts for permission to run Bash, exactly as if defaultMode were default.

Diagnosis

I traced this through the CLI binary (/path/to/claude/versions/2.1.141, version 2.1.141 on Linux).

Step 1 — The daemon dispatches spares with no permission-mode flag. From ~/.claude/daemon/roster.json after creating a fresh agent:

"launch": {
  "mode": "prompt",
  "args": [
    "--session-id", "<uuid>",
    "--agent", "claude",
    "--", "<prompt>"
  ]
}

No --permission-mode bypassPermissions (or --dangerously-skip-permissions).

Step 2 — The dispatcher passes launch.args through verbatim. From the binary's dh4() function:

function dh4(H, $, q, K, _) {
  if ($ > 1 && q) return ["--resume", K, ..._];
  if (H.launch.mode === "resume") return [...H.launch.fork ? ["--session-id", H.sessionId, "--fork-session"] : [], "--resume", H.launch.sessionId, ...H.launch.flagArgs];
  return H.launch.args;   // <-- "prompt" mode: returned verbatim, no synthesis from user defaultMode
}

For the mode: "prompt" path (new agent creation), H.launch.args is returned unmodified. The dispatcher never reads permissions.defaultMode from user settings and translates it into a startup flag.

Step 3 — bypassPermissions requires a startup flag. From the permission-modes docs:

You cannot enter bypassPermissions from a session that was started without one of the enabling flags; restart with one to enable it: ``bash claude --permission-mode bypassPermissions ``

So even though ~/.claude/settings.json says defaultMode: bypassPermissions, the spare session never sees a flag that allows it to enter that mode, so it falls back to default.

Why does interactive CLI work then? When claude is invoked directly in a terminal, the startup code reads defaultMode from settings and synthesizes the equivalent of the --permission-mode flag internally. This synthesis does not happen on the bg-spare dispatch code path.

Auto mode overlap (separate issue, related symptom)

Before applying disableAutoMode: "disable", the same setup landed in auto mode instead of default, because of this policy in the binary:

[auto-mode] hasAutoModeOptIn=true policy defaultMode=auto implies consent

When the user's account is opted into auto mode (Team-plan admin toggle), the auto-mode policy silently overrides permissions.defaultMode from settings.json for bg-spawned sessions and applies auto. Adding disableAutoMode: "disable" to user settings turns this off — but the session then falls back to default (this bug), not to bypassPermissions as the user configured.

So this is really two related problems:

  1. Auto-mode opt-in overrides user-configured defaultMode for fleet/bg sessions without telling the user.
  2. The fleet/bg dispatcher doesn't synthesize a startup flag from user defaultMode, so bypassPermissions can never activate even when the auto-mode override is disabled.

Suggested fix

In the dispatcher path that constructs launch.args for mode: "prompt" (and similar new-session modes), read permissions.defaultMode from the merged settings and, when it's bypassPermissions, prepend --permission-mode bypassPermissions to launch.args. Mirror the same synthesis the interactive CLI already does at startup.

A second fix should ensure auto-mode opt-in respects permissions.defaultMode from user settings rather than overriding it — opt-in means "auto mode is available," not "auto mode wins over my explicit defaultMode."

Related issues

  • #37442 — Subagents don't inherit bypassPermissions from parent
  • #29026 — Desktop app ignores defaultMode: bypassPermissions
  • #12604 — VS Code extension: defaultMode: bypassPermissions not working
  • #39311 — Desktop app: Auto/Bypass greyed out despite account toggles
  • #38662, #38859, #34095, #32402, #27203 — adjacent permission-inheritance bugs

Environment

  • Claude Code: 2.1.141
  • OS: Linux 6.8.0-63-generic (Ubuntu)
  • Account plan: Max
  • Auto-mode account toggle: enabled (Anthropic-side opt-in)

[AI-assisted - Claude]

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗