CLAUDE_CONFIG_DIR is not honored by .claude/rules/*.md auto-attachment (leaks default profile's rules into isolated profiles)
Description
When CLAUDE_CONFIG_DIR is set to a non-default directory, the automatic .claude/rules/*.md context-injection feature ("nested_memory" attachments, the mechanism behind the InstructionsLoaded hook and per-file-type coding-style/testing/security rules) still resolves rules from the hardcoded default ~/.claude/rules/ path, instead of $CLAUDE_CONFIG_DIR/rules/. This happens even though every other subsystem in the same session (session/transcript storage, settings.json, plugins, OAuth token) correctly honors CLAUDE_CONFIG_DIR.
Additionally, when a same-relative-path rules file does exist under $CLAUDE_CONFIG_DIR/rules/, both it and the default-profile file load simultaneously — there's no precedence or deduplication. The correctly-scoped file is tagged "type":"User" in the transcript; the leaked default-profile file is mistakenly tagged "type":"Project", suggesting the resolution logic isn't even aware it's reading from outside the configured root.
This defeats the isolation purpose of CLAUDE_CONFIG_DIR for anyone running multiple profiles on one machine (e.g. separate work/personal identities, or a profile with a specialized system persona) — content from one profile's rules/ silently bleeds into every other profile whenever a matching file type is read.
Reproduction
- Have a "default" profile at
~/.claudewith a rules file usingpaths:frontmatter, e.g.~/.claude/rules/typescript/coding-style.md:
```markdown
---
paths:
- "**/*.ts"
- "**/*.tsx"
---
# Some default-profile TypeScript rule
```
- Set up a second, isolated profile directory, e.g.
~/.claude-work, with norules/directory at all. - Run a session scoped to the second profile:
``bash``
CLAUDE_CONFIG_DIR="$HOME/.claude-work" claude -p "Read some-file.tsx and reply DONE"
- Inspect the resulting transcript at
~/.claude-work/projects/.../*.jsonl— it contains anested_memoryattachment entry whosepathis/Users/you/.claude/rules/typescript/coding-style.md(the default profile's path), not anything under~/.claude-work.
Additional case — even mirroring the file locally doesn't fix it:
- Create
~/.claude-work/rules/typescript/coding-style.mdwith the samepaths:frontmatter and distinct content. - Repeat step 3.
- The transcript now shows both attachments: the local
~/.claude-work/rules/typescript/coding-style.md("type":"User") and the default-profile~/.claude/rules/typescript/coding-style.md("type":"Project") — the default-profile content loads unconditionally regardless of whether a local override exists.
Expected behavior
.claude/rules/*.md auto-attachment should resolve against $CLAUDE_CONFIG_DIR (falling back to ~/.claude only when CLAUDE_CONFIG_DIR is unset), consistent with how settings.json, plugin state, session storage, and OAuth credentials already behave under CLAUDE_CONFIG_DIR in the same version.
Actual behavior
Rules content from the default ~/.claude/rules/ is injected into sessions regardless of CLAUDE_CONFIG_DIR, and is not deduplicated against or superseded by a same-path file that does exist under the configured profile.
Environment
- Claude Code version: 2.1.215
- OS: macOS (Darwin 25.5.0)
- Both profiles on the same machine, same user account, switched via a shell alias that sets
CLAUDE_CONFIG_DIRand a separateCLAUDE_CODE_OAUTH_TOKENper-invocation (not exported/persisted — confirmed the env var does not leak into later shell commands)
Additional context
Related past fixes suggest this is a recurring category of bug rather than a one-off — the changelog shows CLAUDE_CONFIG_DIR support being patched into individual subsystems one at a time after the fact (IDE shell-integration lock files, the workflow save dialog, /setup-vertex//setup-bedrock path display). The rules/nested_memory auto-attachment subsystem appears to be another one that was missed.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗