Skip to content

fix: symlink CLAUDE.md and .claude/ into new worktrees - #194

Merged
dngrtech merged 2 commits into
mainfrom
fix/worktree-symlink-claude-config
Aug 23, 2026
Merged

fix: symlink CLAUDE.md and .claude/ into new worktrees#194
dngrtech merged 2 commits into
mainfrom
fix/worktree-symlink-claude-config

Conversation

@dngrtech

Copy link
Copy Markdown
Owner

Summary

  • CLAUDE.md and everything under .claude/ (skills, rules, commands, settings) are gitignored in this repo (strict allowlist, never un-ignored), so git worktree add never materializes them into a new worktree.
  • setup-worktree.sh already copies .env and configs/ from the source worktree but had no equivalent step for project instructions/skills — confirmed empirically that existing worktrees are missing both CLAUDE.md and .claude/skills entirely.
  • Adds two symlink steps (not copies, to avoid drift) so a new worktree's CLAUDE.md and .claude/ point back at the source worktree's copies and stay in sync automatically.

Test plan

  • Reviewed diff against existing .env/configs/ copy logic for style consistency
  • Run ./setup-worktree.sh in a freshly created worktree and confirm CLAUDE.md and .claude/ resolve as symlinks to the source worktree

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.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 .env and configs/ — easy to read and maintain.
  • Correct existence checks: Uses -e (any file type, including existing symlinks) for the destination and -f/-d for 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 .env which 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."
fi

Minor (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.
@dngrtech
dngrtech merged commit 405c3e0 into main Aug 23, 2026
2 checks passed
@dngrtech
dngrtech deleted the fix/worktree-symlink-claude-config branch August 23, 2026 16:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant