Bug: Write tool permissions do not match paths outside the project directory

Resolved 💬 3 comments Opened Mar 24, 2026 by m-mcgowan Closed Mar 24, 2026

Problem

The Write tool permission system does not reliably auto-approve writes to paths outside the project directory, regardless of the permission pattern format used. This forces users to manually approve every write to external paths, even when explicit allow rules are configured.

What We Tried

We attempted every documented permission format to allow writes to ~/.cache/ccstatusline/tasks/claude-task-*:

| Permission Pattern | Result |
|---|---|
| Write(//Users/mat/.cache/ccstatusline/tasks/*) | Still prompts |
| Write(~/.cache/ccstatusline/tasks/*) | Still prompts |
| Write(~/.cache/ccstatusline/tasks/claude-task-*) | Still prompts |
| Write(**/claude-task-*) | Still prompts |
| Write(//**/claude-task-*) | Still prompts |
| additionalDirectories + Write(//...) | Still prompts |

In all cases, Claude passes Write(~/.cache/ccstatusline/tasks/claude-task-<uuid>) as the tool argument, which Claude Code resolves and displays as a relative path ../../.cache/ccstatusline/tasks/claude-task-<uuid>. None of the permission patterns match.

For comparison, Read permissions with the same // absolute path format work correctly and auto-approve without prompting.

Workaround

We use a PreToolUse hook on Write that checks if the file path contains claude-task- and returns permissionDecision: "allow":

{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Write",
      "hooks": [{
        "type": "command",
        "command": "jq -r 'if .tool_name == \"Write\" and (.tool_input.file_path | test(\"claude-task-\")) then {\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"allow\"}} else {} end'"
      }]
    }]
  }
}

This works but is heavyweight for what should be a simple permission rule.

Additionally: Bash Permissions Only Support Prefix Matching

We also tried using Bash echo to write the file instead of the Write tool:

| Permission Pattern | Result |
|---|---|
| Bash(echo * > /Users/mat/.cache/.../claude-task-*) | Still prompts |
| Bash(mkdir -p ... && echo * > .../claude-task-*) | Still prompts |

The * glob in Bash permissions does not appear to match across the full command string. The documentation mentions Bash(git:*) prefix matching with :*, but does not document whether * works as a glob within the command pattern. If only prefix matching is supported, this should be clearly documented.

Expected Behavior

Write(//absolute/path/*) should auto-approve writes to matching absolute paths, consistent with how Read(//absolute/path/*) already works.

Environment

  • Claude Code CLI
  • macOS (Darwin 23.5.0)
  • Tested with multiple Claude Code sessions

View original on GitHub ↗

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