claude-code - 💡(How to fix) Fix [Bug] CLI sandbox intercepts writes to .claude/** even when --permission-prompt-tool grants permission [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#54189Fetched 2026-04-29 06:33:53
View on GitHub
Comments
0
Participants
1
Timeline
6
Reactions
0
Participants
Timeline (top)
labeled ×6

When using --permission-prompt-tool to delegate permission decisions to a custom MCP server, writes to paths under .claude/** are still blocked by what appears to be a CLI-level sandbox layer after the prompt tool returns behavior: "allow". The MCP grant is ignored at the actual write step.

This forces tools like Edit/Write/Bash (with redirection) to fail mysteriously even though the user clicked Allow in the host application's modal. The model has to discover a workaround at runtime (write to mktemp, then mv) which works because the rename syscall isn't intercepted — confirming the sandbox is a write-time check on a path allow-list.

Error Message

  1. Host applications can warn users instead of silently failing

Root Cause

I'm building a KittStudio, a Tauri-based SDD workflow IDE that uses --permission-prompt-tool to surface a UI modal for every privileged tool call. The whole point of this is to give users explicit consent over what Claude does, with persistent allow-rules for repeated actions.

.claude/workspace/** is where our workflow engine (kitt) writes its artifacts (specs, plans, session logs). The user explicitly trusts these writes — that's why they ran the agent in the first place. Having the CLI silently veto them after the user clicked Allow is confusing UX and removes the value of the prompt-tool integration.

I'm aware of and have already worked around the .claude/settings.local.json super-guard separately by routing those edits through our own filesystem layer. But that's a one-file workaround. A blanket .claude/** block is much wider.

Fix Action

Fix / Workaround

This forces tools like Edit/Write/Bash (with redirection) to fail mysteriously even though the user clicked Allow in the host application's modal. The model has to discover a workaround at runtime (write to mktemp, then mv) which works because the rename syscall isn't intercepted — confirming the sandbox is a write-time check on a path allow-list.

I'm aware of and have already worked around the .claude/settings.local.json super-guard separately by routing those edits through our own filesystem layer. But that's a one-file workaround. A blanket .claude/** block is much wider.

Happy to test patches or provide more detailed traces (CLI version, MCP exchange logs) on request.

Code Example

claude -p \
     --mcp-config ~/.kitt-studio/mcp-config.json \
     --permission-prompt-tool mcp__kitt_perm__permission_request
RAW_BUFFERClick to expand / collapse

[Bug] CLI sandbox intercepts writes to .claude/** even when --permission-prompt-tool grants permission

Summary

When using --permission-prompt-tool to delegate permission decisions to a custom MCP server, writes to paths under .claude/** are still blocked by what appears to be a CLI-level sandbox layer after the prompt tool returns behavior: "allow". The MCP grant is ignored at the actual write step.

This forces tools like Edit/Write/Bash (with redirection) to fail mysteriously even though the user clicked Allow in the host application's modal. The model has to discover a workaround at runtime (write to mktemp, then mv) which works because the rename syscall isn't intercepted — confirming the sandbox is a write-time check on a path allow-list.

Reproduction

Tested on Claude Code CLI (latest as of 2026-04-28), macOS.

  1. Spawn the CLI with a custom permission prompt tool:

    claude -p \
      --mcp-config ~/.kitt-studio/mcp-config.json \
      --permission-prompt-tool mcp__kitt_perm__permission_request

    where mcp-config.json defines a stdio MCP server that echoes back {"behavior":"allow", ...} for every permission_request tool call.

  2. Ask the model to write a file under .claude/workspace/<some_subfolder>/:

    "Create .claude/workspace/refactors/example/metadata.json with content {}"

  3. Observe:

    • The CLI calls the MCP permission_request tool. Our server returns {"behavior":"allow", "updatedInput":{...}}.
    • The tool result shows OUTPUT {"behavior":"allow", ...} in the chat — grant is recognized.
    • The actual Bash mkdir -p ... or cat > ... fails (red X in the tool card).
    • The model itself reports: "The permission was granted but the sandbox still intercepts .claude/ writes at a system level."
  4. The model self-rescues by writing to $(mktemp) then mv-ing into place. The mv succeeds. This confirms the sandbox checks open(O_WRONLY) against the path allow-list but does NOT check rename().

Expected behavior

When --permission-prompt-tool is configured and the tool returns behavior: "allow", the originating tool call should proceed. The MCP grant should be authoritative — that's the documented purpose of the flag.

If there is a separate hardcoded protection on .claude/** (similar to the known .claude/settings*.json super-guard), please document it explicitly so:

  1. Permission-prompt-tool implementers know not to expect grants for those paths
  2. Host applications can warn users instead of silently failing

Why this matters

I'm building a KittStudio, a Tauri-based SDD workflow IDE that uses --permission-prompt-tool to surface a UI modal for every privileged tool call. The whole point of this is to give users explicit consent over what Claude does, with persistent allow-rules for repeated actions.

.claude/workspace/** is where our workflow engine (kitt) writes its artifacts (specs, plans, session logs). The user explicitly trusts these writes — that's why they ran the agent in the first place. Having the CLI silently veto them after the user clicked Allow is confusing UX and removes the value of the prompt-tool integration.

I'm aware of and have already worked around the .claude/settings.local.json super-guard separately by routing those edits through our own filesystem layer. But that's a one-file workaround. A blanket .claude/** block is much wider.

Related issues

This bug sits at the intersection of several existing issues that don't fully cover the MCP+.claude/** angle:

  • #41615permissions.allow and PreToolUse hooks cannot override .claude/ sensitive-file prompt — same symptom, different mechanism (hooks, not MCP).
  • #52822 — PreToolUse hook permissionDecision: "allow" does not suppress native prompt — same "allow ignored" pattern but not scoped to .claude/.
  • #39666 — ExitPlanMode approval via --permission-prompt-tool stdio silently ignored — same mechanism (MCP prompt-tool) but specific to ExitPlanMode.
  • #1175--permission-prompt-tool needs minimal working example — this very integration is one of the examples being asked for.
  • #30519 — Permissions matching is fundamentally broken — meta-issue tracking 30+ open permission issues with no staff engagement.

I'd happily cross-link this report into #1175 as a reference implementation and into #30519 as another data point on the MCP path-tool branch.

Prior art (working integrations)

Apps using the Anthropic API directly (not the CLI as subprocess) don't hit this issue because they implement their own permission system without inheriting the CLI sandbox:

The trade-off: those apps reimplement session management, slash commands, plan mode, etc. from scratch. The CLI offers all of that for free, but the sandbox restrictions come along.

Suggested resolution

Any of:

  1. Honor the grant. When the prompt tool returns allow, bypass the path allow-list for that tool call.
  2. Carve .claude/** out of the allow-list when prompt-tool is wired. The user has explicitly opted into a more granular permission model — the catch-all CLI sandbox no longer adds safety, only friction.
  3. Document the layering clearly. If the sandbox is intentionally orthogonal to the prompt tool, say so in the docs for --permission-prompt-tool and --mcp-config. We'd at least know to surface a warning to users.

Happy to test patches or provide more detailed traces (CLI version, MCP exchange logs) on request.

Environment

  • macOS Sonoma 14.x
  • Claude Code CLI: paste your version from claude --version
  • Host app: kitt-studio (Tauri 2 + Svelte 5 + Rust)
  • Bridge: stdio MCP server in a sibling subprocess of the CLI, shim → unix socket → host main app

extent analysis

TL;DR

The CLI sandbox intercepts writes to .claude/** even when --permission-prompt-tool grants permission, and a potential fix is to honor the grant by bypassing the path allow-list for that tool call.

Guidance

  • Investigate the --permission-prompt-tool documentation to see if there are any known limitations or caveats when used with .claude/** paths.
  • Verify that the MCP server is correctly configured and returning the expected {"behavior":"allow", ...} response for permission_request tool calls.
  • Consider implementing a workaround by writing to a temporary location and then renaming the file to the desired location under .claude/**, as the rename() syscall is not intercepted by the sandbox.
  • Review the related issues (#41615, #52822, #39666, #1175, #30519) to see if there are any other relevant details or potential solutions.

Example

# Write to a temporary location
tmp_file=$(mktemp)
echo "{}" > "$tmp_file"

# Rename the file to the desired location
mv "$tmp_file" ".claude/workspace/refactors/example/metadata.json"

Notes

The issue seems to be specific to the interaction between the --permission-prompt-tool and the CLI sandbox, and may require changes to the CLI or the MCP server configuration to resolve.

Recommendation

Apply a workaround by writing to a temporary location and then renaming the file to the desired location under .claude/**, as this approach has been shown to work in the provided example.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

When --permission-prompt-tool is configured and the tool returns behavior: "allow", the originating tool call should proceed. The MCP grant should be authoritative — that's the documented purpose of the flag.

If there is a separate hardcoded protection on .claude/** (similar to the known .claude/settings*.json super-guard), please document it explicitly so:

  1. Permission-prompt-tool implementers know not to expect grants for those paths
  2. Host applications can warn users instead of silently failing

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING