Repository navigation
feat(worktree): release a Claude session's checkout when the session ends - #556
Conversation
Quest-Claim: 6e5f49fb67b763fa
…ends quest worktree hook now handles SessionStart and SessionEnd. A checkout it makes for a session (not a subagent) records each session that created or started in it; the last one to end releases it, keeping .tmp/, and a session that resumes or starts there claims it again. /clear hands it to the next session without a release. A release cut short stays recorded as a failure. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…submodule sessions Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 23 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed head 6ef7b315ba70fed014de82b628ef7b4f4676bbc0 against base d742cea566ccac03d7822060602c48f1ba064867.
Finding: [P2] Preserve the session workspace when a supervised run finishes last. In src/cli/worktree.ts:947 (also reconcile() at line 505), the deferred release calls settle() without the session hook's keep list. For a session checkout with declared scratch ["cache", ".tmp"], start a supervised run, then end the last Claude session before that run exits. detach(session, true, [".tmp"]) marks the session false but returns at line 892 because the run is still present. When that run finishes, this call prunes both directories, deleting the reports/logs that the new session-release contract says survive for a resumed session. Orphan reconciliation has the same outcome.
Carry the session-release retention policy through deferred run completion and reconciliation. Add coverage for this reverse ordering with an actual .tmp file; the new supervised-run test only finishes the run while the session is still active, then ends the session.
The overall direction is sound: session-ID tracking handles resume from the launch directory, and the two-stage immediate release makes interrupted cleanup visible. The prior fixes described in the PR body are present, but the mixed session/run lifecycle still needs the retention fix above.
Verification: static review through the GitHub connector of all seven changed files and the surrounding lifecycle code, plus comparison with the base. No tests, builds, shell commands, or live Claude sessions were run. The PR was open and non-draft with unchanged head/base and no submitted reviews immediately before posting. This is a COMMENT review, not an approval.
(Written by review (OpenAI))

Summary
Before this change, a checkout
quest worktree hookmade for a Claude Code session (--worktree,EnterWorktree,--bg, agent view, remote control) was never released, so session checkouts piled up with their build output. Now:quest worktree hookalso handlesSessionStartandSessionEnd, and the README's opt-in JSON gains both entries.SessionEndasks for"timeout": 60, the most Claude Code allows.WorktreeCreatename other than a subagent'sagent-*or a workflow agent'swf_*, records the sessions that created it or started in it, by ID, and whether each is still running (sessionson the registry record).SessionEndmarks the session ended. Once no recorded session runs, it releases the checkout as a subagent's release does, deleting declared scratch but keeping.tmp/.SessionStartclaims the checkout again, either for a session that held it before or for any session starting inside it. When a release had deleted scratch, it tells the session what to reinstall./clearends a session only to start another in the same checkout, so it hands the checkout over without releasing it.quest worktree statusuntil a session starts there orquest worktree releasefinishes it.quest worktree create,quest agent) are left alone.Choices made without asking
quest setup. That is what the quest's Plan says. Folding the worktree hooks intoquest setupwould replace the pasted block, and moq-dev/quest#544's guard on it, with one command. That is suggested as a follow-up below./cleardoes not release. The Plan accepted a release followed by a reclaim on/clear. That would deletenode_modulesand other build output on every/clearfor nothing, so aclearreason only hands the checkout over.claude --resumefiresSessionStartwith the launch directory ascwd, before Claude enters the worktree. A lookup bycwdalone would never reclaim the checkout, so the hook also matches on session ID. The record grows by one entry per session that used the checkout and goes away when the checkout is removed..tmp/survives a session's release, as it does a subagent's, so a resumed session still has its reports and logs.WorktreeCreatenow requiressession_id(a common field Claude Code always sends) for a session's checkout, and fails loud without it.Public API and wire impact
quest worktree hookhandles two more events,SessionStartandSessionEnd; its help text says so.sessionsmap. Per AGENTS.md, nothing is migrated.Validation
quest gate just check: passes.quest gate just teston the merged head: passes (1171 passed, 5 skipped; worker 539 passed). One earlier run under host load failedtest/gate.test.ts›concurrent processes never admit past the headroom, and admit every caller, a test this PR doesn't touch; the rerun passed.holds a session's checkout while a session uses it and releases it when the last endscovers: two sessions sharing a checkout; ending a session that holds nothing;/clearhandover; release from outside the checkout; resume from the launch directory with the reinstall note; a cut-short release finished by the next session; and the subagent and manual checkouts it must leave alone.Live verification (Claude Code 2.1.319)
Run from a scratch repository under this checkout's
.tmp/, not itself worktree-isolated. Hooks came from--settings, through a wrapper that logged each input and pointedQUEST_WORKTREE_HOMEat a scratch registry, so the real registry was never touched.claude -p --worktreeWorktreeCreate,SessionStart(cwd = worktree),SessionEndother, all with one session IDcache/deletedclaude -p --resume <id>SessionStartresumewith cwd = launch directory, thenSessionEndin the worktreeEnterWorktreefrom a-psessionSessionStart,WorktreeCreate(same ID),SessionEndin the worktree--worktree+/clear+ exitSessionEndclear,SessionStartclearwith a new ID in the worktree,SessionEndclaude --bg --worktree+claude stopWorktreeCreate,SessionStart,SessionEndotheron stopbridge-*ifSessionEndfires thereTiming: releasing about 196k entries (12 hard-linked copies of this repository's
node_modules) took 0.85 s through the hook, against Claude's 1.5 s defaultSessionEndbudget. A cold cache or a larger Rusttarget/would overrun that default, hence the 60 stimeout.Killed release: a
SessionEndwith about 489k entries was killed (SIGKILL) at 0.6 s. The record stayedactivewith the cut-short failure shown inquest worktree status. The registry lock was reclaimed. ASessionStartresumefrom the launch directory then reclaimed the checkout, cleared the failure, and printed the note.Probe side effects: the scratch repository's path under
.tmp/was marked trusted in Claude's config, done by Claude's own trust prompt, so--bgwould run. The probe's background session was removed withclaude rm.Quest
Completes
quest/m0/session-checkouts.md: the file is deleted and its link removed fromquest/m0/README.md.Caused by
None. Session checkouts have never been released since the hooks were added, so this gap is as old as the hooks rather than a regression from one PR.
Suggested follow-ups
quest setup. Recommendation: plan it.quest setup(from moq-dev/quest#517) already mergesquest hookentries into the user's settings. An opt-in flag such asquest setup --worktrees, withquest hookdispatching the six worktree events, would replace the pasted README JSON. It would also replace fix(hooks): name the launch route when quest is missing from a hook's PATH #544's PATH guard repeated in every entry, and users would pick up new events, like these two, by rerunning one command.Models
Size: M
Implementer: Claude Code, claude-opus-5-5, medium effort
(Written by Claude Opus 5.5 with medium effort)
Review
Rewritten by
quest reviewafter each round.01a1b815-77e1-73e0-88e1-fb419ff30e52, round 3The incremental changes merge main and adapt the hook documentation and coverage consistently, with no new findings in the branch’s changes.