fix: symlink CLAUDE.md and .claude/ into new worktrees - #194
Conversation
CLAUDE.md and .claude/ (skills, rules, commands, settings) are gitignored, so git worktree add never brings them into a new worktree and setup-worktree.sh didn't fill the gap either — every worktree came up with no project instructions and no local skills. Symlink them back to the source worktree instead of copying so edits stay in sync across all worktrees with no re-sync step.
There was a problem hiding this comment.
PR Review: Symlink CLAUDE.md and .claude/ into New Worktrees
Strengths
- Consistent style (
setup-worktree.sh:53-65): The new blocks follow the exact same guard-then-act pattern already used for.envandconfigs/— easy to read and maintain. - Correct existence checks: Uses
-e(any file type, including existing symlinks) for the destination and-f/-dfor the source, which correctly handles re-running the script on a worktree where the symlinks were already created. - Right tool for the job: Symlinking instead of copying is the right call here. CLAUDE.md is documentation and .claude/ is shared tooling config — both should stay in sync across worktrees, unlike
.envwhich should be per-worktree.
Issues
Critical (Must Fix)
None.
Important (Should Fix)
Silent no-op when source doesn't have CLAUDE.md or .claude (setup-worktree.sh:53-65)
If neither the destination nor the source has CLAUDE.md (or .claude), the script does nothing and logs nothing. The .env block at lines 43-45 emits a warn in this case. A missing .claude/ directory is unlikely to cause confusion, but if the source worktree is unexpectedly missing CLAUDE.md, the developer gets no signal that something is off. Consider adding a warn branch (or at minimum a log) to match the .env pattern and make the script's behavior fully transparent.
if [[ ! -e CLAUDE.md && -f "$source_worktree/CLAUDE.md" ]]; then
log "Linking CLAUDE.md -> $source_worktree/CLAUDE.md"
ln -s "$source_worktree/CLAUDE.md" CLAUDE.md
elif [[ -e CLAUDE.md ]]; then
log "CLAUDE.md already exists."
else
warn "No CLAUDE.md found in this worktree or $source_worktree."
fiMinor (Nice to Have)
Absolute-path symlinks (setup-worktree.sh:55, setup-worktree.sh:62)
ln -s "$source_worktree/CLAUDE.md" CLAUDE.md creates absolute symlinks. This works fine on the machine where the repo was cloned, but breaks if the repository root is ever moved or mounted at a different path. For a local dev script this is acceptable, but a relative symlink (using ../../../CLAUDE.md relative to the worktree) would be more portable. Not a blocker.
Shared .claude/ has write-through semantics
This is a design note rather than a bug: because .claude/ is symlinked, Claude Code sessions in any worktree will read and write the same memory, settings, and hooks. This is almost certainly intentional (it's the stated goal of the PR), but it's worth documenting in CLAUDE.md or a comment so future maintainers don't accidentally assume worktrees are isolated at the Claude config level.
Security (OWASP)
No new security issues introduced by this change. The pre-existing SECRET_KEY="dev-key-for-development-only" on line 80 is a known dev-only default and out of scope for this PR.
The symlink creation does not introduce TOCTOU or path-traversal risk: $source_worktree is derived from git worktree list output and the script already cds to the validated $script_dir before running.
Assessment
Ready to merge? Yes (with the warning branch as a should-fix, not a blocker)
Reasoning: The change is small, correct, and solves a real developer-experience pain point. The only gap is a missing warn branch for the case where the source doesn't have CLAUDE.md/.claude, which would make the script's behavior fully consistent with its own established patterns.
Matches the existing .env block's pattern of warning when the file is missing from both the current and source worktree, instead of silently doing nothing.
Summary
CLAUDE.mdand everything under.claude/(skills, rules, commands, settings) are gitignored in this repo (strict allowlist, never un-ignored), sogit worktree addnever materializes them into a new worktree.setup-worktree.shalready copies.envandconfigs/from the source worktree but had no equivalent step for project instructions/skills — confirmed empirically that existing worktrees are missing bothCLAUDE.mdand.claude/skillsentirely.CLAUDE.mdand.claude/point back at the source worktree's copies and stay in sync automatically.Test plan
.env/configs/copy logic for style consistency./setup-worktree.shin a freshly created worktree and confirmCLAUDE.mdand.claude/resolve as symlinks to the source worktree