settings.local.json: 'Yes, allow' permission prompt writes malformed Read(//abs/path) with double leading slash
Summary
When a user clicks "Yes, allow" on a permission prompt for a Read(...) on an absolute path, Claude Code writes the entry to .claude/settings.local.json with a leading double slash (Read(//home/acs/...)) instead of a single slash. The malformed matcher never fires on subsequent sessions, so the same prompt recurs indefinitely — clicking "Yes, allow" again only appends another broken entry.
Reproduction
- In any project, trigger a Claude Code
Readoperation on an absolute-path target (e.g. reading a symlinked skill file whose realpath starts with/home/...). - The permission prompt appears. Click "Yes, allow reading from X during this session" or similar persistent-allow option.
- Inspect
.claude/settings.local.json.
Expected: Read(/home/user/some/path/**)
Actual:
{
"permissions": {
"allow": [
"Read(//home/user/some/path/**)"
]
}
}
The leading // makes the matcher inert — the permission checker canonicalises requested paths with a single leading /, so //home/... never matches /home/.... Every new session re-prompts for the same Read, and clicking "Yes, allow" adds yet another broken entry.
Field-observed example
.claude/settings.local.json in one affected project accumulated three broken entries from repeated prompts:
Read(//home/acs/.claude/agents/adt/**)
Read(//home/acs/.claude/commands/adt/**)
Read(//home/acs/.claude/commands/**)
None of these match any real read because the actual paths canonicalise to /home/acs/....
Environment
- Claude Code: 2.1.119
- OS: Linux (Ubuntu 22.04, kernel 5.15)
- Shell: bash
- Config files:
~/.claude/settings.json(user-level, hand-written) +<project>/.claude/settings.local.json(auto-written by prompts)
Impact
- Users who rely on symlinked skills/agents (e.g. skills installed by editing a file under one path but exposed via
~/.claude/skills/symlink) hit the permission prompt on every session, forever. - Clicking "Yes, allow" appears to work at the moment but silently fails to persist.
- The workaround — hand-editing
settings.jsonto add a correctly-formedRead(/path/**)— is fiddly and not discoverable.
Likely fix location
The code path that translates the "Yes, allow" prompt's chosen path into the settings.local.json matcher string is prefixing the canonical path with an extra /. Stripping one leading slash before wrapping in Read(...) should resolve the issue.
Workaround for affected users
Manually edit settings.local.json and strip the leading / from any Read(//...) entries, OR preemptively add a correct Read(/...) rule to ~/.claude/settings.json. The adt tool at github.com/AntonioCS/agent-dev-tools (ticket wTmQcH7F) now does this automatically during install to work around the issue for users of that project.
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗