From compound-workflows
Manage session worktrees — resume, cleanup, rename, switch, create
npx claudepluginhub adamfeldman/compound-workflows --plugin compound-workflowsThis skill uses the workspace's default tool permissions.
Manage session worktrees interactively. Resume existing worktrees, clean up orphans,
Creates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Manage session worktrees interactively. Resume existing worktrees, clean up orphans, rename the current session, or create new worktrees.
#$ARGUMENTS
Argument parsing:
cleanup → cleanup subcommand (skip to orphan cleanup)rename <new-name> → rename subcommand (rename current worktree)status → status subcommand (display-only, no action)All modes begin by scanning worktree state from scratch. Do NOT rely on hook output — state may have changed since the hook ran.
ls -dt .worktrees/session-*
If no session worktrees exist, report "No session worktrees found." and exit (unless in interactive mode, where "create new" is still offered).
stat -f '%m' <dir> on macOS, stat -c '%Y' <dir> on Linux.
If neither works, skip freshness for that worktree (treat as unknown age). Compute human-readable
age from (now - mtime)..worktrees/.metadata/<name>/pid.* files. Also check old-format
.worktrees/<name>/.session.pid (backward compat). For each PID, run kill -0 <pid> to test
liveness. Report: "alive" if ANY PID is alive, "dead" if all dead, "none" if no PID files.git -C <path> status --porcelain --untracked-files=no | wc -lgit -C <path> ls-files --others --exclude-standard | wc -lgit symbolic-ref --short refs/remotes/origin/HEAD | sed 's|origin/||', fallback to main), get the worktree's branch (git -C <path> rev-parse --abbrev-ref HEAD), then git log <default>..<branch> --oneline | wc -l| Worktree | Age | PID | Uncommitted | Untracked | Unmerged | Actions |
|----------|-----|-----|-------------|-----------|----------|---------|
Action column rules:
Run the Shared Worktree State Scanner above.
If no session worktrees exist, skip to "create new" directly — generate a random 4-char hex ID and create the worktree (see Step 3, "Create new").
If worktrees exist, present a single AskUserQuestion with:
Issue warning (if applicable): If any worktree has uncommitted changes, untracked files, or unmerged commits, display above the table:
"N worktrees have unsaved work. Choose 'resume' to continue working, or 'cleanup' to review and resolve."
Worktree table (from scanner Step 3).
Options:
Example prompt:
"Session worktrees found:
| Worktree | Age | PID | Uncommitted | Untracked | Unmerged | Actions |
|---|---|---|---|---|---|---|
| session-a7f2 | 5m | alive | 3 | 1 | 2 | resume |
| session-x3k9 | 2d | dead | 0 | 0 | 0 | remove, resume |
Which worktree to use? (e.g., 'resume session-a7f2', 'remove session-x3k9', 'create new', 'skip')"
Resume:
echo $PPID in a separate Bash call.rm -f .worktrees/.metadata/<hook-recommended-name>/pid.<claude-pid>bash ${CLAUDE_SKILL_DIR}/../../scripts/write-session-pid.sh <chosen-name> <claude-pid>rm -f .worktrees/.opted-outcd <absolute-path-to-worktree><name>. Working directory: <absolute-path>"Remove:
echo $PPID in a separate Bash call.bash ${CLAUDE_SKILL_DIR}/../../scripts/session-gc.sh <worktree-name> --caller-pid <claude-pid>REMOVED <name> → report successSKIPPED <name> <reason> → explain why removal was blockedERROR <name> <detail> → report errorCreate new:
echo $PPID in a separate Bash call.rm -f .worktrees/.metadata/session-*/pid.<claude-pid> (glob catches whichever worktree the hook chose).openssl rand -hex 2bd worktree create .worktrees/session-<id>bash ${CLAUDE_SKILL_DIR}/../../scripts/write-session-pid.sh session-<id> <claude-pid>rm -f .worktrees/.opted-outcd <absolute-path-to-new-worktree>session-<id>. Working directory: <absolute-path>"Skip:
echo $PPID in a separate Bash call.rm -f .worktrees/.metadata/session-*/pid.<claude-pid> (glob catches whichever
worktree the hook chose)./do:start cleanup)Run the Shared Worktree State Scanner.
Skip the worktree the user is currently inside. Compare pwd output against each worktree's
absolute path. The current worktree is never a cleanup candidate — use /do:compact-prep to
merge the current session.
If no other session worktrees exist, report "No other session worktrees to clean up." and exit.
Capture Claude PID: echo $PPID in a separate Bash call.
Run session-gc.sh on all eligible worktrees (passing captured PID for self-exclusion):
bash ${CLAUDE_SKILL_DIR}/../../scripts/session-gc.sh --caller-pid <claude-pid>
Parse each line of stdout:
REMOVED <name> → count as removedSKIPPED <name> untracked-files-present → collect for user prompt (Step 3)SKIPPED <name> <other-reason> → count as retained with reasonERROR <name> <detail> → count as errorFor each worktree SKIPPED with "untracked-files-present":
AskUserQuestion: "Worktree <name> has untracked files. Delete anyway?"
--skip-untracked:
bash ${CLAUDE_SKILL_DIR}/../../scripts/session-gc.sh <worktree-name> --caller-pid <claude-pid> --skip-untracked"Cleanup complete. Removed N worktrees. M retained (reasons: ...)."
If all worktrees have active PIDs: "All worktrees have active sessions. Nothing to clean up."
/do:start rename <new-name>)Parse <new-name> from the arguments (second word after rename).
If <new-name> is missing, use AskUserQuestion: "What should the new session name be?
(e.g., 'fix-login-bug', 'explore-caching')"
Check git plumbing (Decision 11):
git rev-parse --git-dir
git rev-parse --git-common-dir
If git-dir == git-common-dir → NOT in a worktree. Error: "Not inside a worktree.
/do:start rename must be run from inside a session worktree." Exit.
Also verify the worktree is a session worktree (path or branch contains session-).
If inside a work worktree or other type, error: "Inside a work worktree, not a session
worktree. /do:start rename only applies to session worktrees." Exit.
/do:workCheck for sentinel files in .workflows/.work-in-progress.d/:
ls .workflows/.work-in-progress.d/
If sentinel files exist:
session_worktree_stale_minutes from compound-workflows.local.md (default: 60)./do:work:
"Stale /do:work sentinel found ( minutes old). No active /do:work detected.
Cleaning up and proceeding with rename."
Remove stale sentinels and proceed.rm .workflows/.work-in-progress.d/<id> (verify no subagents are running first)."
Exit.Check untracked files:
git ls-files --others --exclude-standard
If untracked files exist, warn via output (not AskUserQuestion — just inform and offer): "N untracked files found. These will be lost during rename unless staged."
Offer to stage: git add <files>
Commit all uncommitted changes (including any just-staged files):
Write checkpoint message to .workflows/scratch/<session-id>-checkpoint-msg.txt via the Write tool, then:
git add -u
git commit -F .workflows/scratch/<session-id>-checkpoint-msg.txt
Message: session checkpoint before /do:start rename to <new-name>
If nothing to commit (clean tree), skip the commit.
Extract the current branch name:
git rev-parse --abbrev-ref HEAD
Store as <old-name>. The new branch name is session-<new-name> (prefix session- if
the user didn't include it; if they did, use as-is).
git branch -m <old-name> session-<new-name>
Capture Claude PID: echo $PPID in a separate Bash call.
Critical ordering: write new PID FIRST, then delete old metadata. A crash between steps leaves stale metadata (minor leak), not data loss.
cd to main repo root (the parent of .worktrees/). Determine via
git worktree list --porcelain (first line, strip worktree prefix).
Write new PID first (crash-safe ordering):
bash <plugin-root>/scripts/write-session-pid.sh session-<new-name> <claude-pid>
(Use the absolute path to the script since CWD changed to main root.)
Delete old metadata: rm -rf .worktrees/.metadata/<old-name>
Remove old worktree: bd worktree remove .worktrees/<old-name>
If bd unavailable, fall back: git worktree remove .worktrees/<old-name>
Create new worktree: bd worktree create .worktrees/session-<new-name>
The branch was already renamed in Step 4, so bd will use the existing branch.
If bd worktree create fails: Emit recovery instructions:
"Worktree recreation failed. Your work is safe on branch session-<new-name>.
Recover with: bd worktree create .worktrees/session-<new-name>
Or: git worktree add .worktrees/session-<new-name> session-<new-name>"
Exit.
cd into new worktree: cd <main-root>/.worktrees/session-<new-name>
Report: "Renamed session worktree from <old-name> to session-<new-name>.
Working directory: <absolute-path>"
/do:start status)Run the Shared Worktree State Scanner.
Present the worktree table (same format as interactive mode Step 2).
No AskUserQuestion — display only, no action taken.
If no session worktrees exist, report: "No session worktrees found."