[BUG] .claude/settings.json and settings.local.json resolve against literal cwd, not git root — subdirectory launches silently drop all project settings
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet as an open issue
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code
What's Wrong?
.claude/settings.json and .claude/settings.local.json are resolved against the literal cwd, not the git root. When Claude Code is launched from a subdirectory of a repo, all project-scoped settings — hooks, permissions/allow-rules, enabledPlugins, autoMemoryDirectory, etc. — silently disappear, with no error. CLAUDE.md and skills correctly walk up to the repo root in the same session, so this is a settings-specific resolution bug, not a general cwd-discovery issue.
This looks like the same underlying bug as #36793 ("Project settings hooks not loaded when working directory is a subdirectory of the repo") and its duplicate #44278 ("Project-scoped settings don't resolve from subdirectories, making project scope identical to local scope"). Both were closed — #36793 auto-closed 2026-05-30 as inactive (not fixed, not rejected on the merits), #44278 closed as a duplicate of #36793. I'm filing fresh per the bot's own instruction on #36793 ("open a new issue if this is still relevant"), since it still reproduces on a version far newer than the close date.
What's new here vs. #36793 / #44278
- A debug session ruled out the workspace-trust gate as an alternative explanation via an intervention test — settings from the subdirectory launch stayed unloaded regardless of trust state. So this is not the trust gate; it's pure path resolution happening before or independent of that gate.
- Confirmed affected by the same root cause: hooks, permissions/allow-rules,
enabledPlugins, andautoMemoryDirectory(all silently drop from a subdirectory launch). - A local
.claude/settings.local.jsonwith an absolute path value does not fix the underlying issue either — the settings file itself isn't found from the subdirectory in the first place, so its contents never come into play. - Below is an actually-executed, copy-pasteable repro with real captured output and
--debug-fileevidence (see "Steps to Reproduce"), not just a description.
What Should Happen?
.claude/settings.json and .claude/settings.local.json should resolve by walking up from the working directory to the nearest git root (the same resolution CLAUDE.md already uses), so all project-scoped config is available from any subdirectory within the project.
Steps to Reproduce
# 1. Create a minimal repo with a project-level hook that blocks edits
mkdir settings-cwd-repro && cd settings-cwd-repro
git init -q
mkdir .claude subdir
cat > .claude/settings.json <<'EOF'
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{ "type": "command", "command": "echo 'HOOK FIRED' >&2; exit 2" }
]
}
]
}
}
EOF
echo hello > file.txt
echo hello > subdir/file.txt
git add -A && git commit -q -m "init repro"
# 2. From the repo root — the hook fires and blocks the edit (WORKS)
claude --permission-mode acceptEdits --allowedTools "Edit" -p \
"Edit file.txt to say 'modified'. Report verbatim whether it succeeded or was blocked."
# 3. From the subdirectory — same repo, same committed settings.json (FAILS)
cd subdir
claude --permission-mode acceptEdits --allowedTools "Edit" -p \
"Edit file.txt to say 'modified'. Report verbatim whether it succeeded or was blocked."
I ran this exact script on v2.1.198. Actual output:
Step 2 (repo root):
The edit was blocked. Verbatim tool error returned: `` PreToolUse:Edit hook error: [echo 'HOOK FIRED' >&2; exit 2]: HOOK FIRED ``
Step 3 (subdirectory):
Edit result (verbatim): The edit tool call succeeded, no hook blocked it. ... no .claude/settings*.json exist in this project directory
That last line is the subagent itself confirming the divergence — from the subdirectory it can't find .claude/settings.json at all, because it's looking in the wrong place.
Direct confirmation via --debug-file on the same two runs — the line the harness logs at startup, listing every settings file it will watch for changes:
From the repo root:
[DEBUG] Watching for changes in setting files /home/elijah/.claude/settings.json, /path/to/settings-cwd-repro/.claude/settings.json, /path/to/settings-cwd-repro/.claude/settings.local.json...
From subdir/:
[DEBUG] Watching for changes in setting files /home/elijah/.claude/settings.json...
From the subdirectory, the repo's own .claude/settings.json and .claude/settings.local.json never even enter the watch list — the resolver looks for subdir/.claude/settings.json (confirmed via the adjacent "Broken symlink or missing file encountered for settings.json at path: .../subdir/.claude/settings.json" debug line), finds nothing, and silently gives up instead of walking up to the git root the way CLAUDE.md resolution does.
Claude Model
N/A (harness-level bug, not model-dependent)
Is this a regression?
Unclear — #36793 reports this as a regression from a state that worked "confirmed working ~March 6, 2026," but I don't have version-pinned before/after evidence myself.
Claude Code Version
2.1.198
Platform
Anthropic API
Operating System
Linux
Terminal/Shell
fish
Additional Information
Workaround: always launch claude from the repo root — e.g. a shell wrapper that cds to ` git rev-parse --show-toplevel first before invoking claude`.
Related/likely-same-family issues: #36793, #44278, #57563, #55973.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗