Rules files loaded twice when using built-in worktree isolation (.claude/worktrees/)
Description
When using Claude Code's built-in worktree isolation (e.g., isolation: "worktree" in Agent tool, or EnterWorktree), the same .claude/rules/*.md files are loaded twice into context — once from the worktree's own .claude/rules/ and once from the parent repo's .claude/rules/ (reachable via directory traversal).
Reproduction
- Have a repo with
.claude/rules/*.mdfiles (e.g., 5-15 rules files) - Start a Claude Code session that uses worktree isolation (plan mode, or Agent with
isolation: "worktree") - Observe the "Loaded" messages — each rules file appears twice:
L Loaded ../../rules/services-infrastructure.md
L Loaded ../../rules/testing.md
L Loaded ../../rules/performance.md
L Loaded ../../rules/clean-architecture.md
L Loaded ../../rules/api-contracts.md
L Loaded .claude/rules/services-infrastructure.md
L Loaded .claude/rules/testing.md
L Loaded .claude/rules/performance.md
L Loaded .claude/rules/clean-architecture.md
L Loaded .claude/rules/api-contracts.md
Root Cause
Worktrees are created inside .claude/worktrees/<name>/:
repo-root/
.claude/
rules/ ← parent repo's rules (path 1)
worktrees/
radiant-conjuring-squirrel/ ← worktree root
.claude/
rules/ ← worktree's own copy (path 2)
Claude Code's rules loader walks up from the working directory looking for .claude/rules/. From the worktree root, it finds:
<worktree>/.claude/rules/*.md— the worktree's checked-out copy<worktree>/../../rules/*.md— resolves to the parent repo's.claude/rules/because the worktree lives inside.claude/worktrees/
Both directories contain identical files (same git content), but the loader treats them as separate because the paths differ.
Impact
- Doubled context window usage for rules. In our case, 5 rules files × ~5-10KB each = ~50-100KB of wasted context per session.
- For repos with many rules files, this significantly reduces available context for actual work.
Expected Behavior
Each rules file should be loaded exactly once, regardless of worktree placement. Options:
- Deduplicate by content hash — skip loading a file if its content matches an already-loaded rules file
- Deduplicate by canonical path — resolve symlinks and
..before loading, skip if the canonical path was already loaded - Stop traversal at worktree boundary — don't walk above the worktree root when looking for
.claude/directories
Environment
- Claude Code CLI (latest)
- macOS Darwin 24.5.0
- Git worktrees created by built-in
isolation: "worktree"agent parameter
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗