[BUG] statusline JSON keeps workspace.current_dir at the launch directory after EnterWorktree, so the status line shows the wrong directory and branch for the rest of the session (2.1.251)
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code (2.1.251)
What's Wrong?
After EnterWorktree moves a session into a linked worktree by path:, the statusline command keeps receiving the launch directory as workspace.current_dir. Any status line that renders the directory or the git branch from that field therefore shows the main checkout and its branch for the remainder of the session, while every tool (Bash, Read, Edit) correctly operates in the worktree.
This contradicts the documented meaning of the field. From Customize your status line:
| field | documented as |
| --- | --- |
| cwd, workspace.current_dir | "Current working directory. Both fields contain the same value; workspace.current_dir is preferred for consistency with workspace.project_dir." |
| workspace.project_dir | "Directory where Claude Code was launched, which may differ from cwd if the working directory changes during a session" |
The project_dir description explicitly anticipates the working directory changing mid-session, and makes current_dir the field that is supposed to follow it. EnterWorktree is exactly such a change, and current_dir does not follow.
The practical effect is worse than a cosmetic glitch: the status line is the one always-visible indicator of where a session is, so it actively asserts that the session is still on the previous branch in the main checkout. In my case that cost a real round of confusion — it looked as though the worktree switch had failed, when git rev-parse from the session proved it had succeeded.
Evidence
My status line script takes the directory from .workspace.current_dir, prints its leaf, and then runs git -C <that directory> status --porcelain=v2 --branch for the branch. It reads no other directory field.
Observed output, many minutes after the switch (refreshInterval is 60, so this is not staleness). Names below are placeholders; myrepo is the launch directory and main is the branch checked out there:
📁 myrepo · ⑂ main
Actual session state at the same moment, from Bash with no cd:
$ pwd
/c/Users/me/work/myrepo/.claude/worktrees/task-x
$ git rev-parse --show-toplevel
C:/Users/me/work/myrepo/.claude/worktrees/task-x
$ git rev-parse --abbrev-ref HEAD
feature/x
$ git rev-parse --git-dir
C:/Users/me/work/myrepo/.git/worktrees/task-x
Both rendered fields — the directory leaf myrepo and the branch main — are mutually consistent with the launch directory and inconsistent with the session. Since the script derives both from current_dir alone, current_dir must have held the launch directory.
Caveat: I inferred this from the script's deterministic output; I did not capture the raw JSON payload. The repro below captures it directly.
Steps to Reproduce
- Configure a status line that dumps its input, so the payload is visible rather than inferred:
``json``
{
"statusLine": {
"type": "command",
"command": "tee ~/statusline-payload.json | jq -r '\"current_dir=\" + .workspace.current_dir + \" project_dir=\" + .workspace.project_dir + \" git_worktree=\" + (.workspace.git_worktree // \"(absent)\")'"
}
}
- Start
claudein a git repository, for example/path/to/repo, on some branch. - Create a worktree on a different branch and enter it by path:
``bash``
git worktree add -b feature/x .claude/worktrees/task-x origin/main
then have the session call EnterWorktree with path: .claude/worktrees/task-x.
- Confirm the session actually moved:
pwdandgit rev-parse --abbrev-ref HEADin Bash both report the worktree andfeature/x. - Read the status line and
~/statusline-payload.json.
Actual: current_dir equals project_dir — the launch directory. A status line built on current_dir shows the original directory and its branch.
Expected: current_dir is the worktree path, project_dir remains the launch directory, and they differ — which is precisely the case the project_dir documentation describes.
Starting a fresh claude session inside the worktree behaves correctly, because the launch directory and the session then agree.
Suspected Root Cause
Very likely the same underlying issue as #89395: EnterWorktree updates the session working directory used by Bash, Read and Edit, but not process.cwd() of the CLI process. The statusline payload appears to be built from the latter, or from the session record captured at launch.
Note on workspace.git_worktree
workspace.git_worktree is documented as "Git worktree name when the current directory is inside a linked worktree created with git worktree add. Absent in the main working tree. Populated for any git worktree, unlike worktree.*". If it is computed from the same stale directory, it will be absent for a session that genuinely did move into a worktree — so it cannot serve as a workaround, and it is worth checking against the same repro.
Suggested Fix
Build the statusline payload's workspace.current_dir (and cwd, and workspace.git_worktree) from the session's current working directory — the same value Bash and the file tools resolve against — rather than from the process launch directory. If a single accessor already returns the session cwd for the tool layer, reusing it here would keep the three consumers from drifting apart.
Related Issues
- #89395 —
/diffpanel runs git withoutcwd, reading the launch directory instead of the session worktree. Same root-cause family, different surface. - #78733 — file links resolve against the original project root after
EnterWorktree. - #89717 — Desktop:
EnterWorktreenever updates the session record, so the branch chip shows the wrong branch. - #85114 — Desktop: worktree directory and branch names diverge; status bar does not follow mid-session branch changes.
Is this a regression?
I do not know.
Environment
- Claude Code: 2.1.251 (CLI, terminal)
- OS: Windows 11 Pro 10.0.26200 (win32)
- Shell: Git Bash
- Status line:
type: command,refreshInterval: 60, PowerShell script reading.workspace.current_dir