Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ version in [`.claude-plugin/plugin.json`](.claude-plugin/plugin.json);

## [0.1.0] - 2026-10-15

- Docs pass before launch: plainer, shorter READMEs and site copy; "Needs:" lines name the `guard-git` hook that any agent install brings; internal decision ids dropped; stale facts fixed (`switch` pre-switch notes, `score-loop` example total, `lanes` decrease, broken `repo-scrub` and `kanban` links).
- `install-skills --skill <name>` / `-Skill <name>` (#233) installs one skill, agent or hook plus what it needs; `--list-skills` / `-ListSkills` lists the names. Combines with `--workflow`. Optional companions are no longer pulled in (e.g. `find-me-a-skill` no longer brings `meta-orchestrator`; `pr-watch` fixes inline without `pair`). Each README says "Works on its own." or what it needs, each site page shows its one-line install, and a test installs every entry alone and checks it links to nothing missing.
- `/switch setup [name]` (#234) runs first-time setup from inside Claude: it shows the profile and settings diff (`setup --dry-run`, new), asks in chat, then writes with `--yes` and says to open a new terminal. `name` names the config dir you're on (`$CLAUDE_CONFIG_DIR`, else `~/.claude`; `main` by default) and is refused when that dir or name is already registered differently. Falls back to `python` when `python3` is the Windows Store stub. The README's first-time steps lead with it; the shell command stays as the fallback.
- `/switch list` (#230) shows per account whether it is logged in (`.credentials.json`, or on macOS an `oauthAccount` in `.claude.json`; never the Keychain), its email, and the last seen session and weekly usage with time left (`-` without a cache, `0%` past a reset). The hook answers `/switch list` itself, launcher or not, so it makes no API call and works at 100%.
Expand Down
8 changes: 4 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ Follow Matt Pocock's [`writing-for-agents`](https://github.com/mattpocock/skills
- **Plugin version and CHANGELOG.** The repo is also the `krish` plugin
([`.claude-plugin/plugin.json`](.claude-plugin/plugin.json)); a new skill
directory at the root or under `kanban/` ships in it automatically.
Plugin users only get changes when `version` there changes, so add a line
Plugin users only get changes when `version` there changes. So add a line
to [`CHANGELOG.md`](CHANGELOG.md) for each user-visible change, and on a
release bump `version` and the top `## ` heading together
(`scripts/lint.py` fails when they differ).
Expand All @@ -84,9 +84,9 @@ python scripts/lint.py
```

Fix anything it reports as a failure. It also prints `WARN:` lines (to
stderr) for a skill README missing one of the required headings above —
warnings don't fail the run, but fix them before submitting if they're
about your own skill. To test the forbidden-word check locally, drop a
stderr) for a skill README missing one of the required headings above.
Warnings don't fail the run, but fix any about your own skill before
submitting. To test the forbidden-word check locally, drop a
throwaway word into `.lint-forbidden.txt` at the repo root (gitignored),
confirm `python scripts/lint.py` fails naming it, then delete the file.

Expand Down
35 changes: 22 additions & 13 deletions README.md

Large diffs are not rendered by default.

35 changes: 19 additions & 16 deletions agents/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Installed by `scripts/install-skills.*` into `~/.claude/agents/`, with `hooks/`

## planner

Needs: `divide`, `next` (installed with it).
Needs: `divide`, `next`, the `guard-git` hook (installed with it).

- **Role:** picks the next single unit of work from the board and writes the kickoff brief.
- Read-only: `disallowedTools: Edit, Write, NotebookEdit`; never creates issues.
Expand Down Expand Up @@ -59,7 +59,7 @@ Needs: `divide`, `next` (installed with it).

## manager

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

- **Role:** owns one task end to end in a worktree.
- Never implements itself: briefs an implementer, then reviews its work as if it didn't trust it.
Expand All @@ -78,7 +78,7 @@ Needs: `handoff-auto`, `kanban-setup`, `next`, `session-handoff`, `implementer`
- Only with no notification path does it return **INTERIM — implementer still running** (callers must not act on it).
4. Reviews every round itself, inline:
- Commit scope, `git diff <base>...HEAD`, reruns tests + lint.
- Checks `git diff --name-only <base>...HEAD` carries no `skilleddocs/HANDOFF.md` (nothing in the handoff folder, `AGENTS.md`/`CLAUDE.md`'s else `skilleddocs/handoffs/`, in commit mode; nothing under `skilleddocs/` or that folder when untracked).
- Checks that `git diff --name-only <base>...HEAD` holds no handoff files: never `skilleddocs/HANDOFF.md`. When handoffs are committed, nothing in the handoff folder (the one `AGENTS.md`/`CLAUDE.md` names, else `skilleddocs/handoffs/`). When they are untracked, nothing under `skilleddocs/` or that folder.
- Fixes one-liners; larger gaps go to the next round.
- Never spawns reviewer subagents.
5. Retries with a **fresh** implementer + `skilleddocs/HANDOFF.md`/findings, up to `max_rounds`; deletes `HANDOFF.md` once picked up (in a commit if tracked).
Expand Down Expand Up @@ -113,20 +113,20 @@ Needs: `handoff-auto`, `kanban-setup`, `next`, `session-handoff`, `implementer`

## implementer

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

- **Role:** implements one well-specified issue from a kickoff brief on its own branch.
- `maxTurns: 200`.
- **You pass:** the kickoff brief verbatim + branch prefix + protected branch + `decisions` (from `manager` or the orchestrator).
- **How it works:**
- Branches off a freshly pulled default (the brief's Branch verbatim, else `<prefix>/issue-<n>-<kebab-title>`).
- If it created the branch, lists "card → In Progress + comment "Started on branch …"" as a manual step in its handoff (its `gh` is read-only, so its caller does it).
- If it created the branch, its handoff lists a manual step for the caller: move the card to In Progress and comment "Started on branch …". Its own `gh` is read-only.
- Commits small.
- Runs the repo's detected test command before claiming done.
- Multi-session task or low turns → writes the handoff early.
- Stuck or past ~100k tokens: writes `skilleddocs/HANDOFF.md` (done / not done / next step / failed attempts), then stops, so a manager can restart a fresh implementer from it. It commits that file only if [`TRACKING.md`](../handoff-auto/TRACKING.md) says so (never on a fork).
- **You get back:**
- Calls `session-handoff` (which wraps `handoff-auto`).
- A handoff written by `session-handoff` (which wraps `handoff-auto`).
- Final message ends with the handoff document's absolute path on its own line.
- The handoff cites any open `A-n` it assumed.
- **Guard:** `guard-git.py` hook (below).
Expand All @@ -149,11 +149,11 @@ Needs: `handoff-auto`, `kanban-setup`, `next`, `session-handoff` (installed with

## verifier

Needs: `consult-plan`, `next`, `update-progress` (installed with it).
Needs: `consult-plan`, `next`, `update-progress`, the `guard-git` hook (installed with it).

- **Role:** verifies an implementation session and closes the loop.
- `maxTurns: 120`.
- No guard hook.
- The guard hook doesn't apply to it.
- **You pass:**
- Handoff path (or saved manager report path).
- Whether it may answer interview-style questions on your behalf.
Expand Down Expand Up @@ -191,8 +191,8 @@ Needs: `consult-plan`, `next`, `update-progress` (installed with it).

**As a plugin.** Claude Code ignores `hooks` frontmatter in plugin agents, so the plugin wires the same command once, plugin-wide, in [`.claude-plugin/plugin.json`](../.claude-plugin/plugin.json), with `--plugin`.

- That hook fires for every session, so with `--plugin` it reads `agent_type` from the hook input and enforces only for `implementer`/`manager` (bare or `<plugin>:`-prefixed); the main session and other agents pass through (exit 0).
- Without Python 3.8+ the plugin command can't run guard-git, so it greps the hook input for the same `agent_type` match: those two agents are blocked (exit 2), everything else passes (exit 0), so a missing Python never locks your own session's Bash.
- That hook fires in every session. With `--plugin` it reads `agent_type` from the hook input and enforces only for `implementer`/`manager` (bare or `<plugin>:`-prefixed); the main session and other agents pass through (exit 0).
- Without Python 3.8+ the plugin command can't run guard-git. It then greps the hook input for the same `agent_type` match: those two agents are blocked (exit 2) and everything else passes (exit 0). A missing Python never locks your own session's Bash.

**It is a guardrail, not a sandbox.** It stops an agent's honest mistakes and the obvious workarounds.

Expand All @@ -211,13 +211,16 @@ Needs: `consult-plan`, `next`, `update-progress` (installed with it).
- **Card moves, issue comments and labels belong to the caller** (orchestrator, `pair`, verifier; none is guarded): implementer and manager list them in their handoff.
- `gh api` is GET only: a non-GET method, or `-f`/`-F`/`--input` without `-X GET` (they imply POST), blocks; `gh api graphql` allows only a literal read query (no `mutation`).
- `curl`/`wget`/`iwr`/`irm` to any `github.com` host (`github.com`, `api.github.com`, `uploads.github.com`) or `/api/v3/`: GET/HEAD only; any URL naming `git-receive-pack` (smart-HTTP push) blocks whatever the method.
- local git (add, commit, branch, merge, rebase, stash, worktree, fetch, pull, checkout/switch, tag, …) stays allowed; `git send-pack`/`http-push` and an unknown git subcommand or `git-*` plugin that names push/merge/sync/delete/ship/land/submit/publish/deploy/traverse/propose (`git subtree push`, `git ship`, `git-ship origin main`) block; commands git runs for you (`rebase -x`, `submodule foreach`, `bisect run`, `-c key=<value>`) are read like any other command.
- local git (add, commit, branch, merge, rebase, stash, worktree, fetch, pull, checkout/switch, tag, …) stays allowed. These block: `git send-pack`/`http-push`, and an unknown git subcommand or `git-*` plugin that names push/merge/sync/delete/ship/land/submit/publish/deploy/traverse/propose (`git subtree push`, `git ship`, `git-ship origin main`). Commands git runs for you (`rebase -x`, `submodule foreach`, `bisect run`, `-c key=<value>`) are read like any other command.
- third-party push/merge/PR tools (#202) block their remote writes, reads pass:
- `hub push|api|merge|fork|create|pull-request|sync|delete` and `hub pr|issue|release|gist` writes (hub is read as git too), `git town ship|sync|propose`, `gt`/`graphite submit|ss|merge|sync|land`, `ghstack` (bare = submit) `land|submit`, Sapling `sl push|pr|ghstack` (Bash only; PowerShell `sl` is Set-Location), `spr`/`git spr land|update|diff|merge`, `git machete traverse|github|gitlab`, `jj git push`, `arc land|diff`, and `gh-pages` (bin or `npx gh-pages`) on every run.
- `hub status`, `gt log`, `sl log`, `git town status`, `git machete status`, `hub pr list` pass.
- Any other program whose arguments pair a push-like verb (push/ship/land/submit/sync/merge/publish/deploy/traverse/propose) with a protected branch, `origin`/`upstream` or a git URL blocks (`mytool ship origin main`; D373); image tools (`docker push`, `helm`, `kubectl`, …) are exempt.
- Any other program whose arguments pair a push-like verb (push/ship/land/submit/sync/merge/publish/deploy/traverse/propose) with a protected branch, `origin`/`upstream` or a git URL blocks (`mytool ship origin main`); image tools (`docker push`, `helm`, `kubectl`, …) are exempt.
- unreadable code that could run a push fails closed: Bash `function f { … }` wrappers, a shell running `<(…)`, `script -c`, `xargs` feeding a shell or interpreter, PowerShell `(expr)` arguments (`git push origin ('ma'+'in')`), `[Diagnostics.Process]::Start`/`ProcessStartInfo` naming git/gh, and inline interpreter code (`deno eval`, `node -e`, …) that mentions push/merge next to a process call or a git/gh word.
- backstop for runners it doesn't model: a command whose head isn't git/gh, a shell, an interpreter, an HTTP client, a handled wrapper or a reader (`echo`, `printf`, `grep`, `rg`, `cat`, `ls`, `test`, `Write-Host`, `Select-String`, …), and whose arguments name a push/merge-capable command (`git … push|send-pack|http-push|subtree|receive-pack`, `gh … pr merge|api|alias|repo`, a gh write as classified above, `api.github.com`, `git-receive-pack`), blocks: `parallel git push …`, `awk 'BEGIN{system("git push …")}'`, `sed '1e git push …'`, `lua -e`, `Rscript -e`.
- backstop for runners it doesn't model. A command blocks when both are true:
- its first word isn't git/gh, a shell, an interpreter, an HTTP client, a handled wrapper or a reader (`echo`, `printf`, `grep`, `rg`, `cat`, `ls`, `test`, `Write-Host`, `Select-String`, …);
- its arguments name a push/merge-capable command (`git … push|send-pack|http-push|subtree|receive-pack`, `gh … pr merge|api|alias|repo`, a gh write as classified above, `api.github.com`, `git-receive-pack`).
- Examples: `parallel git push …`, `awk 'BEGIN{system("git push …")}'`, `sed '1e git push …'`, `lua -e`, `Rscript -e`.
- `uv run`/`poetry run`/`pipenv run`, `npm exec`/`npx` (incl. `-c '…'`), `flock` (incl. `-c`), `strace`/`ltrace`, `coproc` and `trap '…'` are unwrapped and the inner command read as usual, so `uv run pytest` and `uv run git push origin krish/x` pass.
- a shell or `.`/`source` reading its script from `/dev/stdin`, `/dev/fd/N` or `/proc/self/fd/N` is a stdin shell (`bash /dev/stdin <<< 'git push …'`).
- write-then-run: a command that writes a file (`>`/`>>`, `tee`, PowerShell `Set-Content`/`Add-Content`/`Out-File`) and runs that same file (`sh x.sh`, `./x.sh`, `. x.sh`, `pwsh -File x.ps1`, `python x.py`) blocks when its text names a push/merge-capable command or a gh write.
Expand Down Expand Up @@ -351,9 +354,9 @@ Protected branches: `GUARD_PROTECTED_BRANCHES` (comma list), default `main,maste

## Example

One issue through all three steps, as an orchestrator (or you) calls them.
The manager briefs and spawns its own `implementer` inside its turn, so only
its report comes back; you push and merge in between:
One issue through planner, manager and verifier, as an orchestrator (or you)
calls them. The manager briefs and spawns its own `implementer` inside its turn, so only
the manager's report comes back. You push and merge in between:

```transcript
⏺ Agent(subagent_type="planner", prompt="~/code/myrepo; exclusions: label needs-design; order: priority label")
Expand Down
8 changes: 4 additions & 4 deletions find-me-a-skill/CATALOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ human-in-the-loop points: nothing continues without you.
4. you: Answer each round yourself, one ticket per session, until no tickets or fog remain.
5. /divide (skill, opus · medium): Proposes 2+ session-sized issues from the map, each with a done-when; creates nothing yet.
6. you: Say yes to the split: the issues go on the board at Todo, the map gets a Handed off list and closes.
7. /meta-orchestrator (skill, opus · high): Loops planner, manager or implementer, its own merge gate and verifier per issue, logging each step to the ledger.
7. /meta-orchestrator (skill, opus · high): For each issue, runs the planner, then a manager or implementer, its own merge gate and the verifier, logging each step to the ledger.

### pitch-an-idea: Pitch an idea against the plan

Expand All @@ -109,7 +109,7 @@ human-in-the-loop points: nothing continues without you.
1. you: Start /meta-orchestrator on the repo and answer the setup interview that writes the scope contract.
2. /lanes (skill, sonnet · medium): Groups the queued issues into file-disjoint lanes and proposes them with a cost line.
3. you: Confirm the lanes with an explicit yes, or pin, rename or move issues first.
4. /meta-orchestrator (skill, opus · high): Loops planner, manager or implementer, its own merge gate and verifier per issue, logging each step to the ledger.
4. /meta-orchestrator (skill, opus · high): For each issue, runs the planner, then a manager or implementer, its own merge gate and the verifier, logging each step to the ledger.
5. planner (agent, opus · medium): Runs next, picks exactly one issue and returns a kickoff brief of at most 40 lines.
6. manager (agent, opus · high): Briefs an implementer, reviews every round inline and reruns the tests itself, for up to 3 rounds.
7. implementer (agent, sonnet · medium): Implements on its branch, commits small, watches the tests pass and ends with session-handoff.
Expand All @@ -134,7 +134,7 @@ human-in-the-loop points: nothing continues without you.
1. you: Label issues size:XS to size:XL if you know their size, and pick shape auto (or pin pair, swarm or flat) in the meta-orchestrator setup.
2. /meta-orchestrator (skill, opus · high): Reads shape from scope.md (an old execution key counts as shape) and runs each brief in the shape it names.
3. planner (agent, opus · medium): Rates size (a size label wins), recommends a shape and the implementer model, and batches trivial, file-disjoint, exact-spec issues into one swarm brief.
4. implementer (agent, sonnet · medium): Swarm: one haiku implementer per item, each in its own worktree off the batch branch, one parallel slot each; flat: one per issue on the model its size calls for.
4. implementer (agent, sonnet · medium): Swarm: one haiku implementer per item, each in its own worktree off the batch branch and using one parallel slot. Flat: one implementer per issue, on the model its size calls for.
5. manager (agent, opus · high): Pair, the default: picks the implementer model by size (trivial haiku, small or medium sonnet, large or risky opus) and reviews every round; also takes the fix brief when a swarm batch's review finds a problem.
6. verifier (agent, opus · high): Checks the merged issue or batch against git, tests and CI; skips its own code review after pair or swarm, which were already reviewed.
7. you: With merge=ask, approve each PR: one per pair or flat issue, one per swarm batch closing all its items.
Expand Down Expand Up @@ -211,7 +211,7 @@ human-in-the-loop points: nothing continues without you.
1. you: Run claude_switch.py setup (or migrate for existing ~/.claude-<name> dirs) once, then start Claude with claude or claude-<name> so a launcher watches the session.
2. /switch (skill, haiku · low): /switch add <name> makes a new account that shares the first one's skills, settings and history and moves you into it to log in; remove, rename and list manage the rest.
3. you: The statusline shows the account and its session and weekly use; near the limit a warning names the account with the most room. Type /switch or /switch <name>; it is user-only, so Claude can't start it.
4. /switch (skill, haiku · low): A prompt hook writes a request for this terminal's launcher only, with no API call so it works at 100%; the launcher ends the session and resumes it on the target account (--continue when --resume fails).
4. /switch (skill, haiku · low): A prompt hook writes a switch request for this terminal's launcher only. It makes no API call, so it works even at 100% usage. The launcher ends the session and resumes it on the target account (with --continue if --resume fails).
5. /sitrep (skill, haiku · low): On the new account, lists what was running and asked vs done, so nothing from before the move is lost.
6. /remind (skill, haiku · low): /remind when <old account>'s session limit resets takes the reset time from the usage cache and pops a toast then; the next prompt on any account says it once.
7. you: Carry on; /switch with no name goes back to the account you came from.
Loading
Loading