mirror of
https://github.com/mattpocock/skills.git
synced 2026-07-29 02:52:42 +07:00
Compare commits
30
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
41283677d6 | ||
|
|
d4e8664be2 | ||
|
|
6e742d6441 | ||
|
|
ad5ee1e12f | ||
|
|
fa3b2a6b35 | ||
|
|
17f22a371b | ||
|
|
9c32629965 | ||
|
|
b8fd9afa42 | ||
|
|
9603c1cc81 | ||
|
|
fde4cd58cf | ||
|
|
c70cb09193 | ||
|
|
e9fcdf95b4 | ||
|
|
7f68c06dcb | ||
|
|
bbce2f91d6 | ||
|
|
66898f60e8 | ||
|
|
0ac3f3fbf1 | ||
|
|
697d4ce974 | ||
|
|
8f4952b6a3 | ||
|
|
d3275456a4 | ||
|
|
04fee67571 | ||
|
|
33dfc9b28f | ||
|
|
8eb8f58f0f | ||
|
|
3bb587fa5c | ||
|
|
170ad48655 | ||
|
|
2602257241 | ||
|
|
6704a52ac4 | ||
|
|
7d694b7ae9 | ||
|
|
f15b4dca01 | ||
|
|
e74fee89fe | ||
|
|
42a5b70fca |
@@ -0,0 +1,28 @@
|
|||||||
|
# Ship the skill set as a native Claude Code plugin; defer a native Codex plugin
|
||||||
|
|
||||||
|
These skills have always been installable via [skills.sh](https://skills.sh/mattpocock/skills) (`npx skills add mattpocock/skills`), which copies editable skill files into a user's project across Claude Code, Codex, and other Agent-Skills-standard harnesses. A recurring request is a **plug-and-play** distribution: subscribe to the set as a read-only, always-current bundle you don't edit, rather than a fork you own. That is exactly what native plugin systems provide.
|
||||||
|
|
||||||
|
We ship a native **Claude Code plugin** and, for now, **defer** a native **Codex plugin**. The split is forced by how each ecosystem's plugin manifest selects skills, against this repo's bucketed layout.
|
||||||
|
|
||||||
|
## The constraint: bucketed skills vs. single-path selection
|
||||||
|
|
||||||
|
Skills live in bucket folders under `skills/` — `engineering/` and `productivity/` are **promoted** (shipped); `misc/`, `personal/`, `in-progress/`, and `deprecated/` are **not**. A plugin must expose only the promoted set, which spans two of those bucket folders.
|
||||||
|
|
||||||
|
- **Claude Code** — `.claude-plugin/plugin.json` accepts `skills` as an **array of explicit skill-directory paths**. We list the promoted skills one by one, exclude everything else with zero ambiguity, and add `.claude-plugin/marketplace.json` so the repo is its own single-plugin marketplace. Verified end to end: `claude plugin validate . --strict` passes, and `marketplace add` → `install` resolves all promoted skills.
|
||||||
|
|
||||||
|
- **Codex** — `.codex-plugin/plugin.json` accepts `skills` only as a **single path string** (arrays are rejected with `missing or invalid plugin.json`), and Codex discovers `SKILL.md` files recursively under it. There is no way to name two bucket folders, or to curate a subset, from one path. Two escape hatches were tested and rejected:
|
||||||
|
- Pointing at `./skills/` would also ship `deprecated/`, `in-progress/`, `personal/`, and `misc/` — retired, draft, and personal skills we deliberately don't promote.
|
||||||
|
- A curated flat directory of **symlinks** into the buckets does not survive install: Codex copies the plugin tree into its cache and **drops symlinks**, so the skills arrive empty.
|
||||||
|
|
||||||
|
The only robust ways to give Codex a single promoted-only path are (a) **restructure** so `skills/` contains only promoted skills (moving the non-promoted buckets out — a large blast radius across `CLAUDE.md`, `scripts/link-skills.sh`, the bucket READMEs, and the local dev workflow that relies on `in-progress/` and `personal/`), or (b) **commit duplicate copies** of promoted skills into a flat directory (a sync burden and a second source of truth). Both are structural decisions, not something to bundle into shipping the Claude plugin. This is very likely the original, half-remembered reason a plugin wasn't shipped earlier: the manifest formats didn't cleanly express a curated subset of a bucketed repo.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
- Ship the **Claude Code plugin** now (`.claude-plugin/plugin.json` + `.claude-plugin/marketplace.json`), curated to the promoted set, as the headline v1.2 deliverable.
|
||||||
|
- Keep **skills.sh** as the universal installer — it already serves Codex and other harnesses today, so no Codex user is left without an install path.
|
||||||
|
- **Defer** the native Codex plugin until we decide between restructuring `skills/` to promoted-only vs. committing a generated flat copy. Revisit when Codex either supports a `skills` array / include-list or preserves symlinks on install.
|
||||||
|
|
||||||
|
## Invariants this creates
|
||||||
|
|
||||||
|
- Every promoted skill has an entry in `.claude-plugin/plugin.json`'s `skills` array (this already stood as a `CLAUDE.md` rule; it now also gates the plugin's contents).
|
||||||
|
- `.claude-plugin/plugin.json`'s `version` tracks `package.json`'s version — bump both together on release. Claude uses the plugin `version` to decide when installed users see an update.
|
||||||
@@ -2,10 +2,12 @@
|
|||||||
|
|
||||||
Every `SKILL.md` in this repo is a skill. The one axis that splits them is **invocation** — who can reach it:
|
Every `SKILL.md` in this repo is a skill. The one axis that splits them is **invocation** — who can reach it:
|
||||||
|
|
||||||
- **User-invoked** — reachable **only by the human typing its name**. Set `disable-model-invocation: true` in the frontmatter. The `description` is **human-facing**: a one-line summary read by a person browsing slash-commands. Strip trigger lists ("Use when the user says…").
|
- **User-invoked** — reachable **only by the human typing its name**. Set `disable-model-invocation: true` in the frontmatter (Claude Code) and `policy.allow_implicit_invocation: false` in `agents/openai.yaml` (Codex). The `description` is **human-facing**: a one-line summary read by a person browsing slash-commands. Strip trigger lists ("Use when the user says…").
|
||||||
- **Model-invoked** — reachable by **model or user**. The default: omit `disable-model-invocation`. The `description` is **model-facing** and keeps rich trigger phrasing ("Use when the user wants…, mentions…, asks for…") so auto-invocation fires. The test for whether a skill should stay model-invoked: _could the model usefully reach for this autonomously?_ (Reuse is the reason to extract a skill, not the test.)
|
- **Model-invoked** — reachable by **model or user**. The default: omit `disable-model-invocation` and the `policy` block from `agents/openai.yaml`. The `description` is **model-facing** and keeps rich trigger phrasing ("Use when the user wants…, mentions…, asks for…") so auto-invocation fires. The test for whether a skill should stay model-invoked: _could the model usefully reach for this autonomously?_ (Reuse is the reason to extract a skill, not the test.)
|
||||||
|
|
||||||
Because a user-invoked skill has no description, nothing but the human can reach it — no other skill can fire it. So a user-invoked skill may invoke model-invoked skills, but it can never reach another user-invoked skill.
|
Each harness excludes a user-invoked skill from the model's reach in its own way, so nothing but the human can fire it — no other skill can. A user-invoked skill may invoke model-invoked skills, but it can never reach another user-invoked skill.
|
||||||
|
|
||||||
|
Every skill also carries an `agents/openai.yaml` beside its `SKILL.md`. It holds Codex UI metadata — `interface.display_name` and `interface.short_description` for the skill picker — and, for user-invoked skills, the `policy.allow_implicit_invocation: false` that pairs with `disable-model-invocation`. Keep the two in sync: a skill is user-invoked in both harnesses or neither.
|
||||||
|
|
||||||
Bucket `README.md`s and the top-level `README.md` group entries into **User-invoked** and **Model-invoked**.
|
Bucket `README.md`s and the top-level `README.md` group entries into **User-invoked** and **Model-invoked**.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
"mattpocock-skills": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Make `/ask-matt` clued-up about `/wayfinder` — the heaviest, most cognitively demanding flow.
|
||||||
|
|
||||||
|
The router now sharpens the two routing mistakes people most often make with wayfinder:
|
||||||
|
|
||||||
|
- **Over-reaching for it.** It's slower and denser than a single grill, so it's flagged as the heaviest flow and reserved for the idea that genuinely won't fit one session — a well-scoped feature belongs on `/grill-with-docs`, not here.
|
||||||
|
- **Losing the way at the handoff.** When the map clears, wayfinder hands off, it doesn't build: merge onto the main flow at `/to-spec` (which collapses the map's linked decisions into a buildable plan) rather than looping the map straight into `/implement`. Straight-to-`/implement` is only for efforts that turned out genuinely small.
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
"mattpocock-skills": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Add Codex metadata alongside each skill's Claude Code frontmatter so the set works in both harnesses without generated copies.
|
||||||
|
|
||||||
|
- Add an `agents/openai.yaml` beside every `SKILL.md` with Codex UI metadata (`interface.display_name`, `interface.short_description`).
|
||||||
|
- Mark every user-invoked skill with `policy.allow_implicit_invocation: false`, the Codex analog of `disable-model-invocation: true`, so Codex excludes it from implicit invocation while explicit `$skill` invocation still works.
|
||||||
|
- Document the dual-harness invocation model in `.agents/invocation.md`, `CLAUDE.md`, and the promoted-bucket READMEs.
|
||||||
|
- Add `AGENTS.md` as a symlink to `CLAUDE.md` so Codex reads the same repo instructions.
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
"mattpocock-skills": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Graduate **`to-questionnaire`** out of `in-progress/` into the **Productivity** bucket, so it ships in the plugin. It turns a decision you can't answer alone into a Markdown questionnaire for the one person who can — filled in async, or worked through together in a meeting.
|
||||||
|
|
||||||
|
Its defining move is that it grills you about the **send**, not the subject: a normal grilling session interrogates the topic, which is exactly what you can't answer here, so the interview asks only who the questionnaire is going to and what you need back, then aims every question at the gap between the two.
|
||||||
|
|
||||||
|
Now wired as a promoted skill — plugin entry, top-level + Productivity READMEs under **User-invoked**, a docs page at `docs/productivity/to-questionnaire.md`, and a Standalone route in `ask-matt` framing it as the inverse of `/grill-me` (mine someone else, not yourself).
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"mattpocock-skills": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Reword **`grilling`** for general use. Its description and body no longer scope the interview to a software plan: "this plan" → "this", "enact the plan" → "act on it", and "exploring the codebase" → "exploring the environment". The technique is unchanged; it now reads as a stress-test of any plan, decision, or idea.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"mattpocock-skills": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Rework **`grilling`** from one-question-at-a-time to round-by-round. It now maps the decision tree and asks the whole **frontier** — every question whose prerequisites are already settled — in a single numbered round, then recomputes the frontier from the user's answers and asks the next round. Same 13 questions land in ~3 rounds instead of 13. Facts the environment can answer are dispatched to background sub-agents so research never blocks the round: only questions downstream of a running exploration wait for it. The session ends when the frontier is empty.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"mattpocock-skills": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Reshape the **`prototype`** skill's logic branch to produce a **single shareable HTML file** instead of a terminal app. The demo is one self-contained file (plain HTML/CSS/JS, no build, no server) a non-developer can open by double-click and drive in their own domain language: a labelled state panel, always-available free-play buttons, and a set of tabbed **guided walkthroughs** — each a scenario with the ordered buttons to press underneath it. The portable pure-logic module still lifts into the real code; the HTML shell is the throwaway primary source.
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
"mattpocock-skills": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Ship the skill set as a native **Claude Code plugin**. The repo is now its own single-plugin marketplace, so you can subscribe to the promoted skills as a managed, read-only bundle instead of copying editable files:
|
||||||
|
|
||||||
|
```
|
||||||
|
/plugin marketplace add mattpocock/skills
|
||||||
|
/plugin install mattpocock-skills@mattpocock
|
||||||
|
```
|
||||||
|
|
||||||
|
`.claude-plugin/plugin.json` gains full marketplace metadata (version, description, author, license, keywords) and a sibling `.claude-plugin/marketplace.json` lists the plugin. `skills.sh` remains the universal installer (and the path for Codex and other harnesses today); a native Codex plugin is deferred — see `.agents/adr/0002-ship-as-a-claude-code-plugin.md` for why.
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
"mattpocock-skills": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Name the `/wayfinder` unit a **decision ticket**.
|
||||||
|
|
||||||
|
People kept reading a wayfinder ticket as an ordinary *implementation* ticket — a slice of a build to execute — when wayfinder uses them as **decision tickets**: questions whose resolution is a decision. The skill description and its opening line now introduce "decision ticket" (and say what makes it one), and the `ask-matt` / engineering README wayfinder blurbs and the docs page match — while "ticket" stays the everyday word once the term is established. `CONTEXT.md` records **Decision ticket** as a domain term so the "avoid: ticket" guidance no longer contradicts wayfinder's deliberate use of the word.
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
"mattpocock-skills": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Wayfinder now burns research tickets down with subagents instead of leaving them parked for a separately-launched session.
|
||||||
|
|
||||||
|
Research stays a real ticket type — it's a genuine shared blocker that downstream decisions hang on, and that dependency is exactly what the frontier's blocking edges exist to render. What changes is how it's resolved: because research is AFK, charting doesn't stop and read it. After creating the tickets, the charting session fires a `/research` subagent for each research ticket to burn it down in parallel, capturing the findings on a throwaway `research/<name>` branch with a context pointer. Research tickets are the one exception to *one ticket per session*.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"mattpocock-skills": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Extend **`writing-for-agents`**' pruning section with a new leading word: **cache**. Single source of truth now reaches past the document into the environment — `package.json` scripts, config files, directory layout, `--help` output are themselves authoritative, so a doc that restates them is a cache of a lookup, earning its load only when the lookup is expensive. The positive target: cache what the agent cannot find by looking (unwritten conventions, the reason behind a choice, gotchas no config confesses), and leave one-file, one-command lookups to the environment, where they cannot go stale.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"mattpocock-skills": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
**Breaking:** rename **`writing-great-skills`** → **`writing-for-agents`** and restructure it. The reference now covers any document an agent consumes — skills, `AGENTS.md` / `CLAUDE.md`, docs reached by a pointer — not just skills. `GLOSSARY.md` is merged into `SKILL.md` (one authoritative treatment per term; the `_Avoid_` synonym lists and the standalone Predictability definition are gone); the skill-only mechanics (frontmatter, model- vs user-invoked, router skills, the invocation cut of splitting) are disclosed to a new `SKILL-MECHANICS.md`. The skill is now **model-invoked**: it fires when creating or editing skills or modifying `AGENTS.md`/`CLAUDE.md`. `ask-matt`'s pointer updated. Reinstall under the new name; the old name is gone (no alias).
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "mattpocock",
|
||||||
|
"owner": {
|
||||||
|
"name": "Matt Pocock",
|
||||||
|
"url": "https://www.aihero.dev"
|
||||||
|
},
|
||||||
|
"description": "Matt Pocock's skills for real engineering, as an installable Claude Code plugin.",
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "mattpocock-skills",
|
||||||
|
"source": "./",
|
||||||
|
"description": "Matt Pocock's agent skills for real engineering — grilling, spec/ticket flows, TDD, code review, domain modelling and more.",
|
||||||
|
"category": "engineering",
|
||||||
|
"keywords": [
|
||||||
|
"engineering",
|
||||||
|
"skills",
|
||||||
|
"tdd",
|
||||||
|
"code-review",
|
||||||
|
"grilling"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,5 +1,23 @@
|
|||||||
{
|
{
|
||||||
"name": "mattpocock-skills",
|
"name": "mattpocock-skills",
|
||||||
|
"version": "1.2.0",
|
||||||
|
"description": "Matt Pocock's agent skills for real engineering — grilling, spec/ticket flows, TDD, code review, domain modelling and more. Plug-and-play, not vibe coding.",
|
||||||
|
"author": {
|
||||||
|
"name": "Matt Pocock",
|
||||||
|
"url": "https://www.aihero.dev"
|
||||||
|
},
|
||||||
|
"homepage": "https://www.aihero.dev/s/skills-newsletter",
|
||||||
|
"repository": "https://github.com/mattpocock/skills",
|
||||||
|
"license": "MIT",
|
||||||
|
"keywords": [
|
||||||
|
"engineering",
|
||||||
|
"skills",
|
||||||
|
"tdd",
|
||||||
|
"code-review",
|
||||||
|
"grilling",
|
||||||
|
"domain-modeling",
|
||||||
|
"productivity"
|
||||||
|
],
|
||||||
"skills": [
|
"skills": [
|
||||||
"./skills/engineering/ask-matt",
|
"./skills/engineering/ask-matt",
|
||||||
"./skills/engineering/diagnosing-bugs",
|
"./skills/engineering/diagnosing-bugs",
|
||||||
@@ -17,10 +35,12 @@
|
|||||||
"./skills/engineering/domain-modeling",
|
"./skills/engineering/domain-modeling",
|
||||||
"./skills/engineering/codebase-design",
|
"./skills/engineering/codebase-design",
|
||||||
"./skills/engineering/code-review",
|
"./skills/engineering/code-review",
|
||||||
|
"./skills/engineering/resolving-merge-conflicts",
|
||||||
"./skills/productivity/grill-me",
|
"./skills/productivity/grill-me",
|
||||||
"./skills/productivity/grilling",
|
"./skills/productivity/grilling",
|
||||||
"./skills/productivity/handoff",
|
"./skills/productivity/handoff",
|
||||||
"./skills/productivity/teach",
|
"./skills/productivity/teach",
|
||||||
"./skills/productivity/writing-great-skills"
|
"./skills/productivity/to-questionnaire",
|
||||||
|
"./skills/productivity/writing-for-agents"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ Skills are organized into bucket folders under `skills/`:
|
|||||||
- `in-progress/` — drafts not yet ready to ship
|
- `in-progress/` — drafts not yet ready to ship
|
||||||
- `deprecated/` — no longer used
|
- `deprecated/` — no longer used
|
||||||
|
|
||||||
Every skill in `engineering/` or `productivity/` (the **promoted** buckets) must have a reference in the top-level `README.md` and an entry in `.claude-plugin/plugin.json`. Skills in `misc/`, `personal/`, `in-progress/`, and `deprecated/` must not appear in either.
|
Every skill in `engineering/` or `productivity/` (the **promoted** buckets) must have a reference in the top-level `README.md` and an entry in `.claude-plugin/plugin.json`'s `skills` array (the Claude Code plugin ships exactly the promoted set). Skills in `misc/`, `personal/`, `in-progress/`, and `deprecated/` must not appear in either.
|
||||||
|
|
||||||
|
The repo is also its own single-plugin Claude Code marketplace: `.claude-plugin/marketplace.json` lists the one `mattpocock-skills` plugin. When bumping the release version, keep `.claude-plugin/plugin.json`'s `version` in sync with `package.json`'s — Claude uses the plugin `version` to decide when installed users see an update. Run `claude plugin validate . --strict` after touching either manifest. Why a Claude plugin but not (yet) a Codex one lives in [.agents/adr/0002-ship-as-a-claude-code-plugin.md](./.agents/adr/0002-ship-as-a-claude-code-plugin.md).
|
||||||
|
|
||||||
Each skill entry in the top-level `README.md` must link the skill name to its `SKILL.md`.
|
Each skill entry in the top-level `README.md` must link the skill name to its `SKILL.md`.
|
||||||
|
|
||||||
@@ -15,7 +17,7 @@ Each bucket folder has a `README.md` that lists every skill in the bucket with a
|
|||||||
|
|
||||||
Skills in `engineering/` and `productivity/` also have a human-facing docs page at `docs/<bucket>/<skill-name>.md` (the docs tree mirrors those two bucket folders under `skills/`). The published URL is `https://aihero.dev/skills-<skill-name>` regardless of bucket — the docs path is repo organisation only. When you add, rename, or change the behaviour of a skill in `engineering/` or `productivity/`, create or re-sync its docs page following [.agents/writing-docs.md](./.agents/writing-docs.md). Skills in the non-promoted buckets (`misc/`, `personal/`, `in-progress/`, `deprecated/`) get **no** docs page.
|
Skills in `engineering/` and `productivity/` also have a human-facing docs page at `docs/<bucket>/<skill-name>.md` (the docs tree mirrors those two bucket folders under `skills/`). The published URL is `https://aihero.dev/skills-<skill-name>` regardless of bucket — the docs path is repo organisation only. When you add, rename, or change the behaviour of a skill in `engineering/` or `productivity/`, create or re-sync its docs page following [.agents/writing-docs.md](./.agents/writing-docs.md). Skills in the non-promoted buckets (`misc/`, `personal/`, `in-progress/`, `deprecated/`) get **no** docs page.
|
||||||
|
|
||||||
Every `SKILL.md` is either user-invoked (`disable-model-invocation: true`, reachable only by the human) or model-invoked (model- or user-reachable). See [.agents/invocation.md](./.agents/invocation.md).
|
Every `SKILL.md` is either user-invoked (`disable-model-invocation: true` plus `policy.allow_implicit_invocation: false` in `agents/openai.yaml`, reachable only by the human) or model-invoked (model- or user-reachable). See [.agents/invocation.md](./.agents/invocation.md).
|
||||||
|
|
||||||
[`ask-matt`](./skills/engineering/ask-matt/SKILL.md) is the router that maps every user-reachable skill and how they relate. The same trigger that re-syncs a docs page applies to it: whenever you add, rename, remove, or change how a user-reachable skill fits the flows, re-read `ask-matt`'s `SKILL.md` and update it so the map stays accurate — a new skill it never mentions, or a stale one it still routes to, is a router that lies.
|
[`ask-matt`](./skills/engineering/ask-matt/SKILL.md) is the router that maps every user-reachable skill and how they relate. The same trigger that re-syncs a docs page applies to it: whenever you add, rename, remove, or change how a user-reachable skill fits the flows, re-read `ask-matt`'s `SKILL.md` and update it so the map stays accurate — a new skill it never mentions, or a stale one it still routes to, is a router that lies.
|
||||||
|
|
||||||
|
|||||||
+5
-1
@@ -10,7 +10,10 @@ _Avoid_: backlog manager, backlog backend, issue host
|
|||||||
|
|
||||||
**Issue**:
|
**Issue**:
|
||||||
A single tracked unit of work inside an **Issue tracker** — a bug, task, spec, or slice produced by `to-tickets`.
|
A single tracked unit of work inside an **Issue tracker** — a bug, task, spec, or slice produced by `to-tickets`.
|
||||||
_Avoid_: ticket (use only when quoting external systems that call them tickets)
|
_Avoid_: ticket (use only when quoting external systems that call them tickets, or for a **Decision ticket** — see below)
|
||||||
|
|
||||||
|
**Decision ticket**:
|
||||||
|
A `wayfinder` unit — a child **Issue** of a `wayfinder:map` holding a *question* whose resolution is a decision, not a slice of a build to execute. The **decision** qualifier is what keeps it distinct from an implementation ticket; `wayfinder` introduces the term, then uses "ticket".
|
||||||
|
|
||||||
**Triage role**:
|
**Triage role**:
|
||||||
A canonical state-machine label applied to an **Issue** during triage (e.g. `needs-triage`, `ready-for-afk`). Each role maps to a real label string in the **Issue tracker** via `docs/agents/triage-labels.md`.
|
A canonical state-machine label applied to an **Issue** during triage (e.g. `needs-triage`, `ready-for-afk`). Each role maps to a real label string in the **Issue tracker** via `docs/agents/triage-labels.md`.
|
||||||
@@ -19,6 +22,7 @@ A canonical state-machine label applied to an **Issue** during triage (e.g. `nee
|
|||||||
|
|
||||||
- An **Issue tracker** holds many **Issues**
|
- An **Issue tracker** holds many **Issues**
|
||||||
- An **Issue** carries one **Triage role** at a time
|
- An **Issue** carries one **Triage role** at a time
|
||||||
|
- A **Decision ticket** is an **Issue** (a child of a `wayfinder:map`)
|
||||||
|
|
||||||
## Flagged ambiguities
|
## Flagged ambiguities
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,33 @@ npx skills@latest add mattpocock/skills
|
|||||||
|
|
||||||
4. Bam - you're ready to go.
|
4. Bam - you're ready to go.
|
||||||
|
|
||||||
|
## Install as a Claude Code plugin
|
||||||
|
|
||||||
|
Prefer a plug-and-play install you don't maintain by hand? These skills also ship as a native [Claude Code plugin](https://code.claude.com/docs/en/plugins). Instead of copying editable files into your repo, the plugin installs the whole skill set as a managed bundle that updates when I ship a new version — you subscribe rather than fork.
|
||||||
|
|
||||||
|
Inside Claude Code:
|
||||||
|
|
||||||
|
```
|
||||||
|
/plugin marketplace add mattpocock/skills
|
||||||
|
/plugin install mattpocock-skills@mattpocock
|
||||||
|
```
|
||||||
|
|
||||||
|
Or from your shell:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude plugin marketplace add mattpocock/skills
|
||||||
|
claude plugin install mattpocock-skills@mattpocock
|
||||||
|
```
|
||||||
|
|
||||||
|
Then run `/setup-matt-pocock-skills` once per repo, exactly as in the quickstart above.
|
||||||
|
|
||||||
|
Two ways to install, two philosophies:
|
||||||
|
|
||||||
|
- **[skills.sh](https://skills.sh/mattpocock/skills)** copies the skills into your project so you can hack on them and make them your own.
|
||||||
|
- **The plugin** keeps them as a read-only, always-current bundle you don't edit — best when you just want my set to work and follow along as it evolves.
|
||||||
|
|
||||||
|
> Using Codex or another agent? The [skills.sh installer](https://skills.sh/mattpocock/skills) already installs these skills into Codex and other Agent-Skills-standard harnesses today. A native Codex plugin is on the roadmap — see [`.agents/adr/0002-ship-as-a-claude-code-plugin.md`](./.agents/adr/0002-ship-as-a-claude-code-plugin.md).
|
||||||
|
|
||||||
## Why These Skills Exist
|
## Why These Skills Exist
|
||||||
|
|
||||||
I built these skills as a way to fix common failure modes I see with Claude Code, Codex, and other coding agents.
|
I built these skills as a way to fix common failure modes I see with Claude Code, Codex, and other coding agents.
|
||||||
@@ -168,6 +195,7 @@ Skills I use daily for code work.
|
|||||||
- **[domain-modeling](./skills/engineering/domain-modeling/SKILL.md)** — Actively build and sharpen a project's domain model — challenge terms against the glossary, stress-test with edge-case scenarios, and update `CONTEXT.md` and ADRs inline.
|
- **[domain-modeling](./skills/engineering/domain-modeling/SKILL.md)** — Actively build and sharpen a project's domain model — challenge terms against the glossary, stress-test with edge-case scenarios, and update `CONTEXT.md` and ADRs inline.
|
||||||
- **[codebase-design](./skills/engineering/codebase-design/SKILL.md)** — Shared discipline and vocabulary for designing deep modules: a lot of behaviour behind a small interface, placed at a clean seam, testable through that interface.
|
- **[codebase-design](./skills/engineering/codebase-design/SKILL.md)** — Shared discipline and vocabulary for designing deep modules: a lot of behaviour behind a small interface, placed at a clean seam, testable through that interface.
|
||||||
- **[code-review](./skills/engineering/code-review/SKILL.md)** — Two-axis review of the diff since a fixed point: **Standards** (does it follow the repo's coding standards, plus a Fowler smell baseline?) and **Spec** (does it faithfully implement the originating issue/PRD?), run as parallel sub-agents so neither pollutes the other.
|
- **[code-review](./skills/engineering/code-review/SKILL.md)** — Two-axis review of the diff since a fixed point: **Standards** (does it follow the repo's coding standards, plus a Fowler smell baseline?) and **Spec** (does it faithfully implement the originating issue/PRD?), run as parallel sub-agents so neither pollutes the other.
|
||||||
|
- **[resolving-merge-conflicts](./skills/engineering/resolving-merge-conflicts/SKILL.md)** — Work through an in-progress git merge or rebase conflict hunk by hunk, resolving by intent traced to each side's primary source, then finish the operation — never `--abort`.
|
||||||
|
|
||||||
### Productivity
|
### Productivity
|
||||||
|
|
||||||
@@ -178,8 +206,9 @@ General workflow tools, not code-specific.
|
|||||||
- **[grill-me](./skills/productivity/grill-me/SKILL.md)** — Get relentlessly interviewed about a plan or design until every branch of the decision tree is resolved.
|
- **[grill-me](./skills/productivity/grill-me/SKILL.md)** — Get relentlessly interviewed about a plan or design until every branch of the decision tree is resolved.
|
||||||
- **[handoff](./skills/productivity/handoff/SKILL.md)** — Compact the current conversation into a handoff document so another agent can continue the work.
|
- **[handoff](./skills/productivity/handoff/SKILL.md)** — Compact the current conversation into a handoff document so another agent can continue the work.
|
||||||
- **[teach](./skills/productivity/teach/SKILL.md)** — Teach the user a new skill or concept over multiple sessions, using the current directory as a stateful teaching workspace.
|
- **[teach](./skills/productivity/teach/SKILL.md)** — Teach the user a new skill or concept over multiple sessions, using the current directory as a stateful teaching workspace.
|
||||||
- **[writing-great-skills](./skills/productivity/writing-great-skills/SKILL.md)** — Reference for writing and editing skills well: the vocabulary and principles that make a skill predictable.
|
- **[to-questionnaire](./skills/productivity/to-questionnaire/SKILL.md)** — Turn a decision you can't answer alone into a Markdown questionnaire for the one person who can — filled in async, or together over a meeting. It grills you about the send (who it's for, what you need back), not the subject.
|
||||||
|
- **[writing-for-agents](./skills/productivity/writing-for-agents/SKILL.md)** — Writing documents for agents: skills, AGENTS.md/CLAUDE.md, and any doc an agent reaches by a pointer.
|
||||||
|
|
||||||
**Model-invoked**
|
**Model-invoked**
|
||||||
|
|
||||||
- **[grilling](./skills/productivity/grilling/SKILL.md)** — Interview the user relentlessly about a plan or design until every branch of the decision tree is resolved. The reusable loop behind `grill-me` and `grill-with-docs`.
|
- **[grilling](./skills/productivity/grilling/SKILL.md)** — Interview the user relentlessly about a plan, decision, or idea until every branch of the decision tree is resolved. The reusable loop behind `grill-me` and `grill-with-docs`.
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ This skill is stateful — it writes into your repo as it grills. Resolved terms
|
|||||||
|
|
||||||
## The grill
|
## The grill
|
||||||
|
|
||||||
The engine is a **grill**: a relentless, one-question-at-a-time walk down the design tree, resolving dependencies between decisions before moving on, with a recommended answer offered for every question. Questions the codebase can answer are answered by reading the codebase, not by asking you.
|
The engine is a **grill**: a relentless, one-question-at-a-time walk down the decision tree, resolving dependencies between decisions before moving on, with a recommended answer offered for every question. Questions the codebase can answer are answered by reading the codebase, not by asking you.
|
||||||
|
|
||||||
What makes this variant its own skill is where the answers go. As the grill runs, fuzzy language gets sharpened into canonical terms and written to the glossary inline — not batched at the end. The glossary stays a glossary: pure vocabulary, no implementation details, no spec. ADRs are offered sparingly, only when a decision is hard to reverse, surprising without context, and the result of a real trade-off. Most sessions produce a sharper glossary and few or no ADRs, and that's the intended shape.
|
What makes this variant its own skill is where the answers go. As the grill runs, fuzzy language gets sharpened into canonical terms and written to the glossary inline — not batched at the end. The glossary stays a glossary: pure vocabulary, no implementation details, no spec. ADRs are offered sparingly, only when a decision is hard to reverse, surprising without context, and the result of a real trade-off. Most sessions produce a sharper glossary and few or no ADRs, and that's the intended shape.
|
||||||
|
|
||||||
|
|||||||
@@ -38,4 +38,4 @@ Then it stops and asks which one you want to explore. Pick one and it runs the [
|
|||||||
|
|
||||||
## Where it fits
|
## Where it fits
|
||||||
|
|
||||||
`improve-codebase-architecture` is **periodic maintenance** — run it every few days, not as a step in a chain. Its neighbours are [codebase-design](https://aihero.dev/skills-codebase-design), which owns the depth-and-seam vocabulary every candidate is written in, [grilling](https://aihero.dev/skills-grilling), which walks the design tree once you've chosen a candidate, and [domain-modeling](https://aihero.dev/skills-domain-modeling), which keeps `CONTEXT.md` and the ADRs current as the redesign settles. When you're unsure which skill or flow fits, [ask-matt](https://aihero.dev/skills-ask-matt) routes you.
|
`improve-codebase-architecture` is **periodic maintenance** — run it every few days, not as a step in a chain. Its neighbours are [codebase-design](https://aihero.dev/skills-codebase-design), which owns the depth-and-seam vocabulary every candidate is written in, [grilling](https://aihero.dev/skills-grilling), which walks the decision tree once you've chosen a candidate, and [domain-modeling](https://aihero.dev/skills-domain-modeling), which keeps `CONTEXT.md` and the ADRs current as the redesign settles. When you're unsure which skill or flow fits, [ask-matt](https://aihero.dev/skills-ask-matt) routes you.
|
||||||
|
|||||||
@@ -26,10 +26,10 @@ Reach for it when you have a design question that's hard to settle on paper —
|
|||||||
|
|
||||||
The question decides the shape, and there are two shapes:
|
The question decides the shape, and there are two shapes:
|
||||||
|
|
||||||
- **"Does this logic / state model feel right?"** — a tiny interactive terminal app that pushes the state machine through the awkward cases, printing the full state after every action so you can watch what changes.
|
- **"Does this logic / state model feel right?"** — a single shareable HTML file, free-play buttons plus tabbed guided walkthroughs, that pushes the state machine through the awkward cases and shows the full state after every click, so anyone — including a non-developer — can watch what changes.
|
||||||
- **"What should this look like?"** — several radically different UI variations on one route, switchable from a floating bar, so you compare real renders instead of imagining them.
|
- **"What should this look like?"** — several radically different UI variations on one route, switchable from a floating bar, so you compare real renders instead of imagining them.
|
||||||
|
|
||||||
Picking the wrong branch wastes the whole prototype, so the question comes first. Both branches keep state in memory, run from one command, and surface the full state on every step.
|
Picking the wrong branch wastes the whole prototype, so the question comes first. Both branches keep state in memory, are trivial to run, and surface the full state on every step.
|
||||||
|
|
||||||
## Keep the prototype as a primary source
|
## Keep the prototype as a primary source
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ npx skills update wayfinder
|
|||||||
|
|
||||||
## What it does
|
## What it does
|
||||||
|
|
||||||
`wayfinder` takes an effort too big for one agent session — wrapped in fog, where the way from here to the goal isn't visible yet — and charts it as a **shared map** of investigation tickets on your issue tracker, then resolves them one at a time until the way is clear. It **plans, it doesn't do**: every ticket resolves a decision, and the map is done when nothing is left to decide before someone goes and builds the thing — so it produces decisions, not deliverables.
|
`wayfinder` takes an effort too big for one agent session — wrapped in fog, where the way from here to the goal isn't visible yet — and charts it as a **shared map** of **decision tickets** on your issue tracker, then resolves them one at a time until the way is clear. It **plans, it doesn't do**: every ticket resolves a decision — a question to settle, not a slice of a build to execute — and the map is done when nothing is left to decide before someone goes and builds the thing — so it produces decisions, not deliverables.
|
||||||
|
|
||||||
## When to reach for it
|
## When to reach for it
|
||||||
|
|
||||||
@@ -30,13 +30,13 @@ The **map** is a single `wayfinder:map` issue whose tickets are its child issues
|
|||||||
|
|
||||||
Beyond the live tickets lies the **fog of war** — decisions you can tell are coming but can't yet pin down. The test for whether something is a ticket or still fog is whether you can *state the question precisely now*, not whether you can answer it. Resolving a ticket clears the fog ahead of it, **graduating** whatever's now specifiable into fresh tickets. The **frontier** is the open, unblocked, unclaimed tickets — the edge of the known — and it's what the tracker's native blocking renders visually, so you see what's takeable without opening the map. Fog only gathers *toward* the **destination**; work past it is ruled **out of scope**, closed, never graduating.
|
Beyond the live tickets lies the **fog of war** — decisions you can tell are coming but can't yet pin down. The test for whether something is a ticket or still fog is whether you can *state the question precisely now*, not whether you can answer it. Resolving a ticket clears the fog ahead of it, **graduating** whatever's now specifiable into fresh tickets. The **frontier** is the open, unblocked, unclaimed tickets — the edge of the known — and it's what the tracker's native blocking renders visually, so you see what's takeable without opening the map. Fog only gathers *toward* the **destination**; work past it is ruled **out of scope**, closed, never graduating.
|
||||||
|
|
||||||
Every ticket is **HITL** (human in the loop — grilling, prototype) or **AFK** (agent alone — research); a HITL ticket only resolves through a live exchange, so the agent never answers its own questions.
|
Every ticket is **HITL** (human in the loop — grilling, prototype) or **AFK** (agent alone — research); a HITL ticket only resolves through a live exchange, so the agent never answers its own questions. Research stays a real ticket — a shared blocker downstream decisions hang on — but because it's AFK, a session doesn't stop and read: it fires a `/research` **subagent** to burn the ticket down in parallel, keeping the frontier fast, and captures the findings on a throwaway `research/<name>` branch.
|
||||||
|
|
||||||
## It's working if
|
## It's working if
|
||||||
|
|
||||||
- Naming the **destination** is the first act — before any ticket exists — because it fixes the scope every ticket is measured against.
|
- Naming the **destination** is the first act — before any ticket exists — because it fixes the scope every ticket is measured against.
|
||||||
- One map is one `wayfinder:map` issue; tickets are its child issues, referred to by **name**, never a bare `#42`.
|
- One map is one `wayfinder:map` issue; tickets are its child issues, referred to by **name**, never a bare `#42`.
|
||||||
- A session resolves **at most one ticket**, records the answer as a resolution comment, closes the ticket, and appends a one-line pointer to *Decisions so far*.
|
- A session resolves **at most one ticket** (research tickets excepted), records the answer as a resolution comment, closes the ticket, and appends a one-line pointer to *Decisions so far*.
|
||||||
- If the opening grill surfaces **no fog**, it stops and tells you the journey is small enough to skip the map.
|
- If the opening grill surfaces **no fog**, it stops and tells you the journey is small enough to skip the map.
|
||||||
|
|
||||||
## Where it fits
|
## Where it fits
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ You invoke this by typing `/grill-me` — the agent won't reach for it on its ow
|
|||||||
|
|
||||||
Reach for it before you build, when a plan feels roughly right but you can sense unresolved decisions hiding in it — the moment you want the soft spots found and forced into the open. If you want that same interrogation to also leave a paper trail of ADRs and a glossary behind, use [grill-with-docs](https://aihero.dev/skills-grill-with-docs) instead. And if the effort is too big to hold in one session and the route to the goal is still foggy — a greenfield project, a huge feature build — start further upstream with [wayfinder](https://aihero.dev/skills-wayfinder), which charts it as a map of decisions first and then merges back into this flow.
|
Reach for it before you build, when a plan feels roughly right but you can sense unresolved decisions hiding in it — the moment you want the soft spots found and forced into the open. If you want that same interrogation to also leave a paper trail of ADRs and a glossary behind, use [grill-with-docs](https://aihero.dev/skills-grill-with-docs) instead. And if the effort is too big to hold in one session and the route to the goal is still foggy — a greenfield project, a huge feature build — start further upstream with [wayfinder](https://aihero.dev/skills-wayfinder), which charts it as a map of decisions first and then merges back into this flow.
|
||||||
|
|
||||||
## The design tree
|
## The decision tree
|
||||||
|
|
||||||
The session walks the plan as a tree of decisions, resolving dependencies between them one by one — a parent decision settled before the choices that hang off it. The point is not to reach agreement quickly; it is to make every implicit call explicit, so nothing important is left silently assumed. You come out the other side with a plan whose branches have all been visited.
|
The session walks the plan as a tree of decisions, resolving dependencies between them one by one — a parent decision settled before the choices that hang off it. The point is not to reach agreement quickly; it is to make every implicit call explicit, so nothing important is left silently assumed. You come out the other side with a plan whose branches have all been visited.
|
||||||
|
|
||||||
|
|||||||
@@ -12,9 +12,17 @@ npx skills update grilling
|
|||||||
|
|
||||||
## What it does
|
## What it does
|
||||||
|
|
||||||
`grilling` is the relentless interview that stress-tests a plan or design before you build it. It walks down the design tree branch by branch, resolving the dependencies between decisions one at a time until you and the agent share the same understanding.
|
`grilling` is the relentless interview that stress-tests a plan or design before you build it. It maps the plan as a **design tree** — every decision branches into the decisions that hang off it — and works that tree in **rounds** until you and the agent share the same understanding.
|
||||||
|
|
||||||
It asks **one question at a time** and waits for your answer before the next — never a bulk list, which is bewildering. Each question comes with the agent's own recommended answer, and any question the codebase can settle it explores instead of asking you. It won't start enacting the plan until you confirm the shared understanding has been reached.
|
Each round asks the whole **frontier**: every decision whose prerequisites are already settled — the questions it can put to you *now* without guessing at answers it hasn't heard yet. Your answers reshape the tree, pushing the frontier outward, and the next round asks whatever that unblocks. Thirteen questions land in a handful of rounds instead of thirteen. Every question comes with the agent's own recommended answer; any *fact* the environment can settle it dispatches to a background sub-agent rather than asking you — and it doesn't block on that research, only the questions downstream of it wait. It won't act on the plan until you confirm the shared understanding has been reached.
|
||||||
|
|
||||||
|
### Prefer one question at a time?
|
||||||
|
|
||||||
|
If the old one-at-a-time rhythm suited you better, keep it. Add a line to your global `CLAUDE.md`:
|
||||||
|
|
||||||
|
```
|
||||||
|
When grilling, ask one question at a time.
|
||||||
|
```
|
||||||
|
|
||||||
## When to reach for it
|
## When to reach for it
|
||||||
|
|
||||||
@@ -22,9 +30,9 @@ Type `/grilling`, or the agent reaches for it automatically when a task fits —
|
|||||||
|
|
||||||
Reach for it when a plan or design still has soft spots and you want them surfaced before code is written. In practice you usually invoke it through one of its two wrappers rather than by name: for a plain grilling session use [grill-me](https://aihero.dev/skills-grill-me); to have the session also write ADRs and a glossary as it goes, use [grill-with-docs](https://aihero.dev/skills-grill-with-docs).
|
Reach for it when a plan or design still has soft spots and you want them surfaced before code is written. In practice you usually invoke it through one of its two wrappers rather than by name: for a plain grilling session use [grill-me](https://aihero.dev/skills-grill-me); to have the session also write ADRs and a glossary as it goes, use [grill-with-docs](https://aihero.dev/skills-grill-with-docs).
|
||||||
|
|
||||||
## The design tree
|
## The decision tree
|
||||||
|
|
||||||
The mental model is a **design tree**: every plan branches into decisions, and decisions depend on each other. `grilling` descends that tree one node at a time, so an early answer can reshape which questions come next. That is why the questions arrive singly and in dependency order — a firehose of parallel questions loses the structure that makes the interview converge on a shared understanding.
|
The mental model is a **design tree**: every plan branches into decisions, and decisions depend on each other. The **frontier** is the set of decisions whose prerequisites are all settled — the only questions that can be asked without guessing. `grilling` asks the whole frontier at once, then recomputes it from your answers, so a round is exactly the batch of questions that *don't* depend on each other. A question whose answer hinges on another still open this round waits for a later round. Asking in frontier-sized rounds keeps the dependency structure intact while sparing you a question-at-a-time drip.
|
||||||
|
|
||||||
## Pulled out on purpose
|
## Pulled out on purpose
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
Quickstart:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx skills add mattpocock/skills --skill=to-questionnaire
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx skills update to-questionnaire
|
||||||
|
```
|
||||||
|
|
||||||
|
[Source](https://github.com/mattpocock/skills/tree/main/skills/productivity/to-questionnaire)
|
||||||
|
|
||||||
|
## What it does
|
||||||
|
|
||||||
|
`to-questionnaire` turns a decision you can't settle on your own into a **questionnaire** — a Markdown document you hand to the one person who holds what you're missing, to fill in async or work through together in a meeting.
|
||||||
|
|
||||||
|
It grills you about the **send**, never the subject. A normal grilling session interrogates the topic, which is exactly what you can't answer here — that's why you're writing to someone else. So the interview asks only the two things you can always answer: who this is going to, and what you need back from them. The questions in the document are then aimed at the **gap** between the two.
|
||||||
|
|
||||||
|
## When to reach for it
|
||||||
|
|
||||||
|
You invoke this by typing `/to-questionnaire` — the agent won't reach for it on its own.
|
||||||
|
|
||||||
|
Reach for this when a decision is blocked on knowledge that lives in someone else's head — a client, a domain expert, a colleague on another team — and you want a document that pulls it out of them in one pass. When the knowledge is in *your* head and just needs sharpening, use [grill-me](https://aihero.dev/skills-grill-me) instead; when it's in the codebase, use [grill-with-docs](https://aihero.dev/skills-grill-with-docs).
|
||||||
|
|
||||||
|
## The send, not the subject
|
||||||
|
|
||||||
|
The interview is two exchanges, and it stops there:
|
||||||
|
|
||||||
|
- **Who is it going to?** Their role, expertise, and relationship to you. This fixes the tone and how much context the document has to carry — an outside client needs orienting; a teammate does not.
|
||||||
|
- **What do you need back?** The concrete decisions or facts you can't resolve alone. This becomes the checklist the finished questionnaire is measured against: every item you named has a question aimed at it.
|
||||||
|
|
||||||
|
Everything after that is drafting. The output is written to `to-questionnaire-<slug>.md` in the current directory.
|
||||||
|
|
||||||
|
## The document
|
||||||
|
|
||||||
|
It's a **discovery questionnaire**: you lack the context, the recipient holds it. That framing drives its shape — a purpose line and the decision riding on it, a short context section for a recipient who wasn't in your head, and questions ordered **most-important-first**, because async means you may only get one pass. Each question is one idea, never compound, with an answer stub beneath it and a *why this matters* line only where the question could be misread. It closes with a catch-all: anything we didn't ask that we should know?
|
||||||
|
|
||||||
|
## It's working if
|
||||||
|
|
||||||
|
- It asks you about the recipient and the deliverable, then stops asking — no interrogation of the topic itself.
|
||||||
|
- Every item you named as "what I need back" is traceable to a question in the file.
|
||||||
|
- The questions read as aimed at what the *recipient* knows, not as your own open questions copied down.
|
||||||
|
|
||||||
|
## Where it fits
|
||||||
|
|
||||||
|
`to-questionnaire` is a reach-for-it-anytime standalone — it sits at the boundary of your own knowledge, where the next step is another person rather than another skill. Its neighbour is [grill-me](https://aihero.dev/skills-grill-me), because the two split on where the answers live: grilling mines you, a questionnaire mines someone else. What comes back typically feeds the main flow at [grill-with-docs](https://aihero.dev/skills-grill-with-docs) or [to-spec](https://aihero.dev/skills-to-spec). When you're unsure which skill fits the moment, [ask-matt](https://aihero.dev/skills-ask-matt) routes you.
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
Quickstart:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx skills add mattpocock/skills --skill=writing-for-agents
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx skills update writing-for-agents
|
||||||
|
```
|
||||||
|
|
||||||
|
[Source](https://github.com/mattpocock/skills/tree/main/skills/productivity/writing-for-agents)
|
||||||
|
|
||||||
|
## What it does
|
||||||
|
|
||||||
|
`writing-for-agents` is the reference you write agent-facing documents against — skills, `AGENTS.md` / `CLAUDE.md`, and any doc an agent reaches by a pointer. The packaging differs; the writing does not: the same levers make each one predictable, so the agent takes the same *process* every run rather than producing the same output.
|
||||||
|
|
||||||
|
Formerly `writing-great-skills`. The rename tracks what the reference always was underneath: almost none of it is skill-specific. The universal core — context pointers, the two loads, the information hierarchy, completion criteria, leading words, pruning — applies to any document an agent consumes; the genuinely skill-only mechanics (frontmatter, the model- vs user-invoked choice, router skills) are disclosed to a linked `SKILL-MECHANICS.md` you read only when the document you're writing is a skill.
|
||||||
|
|
||||||
|
## When to reach for it
|
||||||
|
|
||||||
|
The agent reaches for it on its own whenever you're creating or editing a skill, or modifying `AGENTS.md` or `CLAUDE.md` — and you can still type `/writing-for-agents` to pull it up directly.
|
||||||
|
|
||||||
|
## The two loads
|
||||||
|
|
||||||
|
The concept the whole reference turns on is a pair of budgets every document and pointer spends:
|
||||||
|
|
||||||
|
- **Context load** — the cost of always-loaded material on the agent's window: an `AGENTS.md` line, a skill description, anything sitting in context every turn whether or not it fires.
|
||||||
|
- **Cognitive load** — the cost on the human: which documents exist and when to reach for each. You are the index. Not a cost to minimise — it's the price of human agency.
|
||||||
|
|
||||||
|
Once you're thinking in these two loads, most authoring decisions — split or don't, inline or disclose, point or push — become the same trade made in different places.
|
||||||
|
|
||||||
|
## The other levers
|
||||||
|
|
||||||
|
- **Context pointers** — the reference held in context that names out-of-context material and encodes when to reach it. A skill description and an `AGENTS.md` line pointing at a doc are the same object; the pointer's *wording*, not its target, decides when and how reliably the agent reaches through it.
|
||||||
|
- **Information hierarchy** — the ladder from in-file step, to in-file reference, to disclosed reference behind a pointer. **Progressive disclosure** is the move down that ladder so the top stays legible; **co-location** decides what sits beside each piece once placed.
|
||||||
|
- **Completion criteria** — the clarity and demand of each step's done-condition, and the **legwork** it drives; the defence against **premature completion**.
|
||||||
|
- **Leading words** — a compact concept already in the model's pretraining (*tight*, *red*, *tracer bullet*) that the agent thinks with while running the document; hunt restatements a single word can retire.
|
||||||
|
- **Pruning** — single source of truth, relevance, and the no-op test applied sentence by sentence, against **sediment** and **sprawl**. Single source of truth reaches past the document into the environment: a doc restating what's already in `package.json`, a config file, or `--help` output is a **cache** of a lookup that was never expensive, and it's the copy that goes stale. Cache what the agent can't find by looking — the unwritten convention, the reason behind a choice.
|
||||||
|
|
||||||
|
## Where it fits
|
||||||
|
|
||||||
|
This is a reach-for-it-anytime standalone reference — the meta-skill you consult while building the rest of the set, not a step in a chain. When you're unsure which skill or flow fits a task, [ask-matt](https://aihero.dev/skills-ask-matt) routes you over the whole set.
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
Quickstart:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npx skills add mattpocock/skills --skill=writing-great-skills
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npx skills update writing-great-skills
|
|
||||||
```
|
|
||||||
|
|
||||||
[Source](https://github.com/mattpocock/skills/tree/main/skills/productivity/writing-great-skills)
|
|
||||||
|
|
||||||
## What it does
|
|
||||||
|
|
||||||
`writing-great-skills` is the reference you write and edit skills against — the shared vocabulary and principles that make a skill predictable.
|
|
||||||
|
|
||||||
A skill's job is to wrangle determinism out of a stochastic system, so the goal is not the same *output* every run but the same *process*. **Predictability** is the root virtue, and every design choice is judged against it — not against how clever, complete, or exhaustive the skill reads.
|
|
||||||
|
|
||||||
## When to reach for it
|
|
||||||
|
|
||||||
You invoke this by typing `/writing-great-skills` — the agent won't reach for it on its own.
|
|
||||||
|
|
||||||
Reach for it whenever you're authoring a new skill or editing an existing one and want it to behave the same way every time: deciding invocation mode, writing a description, choosing what lives in `SKILL.md` versus a linked file, or diagnosing why a skill misfires.
|
|
||||||
|
|
||||||
## Cognitive load
|
|
||||||
|
|
||||||
The concept the whole reference turns on is **cognitive load** — and its counterpart, **context load**. Every skill spends one or the other:
|
|
||||||
|
|
||||||
- A **model-invoked** skill keeps a description in the window every turn, so it costs **context load** but fires on its own.
|
|
||||||
- A **user-invoked** skill strips that description; it costs zero context load, but now *you* are the index that has to remember it exists — that's **cognitive load**.
|
|
||||||
|
|
||||||
Most of these skills are user-invoked, which is why cognitive load is the pressure the whole system is built to manage: when user-invoked skills multiply past what you can hold in your head, the cure is a **router skill** that names the others and when to reach for each. Once you're thinking in these two loads, most authoring decisions — split or don't, inline or disclose, model- or user-invoked — become the same trade made in different places.
|
|
||||||
|
|
||||||
## The other levers
|
|
||||||
|
|
||||||
The rest of the reference is the toolkit for spending those loads well:
|
|
||||||
|
|
||||||
- **Leading words** — a compact concept already in the model's pretraining (_tight_, _red_, _tracer bullet_) that the agent thinks with while running the skill. It anchors execution *and* invocation in the fewest tokens; hunt restatements that a single word can retire.
|
|
||||||
- **Information hierarchy** — the ladder from in-skill step, to in-skill reference, to external reference behind a **context pointer**. **Progressive disclosure** is the move down that ladder so the top stays legible.
|
|
||||||
- **Pruning** — single source of truth, relevance, and the no-op test applied sentence by sentence, against **sediment** and **sprawl**.
|
|
||||||
- **Failure modes** — **premature completion**, **duplication**, **sediment**, **sprawl**, **no-op** — to diagnose a skill that isn't behaving.
|
|
||||||
|
|
||||||
## Where it fits
|
|
||||||
|
|
||||||
This is a reach-for-it-anytime standalone reference — the meta-skill you consult while building the rest of the set, not a step in a chain. Its natural neighbour is any router you maintain, because a router is the direct cure for the cognitive load that user-invoked skills pile up; when you're unsure which skill or flow fits a task, [ask-matt](https://aihero.dev/skills-ask-matt) routes you over the whole set.
|
|
||||||
@@ -8,7 +8,7 @@ set -euo pipefail
|
|||||||
# Links all skills in the repository into the local skill directories used by
|
# Links all skills in the repository into the local skill directories used by
|
||||||
# each agent harness:
|
# each agent harness:
|
||||||
# - ~/.claude/skills — Claude Code
|
# - ~/.claude/skills — Claude Code
|
||||||
# - ~/.agents/skills — pi and other Agent-Skills-standard harnesses
|
# - ~/.agents/skills — Codex and other Agent Skills-compatible harnesses
|
||||||
# Each entry is a symlink into this repo, so a `git pull` is all that's needed
|
# Each entry is a symlink into this repo, so a `git pull` is all that's needed
|
||||||
# to keep installed skills up to date.
|
# to keep installed skills up to date.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Design an Interface"
|
||||||
|
short_description: "Explore alternative module interfaces"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "QA"
|
||||||
|
short_description: "Conversational QA that files issues"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Request Refactor Plan"
|
||||||
|
short_description: "Plan a safe incremental refactor"
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Ubiquitous Language"
|
||||||
|
short_description: "Build a shared domain glossary"
|
||||||
|
policy:
|
||||||
|
allow_implicit_invocation: false
|
||||||
@@ -4,7 +4,7 @@ Skills I use daily for code work.
|
|||||||
|
|
||||||
## User-invoked
|
## User-invoked
|
||||||
|
|
||||||
Reachable only when you type them (`disable-model-invocation: true`).
|
Reachable only when you type them (Claude Code: `disable-model-invocation: true`; Codex: `policy.allow_implicit_invocation: false` in `agents/openai.yaml`).
|
||||||
|
|
||||||
- **[ask-matt](./ask-matt/SKILL.md)** — Ask which skill or flow fits your situation. A router over the user-invoked skills in this repo.
|
- **[ask-matt](./ask-matt/SKILL.md)** — Ask which skill or flow fits your situation. A router over the user-invoked skills in this repo.
|
||||||
- **[grill-with-docs](./grill-with-docs/SKILL.md)** — Grilling session that also builds your project's domain model, sharpening terminology and updating `CONTEXT.md` and ADRs inline.
|
- **[grill-with-docs](./grill-with-docs/SKILL.md)** — Grilling session that also builds your project's domain model, sharpening terminology and updating `CONTEXT.md` and ADRs inline.
|
||||||
@@ -13,7 +13,8 @@ Reachable only when you type them (`disable-model-invocation: true`).
|
|||||||
- **[setup-matt-pocock-skills](./setup-matt-pocock-skills/SKILL.md)** — Configure this repo for the engineering skills (issue tracker, triage labels, domain doc layout). Run once per repo.
|
- **[setup-matt-pocock-skills](./setup-matt-pocock-skills/SKILL.md)** — Configure this repo for the engineering skills (issue tracker, triage labels, domain doc layout). Run once per repo.
|
||||||
- **[to-spec](./to-spec/SKILL.md)** — Turn the current conversation into a spec and publish it to the issue tracker.
|
- **[to-spec](./to-spec/SKILL.md)** — Turn the current conversation into a spec and publish it to the issue tracker.
|
||||||
- **[to-tickets](./to-tickets/SKILL.md)** — Break any plan, spec, or conversation into a set of tracer-bullet tickets, each declaring its blocking edges — text in a local file, or native blocking links on a real tracker.
|
- **[to-tickets](./to-tickets/SKILL.md)** — Break any plan, spec, or conversation into a set of tracer-bullet tickets, each declaring its blocking edges — text in a local file, or native blocking links on a real tracker.
|
||||||
- **[wayfinder](./wayfinder/SKILL.md)** — Plan a huge chunk of work — more than one agent session can hold — as a shared map of investigation tickets on the issue tracker, resolved one at a time until the way to the destination is clear.
|
- **[implement](./implement/SKILL.md)** — Build the work described by a spec or set of tickets, driving `/tdd` at pre-agreed seams and closing out with `/code-review` before committing.
|
||||||
|
- **[wayfinder](./wayfinder/SKILL.md)** — Plan a huge chunk of work — more than one agent session can hold — as a shared map of decision tickets on the issue tracker, resolved one at a time until the way to the destination is clear.
|
||||||
|
|
||||||
## Model-invoked
|
## Model-invoked
|
||||||
|
|
||||||
@@ -27,3 +28,4 @@ Model- or user-reachable (rich trigger phrasing so the model can reach for them)
|
|||||||
- **[domain-modeling](./domain-modeling/SKILL.md)** — Actively build and sharpen a project's domain model — challenge terms, stress-test with scenarios, update `CONTEXT.md` and ADRs inline.
|
- **[domain-modeling](./domain-modeling/SKILL.md)** — Actively build and sharpen a project's domain model — challenge terms, stress-test with scenarios, update `CONTEXT.md` and ADRs inline.
|
||||||
- **[codebase-design](./codebase-design/SKILL.md)** — Shared discipline and vocabulary for designing deep modules: small interfaces, clean seams, testable through the interface.
|
- **[codebase-design](./codebase-design/SKILL.md)** — Shared discipline and vocabulary for designing deep modules: small interfaces, clean seams, testable through the interface.
|
||||||
- **[code-review](./code-review/SKILL.md)** — Two-axis review of the diff since a fixed point: **Standards** (does it follow the repo's coding standards, plus a Fowler smell baseline?) and **Spec** (does it faithfully implement the originating issue/PRD?), run as parallel sub-agents.
|
- **[code-review](./code-review/SKILL.md)** — Two-axis review of the diff since a fixed point: **Standards** (does it follow the repo's coding standards, plus a Fowler smell baseline?) and **Spec** (does it faithfully implement the originating issue/PRD?), run as parallel sub-agents.
|
||||||
|
- **[resolving-merge-conflicts](./resolving-merge-conflicts/SKILL.md)** — Work through an in-progress git merge or rebase conflict hunk by hunk, resolving by intent traced to each side's primary source, then finish the operation — never `--abort`.
|
||||||
|
|||||||
@@ -41,7 +41,9 @@ A starting situation that generates work, then merges onto the main flow.
|
|||||||
|
|
||||||
- **Something's broken** → **`/diagnosing-bugs`**. For the hard ones: the bug that resists a first glance, the intermittent flake, the regression that crept in between two known-good states. It refuses to theorise until it has a **tight feedback loop** — one command that already goes red on *this* bug — then fixes with a regression test. Its post-mortem hands off to **`/improve-codebase-architecture`** when the real finding is that there's no good seam to lock the bug down.
|
- **Something's broken** → **`/diagnosing-bugs`**. For the hard ones: the bug that resists a first glance, the intermittent flake, the regression that crept in between two known-good states. It refuses to theorise until it has a **tight feedback loop** — one command that already goes red on *this* bug — then fixes with a regression test. Its post-mortem hands off to **`/improve-codebase-architecture`** when the real finding is that there's no good seam to lock the bug down.
|
||||||
|
|
||||||
- **A huge, foggy effort — a greenfield project or a huge feature build, too big for one session** → **`/wayfinder`**. When the way from here to the destination isn't visible yet, it charts a **shared map** of investigation tickets on the issue tracker and resolves them one at a time — producing **decisions, not deliverables** — until the fog is pushed back and the way is clear. Then it merges onto the main flow at **`/to-spec`** (or, if the effort turned out small enough, straight to **`/implement`**). Where **`/grill-with-docs`** sharpens an idea you can hold in one session, wayfinder is for the idea you can't.
|
- **A huge, foggy effort — a greenfield project or a huge feature build, too big for one session** → **`/wayfinder`**, the most cognitively demanding flow here. When the way from here to the destination isn't visible yet, it charts a **shared map** of **decision tickets** on the issue tracker and resolves them one at a time — producing **decisions, not deliverables** — until the fog is pushed back and the way is clear. Where **`/grill-with-docs`** sharpens an idea you can hold in one session, wayfinder is for the idea you can't — and it's slower and denser, so save it for exactly that, never a well-scoped feature.
|
||||||
|
|
||||||
|
When the map clears, **it hands off, it doesn't build**: merge onto the main flow at **`/to-spec`**, which collapses the map's linked decisions into a buildable plan, then `/to-tickets` and `/implement` as usual. Looping the map straight into `/implement` skips that collapse and throws the linked detail away — go straight to `/implement` only when the effort turned out genuinely small.
|
||||||
|
|
||||||
## Codebase health
|
## Codebase health
|
||||||
|
|
||||||
@@ -68,8 +70,9 @@ Off the main flow entirely.
|
|||||||
- **`/grill-me`** — the same relentless interview as `/grill-with-docs`, but for when you have **no codebase**. Stateless: it saves nothing locally, builds no `CONTEXT.md`. Reach for it to sharpen any plan or design that doesn't live in a repo.
|
- **`/grill-me`** — the same relentless interview as `/grill-with-docs`, but for when you have **no codebase**. Stateless: it saves nothing locally, builds no `CONTEXT.md`. Reach for it to sharpen any plan or design that doesn't live in a repo.
|
||||||
- **`/prototype`** — a small, throwaway program that answers one design question: does this state model feel right, or what should this UI look like. Throwaway from day one — keep the answer, delete the code. It's the detour in step 2 of the main flow, but reach for it any time a design question is hard to settle on paper.
|
- **`/prototype`** — a small, throwaway program that answers one design question: does this state model feel right, or what should this UI look like. Throwaway from day one — keep the answer, delete the code. It's the detour in step 2 of the main flow, but reach for it any time a design question is hard to settle on paper.
|
||||||
- **`/research`** — delegate reading legwork to a **background agent**: it investigates a question against **primary sources**, then leaves a cited Markdown file in the repo. Keep working while it reads. The file it produces is something to take *into* the main flow at `/grill-with-docs` — research feeds the thinking, it doesn't replace it.
|
- **`/research`** — delegate reading legwork to a **background agent**: it investigates a question against **primary sources**, then leaves a cited Markdown file in the repo. Keep working while it reads. The file it produces is something to take *into* the main flow at `/grill-with-docs` — research feeds the thinking, it doesn't replace it.
|
||||||
|
- **`/to-questionnaire`** — when the thing blocking you isn't in your head or the codebase but in **someone else's**, this writes them a questionnaire to fill in. It's the inverse of `/grill-me`: instead of interviewing you about the subject, it interviews you about the **send** — who it's going to, what you need back — and aims the questions at the gap. What comes back is material for `/grill-with-docs` or `/to-spec`.
|
||||||
- **`/teach`** — learn a concept over multiple sessions, using the current directory as a stateful workspace.
|
- **`/teach`** — learn a concept over multiple sessions, using the current directory as a stateful workspace.
|
||||||
- **`/writing-great-skills`** — reference for writing and editing skills well.
|
- **`/writing-for-agents`** — reference for writing documents agents consume: skills, AGENTS.md, pointed-at docs.
|
||||||
|
|
||||||
## Precondition
|
## Precondition
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Ask Matt"
|
||||||
|
short_description: "Find the right skill or workflow"
|
||||||
|
policy:
|
||||||
|
allow_implicit_invocation: false
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Code Review"
|
||||||
|
short_description: "Review a diff on standards and spec"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Codebase Design"
|
||||||
|
short_description: "Vocabulary for deep-module design"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Diagnosing Bugs"
|
||||||
|
short_description: "Diagnose hard bugs and regressions"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Domain Modeling"
|
||||||
|
short_description: "Build and sharpen a domain model"
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Grill with Docs"
|
||||||
|
short_description: "Grill a design and write its docs"
|
||||||
|
policy:
|
||||||
|
allow_implicit_invocation: false
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Implement"
|
||||||
|
short_description: "Build work from a spec or tickets"
|
||||||
|
policy:
|
||||||
|
allow_implicit_invocation: false
|
||||||
@@ -61,7 +61,7 @@ Do NOT propose interfaces yet. After the file is written, ask the user: "Which o
|
|||||||
|
|
||||||
### 3. Grilling loop
|
### 3. Grilling loop
|
||||||
|
|
||||||
Once the user picks a candidate, run the `/grilling` skill to walk the design tree with them — constraints, dependencies, the shape of the deepened module, what sits behind the seam, what tests survive.
|
Once the user picks a candidate, run the `/grilling` skill to walk the decision tree with them — constraints, dependencies, the shape of the deepened module, what sits behind the seam, what tests survive.
|
||||||
|
|
||||||
Side effects happen inline as decisions crystallize — run the `/domain-modeling` skill to keep the domain model current as you go:
|
Side effects happen inline as decisions crystallize — run the `/domain-modeling` skill to keep the domain model current as you go:
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Improve Codebase Architecture"
|
||||||
|
short_description: "Find and grill architecture improvements"
|
||||||
|
policy:
|
||||||
|
allow_implicit_invocation: false
|
||||||
@@ -1,13 +1,15 @@
|
|||||||
# Logic Prototype
|
# Logic Prototype
|
||||||
|
|
||||||
A tiny interactive terminal app that lets the user drive a state model by hand. Use this when the question is about **business logic, state transitions, or data shape** — the kind of thing that looks reasonable on paper but only feels wrong once you push it through real cases.
|
A single, self-contained HTML file — a **shareable demo** — that lets anyone drive a state model by clicking buttons. Use this when the question is about **business logic, state transitions, or data shape** — the kind of thing that looks reasonable on paper but only feels wrong once you push it through real cases.
|
||||||
|
|
||||||
|
Because it's one file with nothing to install, you can hand it to a non-developer — a designer, a PM, a domain expert — and let them feel the model for themselves. So it speaks their language, not the code's.
|
||||||
|
|
||||||
## When this is the right shape
|
## When this is the right shape
|
||||||
|
|
||||||
- "I'm not sure if this state machine handles the edge case where X then Y."
|
- "I'm not sure if this state machine handles the edge case where X then Y."
|
||||||
- "Does this data model actually let me represent the case where..."
|
- "Does this data model actually let me represent the case where..."
|
||||||
- "I want to feel out what the API should look like before writing it."
|
- "I want to feel out what the API should look like before writing it."
|
||||||
- Anything where the user wants to **press buttons and watch state change**.
|
- Anything where someone wants to **press buttons and watch state change**.
|
||||||
|
|
||||||
If the question is "what should this look like" — wrong branch. Use [UI.md](UI.md).
|
If the question is "what should this look like" — wrong branch. Use [UI.md](UI.md).
|
||||||
|
|
||||||
@@ -15,17 +17,11 @@ If the question is "what should this look like" — wrong branch. Use [UI.md](UI
|
|||||||
|
|
||||||
### 1. State the question
|
### 1. State the question
|
||||||
|
|
||||||
Before writing code, write down what state model and what question you're prototyping. One paragraph, in the prototype's README or a comment at the top of the file. A logic prototype that answers the wrong question is pure waste — make the question explicit so it can be checked later, whether the user is watching now or returning to it AFK.
|
Before writing code, write down what state model and what question you're prototyping. One paragraph, at the top of the demo (in a visible intro, not just a comment). A logic prototype that answers the wrong question is pure waste — make the question explicit so it can be checked later, whether the user is watching now or returning to it AFK.
|
||||||
|
|
||||||
### 2. Pick the language
|
### 2. Isolate the logic in a portable module
|
||||||
|
|
||||||
Use whatever the host project uses. If the project has no obvious runtime (e.g. a docs repo), ask.
|
Put the actual logic — the bit that's answering the question — in a single `<script>` block written as a small, pure module that could be lifted out and dropped into the real codebase later. The page around it is throwaway; this module isn't.
|
||||||
|
|
||||||
Match the project's existing conventions for tooling — don't add a new package manager or runtime just for the prototype.
|
|
||||||
|
|
||||||
### 3. Isolate the logic in a portable module
|
|
||||||
|
|
||||||
Put the actual logic — the bit that's answering the question — behind a small, pure interface that could be lifted out and dropped into the real codebase later. The TUI around it is throwaway; the logic module shouldn't be.
|
|
||||||
|
|
||||||
The right shape depends on the question:
|
The right shape depends on the question:
|
||||||
|
|
||||||
@@ -34,46 +30,38 @@ The right shape depends on the question:
|
|||||||
- **A small set of pure functions** over a plain data type. Good when there's no implicit current state — just transformations.
|
- **A small set of pure functions** over a plain data type. Good when there's no implicit current state — just transformations.
|
||||||
- **A class or module with a clear method surface** when the logic genuinely owns ongoing internal state.
|
- **A class or module with a clear method surface** when the logic genuinely owns ongoing internal state.
|
||||||
|
|
||||||
Pick whichever shape best fits the question being asked, *not* whichever is easiest to wire to a TUI. Keep it pure: no I/O, no terminal code, no `console.log` for control flow. The TUI imports it and calls into it; nothing flows the other direction.
|
Pick whichever shape best fits the question being asked, *not* whichever is easiest to wire to a page. Keep it pure: no DOM, no `document`, no button handlers reaching inside it. The page calls into it; nothing flows the other direction. This is what makes the prototype useful past its own lifetime: once the question's answered, the validated reducer / machine / function set lifts into the real module on its own.
|
||||||
|
|
||||||
This is what makes the prototype useful past its own lifetime: when the question's been answered, the validated reducer / machine / function set can be lifted into the real module on its own.
|
### 3. Build the shareable HTML file
|
||||||
|
|
||||||
### 4. Build the smallest TUI that exposes the state
|
One file, plain HTML/CSS/JS — no framework, no bundler, no server, everything inline so it opens by double-click and survives being emailed around. Anyone should be able to run it by opening it.
|
||||||
|
|
||||||
Build it as a **lightweight TUI** — on every tick, clear the screen (`console.clear()` / `print("\033[2J\033[H")` / equivalent) and re-render the whole frame. The user should always see one stable view, not an ever-growing scrollback.
|
Write it for a non-developer. Every label is in **domain language**, not code — buttons and state read like the business, not the reducer. Explain in plain words what's happening.
|
||||||
|
|
||||||
Each frame has two parts, in this order:
|
Lay it out with a clean hierarchy, top to bottom:
|
||||||
|
|
||||||
1. **Current state**, pretty-printed and diff-friendly (one field per line, or formatted JSON). Use **bold** for field names or section headers and **dim** for less important context (timestamps, IDs, derived values). Native ANSI escape codes are fine — `\x1b[1m` bold, `\x1b[2m` dim, `\x1b[0m` reset. No need to pull in a styling library unless one is already in the project.
|
1. **Title and one-line explanation** of what this demo lets you explore (the question from step 1).
|
||||||
2. **Keyboard shortcuts**, listed at the bottom: `[a] add user [d] delete user [t] tick clock [q] quit`. Bold the key, dim the description, or vice-versa — whatever reads cleanly.
|
2. **Current state** — the full relevant state, rendered as a readable panel (labelled fields, not a raw JSON dump), re-rendered after every click so the change is visible. Where it helps a non-developer follow, call out what just changed.
|
||||||
|
3. **Free-play buttons** — one button per action, always available, so anyone can poke at the model in any order. Each click dispatches its action and re-renders the state.
|
||||||
|
4. **Guided walkthroughs** — a set of **scenarios**, one per tab. Each tab holds a short plain-language description of the scenario — the situation it sets up and what to watch for — and underneath it, the ordered **buttons to press** for that scenario. Each step is a real button: clicking it performs that action and moves to the next step. Starting a walkthrough resets to a known initial state so the scenario runs the same way every time.
|
||||||
|
|
||||||
Behaviour:
|
Choose scenarios that demonstrate the awkward cases — the happy path, a tricky edge case, an attempt at something that should be illegal — the ones hard to reason about on paper.
|
||||||
|
|
||||||
1. **Initialise state** — a single in-memory object/struct. Render the first frame on start.
|
Keep it beautiful but restrained: clean typography, generous spacing, one accent colour. No animations, no gimmicks — nothing that competes with the state and the buttons.
|
||||||
2. **Read one keystroke (or one line)** at a time, dispatch to a handler that mutates state.
|
|
||||||
3. **Re-render** the full frame after every action — don't append, replace.
|
|
||||||
4. **Loop until quit.**
|
|
||||||
|
|
||||||
The whole frame should fit on one screen.
|
### 4. Hand it over
|
||||||
|
|
||||||
### 5. Make it runnable in one command
|
Send them the file, or open it for them. They'll click through the walkthroughs and free-play whenever they get to it; the interesting moments are when they say "wait, that shouldn't be possible" or "huh, I assumed X would be different" — those are the bugs in the _idea_, which is the whole point. If they want new actions or a new scenario, add them. Prototypes evolve.
|
||||||
|
|
||||||
Add a script to the project's existing task runner (`package.json` scripts, `Makefile`, `justfile`, `pyproject.toml`). The user should run `pnpm run <prototype-name>` or equivalent — never need to remember a path.
|
### 5. Capture the answer and the prototype
|
||||||
|
|
||||||
If the host project has no task runner, just put the command at the top of the prototype's README.
|
Once the prototype has answered its question, capture the answer, then capture the prototype the way the [SKILL](SKILL.md) describes. The logic-specific mapping: the validated reducer / machine / function set lifts into the real module (the decision, absorbed); the HTML shell rides along to the throwaway branch that keeps the prototype as a primary source — and being one self-contained file, it stays trivially re-runnable there.
|
||||||
|
|
||||||
### 6. Hand it over
|
|
||||||
|
|
||||||
Give the user the run command. They'll drive it themselves; the interesting moments are when they say "wait, that shouldn't be possible" or "huh, I assumed X would be different" — those are the bugs in the _idea_, which is the whole point. If they want new actions added, add them. Prototypes evolve.
|
|
||||||
|
|
||||||
### 7. Capture the answer and the prototype
|
|
||||||
|
|
||||||
Once the prototype has answered its question, capture the answer, then capture the prototype the way the [SKILL](SKILL.md) describes. The logic-specific mapping: the validated reducer / machine / function set lifts into the real module (the decision, absorbed); the TUI shell rides along to the throwaway branch that keeps the prototype as a primary source.
|
|
||||||
|
|
||||||
## Anti-patterns
|
## Anti-patterns
|
||||||
|
|
||||||
- **Don't add tests.** A prototype that needs tests is no longer a prototype.
|
- **Don't add tests.** A prototype that needs tests is no longer a prototype.
|
||||||
- **Don't wire it to the real database.** Use an in-memory store unless the question is specifically about persistence.
|
- **Don't wire it to the real database.** Use in-memory state unless the question is specifically about persistence.
|
||||||
- **Don't generalise.** No "what if we wanted to support X later." The prototype answers one question.
|
- **Don't generalise.** No "what if we wanted to support X later." The prototype answers one question.
|
||||||
- **Don't blur the logic and the TUI together.** If the reducer / state machine references `console.log`, prompts, or terminal escape codes, it's no longer portable. Keep the TUI as a thin shell over a pure module.
|
- **Don't blur the logic and the page together.** If the pure module references the DOM, `document`, or button handlers, it's no longer liftable. Keep the page as a thin shell over a pure module.
|
||||||
- **Don't ship the TUI shell into production.** The shell is optimised for being driven by hand from a terminal. The logic module behind it is the bit worth keeping.
|
- **Don't reach for a framework, bundler, or server.** One file the recipient double-clicks; a React app or a dev server defeats "shareable".
|
||||||
|
- **Don't ship the HTML shell into production.** The page is optimised for being clicked through by hand. The logic module behind it is the bit worth keeping.
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ A prototype is **throwaway code that answers a question**. The question decides
|
|||||||
|
|
||||||
Identify which question is being answered — from the user's prompt, the surrounding code, or by asking if the user is around:
|
Identify which question is being answered — from the user's prompt, the surrounding code, or by asking if the user is around:
|
||||||
|
|
||||||
- **"Does this logic / state model feel right?"** → [LOGIC.md](LOGIC.md). Build a tiny interactive terminal app that pushes the state machine through cases that are hard to reason about on paper.
|
- **"Does this logic / state model feel right?"** → [LOGIC.md](LOGIC.md). Build a single shareable HTML file — free-play buttons plus tabbed guided walkthroughs — that pushes the state machine through cases that are hard to reason about on paper, and that a non-developer can drive.
|
||||||
- **"What should this look like?"** → [UI.md](UI.md). Generate several radically different UI variations on a single route, switchable via a URL search param and a floating bottom bar.
|
- **"What should this look like?"** → [UI.md](UI.md). Generate several radically different UI variations on a single route, switchable via a URL search param and a floating bottom bar.
|
||||||
|
|
||||||
The two branches produce very different artifacts — getting this wrong wastes the whole prototype. If the question is genuinely ambiguous and the user isn't reachable, default to whichever branch better matches the surrounding code (a backend module → logic; a page or component → UI) and state the assumption at the top of the prototype.
|
The two branches produce very different artifacts — getting this wrong wastes the whole prototype. If the question is genuinely ambiguous and the user isn't reachable, default to whichever branch better matches the surrounding code (a backend module → logic; a page or component → UI) and state the assumption at the top of the prototype.
|
||||||
@@ -19,7 +19,7 @@ The two branches produce very different artifacts — getting this wrong wastes
|
|||||||
## Rules that apply to both
|
## Rules that apply to both
|
||||||
|
|
||||||
1. **Throwaway from day one, and clearly marked as such.** Locate the prototype code close to where it will actually be used (next to the module or page it's prototyping for) so context is obvious — but name it so a casual reader can see it's a prototype, not production. For throwaway UI routes, obey whatever routing convention the project already uses; don't invent a new top-level structure.
|
1. **Throwaway from day one, and clearly marked as such.** Locate the prototype code close to where it will actually be used (next to the module or page it's prototyping for) so context is obvious — but name it so a casual reader can see it's a prototype, not production. For throwaway UI routes, obey whatever routing convention the project already uses; don't invent a new top-level structure.
|
||||||
2. **One command to run.** Whatever the project's existing task runner supports — `pnpm <name>`, `python <path>`, `bun <path>`, etc. The user must be able to start it without thinking.
|
2. **Trivial to run.** A UI prototype starts from one command in the project's task runner — `pnpm <name>`, `python <path>`, `bun <path>`, etc. A logic demo is a single HTML file the user double-clicks. Either way, no thinking required to start it.
|
||||||
3. **No persistence by default.** State lives in memory. Persistence is the thing the prototype is _checking_, not something it should depend on. If the question explicitly involves a database, hit a scratch DB or a local file with a clear "PROTOTYPE — wipe me" name.
|
3. **No persistence by default.** State lives in memory. Persistence is the thing the prototype is _checking_, not something it should depend on. If the question explicitly involves a database, hit a scratch DB or a local file with a clear "PROTOTYPE — wipe me" name.
|
||||||
4. **Skip the polish.** No tests, no error handling beyond what makes the prototype _runnable_, no abstractions. The point is to learn something fast.
|
4. **Skip the polish.** No tests, no error handling beyond what makes the prototype _runnable_, no abstractions. The point is to learn something fast.
|
||||||
5. **Surface the state.** After every action (logic) or on every variant switch (UI), print or render the full relevant state so the user can see what changed.
|
5. **Surface the state.** After every action (logic) or on every variant switch (UI), print or render the full relevant state so the user can see what changed.
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Prototype"
|
||||||
|
short_description: "Prototype to answer a design question"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Research"
|
||||||
|
short_description: "Research from high-trust sources"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Resolving Merge Conflicts"
|
||||||
|
short_description: "Resolve merge and rebase conflicts"
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Setup Matt Pocock Skills"
|
||||||
|
short_description: "Configure a repo for the skills"
|
||||||
|
policy:
|
||||||
|
allow_implicit_invocation: false
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "TDD"
|
||||||
|
short_description: "Test-driven red-green-refactor"
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "To Spec"
|
||||||
|
short_description: "Turn a conversation into a spec"
|
||||||
|
policy:
|
||||||
|
allow_implicit_invocation: false
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "To Tickets"
|
||||||
|
short_description: "Split a plan into tracer-bullet tickets"
|
||||||
|
policy:
|
||||||
|
allow_implicit_invocation: false
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Triage"
|
||||||
|
short_description: "Move issues through triage roles"
|
||||||
|
policy:
|
||||||
|
allow_implicit_invocation: false
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
---
|
---
|
||||||
name: wayfinder
|
name: wayfinder
|
||||||
description: Plan a huge chunk of work — more than one agent session can hold — as a shared map of investigation tickets on your issue tracker, and resolve them one at a time until the way to the destination is clear.
|
description: Plan a huge chunk of work — more than one agent session can hold — as a shared map of decision tickets on your issue tracker, and resolve them one at a time until the way to the destination is clear.
|
||||||
disable-model-invocation: true
|
disable-model-invocation: true
|
||||||
---
|
---
|
||||||
|
|
||||||
A loose idea has arrived — too big for one agent session, and wrapped in fog: the way from here to the **destination** isn't visible yet. Wayfinding is about finding that way, not charging at the destination. This skill charts the way as a **shared map** on the repo's issue tracker, then works its tickets one at a time until the route is clear.
|
A loose idea has arrived — too big for one agent session, and wrapped in fog: the way from here to the **destination** isn't visible yet. Wayfinding is about finding that way, not charging at the destination. This skill charts the way as a **shared map** on the repo's issue tracker, then works its **decision tickets** — questions whose resolution is a decision, not slices of a build to execute — one at a time until the route is clear.
|
||||||
|
|
||||||
The destination varies per effort, and naming it is the first act of charting — it shapes every ticket. It might be a spec to hand off and iterate on, a decision to lock before planning starts, or a change made in place like a data-structure migration. The map is domain-agnostic — engineering work, course content, whatever fits the shape.
|
The destination varies per effort, and naming it is the first act of charting — it shapes every ticket. It might be a spec to hand off and iterate on, a decision to lock before planning starts, or a change made in place like a data-structure migration. The map is domain-agnostic — engineering work, course content, whatever fits the shape.
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ The answer isn't part of the body — it's recorded on resolution (see [Work thr
|
|||||||
|
|
||||||
Every ticket is either **HITL** — human in the loop, worked *with* a human who speaks for themselves — or **AFK**, driven by the agent alone. A HITL ticket only resolves through that live exchange; the agent never stands in for the human's side of it (a grilling agent that answers its own questions has broken this).
|
Every ticket is either **HITL** — human in the loop, worked *with* a human who speaks for themselves — or **AFK**, driven by the agent alone. A HITL ticket only resolves through that live exchange; the agent never stands in for the human's side of it (a grilling agent that answers its own questions has broken this).
|
||||||
|
|
||||||
- **Research** (AFK): Reading documentation, third-party APIs, or local resources like knowledge bases. Creates a markdown summary as a linked asset. Use when knowledge outside the current working directory is required.
|
- **Research** (AFK): Reading documentation, third-party APIs, or local resources like knowledge bases to surface a fact a decision waits on. Resolved by a `/research` **subagent**. Use when knowledge outside the current working directory is required.
|
||||||
- **Prototype** (HITL): Raise the fidelity of the discussion by making a cheap, rough, concrete artifact to react to — an outline, a rough take, a stub, or UI/logic code via the /prototype skill. Links the prototype as an asset. Use when "how should it look" or "how should it behave" is the key question.
|
- **Prototype** (HITL): Raise the fidelity of the discussion by making a cheap, rough, concrete artifact to react to — an outline, a rough take, a stub, or UI/logic code via the /prototype skill. Links the prototype as an asset. Use when "how should it look" or "how should it behave" is the key question.
|
||||||
- **Grilling** (HITL): Conversation via the /grilling and /domain-modeling skills, one question at a time. The default case.
|
- **Grilling** (HITL): Conversation via the /grilling and /domain-modeling skills, one question at a time. The default case.
|
||||||
- **Task** (HITL or AFK): Manual work that must happen before a *decision* can be made — nothing to decide, prototype, or research, but the discussion is blocked until it's done. Signing up for a service so its API can be judged, provisioning access, moving data so its shape can be seen. This is the one type that *does* rather than decides — and it earns its place by unblocking a decision, not by delivering the destination. The agent drives it alone where it can (AFK); otherwise it hands the human a precise checklist (HITL). Resolved when the work is done; the answer records what was done and any resulting facts (credentials location, new URLs, row counts) later tickets depend on.
|
- **Task** (HITL or AFK): Manual work that must happen before a *decision* can be made — nothing to decide, prototype, or research, but the discussion is blocked until it's done. Signing up for a service so its API can be judged, provisioning access, moving data so its shape can be seen. This is the one type that *does* rather than decides — and it earns its place by unblocking a decision, not by delivering the destination. The agent drives it alone where it can (AFK); otherwise it hands the human a precise checklist (HITL). Resolved when the work is done; the answer records what was done and any resulting facts (credentials location, new URLs, row counts) later tickets depend on.
|
||||||
@@ -102,7 +102,7 @@ Ruling something out of scope is a scoping act, not a step on the route. When a
|
|||||||
|
|
||||||
## Invocation
|
## Invocation
|
||||||
|
|
||||||
Two modes. Either way, **never resolve more than one ticket per session.**
|
Two modes. Either way, **never resolve more than one ticket per session** — with the exception of research tickets.
|
||||||
|
|
||||||
### Chart the map
|
### Chart the map
|
||||||
|
|
||||||
@@ -112,7 +112,8 @@ User invokes with a loose idea.
|
|||||||
2. **Map the frontier.** Grill again, **breadth-first** this time: fan out across the whole space rather than deep on any one thread, surfacing the open decisions and the first steps takeable now. **If this surfaces no fog** — the way to the destination is already clear, the whole journey small enough for one session — you don't need a map. Stop and ask the user how they'd like to proceed.
|
2. **Map the frontier.** Grill again, **breadth-first** this time: fan out across the whole space rather than deep on any one thread, surfacing the open decisions and the first steps takeable now. **If this surfaces no fog** — the way to the destination is already clear, the whole journey small enough for one session — you don't need a map. Stop and ask the user how they'd like to proceed.
|
||||||
3. **Create the map** (label `wayfinder:map`): Destination and Notes filled in, Decisions-so-far empty, the fog sketched into **Not yet specified**.
|
3. **Create the map** (label `wayfinder:map`): Destination and Notes filled in, Decisions-so-far empty, the fog sketched into **Not yet specified**.
|
||||||
4. **Create the tickets you can specify now** as child issues of the map — then wire blocking edges in a **second pass** (issues need ids before they can reference each other). Wiring sorts them into the frontier and the blocked; everything you can't yet specify stays in the fog — the **Not yet specified** section.
|
4. **Create the tickets you can specify now** as child issues of the map — then wire blocking edges in a **second pass** (issues need ids before they can reference each other). Wiring sorts them into the frontier and the blocked; everything you can't yet specify stays in the fog — the **Not yet specified** section.
|
||||||
5. Stop — charting the map is one session's work; do not also resolve tickets.
|
5. **Fire the research subagents.** For each `research` ticket you just created, spin up a `/research` subagent to resolve it in parallel, capturing its findings on a throwaway `research/<name>` branch with a context pointer from the ticket.
|
||||||
|
6. Stop — charting is one session's work; it hand-resolves nothing.
|
||||||
|
|
||||||
### Work through the map
|
### Work through the map
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Wayfinder"
|
||||||
|
short_description: "Map a large effort as decision tickets"
|
||||||
|
policy:
|
||||||
|
allow_implicit_invocation: false
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Claude Handoff"
|
||||||
|
short_description: "Hand off to a background agent"
|
||||||
|
policy:
|
||||||
|
allow_implicit_invocation: false
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Loop Me"
|
||||||
|
short_description: "Spec the workflows you want to build"
|
||||||
|
policy:
|
||||||
|
allow_implicit_invocation: false
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Setup TS Deep Modules"
|
||||||
|
short_description: "Enforce deep TypeScript modules"
|
||||||
|
policy:
|
||||||
|
allow_implicit_invocation: false
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Wizard"
|
||||||
|
short_description: "Generate an interactive setup wizard"
|
||||||
|
policy:
|
||||||
|
allow_implicit_invocation: false
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Writing Beats"
|
||||||
|
short_description: "Assemble raw material into beats"
|
||||||
|
policy:
|
||||||
|
allow_implicit_invocation: false
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Writing Fragments"
|
||||||
|
short_description: "Mine raw writing fragments"
|
||||||
|
policy:
|
||||||
|
allow_implicit_invocation: false
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Writing Shape"
|
||||||
|
short_description: "Shape raw material into an article"
|
||||||
|
policy:
|
||||||
|
allow_implicit_invocation: false
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Git Guardrails for Claude Code"
|
||||||
|
short_description: "Block dangerous git commands"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Migrate to Shoehorn"
|
||||||
|
short_description: "Replace test assertions with shoehorn"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Scaffold Exercises"
|
||||||
|
short_description: "Scaffold lint-ready course exercises"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Setup Pre-Commit"
|
||||||
|
short_description: "Add pre-commit quality checks"
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Edit Article"
|
||||||
|
short_description: "Restructure and tighten a draft"
|
||||||
|
policy:
|
||||||
|
allow_implicit_invocation: false
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Obsidian Vault"
|
||||||
|
short_description: "Manage linked notes in Obsidian"
|
||||||
@@ -4,15 +4,16 @@ General workflow tools, not code-specific.
|
|||||||
|
|
||||||
## User-invoked
|
## User-invoked
|
||||||
|
|
||||||
Reachable only when you type them (`disable-model-invocation: true`).
|
Reachable only when you type them (Claude Code: `disable-model-invocation: true`; Codex: `policy.allow_implicit_invocation: false` in `agents/openai.yaml`).
|
||||||
|
|
||||||
- **[grill-me](./grill-me/SKILL.md)** — Get relentlessly interviewed about a plan or design until every branch of the decision tree is resolved.
|
- **[grill-me](./grill-me/SKILL.md)** — Get relentlessly interviewed about a plan or design until every branch of the decision tree is resolved.
|
||||||
- **[handoff](./handoff/SKILL.md)** — Compact the current conversation into a handoff document so another agent can continue the work.
|
- **[handoff](./handoff/SKILL.md)** — Compact the current conversation into a handoff document so another agent can continue the work.
|
||||||
- **[teach](./teach/SKILL.md)** — Teach the user a new skill or concept over multiple sessions, using the current directory as a stateful teaching workspace.
|
- **[teach](./teach/SKILL.md)** — Teach the user a new skill or concept over multiple sessions, using the current directory as a stateful teaching workspace.
|
||||||
- **[writing-great-skills](./writing-great-skills/SKILL.md)** — Reference for writing and editing skills well: the vocabulary and principles that make a skill predictable.
|
- **[to-questionnaire](./to-questionnaire/SKILL.md)** — Turn a decision you can't answer alone into a Markdown questionnaire for the one person who can — filled in async, or together over a meeting.
|
||||||
|
- **[writing-for-agents](./writing-for-agents/SKILL.md)** — Writing documents for agents: skills, AGENTS.md/CLAUDE.md, and any doc an agent reaches by a pointer.
|
||||||
|
|
||||||
## Model-invoked
|
## Model-invoked
|
||||||
|
|
||||||
Model- or user-reachable (rich trigger phrasing so the model can reach for them).
|
Model- or user-reachable (rich trigger phrasing so the model can reach for them).
|
||||||
|
|
||||||
- **[grilling](./grilling/SKILL.md)** — Interview the user relentlessly about a plan or design until every branch of the decision tree is resolved.
|
- **[grilling](./grilling/SKILL.md)** — Interview the user relentlessly about a plan, decision, or idea until every branch of the decision tree is resolved.
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Grill Me"
|
||||||
|
short_description: "Sharpen a plan through interview"
|
||||||
|
policy:
|
||||||
|
allow_implicit_invocation: false
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
---
|
---
|
||||||
name: grilling
|
name: grilling
|
||||||
description: Grill the user relentlessly about a plan or design. Use when the user wants to stress-test a plan before building, or uses any 'grill' trigger phrases.
|
description: Grill the user relentlessly about a plan, decision, or idea. Use when the user wants to stress-test their thinking, or uses any 'grill' trigger phrases.
|
||||||
---
|
---
|
||||||
|
|
||||||
Interview me relentlessly about every aspect of this plan until we reach a shared understanding. Walk down each branch of the design tree, resolving dependencies between decisions one-by-one. For each question, provide your recommended answer.
|
Interview the user relentlessly until you reach a shared understanding. Map this as a **design tree**: every decision branches into the decisions that hang off it.
|
||||||
|
|
||||||
Ask the questions one at a time, waiting for feedback on each question before continuing. Asking multiple questions at once is bewildering.
|
Work the tree in **rounds**. The **frontier** is every decision whose prerequisites are already settled — the questions you can ask _now_ without guessing at answers you haven't heard yet. Ask the whole frontier in one round: number each question and give your recommended answer. Then wait for the user's answers before the next round.
|
||||||
|
|
||||||
If a *fact* can be found by exploring the codebase, look it up rather than asking me. The *decisions*, though, are mine — put each one to me and wait for my answer.
|
Each round the user answers reshapes the tree — settled decisions push the frontier outward and unblock questions that depended on them. Recompute the frontier and ask the next round. A question whose answer depends on another question still open in this round belongs to a _later_ round, not this one.
|
||||||
|
|
||||||
Do not enact the plan until I confirm we have reached a shared understanding.
|
Finding _facts_ is your job, never the user's. When a frontier question needs a fact from the environment (filesystem, tools, etc.), dispatch a sub-agent to find it — don't ask the user for anything you could look up yourself. Don't block on it: a running exploration is an unsettled prerequisite, so only the questions downstream of it wait for the sub-agent to report — ask the rest of the frontier now. The _decisions_ are the user's — put each to them and wait.
|
||||||
|
|
||||||
|
The session is done when the frontier is empty: every branch of the design tree visited, nothing left silently assumed. Do not act on it until the user confirms you have reached a shared understanding.
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Grilling"
|
||||||
|
short_description: "Stress-test thinking one question at a time"
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Handoff"
|
||||||
|
short_description: "Compact a conversation into a handoff"
|
||||||
|
policy:
|
||||||
|
allow_implicit_invocation: false
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Teach"
|
||||||
|
short_description: "Learn a concept in a guided workspace"
|
||||||
|
policy:
|
||||||
|
allow_implicit_invocation: false
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
---
|
||||||
|
name: to-questionnaire
|
||||||
|
description: Turn a decision you can't fully answer into a questionnaire for someone else to fill in.
|
||||||
|
disable-model-invocation: true
|
||||||
|
---
|
||||||
|
|
||||||
|
Turn something the user can't answer alone into a **questionnaire** — a Markdown document they hand to one person to fill in async, or fill out together over a meeting. The recipient holds knowledge the user lacks; the questionnaire pulls it out of them.
|
||||||
|
|
||||||
|
**Grill the send, not the subject.** Interview the user only about the _send_, which they can always answer: who it goes to, and what they need back. The questions in the document then target the **gap** between what the recipient knows and what the user needs.
|
||||||
|
|
||||||
|
1. **Who is it going to?** Ask, in one exchange, the recipient's role, expertise, and relationship to the user. This fixes the questionnaire's tone and how much context it must carry. Done when you know who the recipient is and what they know that the user doesn't.
|
||||||
|
|
||||||
|
2. **What do you need back?** Ask, in one exchange, the specific decisions or facts the user can't resolve alone and needs from this person. Done when you have a concrete list of what the user must walk away able to do or decide.
|
||||||
|
|
||||||
|
3. **Write the questionnaire.** Draft questions aimed at the gap from steps 1–2, following the Document structure below. Write it to `to-questionnaire-<slug>.md` in the current directory (slug from the topic) and report the path. Done when the file exists and every item the user named in step 2 is covered by a question.
|
||||||
|
|
||||||
|
## Document structure
|
||||||
|
|
||||||
|
Frame the document as a **discovery questionnaire**: the user lacks context, the recipient holds it. Order questions most-important-first — async means you may only get one pass — and group them under `##` headings by theme once there are more than a handful. Write it using the template below.
|
||||||
|
|
||||||
|
<questionnaire-template>
|
||||||
|
|
||||||
|
# <Questionnaire title>
|
||||||
|
|
||||||
|
**Purpose:** why this questionnaire exists and the decision riding on it.
|
||||||
|
|
||||||
|
**From:** <the user> — **To:** <the recipient> — **How your answers will be used:** <where they go>
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
One paragraph orienting a recipient who wasn't in the user's head. Enough to answer well, not a page.
|
||||||
|
|
||||||
|
## How to answer
|
||||||
|
|
||||||
|
Deadline and rough effort. Partial answers and "I don't know" are useful — flag anything you're unsure of rather than skipping it.
|
||||||
|
|
||||||
|
## <Theme heading>
|
||||||
|
|
||||||
|
One `##` section per theme. Under each, its questions, most-important-first. Every question is one idea — never compound — with an answer stub directly beneath, and a one-line _why this matters_ only where the question could be misread or invite a throwaway answer.
|
||||||
|
|
||||||
|
<question-example>
|
||||||
|
### What load is the system expected to handle at launch?
|
||||||
|
|
||||||
|
_Why this matters: it decides whether we provision for burst traffic now or defer it._
|
||||||
|
|
||||||
|
>
|
||||||
|
</question-example>
|
||||||
|
|
||||||
|
## Anything else?
|
||||||
|
|
||||||
|
A closing catch-all: anything we didn't ask that we should know?
|
||||||
|
|
||||||
|
</questionnaire-template>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "To Questionnaire"
|
||||||
|
short_description: "Front-load questions into a doc for someone to answer"
|
||||||
|
policy:
|
||||||
|
allow_implicit_invocation: false
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# Skill mechanics
|
||||||
|
|
||||||
|
The skill-specific branch of [`writing-for-agents`](SKILL.md): what changes when the document is a skill — frontmatter, the invocation choice, and router skills. Everything else about writing it is the universal reference in `SKILL.md`.
|
||||||
|
|
||||||
|
## Invocation
|
||||||
|
|
||||||
|
Two choices, trading the two loads:
|
||||||
|
|
||||||
|
- A **model-invoked** skill keeps a `description`, so the agent can fire it autonomously — and other skills can reach it. You can still type its name: model-invocation always _includes_ user reach; a description only ever adds agent discovery, never removes the human's. The description is the skill's top-level context pointer, forced to stay loaded at all times — permanent context load in exchange for discoverability. A model-invoked skill whose content is all reference is also one home for shared reference: another skill can invoke it, so reference needed by several skills lives in one place. Mechanics: omit `disable-model-invocation`, and write a model-facing description carrying the trigger branches (the pointer-writing rules in `SKILL.md` apply in full).
|
||||||
|
- A **user-invoked** skill strips the description from the agent's reach: only the human typing its name can invoke it, and no other skill can. Zero context load, but it spends cognitive load — you are the index that must remember it exists. Mechanics: set `disable-model-invocation: true`; the `description` becomes human-facing — a one-line summary, trigger lists stripped.
|
||||||
|
|
||||||
|
Pick model-invocation only when the agent must reach the skill on its own, or another skill must. If it only ever fires by hand, make it user-invoked and pay no context load.
|
||||||
|
|
||||||
|
Shared reference that two user-invoked skills both need can live in neither — with no descriptions, neither can fire the other. Push it to a plain file outside the skill system: external reference any skill can point at.
|
||||||
|
|
||||||
|
## Splitting by invocation
|
||||||
|
|
||||||
|
The invocation cut of splitting (the sequence cut lives in `SKILL.md`): split off a model-invoked skill when you have a distinct leading word that should trigger it on its own — a trigger word you actually use in your prompts — or another skill must reach it. You pay context load for the new always-loaded description, so that independent reach has to be worth it.
|
||||||
|
|
||||||
|
## Router skills
|
||||||
|
|
||||||
|
When user-invoked skills multiply past what you can remember, that piled-up cognitive load is cured by a **router skill**: one user-invoked skill that names the others and when to reach for each, so the human has one skill to remember instead of many. It can only hint, never fire them: user-invoked skills have no description, so nothing but the human can reach them.
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
---
|
||||||
|
name: writing-for-agents
|
||||||
|
description: Writing documents for agents. Use when creating or editing skills, or modifying AGENTS.md or CLAUDE.md.
|
||||||
|
---
|
||||||
|
|
||||||
|
Reference for writing any document an agent consumes — a skill, an `AGENTS.md` / `CLAUDE.md`, a doc reached by a pointer. The packaging differs; the writing does not: the same levers make each one predictable — the agent taking the same _process_ every run, not producing the same output.
|
||||||
|
|
||||||
|
When the document you're writing is a skill, read [`SKILL-MECHANICS.md`](SKILL-MECHANICS.md) for frontmatter, invocation choice, and router skills.
|
||||||
|
|
||||||
|
## Context pointers
|
||||||
|
|
||||||
|
A **context pointer** is a reference held in the agent's context that names some out-of-context material and encodes the condition for reaching it. A skill's description is one; a line in `AGENTS.md` naming a doc is the same object. The pointer's _wording_, not its target, decides when the agent reaches the material — and how reliably. A must-have target behind a weakly worded pointer is a variance bug: sharpen the wording first, and inline the material only if sharpening fails.
|
||||||
|
|
||||||
|
A pointer does two jobs — state what the material is, and list the **branches** that should trigger reaching it (a branch is a distinct case the document handles, so different runs take different paths through it). Every word of an always-loaded pointer costs on every turn, so it earns even harder pruning than the body:
|
||||||
|
|
||||||
|
- **Front-load the leading word** — the pointer is where it does its triggering work.
|
||||||
|
- **One trigger per branch.** Synonyms that rename a single branch are one branch written twice; collapse them and keep only genuinely distinct branches.
|
||||||
|
- **Cut identity the body already carries.**
|
||||||
|
|
||||||
|
## The two loads
|
||||||
|
|
||||||
|
Every document and pointer you add spends one of two budgets:
|
||||||
|
|
||||||
|
- **Context load** — the cost of always-loaded material on the agent's window: an `AGENTS.md` line, a skill description, anything sitting in context every turn, spending tokens and attention whether or not it fires.
|
||||||
|
- **Cognitive load** — the cost on the human: which documents exist and when to reach for each. The human is the index. Not a cost to minimise — it is the price of human agency; spend it where human judgement matters, remove it where it does not.
|
||||||
|
|
||||||
|
Material reached only through a pointer escapes context load at the price of the pointer's own line; material with no pointer at all rides entirely on cognitive load.
|
||||||
|
|
||||||
|
## Information hierarchy
|
||||||
|
|
||||||
|
A document is built from two content types — **steps** (the ordered actions the agent performs) and **reference** (definitions, rules, facts consulted on demand) — that mix freely: all steps (a recipe), all reference (a review's rules, this skill), or both. The core decision is where each piece sits on the **information hierarchy**, a ladder ranked by how immediately the agent needs the material:
|
||||||
|
|
||||||
|
1. **In-file step** — the primary tier: what the agent does, in order.
|
||||||
|
2. **In-file reference** — consulted on demand. Often a legitimately flat peer-set (every rule of a review on one rung) — a fine arrangement, not a smell.
|
||||||
|
3. **Disclosed reference** — pushed out into a separate file, reached by a context pointer, loaded only when the pointer fires. Spans a sibling file in the same folder through fully external reference that lives anywhere and any document can point at.
|
||||||
|
|
||||||
|
Push too little down and the top bloats; push too much and you hide material the agent actually needs. That tension is the whole decision.
|
||||||
|
|
||||||
|
**Progressive disclosure** is the move down the ladder — out of the main file and behind a pointer — so the top stays legible. Not primarily a token optimisation: it is how the hierarchy is protected. Branching is the cleanest disclosure test: inline what every branch needs, and push behind a pointer what only some branches reach. When a document has steps, in-file reference that should be disclosed buries them and turns attending to them into a coin-flip — a variance lever, not just a legibility one.
|
||||||
|
|
||||||
|
**Co-location** is the within-file companion: where the ladder decides _how far down_ a piece sits, co-location decides _what sits beside it_ once there. Keep a concept's definition, rules, and caveats under one heading rather than scattered, so reading one part brings its neighbours with it. The test: the document should read like documentation written for the agent — grouped material reads that way; scattered material does not. (Distinct from duplication: that repeats one meaning in two places; scattering fragments one meaning across many.)
|
||||||
|
|
||||||
|
**Sprawl** is the failure mode here: a document simply too long, even when every line is live and unique. Attention thins across the excess, and every extra line is one more to keep relevant. The cure is the ladder: disclose reference behind pointers, and split by branch or sequence so each path carries only what it needs.
|
||||||
|
|
||||||
|
## Steps and completion criteria
|
||||||
|
|
||||||
|
Every step ends on a **completion criterion** — the condition that tells the agent the work is done. Two properties make it a lever:
|
||||||
|
|
||||||
|
- **Clarity** — can the agent tell done from not-done? A vague bound ("understanding reached") invites **premature completion**: ending the step before it is genuinely done, attention slipping to _being done_. The visible steps still ahead — the **post-completion steps** — supply the pull; the criterion's clarity is the resistance. Defend in order: **sharpen the bound first** (local and cheap); only if it is irreducibly fuzzy _and_ you observe the rush, hide the later steps by splitting the sequence — and hiding only works across a real context boundary (a hand-off or a subagent dispatch; an inline call leaves the later steps in context and clears nothing).
|
||||||
|
- **Demand** — how much it requires. "Every modified model accounted for" forces thorough work where "produce a change list" does not. Demand drives **legwork** — the digging the agent does within the work, latent in the wording rather than written as its own step — and it is not step-bound: "every rule applied" binds a body of flat reference just as "every step done" binds a sequence, which is how an all-reference document still carries an exhaustiveness bar.
|
||||||
|
|
||||||
|
The strongest criteria are both checkable and exhaustive.
|
||||||
|
|
||||||
|
## When to split
|
||||||
|
|
||||||
|
Splitting one document into two spends one of the two loads, so split only when the cut earns it:
|
||||||
|
|
||||||
|
- **By sequence** — split a run of steps where the post-completion steps tempt the agent to rush the one in front of it. Keeping them out of view drives more legwork on the current task. Beware the reverse: merging sequences exposes each step's later steps to what follows, inviting premature completion.
|
||||||
|
- **By invocation** — skill-specific: see [`SKILL-MECHANICS.md`](SKILL-MECHANICS.md).
|
||||||
|
|
||||||
|
## Leading words
|
||||||
|
|
||||||
|
A **leading word** is a compact concept already living in the model's pretraining that the agent thinks with while running the document (_lesson_, _fog of war_, _tracer bullets_). Repeated as a token, never as a sentence, it accumulates a distributed definition and anchors a whole region of behaviour in the fewest tokens, by recruiting priors the model already holds. Coining your own works if you define it clearly, but a made-up word recruits no priors — you pay in definition tokens what a pretrained word gives free; reach for an existing word first.
|
||||||
|
|
||||||
|
It anchors twice. In the body, _execution_: the agent reaches for the same behaviour every time the word appears, and inside flat reference it focuses attention on a class of thing to look for. In a pointer, _invocation_: when the same word lives in your prompts, your docs, and your codebase, the agent links that shared language to the material and reaches it more reliably.
|
||||||
|
|
||||||
|
Hunt for opportunities to refactor with leading words. A triad spelled out at three sites, a pointer spending a sentence to gesture at one idea — each is a passage begging to collapse into a single token:
|
||||||
|
|
||||||
|
- "fast, deterministic, low-overhead" → _tight_ (a _tight_ loop).
|
||||||
|
- "a loop you believe in" → _red_ — a fuzzy gate becomes a binary observable state (the loop goes _red_ on the bug, or it doesn't).
|
||||||
|
|
||||||
|
You win twice: fewer tokens, and a sharper hook for the agent to hang its thinking on. Assume every document is carrying restatements that leading words retire — go find them.
|
||||||
|
|
||||||
|
**Negation** is the failure mode beside this lever: steering by prohibition drags the forbidden behaviour into context and makes it _more_ available, not less. _Don't think of an elephant_, and the elephant is all there is; the negation is a weak modifier the strongly-activated concept overruns, so the ban half-reads as an instruction to do the thing. Prompt the **positive** — state the target behaviour ("write one-line comments") so the banned one is never spoken. A prohibition earns its place only as a hard guardrail you cannot phrase positively; even then, pair it with the positive target so attention lands on what to do.
|
||||||
|
|
||||||
|
## Pruning
|
||||||
|
|
||||||
|
- Keep each meaning in a **single source of truth**: one authoritative place, so changing the behaviour is a one-place edit. **Duplication** — the same meaning in more than one place — costs maintenance and tokens, and inflates a meaning's prominence on the ladder past its real rank. (The accidental inverse of a leading word, which repeats a token on purpose, never the meaning.)
|
||||||
|
- The **environment** is a source of truth too — `package.json` scripts, config files, the directory layout, `--help` output — and a document that restates it is a **cache**: a copy of a lookup, earning its load only when the lookup is expensive. Cache what the agent cannot find by looking: the unwritten convention, the reason behind a choice, the gotcha no config confesses. Leave the one-file, one-command lookups to the environment, where they cannot go stale.
|
||||||
|
- Check every line for **relevance**: does it still bear on what the document does? A line loses relevance by never bearing on the task (mere exposition, or a branch that should be disclosed) or by going stale as the behaviour or world it describes changes. Shorter documents are easier to keep relevant. Without a pruning discipline the default fate is **sediment**: stale layers that settle because adding feels safe and removing feels risky, until you must core down through them to find what is still live.
|
||||||
|
- Hunt **no-ops** sentence by sentence: an instruction the model already obeys by default pays load to say nothing. The test — does it change behaviour versus the default? — is model-relative, not reader-relative: two people disagreeing about a no-op disagree about the default, and settle it by running the document, not by debate. When a sentence fails, delete the whole sentence rather than trim words from it. The test also grades leading words: a word too weak to beat the default (_be thorough_ when the agent is already thorough-ish) is a no-op, and the fix is a stronger word (_relentless_), not a different technique.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Writing Great Skills"
|
||||||
|
short_description: "Principles for predictable skills"
|
||||||
|
policy:
|
||||||
|
allow_implicit_invocation: false
|
||||||
@@ -1,201 +0,0 @@
|
|||||||
# Glossary — Building Great Skills
|
|
||||||
|
|
||||||
The domain model for what makes a skill great. A skill exists to wrangle determinism out of a stochastic system; the root virtue is **Predictability**, and every term below is a lever on it. This is the disclosed reference for [`writing-great-skills`](SKILL.md).
|
|
||||||
|
|
||||||
The terms are grouped by axis: **Invocation** (how a skill is reached), **Information Hierarchy** (how its content is arranged), **Steering** (how the agent's runtime behaviour is shaped), and **Pruning** (how it is kept lean). Each **failure mode** lives beside the lever that cures it, tagged _failure mode_.
|
|
||||||
|
|
||||||
**Bold terms** in any definition are themselves defined in this glossary; find them by their heading.
|
|
||||||
|
|
||||||
## Predictability
|
|
||||||
|
|
||||||
The degree to which a skill makes the agent behave the same _way_ on every run — the same process, not the same output (a brainstorming skill should _predictably_ diverge; its tokens vary, its behaviour doesn't). The root virtue every other term serves — cost and maintainability are symptoms of it, not rivals.
|
|
||||||
|
|
||||||
_Avoid_: consistency, reliability, robustness, output-determinism
|
|
||||||
|
|
||||||
## Invocation
|
|
||||||
|
|
||||||
How a skill is reached — and the two loads you pay for the choice.
|
|
||||||
|
|
||||||
### Model-Invoked
|
|
||||||
|
|
||||||
A skill that keeps its **description** field, so the agent can see it and fire it autonomously — and the human can still type its name, so model-invocation always _includes_ user reach. There is no model-only state: a description only ever _adds_ agent discovery, never removes the human's. Pays a permanent **context load** on every turn in exchange for that discoverability. Reachable by other skills, because the description that makes it agent-discoverable makes it invocable. A model-invoked skill whose content is all **reference** is also one home for shared reference: another skill can invoke it, so reference needed by several skills lives in one place. Pick model-invocation only when the agent must reach the skill on its own; if it never fires except by hand, drop the description and pay no context load.
|
|
||||||
|
|
||||||
_Avoid_: ability, tool, capability
|
|
||||||
|
|
||||||
### User-Invoked
|
|
||||||
|
|
||||||
A skill with its **description** stripped — invisible to the agent and reachable only by the human typing its name (user-_only_, where **model-invoked** is user-_and-agent_). Trades agent-discoverability for zero **context load**. Because it has no description, nothing but the human can reach it: no other skill can fire it.
|
|
||||||
|
|
||||||
_Avoid_: procedure, workflow, command
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
The skill's machine-readable trigger, and the one **context pointer** a **model-invoked** skill is forced to keep loaded at all times. Its mere presence _is_ the invocation axis: keep it and the skill is model-invoked (and reachable by other skills); delete it and the skill is **user-invoked**, reachable only by the human. The source of a model-invoked skill's **context load**.
|
|
||||||
|
|
||||||
_Avoid_: frontmatter, summary
|
|
||||||
|
|
||||||
### Context Pointer
|
|
||||||
|
|
||||||
A reference held in the agent's context that names some out-of-context material and encodes the condition for reaching it. The **description** is the top-level context pointer (context window → skill); pointers to disclosed files are the same object one level down. Its wording, not the target, decides _when_ the agent reaches — and _how reliably_. A must-have target behind a weakly worded pointer is a variance bug: fix the wording first, and inline the material only if sharpening fails.
|
|
||||||
|
|
||||||
_Avoid_: link, reference, import
|
|
||||||
|
|
||||||
### Context Load
|
|
||||||
|
|
||||||
The cost a **model-invoked** skill imposes on the agent's context window — its **description**, always loaded, spending both tokens and attention. What **user-invoked** skills escape by having no description, and the brake on splitting into more model-invoked skills.
|
|
||||||
|
|
||||||
_Avoid_: token cost, context bloat
|
|
||||||
|
|
||||||
### Cognitive Load
|
|
||||||
|
|
||||||
The cost a **user-invoked** skill imposes on the human — what they must hold in their head: which skills exist and when to reach for each (the human is the index). What **model-invocation** removes by being agent-discoverable, and the brake on splitting into more user-invoked skills. Not a cost to minimise: it is the price of human agency, the reason some skills stay user-invoked. Spend it where human judgement matters; remove it where it does not.
|
|
||||||
|
|
||||||
_Avoid_: human index, burden, overhead
|
|
||||||
|
|
||||||
### Router Skill
|
|
||||||
|
|
||||||
A **user-invoked** skill whose job is to point at your other user-invoked skills — naming each and when to reach for it — so the human has one skill to remember instead of many. It can only hint, never fire them: user-invoked skills have no **description**, so nothing but the human can reach them. The cure for **cognitive load** when user-invoked skills multiply.
|
|
||||||
|
|
||||||
_Avoid_: dispatcher, menu, registry, index, router procedure
|
|
||||||
|
|
||||||
### Granularity
|
|
||||||
|
|
||||||
How finely you divide skills. Finer division spends one of the two loads: more **model-invoked** skills spend **context load** (more descriptions crowding the window and competing for attention); more **user-invoked** skills spend **cognitive load** (more for the human to remember and reach for). Two cuts guide the division. By **invocation**, split off a model-invoked skill where you have a distinct **leading word** to trigger it — a trigger word you actually use in your prompts. By **sequence**, split a run of **steps** where a step's **post-completion steps** need hiding, since isolating it in its own context clears what follows. Beware the reverse: merging sequences exposes each step's post-completion steps to what follows, inviting premature completion.
|
|
||||||
|
|
||||||
_Avoid_: chunking, modularity
|
|
||||||
|
|
||||||
## Information Hierarchy
|
|
||||||
|
|
||||||
How a skill's content is arranged, and how far down the ladder each piece sits.
|
|
||||||
|
|
||||||
### Information Hierarchy
|
|
||||||
|
|
||||||
A skill's content ranked by how immediately the agent needs it — a single ladder, produced by two cuts: in-file or behind a pointer, and step or reference. The rungs:
|
|
||||||
|
|
||||||
- **Steps** — in-file, primary
|
|
||||||
- **Reference**, in-file — secondary
|
|
||||||
- **Reference**, disclosed — behind a **context pointer**
|
|
||||||
|
|
||||||
A skill with no **steps** uses just the bottom two rungs — often a legitimately flat peer-set (e.g. every rule of a review on one rung), which is a fine arrangement, not a smell. The hierarchy is independent of invocation: a skill can be model- or user-invoked whether it is all steps, all reference, or both. When a skill has steps, in-file reference that should be disclosed buries them and turns attending to them into a coin-flip — a variance lever, not just a legibility one. Keep the top of the ladder legible; push down it whatever you can.
|
|
||||||
|
|
||||||
_Avoid_: structure, organization, layout
|
|
||||||
|
|
||||||
### Steps
|
|
||||||
|
|
||||||
The ordered actions the agent performs — when a skill has them, the primary tier of its content, and the part that earns its place in SKILL.md. Not every skill has steps: a skill can be all steps (`tdd`), all **reference** (a review), or both, independent of invocation. Every step ends on a **completion criterion**, clear or vague.
|
|
||||||
|
|
||||||
_Avoid_: workflow, instructions, choreography
|
|
||||||
|
|
||||||
### Reference
|
|
||||||
|
|
||||||
Material the agent refers to on demand — definitions, facts, parameters, examples, conditional instructions. When a skill has **steps** it is secondary to them; when a skill has none it is the entire content; or it lives outside any skill entirely — see **External Reference**. Reached via **context pointers**, and the prime candidate for **progressive disclosure**.
|
|
||||||
|
|
||||||
_Avoid_: supporting material, docs, background
|
|
||||||
|
|
||||||
### External Reference
|
|
||||||
|
|
||||||
**Reference** that lives outside the skill system — a plain file, no **description**, no **steps**, not invocable — that any skill can point at. The home for shared reference that needn't fire on its own, and the only shared home two **user-invoked** skills can use, since neither has a description and so neither can fire the other.
|
|
||||||
|
|
||||||
_Avoid_: doc, resource, knowledge base
|
|
||||||
|
|
||||||
### Progressive Disclosure
|
|
||||||
|
|
||||||
Moving **reference** down the ladder — out of SKILL.md and behind a **context pointer** — so the top stays legible. Not primarily a token optimisation; it is how the **information hierarchy** is protected. Licensed by **branching**: disclose what only some branches need, inline what every path needs, and if a pointer fires unreliably on must-have material, sharpen its wording, and pull it back inline only if that fails.
|
|
||||||
|
|
||||||
_Avoid_: lazy loading, chunking
|
|
||||||
|
|
||||||
### Co-location
|
|
||||||
|
|
||||||
Keeping the material an agent needs at once in one place — a concept's definition, rules, and caveats under a single heading, not scattered across the file — so reading one part brings its neighbours with it. The within-file companion to the **Information Hierarchy**: the hierarchy ranks _how far down_ a piece sits; co-location decides _what sits beside it_ once there. There is no formula for the right format of a body of **reference**; the test is that a skill should read like documentation written for the agent, and grouped material reads that way where scattered material does not. Distinct from **Duplication**: that repeats one meaning in two places, where scattering fragments a single meaning across many.
|
|
||||||
|
|
||||||
_Avoid_: grouping, clustering, cohesion
|
|
||||||
|
|
||||||
### Sprawl
|
|
||||||
|
|
||||||
_Failure mode._ A skill that is simply too long — too many lines in SKILL.md — independent of whether they are stale or repeated. Even an all-live, all-unique skill can sprawl. It costs readability (the agent wades through more before it can act, and attention thins across the excess), maintainability (every extra line is one more to keep **relevant**), and tokens. The cure is the **information hierarchy**: push **reference** down behind **context pointers**, and split by **branch** or sequence so each path carries only what it needs. Distinct from **sediment** (length from stale accumulation) and **duplication** (length from repeated meaning) — sprawl is length itself, whatever its cause.
|
|
||||||
|
|
||||||
_Avoid_: bloat, length, size, verbosity
|
|
||||||
|
|
||||||
## Steering
|
|
||||||
|
|
||||||
The levers that shape the agent's runtime behaviour toward **Predictability**.
|
|
||||||
|
|
||||||
### Branch
|
|
||||||
|
|
||||||
A distinct way a skill can be invoked — a case the skill handles — so different runs take different paths through it. A skill with many steps may carry many branches; a linear one has none.
|
|
||||||
|
|
||||||
_Avoid_: path, case, fork
|
|
||||||
|
|
||||||
### Leading Word
|
|
||||||
|
|
||||||
A compact concept — also called a _Leitwort_ — already living in the model's pretraining, that the agent thinks with while running the skill. It encodes a behavioural principle in the fewest possible tokens by invoking priors the model already holds (e.g. _lesson_, _proximal zone of development_, _fog of war_, _tracer bullets_). Repeated as a token, never as a sentence, it accumulates a distributed definition across the skill and anchors a whole region of behaviour. Coining your own works if you define it clearly, but a made-up word recruits no priors — you pay in definition tokens what a pretrained word gives free. Reach for an existing word first.
|
|
||||||
|
|
||||||
A leading word serves **predictability** twice. In the body it anchors **execution** — the agent reaches for the same behaviour every time the concept appears, and inside flat reference it focuses attention on a class of thing to look for, recruiting the right checks each run. In the **description** it anchors **invocation** — and not only within the skill: when the same word lives in your prompts, your docs, and your codebase, the agent links that shared language to the skill and fires it more reliably. Word a description with the leading words you actually use when you want the skill.
|
|
||||||
|
|
||||||
_Avoid_: keyword, term, motif
|
|
||||||
|
|
||||||
### Completion Criterion
|
|
||||||
|
|
||||||
The condition that tells the agent a unit of work is done — the target it judges against. Two properties make it a lever, not just a quality. Its **clarity** (can the agent tell done from not-done?) resists **premature completion** — a vague bound ("understanding reached") lets the agent declare done and slip to the next step; this axis needs _steps_ to bite, since premature completion is a between-steps failure. Its **demand** (how much it requires) sets **legwork** — "every modified model accounted for" forces thorough work where "produce a change list" does not — and this axis is _not_ step-bound: it can bind a body of flat reference too, which is how a skill with no steps still carries an exhaustiveness bar ("every rule applied"). The strongest criteria are both checkable and exhaustive.
|
|
||||||
|
|
||||||
_Avoid_: done condition, exit condition, stopping rule
|
|
||||||
|
|
||||||
### Legwork
|
|
||||||
|
|
||||||
The work an agent does behind the scenes within a single step — reading files, exploring the codebase, making changes, digging up what it needs rather than offloading to the user. It lives below the step structure: never written as its own step, latent in the wording, controlled by the agent rather than the skill. The within-step counterpart to **post-completion steps**' across-step pull. Raised by a **leading word** (_comprehensive_, _thorough_) or a **completion criterion** that demands the work be exhaustive — including the demand axis applied to flat reference, which is what drives a skill of flat reference to cover all its rungs. Goes thin either when that demand is missing or when **premature completion** cuts the step short.
|
|
||||||
|
|
||||||
_Avoid_: scope, effort, diligence, coverage
|
|
||||||
|
|
||||||
### Post-Completion Steps
|
|
||||||
|
|
||||||
The **steps** that follow the current step. Visible, they pull the agent forward into **premature completion** — the more it sees, the stronger the tug; the defence is to hide them by splitting the sequence of steps into two.
|
|
||||||
|
|
||||||
_Avoid_: horizon, fog of war, lookahead
|
|
||||||
|
|
||||||
### Premature Completion
|
|
||||||
|
|
||||||
_Failure mode._ Ending the current step before it is genuinely done, because the agent's attention slips to being done rather than to the work. A between-steps failure: it needs **steps** to occur — a skill with no steps that quits early isn't premature completion but thin **legwork** under an unmet demand. A tug-of-war between two forces: visible **post-completion steps** (the pull forward) and the **completion criterion**'s clarity (the resistance — a sharp, checkable bar holds; a vague one gives way). Fuzziness is the necessary condition: a sharp bound resists the pull no matter how many later steps are visible, so a step that never rushes needs no defending. Two levers hold a step that does, but reach for them in order: **sharpen the bound first** — it is local and cheap. Only when the criterion is irreducibly fuzzy _and_ you actually observe the rush do you **hide the later steps** — and hiding only works across a real context boundary (a user-invoked hand-off or a subagent dispatch; an inline model-invoked call leaves the later steps in context and clears nothing). One cause of thin legwork, but distinct from it: legwork can be thin even when a step runs to full completion.
|
|
||||||
|
|
||||||
_Avoid_: premature closure, the rush, rushing, shortcutting
|
|
||||||
|
|
||||||
### Negation
|
|
||||||
|
|
||||||
_Failure mode._ Steering by prohibition — telling the agent what _not_ to do — which drags the forbidden behaviour into context and makes it _more_ available, not less. _Don't think of an elephant_, and the elephant is all there is; _never write verbose comments_, and verbosity is the pattern the agent has just read. The negation is a weak modifier the strongly-activated concept overruns, so the ban half-reads as an instruction to do the thing. Its **leading word** is the _elephant_: whatever a prohibition names into the frame. Cure: prompt the **positive** — describe the target behaviour ("write one-line comments") so the banned one is never spoken. A prohibition earns its place only as a hard guardrail on a behaviour you cannot phrase positively; even then, pair it with the positive target so attention lands on what to do.
|
|
||||||
|
|
||||||
_Avoid_: ironic rebound, don't-prompting, the pink elephant
|
|
||||||
|
|
||||||
## Pruning
|
|
||||||
|
|
||||||
Keeping a skill lean — each remedy paired with the failure it cures.
|
|
||||||
|
|
||||||
### Single Source of Truth
|
|
||||||
|
|
||||||
The desired state where each meaning lives in exactly one authoritative place, so a change to the skill's behaviour is a change in one place. **Duplication** is its violation.
|
|
||||||
|
|
||||||
_Avoid_: home, canonical location
|
|
||||||
|
|
||||||
### Duplication
|
|
||||||
|
|
||||||
_Failure mode._ The same meaning given more than one **single source of truth**. It costs maintenance (change one place, you must change the others), costs tokens, and inflates prominence — repeating a meaning weights it on the ladder past its real rank. The accidental inverse of a **leading word**, which raises attention on purpose by repeating a token, never the meaning.
|
|
||||||
|
|
||||||
_Avoid_: repetition, redundancy
|
|
||||||
|
|
||||||
### Relevance
|
|
||||||
|
|
||||||
Whether a line still bears on what the skill does — the lens for what to keep. A line loses relevance either by never bearing on the task (mere exposition, or a **branch** that should be disclosed) or by going stale: drifting out of date as the behaviour or world it describes changes. Shorter skills are easier to keep relevant, because each line is cheaper to check. Distinct from **no-op**: relevance asks whether a line bears on the task, not whether it changes behaviour.
|
|
||||||
|
|
||||||
_Avoid_: load-bearing, staleness, freshness
|
|
||||||
|
|
||||||
### Sediment
|
|
||||||
|
|
||||||
_Failure mode._ Layers of old content that settle in a skill and are never cleared, because adding feels safe and removing feels risky — so stale and irrelevant lines accumulate and you must core down through them to find what is still live. The default fate of any skill without a pruning discipline; the slow erosion of **relevance**, as opposed to **duplication**'s repeated meaning.
|
|
||||||
|
|
||||||
_Avoid_: accretion, bloat, cruft, rot
|
|
||||||
|
|
||||||
### No-Op
|
|
||||||
|
|
||||||
_Failure mode._ An instruction that changes nothing because the model already does it by default — you pay load to tell the agent what it would do anyway. The test: does a line change behaviour versus the default? A line can be perfectly **relevant** and still be a no-op. The same priors that make a **leading word** free make a no-op worthless.
|
|
||||||
|
|
||||||
A leading word is a _technique_; No-Op is a _verdict_ on a line — and they cross. A leading word too weak to beat the default is a no-op (_be thorough_ when the agent is already thorough-ish), and the fix is a stronger word that passes the verdict (_relentless_), not a different technique. So the No-Op test — does it change behaviour versus the default? — is also how you grade whether a leading word is earning its repetitions. This is model-relative, not reader-relative: two people disagreeing over whether a line is a no-op disagree about the default, and settle it by running the skill, not by debate.
|
|
||||||
|
|
||||||
_Avoid_: redundant instruction, restating the obvious, belaboring
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
---
|
|
||||||
name: writing-great-skills
|
|
||||||
description: Reference for writing and editing skills well — the vocabulary and principles that make a skill predictable.
|
|
||||||
disable-model-invocation: true
|
|
||||||
---
|
|
||||||
|
|
||||||
A skill exists to wrangle determinism out of a stochastic system. **Predictability** — the agent taking the same _process_ every run, not producing the same output — is the root virtue; every lever below serves it.
|
|
||||||
|
|
||||||
**Bold terms** are defined in [`GLOSSARY.md`](GLOSSARY.md); look them up there for the full meaning.
|
|
||||||
|
|
||||||
## Invocation
|
|
||||||
|
|
||||||
Two choices, trading different costs:
|
|
||||||
|
|
||||||
- A **model-invoked** skill keeps a **description**, so the agent can fire it autonomously _and_ other skills can reach it (you can still type its name too). It contributes to **context load** — the description sits in the window every turn. Mechanics: omit `disable-model-invocation`, and write a model-facing description with rich trigger phrasing ("Use when the user wants…, mentions…").
|
|
||||||
- A **user-invoked** skill strips the description from the agent's reach: only you, typing its name, can invoke it — and no other skill can. Zero context load, but it spends **cognitive load**: _you_ are the index that must remember it exists. Mechanics: set `disable-model-invocation: true`; the `description` becomes human-facing — a one-line summary, trigger lists stripped.
|
|
||||||
|
|
||||||
Pick model-invocation only when the agent must reach the skill on its own, or another skill must. If it only ever fires by hand, make it user-invoked and pay no context load.
|
|
||||||
|
|
||||||
When user-invoked skills multiply past what you can remember, that piled-up cognitive load is cured by a **router skill**: one user-invoked skill that names the others and when to reach for each.
|
|
||||||
|
|
||||||
## Writing the description
|
|
||||||
|
|
||||||
A model-invoked **description** does two jobs — state what the skill is, and list the **branches** that should trigger it. Every word increases **context load**, so a description earns even harder pruning than the body:
|
|
||||||
|
|
||||||
- **Front-load the skill's leading word** — the description is where it does its invocation work.
|
|
||||||
- **One trigger per branch.** Synonyms that rename a single branch are **duplication** — "build features using TDD … asks for test-first development" is one branch written twice. Collapse them; keep only genuinely distinct branches.
|
|
||||||
- **Cut identity that's already in the body.** Keep the description to triggers, plus any "when another skill needs…" reach clause.
|
|
||||||
|
|
||||||
## Information hierarchy
|
|
||||||
|
|
||||||
A skill is built from two content types — **steps** and **reference** — that mix freely: a skill can be all steps, all reference, or both. The core decision is which to use and where each sits on the **information hierarchy**, a ladder ranked by how immediately the agent needs the material:
|
|
||||||
|
|
||||||
1. **In-skill step** — an ordered action in `SKILL.md`, the primary tier: what the agent does, in order. Each step ends on a **completion criterion**, the condition that tells the agent the work is done. Make it _checkable_ (can the agent tell done from not-done?) and, where it matters, _exhaustive_ ("every modified model accounted for", not "produce a change list") — a vague criterion invites **premature completion**.
|
|
||||||
2. **In-skill reference** — a definition, rule, or fact in `SKILL.md`, consulted on demand. Often a legitimately flat peer-set (every rule of a review on one rung) — a fine arrangement, not a smell. _This skill is all reference._
|
|
||||||
3. **External reference** — reference pushed out of `SKILL.md` into a separate file, reached by a **context pointer**, loaded only when the pointer fires. (Spans _disclosed_ reference — a sibling file like `GLOSSARY.md`, still part of the skill — through fully **external reference** that lives outside the skill system and any skill can point at.)
|
|
||||||
|
|
||||||
A demanding completion criterion drives thorough **legwork** — the digging the agent does within the work — whether the skill has steps or not, since "every rule applied" binds flat reference just as "every step done" binds a sequence.
|
|
||||||
|
|
||||||
Push too little down and the top bloats; push too much and you hide material the agent actually needs. That tension is the whole decision.
|
|
||||||
|
|
||||||
**Progressive disclosure** is the move down the ladder — out of `SKILL.md` into a linked file — so the top stays legible. Mechanics: a linked `.md` file in the skill folder, named for what it holds (this skill discloses its full definitions to `GLOSSARY.md`). Some skills are used in more than one way, and each distinct way is a **branch** — different runs taking different paths through the skill. Branching is the cleanest disclosure test: inline what every branch needs, and push behind a pointer what only some branches reach. A **context pointer**'s _wording_, not its target, decides when and how reliably the agent reaches the material.
|
|
||||||
|
|
||||||
Where the ladder decides _how far down_ a piece sits, **co-location** decides _what sits beside it_ once there: keep a concept's definition, rules, and caveats under one heading rather than scattered, so reading one part brings its neighbours with it.
|
|
||||||
|
|
||||||
## When to split
|
|
||||||
|
|
||||||
**Granularity** is how finely you divide skills, and each cut spends one of the two loads, so split only when the cut earns it. Two cuts:
|
|
||||||
|
|
||||||
- **By invocation** — split off a **model-invoked** skill when you have a distinct **leading word** that should trigger it on its own, or another skill must reach it. You pay **context load** for the new always-loaded **description**, so that independent reach has to be worth it.
|
|
||||||
- **By sequence** — split a run of **steps** when the steps still ahead (a step's **post-completion steps**) tempt the agent to rush the one in front of it (**premature completion**). Keeping them out of view encourages the agent to do more **legwork** on the current task.
|
|
||||||
|
|
||||||
## Pruning
|
|
||||||
|
|
||||||
Keep each meaning in a **single source of truth**: one authoritative place, so changing the behaviour is a one-place edit.
|
|
||||||
|
|
||||||
Check every line for **relevance**: does it still bear on what the skill does?
|
|
||||||
|
|
||||||
Then hunt **no-ops** sentence by sentence, not just line by line: run the no-op test on each sentence in isolation, and when one fails, delete the whole sentence rather than trim words from it. Be aggressive — most prose that fails should go, not be rewritten.
|
|
||||||
|
|
||||||
## Leading words
|
|
||||||
|
|
||||||
A **leading word** is a compact concept already living in the model's pretraining that the agent thinks with while running the skill (e.g. _lesson_, _fog of war_, _tracer bullets_). Repeated throughout the text (though not necessarily - a strong leading word might only be needed once), it accumulates a distributed definition and anchors a whole region of behaviour in the fewest tokens, by recruiting priors the model already holds.
|
|
||||||
|
|
||||||
It serves predictability twice. In the body it anchors _execution_: the agent reaches for the same behaviour every time the word appears. In the description it anchors _invocation_: when the same word lives in your prompts, docs, and code, the agent links that shared language to the skill and fires it more reliably.
|
|
||||||
|
|
||||||
Hunt for opportunities to refactor skills to use leading words. A triad spelled out at three sites (**duplication**), a description spending a sentence to gesture at one idea — each is a passage begging to **collapse** into a single token. Examples include:
|
|
||||||
|
|
||||||
- "fast, deterministic, low-overhead" -> _tight_ — one quality restated across a phase — into a single pretrained word (a _tight_ loop).
|
|
||||||
- "a loop you believe in" -> _red_ — converts a fuzzy gate into a binary observable state (the loop goes _red_ on the bug, or it doesn't).
|
|
||||||
|
|
||||||
You win twice over: fewer tokens, _and_ a sharper hook for the agent to hang its thinking on. Assume every skill is carrying restatements that leading words retire — go find them.
|
|
||||||
|
|
||||||
## Failure modes
|
|
||||||
|
|
||||||
Use these to diagnose issues the user may be having with the skill.
|
|
||||||
|
|
||||||
- **Premature completion** — ending a step before it's genuinely done, attention slipping to _being done_. Defence, in order: sharpen the completion criterion first (cheap, local); only if it is irreducibly fuzzy _and_ you observe the rush, hide the post-completion steps by splitting (the sequence cut).
|
|
||||||
- **Duplication** — the same meaning in more than one place. Costs maintenance and tokens, and inflates a meaning's prominence on the ladder past its real rank.
|
|
||||||
- **Sediment** — stale layers that settle because adding feels safe and removing feels risky. The default fate of any skill without a pruning discipline.
|
|
||||||
- **Sprawl** — a skill simply too long, even when every line is live and unique. Hurts readability and maintainability and wastes tokens. The cure is the ladder: disclose **reference** behind pointers, and split by **branch** or sequence so each path carries only what it needs.
|
|
||||||
- **No-op** — a line the model already obeys by default, so you pay load to say nothing. The test: does it change behaviour versus the default? A weak leading word (_be thorough_ when the agent is already thorough-ish) is a no-op; the fix is a stronger word (_relentless_), not a different technique.
|
|
||||||
- **Negation** — steering by prohibition backfires: _don't think of an elephant_ names the elephant and makes it more available, not less. Prompt the **positive** — state the target behaviour so the banned one is never spoken; keep a prohibition only as a hard guardrail you can't phrase positively, and even then pair it with what to do instead.
|
|
||||||
Reference in New Issue
Block a user