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

Resolved 💬 1 comment Opened Apr 28, 2026 by bacleclement Closed May 30, 2026

[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:

``bash
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.

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

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

  1. 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."
  1. 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

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗