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
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-*:Write(//Users/mat/.cache/ccstatusline/tasks/*)Write(~/.cache/ccstatusline/tasks/*)Write(~/.cache/ccstatusline/tasks/claude-task-*)Write(**/claude-task-*)Write(//**/claude-task-*)additionalDirectories+Write(//...)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,
Readpermissions with the same//absolute path format work correctly and auto-approve without prompting.Workaround
We use a
PreToolUsehook onWritethat checks if the file path containsclaude-task-and returnspermissionDecision: "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:
Bash(echo * > /Users/mat/.cache/.../claude-task-*)Bash(mkdir -p ... && echo * > .../claude-task-*)The
*glob in Bash permissions does not appear to match across the full command string. The documentation mentionsBash(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 howRead(//absolute/path/*)already works.Environment