Claude Code skills are small instruction files that teach Claude Code a new command.
I made these to run many AI agents at once without losing track of what was asked, which agent is on it, and what came back. They are free to use under the MIT license.
To install one, unzip it into ~/.claude/skills/ and start a new Claude Code session. Then type the command.
Topics
Gives every request a number (T1, T2, T3) and keeps a small ledger of them. Each agent is tagged with the topic it serves, each result opens with the topic it answers, and the Claude Code status line shows what is still open. It helps once results start arriving out of order and you can no longer tell which request they belong to. It also carries my working notes on keeping agent prompts small and on what actually costs tokens.
/topics /topics clear
Download topics.zip. Install: unzip into ~/.claude/skills/.
Read topics/SKILL.md
---
name: topics
description: Group multi-agent work into numbered topics (T1, T2…) so you can follow which agent, question and result belongs to which request. Maintains a ledger shown in the Claude Code status line. Use whenever several background agents are running at once, and when the user types /topics.
---
# Topics
When you fire requests rapid-fire while agents run, results land "three agents behind" and it is hard to tell which request a result answers. This skill fixes that by giving every piece of work a **topic** and making every message say which topic it is about.
It works in any session that runs background agents. If you also use an orchestrator skill (one that delegates all work to background agents), have that skill load this one at the start.
Ledger tool: `python3 ~/.claude/skills/topics/topics.py` (one ledger file per working directory, in `~/.claude/topics/`). The status line (`~/.claude/skills/topics/statusline.sh`) shows the open topics live at the bottom of the terminal, e.g. `T3 Signup form ⟳ · T5 Nav rename ◆ · T6 Footer copy ? (4✓ 1‖)`.
Status icons: `◌ queued` · `⟳ running` · `? waiting` (on the user) · `◆ review` (result delivered, user hasn't reacted) · `✓ done` · `‖ parked`.
## Rules
1. **Every new request is a topic.** When the user asks for something new, run `topics.py add "<2 or 3 word name>" --ask "<user's words, short>"`. Several asks in one message means several topics. A follow-up to existing work joins that topic (`set T3 --note ...`), never a new one.
2. **Every agent belongs to a topic.** When dispatching, `set Tn --status running --agent "<short agent label>"`, and put `Tn` in the Agent `description` (e.g. `T3 signup form validation`). One agent may serve several topics; list it on each.
3. **Every relay opens with a topic header**, in this exact shape:
> **T3 · Signup form**: you asked (14:02): "add validation to the signup form"
Then the result. If the result is for a topic older than the one the user is currently talking about, say so plainly on the next line: *"This is the older request, from before the nav change."* Never mix two topics' results in one paragraph; use one header per topic.
4. **Questions carry their topic.** Prefix AskUserQuestion headers and questions with the topic id (`T6 Footer`), and set the topic to `waiting` until answered.
5. **Status upkeep.** `running` on dispatch, `review` when the result is relayed, `parked` for "hold / park / next session", `waiting` while a question is open. When the user responds approvingly or moves on to new asks, run `ack` for the relayed topics: `topics.py ack` with no args marks every topic in review as `done`; `topics.py ack T3 T5` acks just those. Deploys are their own topic (e.g. `T9 Deploy`).
6. **End-of-message footer.** After relays, end with the one-line board: the output of `topics.py line`.
7. **`/topics`** prints `topics.py board` as a table, plus one line per open topic saying what the user needs to do, if anything. `/topics clear` runs `clear-done`.
8. **Keep it cheap.** Ledger calls are glue, not work: batch them into the same Bash call as other glue where possible. Never let ledger upkeep delay a relay.
9. **Every agent gets its topic's slice and nothing else.** See "Context slices" below. An agent prompt carries what THIS topic needs; shared session facts are referenced by path, never re-pasted per agent.
## Context slices (token discipline)
A topic is a context boundary, not just a label. Each agent gets the smallest slice that lets it work correctly.
**One brief, written once, read by all.** At the first dispatch of a session, write the shared facts to `<scratchpad>/SESSION-BRIEF.md`: repo path, what is frozen or running, standing constraints (branch, staging, "don't touch X"), the user's preferred tone. Every agent prompt then says one line: *"Read `<path>/SESSION-BRIEF.md` first; it holds the session's standing constraints."* Update the brief when a fact changes; never re-paste it into prompts. Re-pasting the same 300 words into ten prompts wastes tokens, and it is also how briefs drift out of agreement with each other.
**Per-topic slice.** When a topic needs more than the brief (a diagnosis already established, numbers already measured, a decision the user made), write `<scratchpad>/T<n>-brief.md` and point the topic's agents at it. Two agents on one topic read the same file, so they cannot be told different things.
**The prompt itself carries only:** this topic's task and acceptance criteria; the exact file paths and line numbers already known; what is already established and must NOT be re-derived; what is out of scope; a report cap.
**What actually costs tokens.** In practice, prompts are a tiny fraction of an agent's spend. The big costs are:
- **Searching for what you could have named.** Always hand over paths, line numbers and command invocations already in hand. An agent that greps a whole repo to find one function spends more than the entire prompt.
- **Re-deriving settled facts.** Say "this is established, do not re-derive it" explicitly, and give the numbers.
- **Guards and self-tests.** A standing rule like "always leave a guard behind", plus verifying both ways against live data, is often the single largest multiplier. A sensible default: a small fix is just the fix, with no guard ceremony; anything that is not small gets filed as a gap instead of done in passing; a guard that a class of bug genuinely warrants is filed as its own gap, not built in the same breath. "Small" means small in consequence, not line count: a one-line change to a deploy gate, an importer, or anything writing the system of record is not small.
- **Uncapped reports.** State a word cap and the structure. An agent given no cap writes to the length of its own investigation.
- **The wrong tier.** A census, a rename or a file listing does not need the model tier that judged the design.
**Never trim these to save tokens:** the constraints that stop an agent breaking something (what not to touch, what not to commit, what is frozen), the instruction to report honestly what it could not verify, and the acceptance criteria. A cheap agent that corrupts state is the most expensive outcome available.
## First run in a session
If the ledger is empty but work is already in flight, seed it from the conversation: one topic per open thread, with status, before relaying anything else. Then show the board once.
## Status line
If `~/.claude/settings.json` has no `statusLine`, add:
```json
"statusLine": { "type": "command", "command": "~/.claude/skills/topics/statusline.sh" }
```
If one already exists, don't overwrite it. Ask the user whether to chain it.
Topic
The front door to Topics. /topic <text> files a new request under the next number and starts on it straight away: a quick answer if it is a lookup, a background agent if it is real work, or one short question if it is blocked on a decision only you can make. A follow-up to an open topic is added to that topic instead of starting a new one.
/topic add a print stylesheet for invoices /topic park: look at image sizes later
Download topic.zip. Install: unzip into ~/.claude/skills/.
Read topic/SKILL.md
---
name: topic
description: Start a new topic in the running /topics list. /topic <text> adds it as the next T-number and starts work on it right away, following the /topics rules. Requires the topics skill. Use when the user invokes /topic.
---
# /topic: start a new topic
`/topic <text>` is how you hand over a new piece of work. It joins the same list that `/topics` runs, gets the next T-number, and **starts work straight away**, like any other request in the session.
Requires the `topics` skill, installed at `~/.claude/skills/topics/`.
## Steps
1. **Add it.** Run `python3 ~/.claude/skills/topics/topics.py add "<2 or 3 word name>" --ask "<user's words, short>"`. That prints the new id, for example `T12`.
2. **Start it**, following the rules in `~/.claude/skills/topics/SKILL.md` (read that file if it isn't already loaded):
- Quick lookup or answer: do it now. Reply with a topic header, `**T12 · <name>**: you asked: "<text>"`, then the answer, and set the topic to `review`.
- Real work: dispatch a background agent with `T12` in its description, and set the topic to `running` with `--agent "<label>"`. Give the agent only this topic's slice. Tell the user in one line: `T12 · <name>: started.`
- Blocked on a decision only the user can make: ask one short question tagged `T12`, and set the topic to `waiting`.
- If the text says "later", "park" or "just note it": set the topic to `parked` and don't start work.
3. **Follow-ups.** If the text is plainly a follow-up to an open topic, don't make a new one. Add it to that topic with `topics.py set Tn --note "<text>"`, and act on it under that topic's number.
4. **End** with the board line from `topics.py line`.
The rules on topic headers, relays and statuses all come from `/topics`. This skill is just the front door.
## Bare `/topic`
Show the board line and say: "Type /topic <text> to start a new topic."
Gap
A queue for the things you notice while reviewing work: bugs, gaps, small ideas. /gap <text> writes one line to GAPS.md at the root of the repo the find belongs to, with an id, a status and an optional size (easy, med, hard). Agents pick queued finds up, mark them ready when the work lands, and only you close them. It helps when you spot five things mid-review and don’t want to interrupt the agent that is already working.
/gap the footer looks cramped on phones /gap list /gap size /gap pickup /gap close 2
Download gap.zip. Install: unzip into ~/.claude/skills/.
Read gap/SKILL.md
---
name: gap
description: Your queue of "finds" (gaps, bugs, ideas). /gap <text> files one; list/edit/remove/close manage the queue; an orchestrator (or /gap pickup) picks queued finds up and marks them ready; only you close them. Data file is GAPS.md at the root of whichever repo the find belongs to.
---
# Gap Queue
A queue of **finds** you keep: gaps, bugs and ideas spotted while reviewing a project, which agents pick up between waves of work.
**The queue is per repo.** The data file is `GAPS.md` at the root of the repo the find belongs to. Never a fixed path, and never another project's queue. Decide from the find itself which repo it concerns; if the find names a file, a URL or a subsystem, that names the repo. Create `GAPS.md` from the format below if the repo has none.
If you work across several repos, you can list the known queues here, one line each, so the right file is always found:
```
- ~/code/project-a/GAPS.md: Project A
- ~/code/project-b/GAPS.md: Project B
```
Filing into the wrong repo is worse than not filing: the find is lost to the project that needed it and clutters one that does not. When genuinely unsure which repo owns a find, ask.
## Lifecycle
`queued` (you filed it) → `in-progress` (an agent picked it up) → `ready` (work landed and verified; awaiting your approval) → `closed` (you approved).
## Entry format (one line per find, under `## Open`; move to `## Closed` when closed)
```
- [ ] GAP-002 · queued · easy · 2026-01-15 · the footer looks cramped on phones
- [ ] GAP-001 · ready · med · 2026-01-15 · search results need a sort option → done: sort menu shipped in abc1234
- [ ] GAP-003 · queued · 2026-01-15 · some idea nobody has sized yet
```
IDs increment forever and are never reused. Append `→ done: <one-line result>` when marking ready, and the close date when closing.
**Difficulty tag (optional):** a size segment, `easy` · `med` · `hard`, may sit right after the status (`… · queued · hard · <date> …`). An entry with no size segment (like GAP-003 above) is **unsized**. Sizing is an estimate of effort, not priority:
- **easy**: one file, small and well scoped: copy, CSS, config, a template tweak; no new data model. (cheapest model tier)
- **med**: a feature or fix across a few files with real logic, following a known pattern. (middle tier)
- **hard**: multi-file, a new data model or architecture, ambiguous requirements, or cross-repo coordination. (strongest tier)
## Commands
- `/gap <text>`: append as `queued` with the next ID and today's date.
- `/gap list`: show Open grouped by status, plus the 5 most recently Closed.
- `/gap size` (alias `/gap difficulty`): show Open finds bucketed by difficulty: **🟢 Easy**, **🟡 Medium**, **🔴 Hard**, then an **⚪ Unsized** bucket. Each line: `GAP-id · status · short text`. For any **unsized** find, estimate its size from its text and show it in the bucket you would assign, prefixed `~` to mark it an on-the-fly guess (display only; it does not write the tag). End with a one-line tally (e.g. `4 easy · 3 med · 2 hard · 1 unsized`). Sort each bucket by status (queued → in-progress → ready), then by id.
- `/gap size <id> <easy|med|hard>`: persist a find's difficulty: insert or replace its size segment after the status, then commit. Use this to lock in an estimate.
- `/gap edit <id> <new text>`: replace the find's text.
- `/gap remove <id>`: delete outright (you changed your mind; no work happened).
- `/gap close <id>`: your approval: check the box, move to `## Closed`, stamp the date.
- `/gap pickup`: process queued finds now instead of waiting for a batch of work to finish.
## Pickup (with or without an orchestrator)
This skill works on its own: `/gap pickup` starts work on queued finds whenever you ask. If you also run an orchestrator skill that delegates work to background agents, have it check the queue at every wave completion as well.
On pickup: read GAPS.md. For each `queued` find, start work on it (batching related finds together is encouraged) and mark it `in-progress`. When the work lands and verifies, mark it `ready`, append the one-line result, and tell the user what changed. **Only the user closes a find**, by explicit approval ("close gap 2", `/gap close 2`, or unambiguous approval language). Update and commit the file at every status transition so the queue survives context compaction and session ends.
**Use the difficulty tag to route work.** When picking up a find, its size picks the model tier (easy → cheapest, med → middle, hard → strongest). If a find about to be picked up is **unsized**, size it first (write the tag via `/gap size <id> <size>`) so the routing is recorded, then start. When filing a new find with `/gap <text>`, add a size segment if the effort is obvious; leave it unsized if genuinely unsure (it gets sized at pickup).
Orchestrate
Turns the main Claude Code session into a dispatcher. Every task goes to a background agent, so the chat stays free for your next request. It opens with one short round of questions (what the request is missing, what contradicts, how much you want to spend), then draws agents from a fixed pool per model tier and asks before it goes over. It helps when you have a long list of things to get done and want to keep talking while they run.
/orchestrate fix the signup form and add a sort option to search /orchestrate status /orchestrate off
Download orchestrate.zip. Install: unzip into ~/.claude/skills/.
Read orchestrate/SKILL.md
---
name: orchestrate
description: Delegate ALL work to background agents drawn from a fixed per-model pool (5 Haiku, 5 Sonnet, 5 Opus, 5 Fable per session), keeping the chat line free for the user. Opens with a mild discovery round (coach the request, surface contradictions or bigger ideas, ask about cost) before the first wave. Use when the user invokes /orchestrate, optionally followed by a task.
---
# Orchestrate
You are now an **orchestrator, not a worker**. From the moment this skill is invoked until the session ends (or the user says `/orchestrate off`), you do not execute substantive work inline. Every task (searches, edits, builds, research, reviews) is sent to a background agent. Your own tool use is limited to: spawning and messaging agents, trivial glue (reading an agent's result, relaying a one-line answer you already know), and asking the user questions.
## Discovery first (mild, before the first wave)
Before sending the first wave for any substantive task, run a **short discovery conversation**: one round, not an interrogation. The goal is to catch cheap-to-fix problems while they are still cheap. Cover, in this order:
1. **Coach the request up front.** If there are things the user could do better (missing acceptance criteria, an unstated priority order, a decision that will block agents mid-flight, a quality bar you'll have to guess at), say so plainly FIRST, before any plan. Be direct, not deferential: "this will go better if you tell me X" beats discovering X three agents deep.
2. **Name contradictions and bigger ideas.** If parts of the request contradict each other, or a detail hints at a larger idea than what was literally asked (a one-off task that smells like it wants to be a repeatable system, a fix that implies a missing feature), name it and ask. Never silently pick an interpretation or quietly expand scope.
3. **Ask about cost, every session.** Ask what the spend appetite is for this session: which model tiers to favor, whether pool limits may stretch, and roughly how much usage is acceptable. Do not assume a prior session's cost permissions carry over. If the user's appetite changes mid-session ("usage is going up"), re-tier future waves and say what changed.
Keep it **mild**: bundle the above into a single AskUserQuestion round (max 4 questions) plus a few lines of plain-text coaching, then send. If the task is trivial, or the user says "just go", skip discovery and go. Never re-run discovery for follow-up tasks in the same session unless something new is contradictory or cost-relevant.
## Why background agents
Send every agent out with `run_in_background: true` (the default). This returns control to the user immediately, so the chat line stays open. When an agent completes you'll be notified; summarize its result for the user then. Never run an agent synchronously unless the user explicitly asks you to wait.
## The agent pool
You have a session budget of **20 agent slots**, 5 per model tier:
| Tier | Slots | Use for |
|--------|-------|---------|
| Haiku | 5 | Mechanical work: file listings, renames, simple greps, formatting, boilerplate, status checks |
| Sonnet | 5 | Standard coding tasks: implement a well-specified feature, write tests, routine debugging, docs |
| Opus | 5 | Complex work: multi-file refactors, tricky bugs, architecture, ambiguous requirements |
| Fable | 5 | Hardest problems only: deep reasoning, critical correctness, final adversarial review, work where a wrong answer is expensive |
Adjust the tier names and slot counts to the models you have access to.
Rules:
- **Spend slots deliberately.** Use the cheapest tier that can genuinely do the task well. Don't burn the top tier on grunt work; don't send the smallest model to do architecture.
- Each `Agent` call with a `model` override consumes one slot from that tier. **Continuing an existing agent via `SendMessage` is free**: prefer following up with an agent you already spawned over spawning a fresh one for related work.
- Track the tally yourself in the conversation. After every wave, show the user a one-line pool status, e.g.:
`Pool: Haiku 3/5 · Sonnet 4/5 · Opus 5/5 · Fable 5/5 remaining`
- Split independent subtasks across multiple agents sent **in a single message** so they run concurrently.
- Give each agent a self-contained prompt: full context, file paths, acceptance criteria, and an instruction to report back a concise structured result. Agents don't see this conversation.
## When you need more than the pool allows
If a tier is exhausted, or a task genuinely needs a stronger model than you have slots for, **stop and ask** with AskUserQuestion. Offer exactly these options:
1. **One-time permission**: one extra agent at the named tier, this task only.
2. **Entire session permission**: unlimited agents at that tier for the rest of the session.
3. **Use a lower tier instead**: proceed with the best available slot.
Never silently exceed the pool, and never silently downgrade a task that needs a stronger model. The user decides.
## Gap queue pickup (optional)
If the `gap` skill is installed and the project has a `GAPS.md` at its repo root, check it at every wave completion: pick up `queued` finds (batch related ones together), mark them `in-progress`, then `ready` with a one-line result when the work lands. Only the user closes finds. Without the `gap` skill, skip this section.
## Reporting
- On sending: say what you delegated, to which tier, and why that tier, then the pool status line. Keep it to a few lines; the point is the user gets the prompt back fast.
- On completion notifications: lead with the outcome, relay what matters from the agent's report (the user never sees agent output directly), and note any follow-up you sent.
- If an agent fails or returns garbage, say so plainly and propose the next move (retry the same tier, escalate a tier, or ask the user).
## Invocation forms
- `/orchestrate <task>`: enter orchestrator mode, run the mild discovery round on the task, then send.
- `/orchestrate` (no args): enter orchestrator mode; confirm the pool is live and wait for tasks (discovery runs when the first task arrives).
- `/orchestrate status`: report current pool tallies and running or finished agents.
- `/orchestrate off`: exit orchestrator mode; resume normal inline work.
## Topics (optional, recommended)
If the `topics` skill is installed (`~/.claude/skills/topics/SKILL.md`), orchestrate mode always runs it: every request becomes a numbered topic in the ledger, every agent is tagged with its topic, every relay opens with `**Tn · Name**: you asked: "…"`, and the status line shows the open topics. Read that skill at the start of orchestrate mode and follow it. `/topic <text>` (the `topic` skill) is the quick way to hand over a new request. Without these skills, orchestrate works the same, minus the numbering.