Subagents don't inherit bypassPermissions mode from parent session

Status Closed — not planned
Reported on v2.1.81
Maintainer reply None cached
Activity 11 comments · opened Mar 22, 2026 · closed May 28, 2026

Description

When the parent session is configured with "defaultMode": "bypassPermissions" in ~/.claude/settings.json, subagents spawned via the Agent tool still prompt for tool permissions. This defeats the purpose of bypass mode and creates a disruptive experience — every subagent invocation can trigger permission prompts that the user has already opted out of.

Steps to Reproduce

  1. Set "defaultMode": "bypassPermissions" in ~/.claude/settings.json
  2. Also set "skipDangerousModePermissionPrompt": true
  3. Start a Claude Code session — main agent correctly bypasses all permission prompts
  4. Invoke a task that uses the Agent tool (subagent)
  5. The subagent prompts for permissions on tools the parent session would silently allow

Expected Behavior

Subagents should inherit the parent session's permission mode, including bypassPermissions and all allow patterns.

Actual Behavior

Subagents prompt for permissions as if running in a more restrictive mode.

Environment

  • Claude Code version: 2.1.81
  • OS: Windows 11 Pro (10.0.26200)
  • Shell: bash (Git Bash)

Notes

Persistent issue across multiple sessions over several days. Adding broad allow patterns (e.g., Bash(*)) as a workaround doesn't fully resolve it since bypassPermissions should already cover everything.

View original on GitHub ↗

11 Comments

github-actions[bot] · 5 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/26083
  2. https://github.com/anthropics/claude-code/issues/26479
  3. https://github.com/anthropics/claude-code/issues/36225

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

yurukusa · 5 months ago

The Agent tool has a mode parameter that can explicitly set the permission mode for spawned subagents. Until the inheritance bug is fixed, you can work around this by instructing Claude to use mode: "bypassPermissions" when spawning agents.
In your CLAUDE.md, add:

When using the Agent tool, always set mode: "bypassPermissions"

This tells Claude to pass the mode explicitly on every Agent invocation, bypassing the broken inheritance.
If you want a more enforceable approach, a PreToolUse hook on Agent can inject the mode:

INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
[[ "$TOOL" != "Agent" ]] && exit 0
MODE=$(echo "$INPUT" | jq -r '.tool_input.mode // empty' 2>/dev/null)
if [[ -z "$MODE" || "$MODE" == "null" ]]; then
    echo "NOTE: Agent spawned without explicit mode parameter." >&2
    echo "Add mode: \"bypassPermissions\" to the Agent call." >&2
fi
exit 0

This won't block the call, but will warn when agents are spawned without an explicit mode, helping you catch the inconsistency.

AldereteRuben · 4 months ago

Still repros on claude-opus-4-6 (1M context) via VSCode extension on darwin 25.4.0. Confirming from a real multi-repo scenario where this blocked a 7-blocker pre-launch sprint:

Setup

  • Primary cwd: /repo-front
  • Sibling repo: /repo-api (listed in additionalDirectories)
  • Two git worktrees of /repo-api at /repo-api-be1 and /repo-api-be2 (also in additionalDirectories)

.claude/settings.local.json (project scope):

```​
json
{
"permissions": {
"defaultMode": "bypassPermissions",
"allow": [
"Bash(git:)", "Bash(gh:)", "Bash(pytest:*)",
"Bash(python:)", "Bash(npm:)", "Bash(ruff:)", "Bash(mypy:)"
],
"additionalDirectories": [
"/repo-api", "/repo-api-be1", "/repo-api-be2", "/repo-front"
]
}
}


**Behavior**
- Main thread: Bash works in all four paths. I ran `git commit` + `git push` + `gh pr create` against `/repo-api-be1` from the main thread without any prompt.
- Sub-agents (both `general-purpose` and a custom `frontend` agent, with and without `isolation: "worktree"`): every Bash call returns `Permission to use Bash has been denied` on the very first command (`cd` / `git status` / `pwd`). No permission prompt surfaces to me in the parent — it's a silent auto-deny inside the sub-agent.
- Same result whether I launch the sub-agent in the primary cwd or pass the sibling path as the working directory in the prompt.

**Impact**
`bypassPermissions` + `allow` + `additionalDirectories` are all honored by the main thread but none of them reach the sub-agent. The Agent tool effectively becomes read-only (Read/Grep/Glob/Edit/Write) for sibling repos — which kills parallel fan-out across worktrees, the canonical use case for the tool. The only workaround is running the orchestration sequentially in the parent thread, which defeats the purpose.

Related and likely the same underlying bug: #29110, #32402, #37730, #40242. #45888 was closed for Read/Edit in v2.1.97 but Bash in sub-agents is still silently denied on the current release.
uakdemir · 4 months ago

Confirming this still reproduces as of Claude Code 2.x on WSL2 Ubuntu.

Setup:

  • ~/.claude/settings.json has "defaultMode": "bypassPermissions" at user level
  • Project settings.json has "Bash(*)" in permissions.allow and Task allowed
  • Running a multi-agent pipeline skill (orchestrate --auto, which dispatches up to 7 Task/Agent subagents per spec: 2 review-doc phases + 1 implement + up to 4 review-code iters)

Symptom: parent session correctly bypasses all prompts. Every subagent spawned via the Agent/Task tool re-prompts for tool permissions — including on commands the parent already pre-approved via Bash(*). Accumulating exact-match entries like Bash(PGPASSWORD=... psql -h ...) in settings.local.json per-command is a whack-a-mole workaround that doesn't scale to long pipelines.

Workaround tried: broadening the allowlist in settings.json so subagents inherit it at load time. Insufficient for heredoc and complex-quoted commands, which appear not to match Bash(*) cleanly in the restrictive default mode that subagents start in — possibly a separate matcher issue layered on top of the inheritance gap here.

Upstream effect: users with long, Task-heavy workflows get 20–40 permission prompts per spec run, making automation skills like orchestrate --auto practically unusable despite bypass mode being intentionally enabled at the user level.

ThatDragonOverThere · 4 months ago

Multi-agent coordination broken by permission re-prompting in subagents

Setup: Opus window acts as PM/coordinator and spawns 6-8 Sonnet subagents in parallel via the Task tool. Subagents perform basic filesystem work: reading and writing markdown files in .claude/plans/, docs/, and similar directories.

The problem: Every Sonnet subagent re-prompts for read/write permissions on each file, even though the parent Opus window already has bypassPermissions or acceptEdits configured. The permission grant does not propagate to Task-spawned subagents.

Reproduction steps:

  1. Open Claude Code with an Opus model, bypassPermissions or acceptEdits enabled.
  2. Give it a coordination task that spawns multiple parallel Sonnet subagents via the Task tool.
  3. Each subagent is asked to read one markdown file and write updates to another.
  4. Observe: every subagent immediately blocks on a permission dialog for the read, then again for the write.

Downstream impact: Overnight autonomous runs are completely broken. With 6-8 workers all blocking simultaneously on permission prompts, nothing executes, but API quota burns the entire time. By morning there is zero output and a full quota burn. This started around v2.1.116 and is still present in v2.1.117.

The parent window's permission state should be inherited by Task-spawned subagents, or at minimum there should be a flag to propagate it explicitly. Right now the multi-agent coordination pattern is non-functional for any unattended run.

ThatDragonOverThere · 4 months ago

Clarifying the repro: the user clicks "Allow Always" in the permission dialog, but it does not stick across subagent boundaries -- the next spawned subagent hits the same prompt again for the same tool/path combination. Either "Allow Always" is not writing to settings.local.json at all (UI is lying), or it is writing but subagents are not reading the parent's settings.local.json. Either way, "Allow Always" is effectively broken in multi-agent contexts.

ThatDragonOverThere · 4 months ago

To clarify the reproduction case: the user is clicking "Allow Always" multiple times for the same tool on the same path within a single session -- meaning "Allow Always" is functionally identical to "Allow Once" with zero persistence even within the current session. This is not a subagent inheritance issue; if "Allow Always" were writing correctly to settings.local.json, the same session would not re-prompt for the same operation. The button itself appears broken at the write step.

ThatDragonOverThere · 4 months ago

Diagnostic finding that strongly isolates the bug: the project-level settings.local.json already contains broad wildcard allow rules for Bash(), Read(), Write(), Edit(), Glob(), and Grep() -- as permissive as possible, nothing left to allow. Despite this, subagents spawned via the Task/Agent tool continue to prompt for permissions on every basic file operation. The issue is NOT about what rules are written in settings.local.json -- the subagent process is simply not reading or honoring the file that is present. Clicking 'Allow Always' in the permission prompt apparently appends redundant wildcard entries that were already there, so the UI feedback is misleading: the file write succeeds, but the subagent reads nothing from it.

ThatDragonOverThere · 4 months ago

This bug isn't just user friction. It's actively destabilizing safety infrastructure.

Cascade chain just observed in production:

  1. Permission bug forces hundreds of "Allow always" clicks per session
  2. Each click writes to settings.local.json
  3. Multiple agents read/write the file concurrently -- race conditions
  4. An agent doing a "wholesale sync" or auto-save rewrite silently drops critical sections (in our case: an entire PreToolUse hook block including a RAM watchdog enforcer)
  5. Hook regression goes undetected for days because there is no checksum, no diff alert, no test that the hooks are still wired
  6. RAM watchdog fires repeatedly because the upstream blocks are dead
  7. 50GB Python processes crash the machine -- 4 emergency kills in one evening on the same script

The PreToolUse hook that should have blocked the script BEFORE allocation was wiped out by a sync commit. Recovery: had to git-archaeology the prior settings.json, identify the deleted block, and manually restore it with $CLAUDE_PROJECT_DIR-prefixed paths.

Root cause is the permission churn making settings.local.json a constantly-mutated file that other writes can clobber. Fix the permission persistence bug and you remove an entire class of safety regressions downstream.

github-actions[bot] · 3 months ago

Closing for now — inactive for too long. Please open a new issue if this is still relevant.

github-actions[bot] · 1 month ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.