[BUG] transcript_path in stop hook uses cwd hash instead of git-root hash when running in a git worktree

Resolved 💬 3 comments Opened Apr 7, 2026 by cowwoc Closed Jun 7, 2026

Problem

When Claude Code is opened with a git worktree as the working directory, the session JSONL is stored using the git root path, but transcript_path in stop hook payloads uses the literal cwd path. These produce different directory hashes, so transcript_path points to a file that does not exist.

Root Cause

Claude Code appears to use two different directory resolution strategies:

  • Session JSONL storage: Uses the git repository root (e.g., /workspace) → hash -workspace → stored at ~/.claude/projects/-workspace/{session_id}.jsonl
  • transcript_path in hook payload: Uses the literal cwd (e.g., /workspace/.claude/worktrees/branch-name) → hash -workspace--claude-worktrees-branch-name~/.claude/projects/-workspace--claude-worktrees-branch-name/{session_id}.jsonl

The file at the transcript_path location does not exist. Any stop hook that attempts to read it gets NoSuchFileException / FileNotFoundError.

Reproduction Steps

  1. Open Claude Code inside a git worktree:

``
cd /path/to/repo/.claude/worktrees/my-branch
claude
``

  1. Configure a stop hook that reads transcript_path from the hook input JSON
  2. End any conversation turn
  3. Stop hook crashes — transcript_path points to a non-existent file

Expected Behavior

transcript_path should point to the actual session JSONL file (i.e., use the same path resolution as session storage — the git repository root).

Actual Behavior

transcript_path points to ~/.claude/projects/-workspace--claude-worktrees-branch-name/{session_id}.jsonl which does not exist.

Evidence

# Session JSONL — EXISTS (git root hash)
~/.claude/projects/-workspace/b00a652b-66b6-4223-906f-4ccc3061aa89.jsonl

# transcript_path from hook payload — DOES NOT EXIST (cwd hash)
~/.claude/projects/-workspace--claude-worktrees-rewrite-test-prompts/b00a652b-66b6-4223-906f-4ccc3061aa89.jsonl

Environment variables at the time of hook invocation:

  • CLAUDE_PROJECT_DIR=/workspace (git root — correct)
  • PWD=/workspace/.claude/worktrees/rewrite-test-prompts (cwd — used for transcript_path hash)

Environment

  • Claude Code CLI
  • Linux/WSL2
  • Git worktree path: /workspace/.claude/worktrees/rewrite-test-prompts
  • Git root: /workspace

Workaround

Create a symlink from the cwd-derived path to the actual session file:

ln -s ~/.claude/projects/-workspace/{session_id}.jsonl       ~/.claude/projects/-workspace--claude-worktrees-branch-name/{session_id}.jsonl

Or in hook code: construct the transcript path from CLAUDE_PROJECT_DIR + session_id rather than trusting transcript_path.

Related

  • #34437: Worktrees should share the same project directory

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗