krishpunjabi.com ~/skills

← all commands

/pair

/pair build and orchestrate

Run one task (issue number or free text) in an isolated git worktree via a manager subagent that owns its implementer and retries; you push and open the PR at the end. Use for "implement issue N", "pair on this", or one task on any repo, forks included.

Install

Install just this, from a clone of the repo. Anything it needs comes with it.

./scripts/install-skills.sh --skill pair   # bash, Git Bash, macOS, Linux
.\scripts\install-skills.ps1 -Skill pair   # Windows PowerShell

Needs: handoff-auto, kanban-setup, next, session-handoff, implementer, manager, the guard-git hook (installed with it).

What it does

Runs one task (a GitHub issue or free text) through a manager subagent in an isolated git worktree. The manager spawns and reviews an implementer, retrying up to 3 rounds. You stay in one interactive session; only your session pushes and opens the PR, at the end.

When to use

  • One task on any repo, including OSS forks with no kanban board.
  • "Implement issue #n with a manager + implementer", "pair on this".
  • For a whole backlog, use meta-orchestrator instead.

How to invoke

/pair <issue # | task text> [--no-worktree] [--push] [--model haiku|sonnet|opus]
  • --no-worktree — new branch in the current checkout instead of a worktree.
  • --push — push and open the PR without asking.
  • --model — implementer model override. Default: by the task's size (the issue's size:* label, else the manager's rating): trivial → haiku, small/medium → sonnet, large or risky → opus.

Model-invocable, so "pair on issue 12" also works.

How it works

  1. Resolve the task.
    • Issue number → gh issue view; text → Claude writes a 3–6 item acceptance checklist.
    • Collects default branch, branch prefix (from your CLAUDE.md, else feat), test command, CONTRIBUTING.md/AGENTS.md.
    • On a fork (upstream remote): fetches upstream, fast-forwards the default branch, and checks every file/symbol the issue cites still exists.
  2. Isolate.
    • git worktree add ../_worktrees/<repo>-<slug> -b <prefix>/<slug> <default> (slug = issue-<n>-<kebab-title>).
    • Reuses an existing worktree/branch if present.
    • A relative origin URL (../origin.git) would break inside a worktree, which resolves it from its own root. So it is first made absolute with git remote set-url (same target).
    • Deps (node_modules/.venv) are linked from the main checkout, not reinstalled: ln -s on mac/linux, a mklink /J junction on Windows. On Windows it refuses unless both paths are absolute; from Git Bash it builds them with cygpath -wa and runs with MSYS_NO_PATHCONV=1.
    • For an issue, your session then marks it started: card → In Progress, or label status:todo → status:in-progress (creating that label first if missing). It also comments "Started on branch …". No board: skipped. A board error is reported and never blocks the task.
  3. Delegate. One Agent(subagent_type="manager") call with working dir, task + checklist, verified/missing files, rules, implementer model, max_rounds: 3, "never push, merge, or open a PR". Not fork.
  4. On return.
    • A report titled INTERIM means the implementer is still running: it waits for the manager's next handback. A handback missing its Branch, Tests or Rounds section (a placeholder) is no result either: it asks once, then reruns.
    • Then it shows the manager's report verbatim. It reruns the tests if the report is thin or the change risky. If skilleddocs/HANDOFF.md exists (unfinished), it offers another round.
    • Before pushing, it checks git diff --name-only <default>...HEAD for files that must not ship, and removes any hit in a commit (TRACKING.md):
      • skilleddocs/HANDOFF.md, always.
      • In commit mode, anything in the handoff folder (AGENTS.md/CLAUDE.md's, else skilleddocs/handoffs/).
      • When handoffs are untracked (always the case on a fork), anything under skilleddocs/ or that folder.
    • Pushes + gh pr create … Closes #<n> on --push or your go. Never merges.
    • PR review feedback later → step 3 again in the same worktree.
  5. Print.
    • Branch, worktree path, PR URL (or "not pushed"), test result, rounds used, skilleddocs/HANDOFF.md path.
    • Doesn't clean up the worktree until the PR merges.
    • After the merge, it moves the worktree's dated handoffs into the main checkout's handoff folder, where update-progress finds them. It then unlinks node_modules/.venv (the link only, never a recursive delete). It runs git worktree remove only after a check confirms neither link is left, dangling links included.
    • Never --force: if git still refuses, it stops and reports what's left.

Writes: a worktree + branch; commits (via agents); skilleddocs/HANDOFF.md in the worktree if unfinished (untracked unless the repo tracks skilleddocs/; never pushed).

Flow

Flowchart: Resolve: issue or task, checklist, repo facts to Isolate: worktree and branch; Isolate: worktree and branch to Delegate to a manager subagent; Delegate to a manager subagent to On return: show the report; On return: show the report to Delegate to a manager subagent (unfinished: another round); On return: show the report to Push and open the PR (your go); Push and open the PR to Delegate to a manager subagent (review comments); Push and open the PR to Teardown after merge, links first.Resolve: issue ortask, checklist, repofactsIsolate: worktree andbranchDelegate to a managersubagentOn return: show thereportPush and open the PRTeardown after merge,links firstunfinished: anotherroundyour goreview comments

Design principles

  • Only your session touches the remote. The manager and implementer never push, merge or open a PR (the guard hook enforces it); push and PR happen in your session, on --push or your go. Nothing ever merges.
  • Isolation by worktree. Each task gets its own worktree and branch, so your main checkout stays usable and the agents need no other isolation.
  • Implementation stays out of your context. The manager owns briefing, review and retries; you see one report, verbatim.

Shared context for these principles: Matt Pocock's video.

Use cases

  • Implementing one issue on your own repo without a board or an orchestrator.
  • Contributing to an OSS fork: it syncs upstream first and checks the files the issue names still exist.
  • Addressing PR review comments later: rerun the delegate step in the same worktree with the comments as the task.
  • A free-text task with no issue at all ("pair on adding a --dry-run flag").

Tips

  • Set your branch prefix in your CLAUDE.md; otherwise branches start with feat/.
  • An INTERIM report means the implementer is still running; wait for the real one.
  • If the decisions register lives in an untracked skilleddocs/, the brief passes the main checkout's register header. That way each assumed decision (A-n) is written as a row teardown can copy back to main.
    • A heading or prose entry stops teardown, which lists those lines instead of losing them. Turn them into rows and rerun.
  • Leave the worktree alone while the manager runs.
  • Tear down only after the PR merges, with the exact commands in TEARDOWN.md. In order: move every untracked record in the worktree's doc folders to the main checkout without overwriting (dated handoffs, HANDOFF.md renamed to a dated handoff, decisions register rows); unlink the deps; check that no link and no record is left; then git worktree remove.
    • git worktree remove deletes git-excluded files silently, so a record left behind is lost.
    • Never remove the worktree while a link exists: git worktree remove or a recursive delete follows it and empties the main checkout's copy.
  • Unfinished after 3 rounds? Accept the offer of another round; it restarts from skilleddocs/HANDOFF.md.

Example

Issue #42 in a repo whose default branch is main and with no branch prefix in CLAUDE.md (so feat). --push means no question before the push:

/pair 42 --push
Bash(gh issue view 42) (+3 lines)
title: Fix date parsing state: OPEN Dates with a UTC offset ("2026-09-26T10:00:00+02:00") fail to parse.
Bash(git worktree add ../_worktrees/myrepo-issue-42-fix-date-parsing -b feat/issue-42-fix-date-parsing main) (+1 line)
Preparing worktree (new branch 'feat/issue-42-fix-date-parsing')
#42 is on the board: moved to In Progress, commented "Started on branch feat/issue-42-fix-date-parsing".
Agent(subagent_type="manager", prompt="working directory: /home/you/code/_worktrees/myrepo-issue-42-fix-date-parsing; task: #42 Fix date parsing + checklist; rules: prefix=feat, protected=main, test cmd=pytest; implementer model: by size; max_rounds: 3; never push, merge, or open a PR.") (+7 lines)
Branch: feat/issue-42-fix-date-parsing, base 1a2b3c4, head 9f8e7d6 Commits: 9f8e7d6 fix: parse dates with a UTC offset (#42) Tests: pytest, 118 passed; lint: none configured (run by me) Findings: none Rounds: 1 of 3 Unfinished: none Manual steps for caller: push, open the PR
Bash(git -C ../_worktrees/myrepo-issue-42-fix-date-parsing diff --name-only main...HEAD) (+2 lines)
src/dates.py tests/test_dates.py
Bash(git -C ../_worktrees/myrepo-issue-42-fix-date-parsing push -u origin feat/issue-42-fix-date-parsing)
Bash(gh pr create --head feat/issue-42-fix-date-parsing --title "Fix date parsing" --body "Parse dates with a UTC offset. Closes #42") (+1 line)
https://github.com/you/myrepo/pull/57
Branch feat/issue-42-fix-date-parsing, worktree ../_worktrees/myrepo-issue-42-fix-date-parsing, PR https://github.com/you/myrepo/pull/57, tests pytest 118/118, rounds 1/3, no HANDOFF.md. The worktree stays until the PR merges.
  • Spawns the manager agent, which spawns implementer.
  • meta-orchestrator runs the same manager per issue with shape: pair (its default); flat and swarm are its other shapes (see its README).
  • Needs gh and the agents installed.

Prereqs

  • gh, authenticated, and origin on GitHub for the issue lookup and the PR step.
  • The manager and implementer agents installed (the install scripts do this), with their guard-hook needs: Python 3.8+, and Git Bash on Windows.

Sample workflows

Source

Use cases & tips from the community