HUD: Worktrees · git:20260814.769885b · 2026-08-14 · sha256 bd00481e765075a7
HUD: Worktrees git:20260814.769885bA
Immutable. This exact content is served forever at /api/v1/blob/bd00481e765075a7.
--- name: "HUD: Worktrees" description: "Map every worktree in this repo in plain language and shepherd safe create/remove actions" when_to_use: "When the user asks what worktrees exist, seems confused about which checkout they're in, wants to create or remove a worktree, or a worktree-related git error appears; worktrees are easy to get wrong, which is why this skill exists." model: sonnet effort: medium metadata: glyph: ᛊ family: hud disable-model-invocation: false # confusion about worktrees is exactly when it should appear; every mutation awaits approval allowed-tools: ["Bash(git:*)", "Read", "Glob"] arguments: ["action", "branch"] argument-hint: "[new <branch> | clean] (no args = show the map)" --- # HUD: Worktrees Worktrees go wrong in predictable ways: removing the one you're standing in, creating a duplicate branch because one already existed, forgetting a worktree exists and wondering why a branch won't delete. This skill's job is to make the current state impossible to misread, and to fence every action with the checks that prevent those mistakes. ## Always start with the map Regardless of arguments, gather first: 1. `git worktree list --porcelain`: every worktree, its path, branch, HEAD. 2. For each worktree: `git -C <path> status --porcelain` (dirty?) and `git -C <path> rev-list --left-right --count origin/main...HEAD` (ahead/behind, skip if no upstream). 3. `pwd`: establish **which worktree you are standing in right now**. This drives every safety check below. Render as a table plus one plain-English sentence per worktree: what it is, what state it's in, whether it's safe to touch: ```markdown | Worktree | Branch | State | You are here | |---|---|---|---| | ~/code/app (main checkout) | main | clean, up to date | | | ~/code/app-worktrees/feat/search | feat/search | 2 uncommitted files, 3 ahead | ◀ | ``` Then a **Suggestions** line naming anything that deserves attention: a worktree whose branch is already merged to main (candidate for cleanup), a dirty worktree untouched for weeks, a branch checked out in a worktree that someone might try to check out elsewhere. With no arguments, stop here; the map is the deliverable. ## Action: `new <branch>` 1. Check whether `<branch>` already exists (`git branch --list <branch>`, `git worktree list`). If it exists **use it**; never create `feat/search-2` because `feat/search` was taken. If it's already checked out in another worktree, point there instead of creating anything. 2. Follow the project's existing worktree path convention if the map shows one; otherwise default to a sibling directory: `../<repo>-worktrees/<branch>`. 3. Show the exact command (`git worktree add <path> <branch>` or `-b <branch>` for a new branch), **await approval**, run it. 4. Remind: a fresh worktree has no `node_modules`, so run the project's install (and any codegen like `svelte-kit sync`) before trusting test output there. ## Action: `clean` 1. From the map, list removal candidates: worktrees whose branch is merged into main and whose tree is clean. A dirty worktree is **never** a silent candidate; show what's uncommitted and ask. 2. **Never remove the worktree you are standing in.** If the target is the current directory, first give the user the `cd` back to the main checkout, and only proceed after they've moved. 3. For each approved removal, in order: `git worktree remove <path>`, then offer `git branch -d <branch>` (only `-d`, never `-D`; if git refuses, the branch isn't merged and that's worth knowing, not overriding). 4. Finish with `git worktree prune` and a fresh map so the user sees the end state. ## Red flags **Never:** remove a worktree while inside it; use `git worktree remove --force` or `git branch -D` to silence a refusal (the refusal is information); create a new branch when one with the intended name already exists; leave the user in a deleted directory; always land them back in the main checkout. <raw-arguments value="$ARGUMENTS" />