Dual ~/.claude.json divergence — session reads /home/claude/.claude.json not /root
Claude Code has TWO parallel user-config files that can drift silently:
/home/claude/.claude.json— read when the session runs asclaudeuser (default)/root/.claude.json— read whensudo claudeor any root-invoked claude CLI runs
Silent drift symptom: MEMORY.md asserts “Permanent 10 MCPs”, but live claude mcp list (as claude-user) showed only 8. Root cause: 2 MCPs (researchclaw, xint) were registered only in /root/.claude.json, never cascaded to /home/claude/.claude.json. Session couldn’t see them.
Detection command:
diff <(jq -S .mcpServers /home/claude/.claude.json) <(jq -S .mcpServers /root/.claude.json)Empty diff = synced; any output = drift.
Reconciliation:
import json
home_cfg = json.load(open('/home/claude/.claude.json'))
root_cfg = json.load(open('/root/.claude.json'))
all_names = set(home_cfg.get('mcpServers',{})) | set(root_cfg.get('mcpServers',{}))
# For each name, ensure it's in both with identical configRule: when claude mcp add --scope user is used, it writes ONLY to the running-user’s home. Always cascade to both files manually, or use a prepare-mcp hook. MEMORY.md now documents this as a CRITICAL system invariant. Session-start pristine sweep added a dual-config diff check (evolution-backlog item).
Universal lesson: when the same data has TWO physical homes (root-user vs claude-user, host vs container, primary vs replica), documentation cannot prevent drift — only automated diff/sync can.
Related
- docker
- salesforce
- 2026-04-04-oracle-001-self-architecture-analysis
- openclaw
- notebooklm
- dual-claude-json-sync-invariant-session-user-determines-acti
- claude-json-dual-config-root-requires-sudo