Bug: Write tool permissions do not match paths outside the project directory
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
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗