A .claude config root at or above cwd is treated as project scope and overrides the CLAUDE_CONFIG_DIR profile's settings
Description
Claude Code discovers project-level settings by walking up from the current working directory looking for a .claude/ directory, and project settings outrank user settings for every key. The default user-configuration root is itself ~/.claude. As a result, whenever a .claude directory that is actually a config root sits at or above the current working directory, it is discovered as a project settings source, and its settings.json overrides the user-level profile selected by CLAUDE_CONFIG_DIR.
CLAUDE_CONFIG_DIR is meant to select which user profile is active. This defeats that selection: the profile's own settings.json is silently outranked by a config-root .claude that happens to lie on the path from / down to cwd.
Because settings precedence is shared across all keys, this is not cosmetic. permissions, hooks, env, statusLine, and every other settings.json key from the wrong profile are applied. The statusLine is just where it is first noticed, because a per-profile status indicator visibly renders the wrong one.
Mechanism
1. Launch with CLAUDE_CONFIG_DIR pointing at profile B, from a cwd that has a
config-root `.claude` at or above it (the common case: cwd is $HOME and the
default profile lives at $HOME/.claude).
2. User settings load from profile B's settings.json (correct)
3. Project discovery walks up from cwd, finds the config-root .claude/
4. That .claude/settings.json is treated as PROJECT scope
5. Project > User precedence -> the config-root profile's settings win
The precedence order (highest to lowest) is: managed, command-line args, project .claude/settings.local.json, project .claude/settings.json, user (~/.claude or $CLAUDE_CONFIG_DIR). The root cause is that a directory serving as a user-config root is not excluded from project-scope discovery, even though the two roles are conceptually distinct.
Reproduction
- Keep two profiles: the default at
~/.claude/settings.jsonand a second selected viaCLAUDE_CONFIG_DIR, each with a distinctstatusLinecommand (any other key such aspermissionsdemonstrates it equally). cd ~CLAUDE_CONFIG_DIR=~/.some-other-profile claude- The status line renders the
~/.claudecommand, not the selected profile's.
The same collision loads ~/.claude/CLAUDE.md as project memory alongside the selected profile's user memory, merging two profiles' instructions.
More generally, the trigger is not specific to $HOME. Any layout where a config-root .claude lies at or above cwd reproduces it. Launching from the home directory is simply the most common instance, since the default config root is $HOME/.claude.
Expected
A directory that is a user-configuration root (the default ~/.claude, or any directory pointed to by CLAUDE_CONFIG_DIR) should not simultaneously be eligible as a project-settings source when it happens to sit at or above cwd. Selecting a profile via CLAUDE_CONFIG_DIR should apply that profile's settings, regardless of where the session is launched from.
Actual
The config-root .claude/settings.json is applied as project-scope settings and overrides the CLAUDE_CONFIG_DIR-selected profile for every settings key.
On the obvious workaround, and why it is not a fix
Because project discovery matches directories literally named .claude, while CLAUDE_CONFIG_DIR can point at any name, a user can sidestep this specific collision by giving every profile a non-default name (for example ~/.claude-work and ~/.claude-personal, with no ~/.claude present). Then no .claude config root exists at or above $HOME, so nothing is mis-promoted to project scope.
This is a workaround, not a fix:
- It requires abandoning the default
~/.claudelocation that ships out of the box, so the large majority of users who use the default are still exposed. - Running bare
claudewith noCLAUDE_CONFIG_DIRrecreates a fresh~/.claude, reintroducing the collision the next time a session is launched from$HOME. - It does not address the hardcoded
~/.claudefallback reported separately (see Related), which references the literal path regardless of the configured name.
The underlying design gap remains: a config-root directory is treated as project scope.
Related
- #80580 (
CLAUDE_CONFIG_DIRdoes not fully isolate user-levelCLAUDE.mddiscovery from$HOME/.claude). Same theme, but that reproduction has cwd outside$HOME, which points at a hardcoded~/.claudememory fallback rather than cwd-walk project discovery. This report is specifically aboutsettings.jsonprecedence when a config-root.claudeis at or above cwd. - #79233 (
.claude/rules/*.mdauto-attachment leaks the default profile's rules into isolated profiles).
Environment
- Claude Code version: 2.1.218 (behavior is precedence logic, not believed to be version-specific)
- OS: Linux
- Install: native binary
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗