Skip to content

Fix transcript path resolution for Claude Code worktrees#817

Open
pjbgf wants to merge 2 commits intomainfrom
pjbgf/claude-worktrees
Open

Fix transcript path resolution for Claude Code worktrees#817
pjbgf wants to merge 2 commits intomainfrom
pjbgf/claude-worktrees

Conversation

@pjbgf
Copy link
Copy Markdown
Member

@pjbgf pjbgf commented Mar 31, 2026

When Claude Code uses --worktree, it creates git worktrees under .claude/worktrees/<branch>/. Entire's resolveTranscriptPath used WorktreeRoot() which returned the worktree path, causing GetSessionDir to derive a different Claude project directory than the main repo. This broke rewind and resume operations.

Add paths.MainRepoRoot() to resolve back to the main repository root from linked worktrees, and use it in cli.resolveTranscriptPath. Refactor GetWorktreeID, IsLinkedWorktree, and MainRepoRoot to use os.Root for traversal-resistant .git file access.


Note

Medium Risk
Moderate risk because it changes how repository roots are resolved in worktree contexts and introduces new .git parsing logic; failures would break transcript/rewind/resume pathing rather than core data integrity.

Overview
Fixes transcript path resolution for Claude Code when running inside linked git worktrees by switching resolveTranscriptPath to use paths.MainRepoRoot() instead of paths.WorktreeRoot(), ensuring worktrees map to the same Claude project directory as the main repo.

Adds paths.IsLinkedWorktree and paths.MainRepoRoot (and refactors GetWorktreeID) to read .git via os.Root/osroot.ReadFile for traversal-resistant worktree detection and main-repo root extraction, and updates strategy helpers to delegate to the new paths APIs.

Extends coverage with new tests for main-repo vs linked-worktree root resolution and a regression test demonstrating that ClaudeCodeAgent.GetSessionDir yields different directories when given a worktree path.

Written by Cursor Bugbot for commit 02f445b. Configure here.

Copilot AI review requested due to automatic review settings March 31, 2026 11:19
When Claude Code uses --worktree, it creates git worktrees under
.claude/worktrees/<branch>/. Entire's resolveTranscriptPath used
WorktreeRoot() which returned the worktree path, causing GetSessionDir
to derive a different Claude project directory than the main repo.
This broke rewind and resume operations.

Add paths.MainRepoRoot() to resolve back to the main repository root
from linked worktrees, and use it in cli.resolveTranscriptPath.
Refactor GetWorktreeID, IsLinkedWorktree, and MainRepoRoot to use
os.Root for traversal-resistant .git file access.

Signed-off-by: Paulo Gomes <paulo@entire.io>
Assisted-by: Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: c6491956c19f
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes Claude Code transcript path resolution when running Entire inside linked git worktrees (notably Claude’s .claude/worktrees/<branch>/ layout) by resolving transcript/project directories relative to the main repository root rather than the current worktree root.

Changes:

  • Switch transcript path resolution to use paths.MainRepoRoot() so Claude sessions map to the same project directory from linked worktrees.
  • Add paths.IsLinkedWorktree() and paths.MainRepoRoot() with traversal-resistant .git access using os.Root, and refactor strategy helpers to delegate to these.
  • Add unit tests for MainRepoRoot/IsLinkedWorktree and a Claude agent regression test demonstrating the root cause.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
cmd/entire/cli/transcript.go Resolve transcript paths using main repo root to avoid worktree-specific Claude project dirs.
cmd/entire/cli/strategy/common.go Delegate worktree detection / main-root resolution to paths helpers.
cmd/entire/cli/paths/worktree.go Use os.Root-scoped reads for .git parsing in GetWorktreeID.
cmd/entire/cli/paths/paths.go Introduce IsLinkedWorktree + MainRepoRoot using traversal-resistant .git access.
cmd/entire/cli/paths/paths_test.go Add tests for MainRepoRoot and IsLinkedWorktree.
cmd/entire/cli/agent/claudecode/worktree_test.go Add regression test demonstrating why WorktreeRoot breaks Claude session dir resolution.

IsLinkedWorktree now reads the .git gitfile and checks for worktree
admin markers (.git/worktrees/ or .bare/worktrees/) instead of just
checking whether .git is a file. This prevents submodules (which use
.git/modules/) from being misidentified as linked worktrees.

MainRepoRoot now supports both .git/worktrees/ and .bare/worktrees/
markers when extracting the main repo root, and handles relative
gitdir paths by resolving them against the worktree root. The shared
parseGitfile helper normalizes paths with filepath.ToSlash for
consistent marker matching.

Extract parseGitfile and hasWorktreeMarker into shared helpers used
by GetWorktreeID, IsLinkedWorktree, and MainRepoRoot. Fix git
worktree add argument order in tests (-b before path).

Signed-off-by: Paulo Gomes <paulo@entire.io>
Assisted-by: Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: f6d95094dfb9
@pjbgf pjbgf force-pushed the pjbgf/claude-worktrees branch from 02f445b to c404ef1 Compare March 31, 2026 11:48
@pjbgf pjbgf marked this pull request as ready for review March 31, 2026 12:03
@pjbgf pjbgf requested a review from a team as a code owner March 31, 2026 12:03
@ALRubinger
Copy link
Copy Markdown

Appreciate y'all! HMU if you need more context or user testing: https://x.com/ALRubinger/status/2038743082901115180?s=20

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants