Plugin marker hooks follow the shell's cwd, so a `cd` mid-session marks the wrong repository

Open
#3,921 4 comments 1 reaction 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
48/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
git, shell
Domain
cli

Research direction

Start with the six marker hooks in plugins/worktrunk/hooks/hooks.json and read how hooks/wt.sh handles config state marker and worktree/session state. Reproduce the reported behavior by running the marker commands from a second repository and a non-repository during a session. Done means marker set and clear operate on the session's worktree even after the shell changes directory, without changing markers elsewhere.

Written by the indexing model from the issue text.

Description

The six marker hooks in plugins/worktrunk/hooks/hooks.json — marker set on
UserPromptSubmit, Notification, PreToolUse, PermissionRequest and Stop,
and marker clear on SessionEnd — run without -C:

bash "$CLAUDE_PLUGIN_ROOT/hooks/wt.sh" config state marker set 💬 || true

So the marker resolves against the hook process's working directory. That is the
agent's shell cwd, and an agent moves it during a turn — reading files out of a
second checkout, for instance. The two hooks in the same file that do reach for a
directory both scope it: WorktreeRemove passes -C "$p", and WorktreeCreate
cds to CLAUDE_PROJECT_DIR.

Three consequences, all silent:

  • A cd into another repository marks that repository's branch instead, and the
    session's own marker stops updating. The statusline then carries a stale
    marker on the branch being worked on and a spurious one somewhere else.
  • A session that ends while the shell sits in another repository clears that
    repository's marker on SessionEnd, and leaves its own set.
  • In a directory that is not a repository the command prints
    ✗ git rev-parse --git-common-dir failed (exit 128) and exits 1. The trailing
    || true turns that into a success, so nothing surfaces.

Repro, given a worktree of one repo and any second repo:

cd /tmp/repo-a.feature && wt config state marker set 🧪
# ✓ Set marker for feature to 🧪

cd /tmp/repo-b && wt config state marker set 🧪
# ✓ Set marker for main to 🧪      <- repo-b's branch, from a session on `feature`

cd /tmp/not-a-repo && wt config state marker set 🧪
# ✗ git rev-parse --git-common-dir failed (exit 128), rc 1

The marker should track the worktree the session belongs to rather than wherever
its shell currently is. -C <path> would carry that, but the value to pass isn't
obvious: CLAUDE_PROJECT_DIR is the launch directory and goes stale once the
session moves to another worktree mid-run, and the hook payload's cwd is the
same directory that drifted. Pinning the worktree at session start is one route;
resolving it from the session record is another.

Seen on worktrunk e4238e8.

This was written by Claude Code on behalf of max-sixty

Dominant language
Rust
Stars
8.8k
Forks
315
Avg merge
1d 6h
Merged PRs (30d)
204

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from max-sixty/worktrunk

All issues in max-sixty/worktrunk

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.