Claude Code hook: set the marker in-process, and allow async for marker-only events
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 40/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- git, rust
- Domain
- cli, performance
Research direction
Locate the Claude Code hook handler in the Rust CLI and the plugin hooks.json that registers UserPromptSubmit, Stop, Notification, PreToolUse (AskUserQuestion) and PermissionRequest. Start by tracing the Stop path and the re-exec of wt -C <repo> config state marker set, then compare it with the repository discovery already done in-process. The change is done when marker writes reuse that discovery, the four marker-only events are marked async (PermissionRequest, WorktreeCreate and WorktreeRemove stay synchronous), and concurrent writes are ordered with a set_at timestamp and a short config.lock retry.
Written by the indexing model from the issue text.
Description
wt config plugins claude hook runs synchronously on UserPromptSubmit, Stop, Notification, PreToolUse (AskUserQuestion) and PermissionRequest, so Claude Code waits for it each time. In a repository with 88 worktrees on a Linux host, one Stop run takes about 140 ms. Over a week of sessions alongside other plugins' hooks, it was the slowest synchronous Stop hook at about half of turn ends.
Most of that time is process and git overhead, not the marker write. Averages of 10 untraced runs:
| Step | Time |
|---|---|
| Whole hook, Stop event | 141 ms |
The wt -C <repo> config state marker set 💬 it re-execs |
94 ms |
git worktree list alone |
31 ms |
The git config marker write alone |
21 ms |
An strace -f -e trace=execve of one Stop run shows the sequence. The hook process discovers the repository with git --version, git rev-parse ... and git config --list -z. It then re-execs wt -C <repo> config state marker set, which runs the same three git calls again. The child also runs git worktree list --porcelain -z and git rev-parse --git-dir twice before the git config write.
Suggestions:
-
Set the marker in the hook process instead of re-execing
wt. Reusing the discovery the process has already done removes about 47 ms per run. The child'sgit worktree listand duplicaterev-parse --git-dirlook unneeded for writing one branch's marker. Skipping them as well should bring a run close to one discovery plus the 21 ms write. That second part is inferred, not measured. -
Mark the marker-only registrations
"async": truein the plugin'shooks.json: UserPromptSubmit, Notification, PreToolUse (AskUserQuestion) and Stop. Claude Code 2.1.310 backgrounds an async command hook about 17 ms after spawning it. It drops the hook's decisions and plain-text output. These events print nothing on stdout, so nothing is lost. PermissionRequest has to stay synchronous, because it answers the EnterWorktree permission prompt. WorktreeCreate and WorktreeRemove also stay synchronous, because Claude Code uses their output and exit status.Async needs ordered marker writes first. Today Claude Code waits for the Stop write before it starts a queued prompt's hooks. With async, a prompt queued at turn end can start its 🤖 write while the Stop's 💬 write is still running, and whichever finishes last wins. That leaves the wrong emoji until the next event. Writes that start together also contend on
config.lock: in a scratch probe, 40 simultaneous starts gave 30 lock failures. One way to make the end state independent of completion order:- stamp
set_atin milliseconds when the hook starts; - skip the write when the stored
set_atis newer; - retry briefly when
config.lockis held.
- stamp
Seen on worktrunk wt v0.81.0.
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
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from max-sixty/worktrunk
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
max-sixty/worktrunk#4727 · 7 comments · 1 reaction ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
max-sixty/worktrunk#4260 · 5 comments · 1 reaction ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
max-sixty/worktrunk#3847 · 1 comment ·
Maintainers usually reply within 1 day
-
`wt step` confusionOpen
Difficulty 5/5 Over a week Newbie friendliness 28/100
max-sixty/worktrunk#4728 · 3 comments ·
Maintainers usually reply within 1 day
-
Difficulty 3/5 1-2 days Newbie friendliness 25/100
max-sixty/worktrunk#4718 · 1 comment ·
Maintainers usually reply within 1 day
All issues in max-sixty/worktrunk
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 1 day
-
follow-up
Difficulty 2/5 1-3 hours Newbie friendliness 73/100
carrick-sh/carrick#1859 ·
Maintainers usually reply within 1 day
-
crate: spate-kafka documentation priority: medium
Difficulty 1/5 Under an hour Newbie friendliness 88/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
balovess/aria2_rust#88 ·