| name | worktree-pr |
| description | Use this skill at the start of any change request. Creates a git worktree branched from main, does the work in isolation, then commits, pushes, and opens a PR. This is the default workflow — never commit directly to main or to whatever branch happens to be checked out. |
Worktree + PR workflow
Default workflow for any change in this repo. Isolates work from main and from any other in-flight branches, and produces a PR with title and body that match the diff.
When to use
- Any non-trivial change (feature, fix, refactor, docs)
- Any change that will be reviewed or merged
- Anything you would otherwise be tempted to commit directly on
main
Skip only for ephemeral local experimentation that will never be committed.
Procedure
1. Pick a branch name
Use the conventional-commit type as the branch prefix, mirroring the eventual PR title:
feat/icmp-availability
fix/dark-theme-readonly
docs/claude-md
chore/update-deps
Allowed types: feat, fix, docs, ci, chore, refactor, test, perf. The branch name does not need to match the PR title exactly, but the type must.
2. Create the worktree from main
git fetch origin main
git worktree add .claude/worktrees/<type>+<short-name> -b <type>/<short-name> origin/main
Worktrees live under .claude/worktrees/ (gitignored). The branch is created from origin/main, not local main, so the work starts from the latest pushed state regardless of what the user has checked out locally.
3. Work in the worktree
All edits, builds, and tests happen inside .claude/worktrees/<type>+<short-name>/. Use absolute paths or cd into the worktree. Never edit files in the main checkout for this change.
4. Commit
Local commit messages during development are flexible — they will be squashed on merge. Stage specific files (avoid git add -A to keep stray files out).
5. Push and open the PR
git push -u origin <type>/<short-name>
gh pr create --title "<type>: <description>" --body "$(cat <<'EOF'
## Summary
<1-3 bullet points>
## Test plan
- [ ] <verification step>
EOF
)"
PR title rules (from development/contributing.md):
- Conventional commits format:
<type>: <description>
- Description starts lowercase
- Validated by CI (
pr-title.yml)
6. On every subsequent push
Re-check the PR title and body. If the diff has moved beyond the original framing (added scope, removed scope, changed approach), update them with gh pr edit. The PR title becomes the squash-merge commit on main, so it must accurately describe the final diff at merge time.
7. After merge
The squash merge deletes the remote branch automatically. Clean up the worktree:
gh pr view <pr-number> --json state -q .state
git worktree remove .claude/worktrees/<type>+<short-name>
git branch -D <type>/<short-name>
git branch -d (lowercase) does not work here: squash merge creates a new commit on main with a different SHA than the branch's commits, so Git does not recognize the branch as merged and -d will refuse. -D is required, but only after the gh pr view check confirms MERGED. Do not skip the check — destructive operations on local branches need explicit confirmation that the work is preserved upstream.
Why
- Isolation: no accidental commits to
main or to whatever branch the user is on
- Multiple in-flight branches can coexist without
git stash or context-switching
- The worktree directory name and branch name match, making it obvious what is where
- Branching from
origin/main (not local main) avoids working from a stale base