Compare commits

..
Author SHA1 Message Date
Matt PocockandClaude Opus 5 4f6e25d91e docs: shrink the CLAUDE.md change to the pointer that earns it
CLAUDE.md is always-loaded, so every word costs on every turn. The
edit had grown it by ~65 words, nearly all of which paid load without
changing behaviour:

- The official-marketplace sentence was exposition — a fact the
  pointer target already carries.
- "Never reword an install command" steered by prohibition, which
  makes the banned behaviour more available, not less.
- The fallback rationale was a third copy of what install-block.md
  owns.
- The paragraph split doubled the surface with no branch behind it.

What remains is the one line that does work — the context pointer,
front-loaded on its trigger — leaving CLAUDE.md 10 words longer than
before rather than 65.

Refs mattpocock/personal-wiki#250

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 10:15:18 +01:00
Matt PocockandClaude Opus 5 ad98b80dbd docs: sharpen the canonical install block after review
- install-block.md: state the invariant as a requirement rather than
  as already-true (docs/ is brought into line downstream); mark all
  three canonical snippets, not just the Claude Code one; pin the
  `skills@latest` spelling; restore the `setup-matt-pocock-skills`
  instruction the whole-set form carries; cite the docs source for
  the auto-update claim.
- writing-docs.md: say plainly that the template's Quickstart is the
  older wording, so the file no longer contradicts itself.
- CLAUDE.md: split the paragraph, stop restating the fallback rationale.
- ADR 0002: record what was actually verified, on which version, and
  the two things that were not — the pinned sha in the official
  listing, and the in-session slash command.

Refs mattpocock/personal-wiki#250

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 10:00:45 +01:00
Matt PocockandClaude Opus 5 c474642895 docs: tell one true install story (official marketplace)
mattpocock-skills is now listed in Claude Code's official marketplace,
so the own-marketplace route is superseded. The queued changeset still
documented it, and changeset bodies ship verbatim into CHANGELOG.md —
the release would have published a superseded install route as its
headline.

- Rewrite .changeset/ship-as-claude-plugin.md around
  `claude plugins install mattpocock-skills`.
- Add .agents/install-block.md as the single source for install
  wording, so the docs pass has one true thing to copy.
- Point .agents/writing-docs.md and CLAUDE.md at it.
- Note the official listing in ADR 0002, and record that it reads
  plugin.json directly and does not depend on marketplace.json.

.claude-plugin/marketplace.json is kept as a fallback for direct-repo
installs; nothing in CI or scripts references it.

Refs mattpocock/personal-wiki#250

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 09:57:57 +01:00
9 changed files with 95 additions and 91 deletions
@@ -26,3 +26,16 @@ The only robust ways to give Codex a single promoted-only path are (a) **restruc
- 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.
## Update, 2026-08-05
`mattpocock-skills` was accepted into **Claude Code's official marketplace** — configured name `claude-plugins-official`, source repo `anthropics/claude-plugins-official` — which every Claude Code install has by default. `claude plugins install mattpocock-skills` is now the documented route, and the `marketplace add``install` path above is superseded. The install wording lives in [.agents/install-block.md](../install-block.md).
The official listing points at this repo's git URL and reads `.claude-plugin/plugin.json` directly, so it does not depend on `.claude-plugin/marketplace.json`. That file is retained only as a fallback for installing the repo directly (an unreleased commit, or a fork).
Verified 2026-08-05, on Claude Code 2.1.222, against the live listing:
- `claude plugins install mattpocock-skills` resolves with no marketplace added first, and reports `mattpocock-skills@claude-plugins-official`.
- `claude plugin details mattpocock-skills` then reports version 1.2.0 and loads the promoted skills.
- The listing's `source` is `{"source": "url", "url": "https://github.com/mattpocock/skills.git", "sha": …}` — the **sha is pinned**, so a release reaches installed users when that pin moves, not the moment we tag. At the time of writing the pin sits two commits behind `main`, which is why it lists 22 skills rather than the 24 in `plugin.json`.
- The in-session `/plugin install mattpocock-skills` was **not** exercised — `/plugin` is unavailable in headless (`claude -p`) sessions. It runs the same resolver as the CLI, and the documented example form is `/plugin install <name>@claude-plugins-official`.
+61
View File
@@ -0,0 +1,61 @@
# The canonical install block
One install story, one wording. `README.md`, `.changeset/*`, and every page under `docs/` must say **this** and nothing else. Change it here first, then propagate.
`mattpocock-skills` is listed in **Claude Code's official marketplace** — configured name `claude-plugins-official`, source repo `anthropics/claude-plugins-official` — which every Claude Code install has out of the box. There is no marketplace to add first. Official Anthropic marketplaces have auto-update enabled by default ([discover-plugins](https://code.claude.com/docs/en/discover-plugins)), so "updates arrive automatically" is a true claim, not a hope.
## Claude Code — the plugin
<canonical-block name="claude-code">
```bash
claude plugins install mattpocock-skills
```
Or, from inside a session:
```
/plugin install mattpocock-skills
```
It's in Claude Code's official marketplace, so there's nothing to add first, and updates arrive automatically.
</canonical-block>
## Codex, and other agents — skills.sh
The plugin is Claude Code only. Everywhere else, [skills.sh](https://skills.sh/mattpocock/skills) copies editable skill files into the project. Use the whole-set form on `README.md`:
<canonical-block name="skills-sh-whole-set">
```bash
npx skills@latest add mattpocock/skills
```
Pick the skills you want, and which coding agents to install them on. **The installer lets you choose which skills to take — make sure `setup-matt-pocock-skills` is one of them.**
</canonical-block>
…and the single-skill form on a `docs/` page, where the page already names one skill:
<canonical-block name="skills-sh-one-skill">
```bash
npx skills@latest add mattpocock/skills --skill=<name>
```
```bash
npx skills@latest update <name>
```
</canonical-block>
`skills@latest` is the pinned spelling in all three. The Quickstart template in [writing-docs.md](./writing-docs.md), and the 24 pages under `docs/`, still carry the older bare `npx skills …`; the docs pass brings them into line.
## The two routes are exclusive
The plugin is a managed, read-only bundle you subscribe to. skills.sh writes files you own and edit. Installing both leaves the user with every skill twice — always say "pick one".
## Not the install story
`.claude-plugin/marketplace.json` makes the repo its own single-plugin marketplace (`/plugin marketplace add mattpocock/skills`, then `/plugin install mattpocock-skills@mattpocock`). The official listing supersedes it. It is kept as a fallback for installing the repo directly — an unreleased commit, or a fork — and is **not** documented to users.
+2
View File
@@ -14,6 +14,8 @@ There is no H1 — the published page takes its title from the slug.
Fill the template below. The **fixed frame** (Quickstart block, source link, `## What it does`, `## When to reach for it`, `## Where it fits`) appears on every page. The **adaptable middle**`## Prerequisites` and the free-form substance sections — carries only what this particular skill earns; delete the rest.
Install commands are not written per page. Copy them verbatim from [the canonical install block](./install-block.md) — it is the single source for how anyone installs these skills, and a page that words it differently is a page that tells a second story. The Quickstart block in the template below is the older wording and does not yet match; the docs pass replaces it from the canonical block.
<page-template>
Quickstart:
-13
View File
@@ -1,13 +0,0 @@
---
"mattpocock-skills": patch
---
Give `/ask-matt` the **phase boundary** decision tree, replacing the two-bullet `Crossing sessions` section.
A **phase** is a chunk of work inside a session — the grilling, the implementation, the QA — and the boundary between two of them is where you decide what to do with the context you've built. The router now carries all five options in order (**continue**, `/clear`, `/handoff`, **subagent**, `/compact`), with the ordered tree and its reasoning disclosed in a new `PHASE-BOUNDARIES.md`. Three fixes come with it:
- **`/handoff` was oversold.** It read as the general bridge between context windows. It's narrow: you need it only when something has to *travel* — a new harness, a new directory, a colleague, or a side task forked mid-phase. What it buys is portability.
- **`/compact` is the default, not the first reach.** It sits at the bottom of the tree, after the four cheaper or more precise questions above it. Starting there produces a session that's confidently wrong about whatever the summary flattened.
- **Two branches were missing entirely.** **Continue** is the one to rule out first — it's the only move that keeps the conversation as a primary source rather than a summary of one — and a **subagent** handles anything scoped tightly enough to run AFK.
Context hygiene's escape hatch now says `/compact` rather than `/handoff` (same harness, same directory, at a boundary — the handoff clause doesn't apply), and the smart zone figure is updated from ~120k to ~150k tokens.
+12 -5
View File
@@ -2,11 +2,18 @@
"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:
Ship the skill set as a native **Claude Code plugin**, listed in Claude Code's official marketplace. You can now 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
```bash
claude plugins install mattpocock-skills
```
`.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.
Or, from inside a session:
```
/plugin install mattpocock-skills
```
There is no marketplace to add first — the official marketplace is configured by default.
`.claude-plugin/plugin.json` carries the full plugin metadata (version, description, author, license, keywords) and the explicit list of promoted skills. `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.
+1 -1
View File
@@ -9,7 +9,7 @@ Skills are organized into bucket folders under `skills/`:
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).
Install commands are copied verbatim from [.agents/install-block.md](./.agents/install-block.md). `.claude-plugin/marketplace.json` makes the repo its own single-plugin marketplace — a fallback the install block explains, not the documented route. 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`.
-4
View File
@@ -26,10 +26,6 @@ Reach for it whenever you're unsure which skill or flow a situation calls for: y
The idea `ask-matt` gives you to think with is the **flow** — a path *through* the skills rather than a single one. Most work runs along one **main flow** (idea → ship: grill → spec → tickets → implement → review), two **on-ramps** merge onto it (a triage lane for incoming bugs and requests; a codebase-health lane that generates ideas), and everything else is a **standalone** you reach for on its own. Ask a question and you get placed on the right flow, at the right step — not just handed a tool.
## Phase boundaries
The other idea it hands you is the **phase boundary**. A **phase** is a chunk of work inside a session — the grilling, the implementation, the QA — and the boundary between two of them is where you decide what to do with the context you've built up. You have five options: **continue**, **`/clear`**, **`/handoff`**, a **subagent**, or **`/compact`**. `ask-matt` carries the decision tree that orders them, and the two corrections most people need: `/handoff` is narrow — it earns its keep only when something has to *travel* (a new harness, a new directory, a colleague, a side task forked mid-phase) — and `/compact` is the tree's default at the bottom, not its first reach. Reach for the tree at a boundary; mid-phase there's nothing to decide.
## Where it fits
`ask-matt` is the **router** — the standalone map that sits over the whole set. It is the node every other docs page links back to as [ask-matt](https://aihero.dev/skills-ask-matt), so it never sits *in* a chain; it points *into* every chain. From here you'll most often land on [grill-with-docs](https://aihero.dev/skills-grill-with-docs), the head of the main flow, or [triage](https://aihero.dev/skills-triage), the on-ramp for work you didn't create. When even the router's own picture is stale, its [Source](https://github.com/mattpocock/skills/tree/main/skills/engineering/ask-matt) is the map of record.
@@ -1,55 +0,0 @@
# Phase boundaries
A **phase** is a chunk of work inside a session — the grilling, the implementation, the QA. The definition is fuzzy on purpose: a phase ends when you think *"ok, we're done with that"*.
The **phase boundary** is the gap between two phases, and it is the only place this decision belongs. Mid-phase there is no decision to make — continue, or split the work that's left into subagents. Compacting mid-phase makes the agent lose the thread.
## The five options
| Option | What it does |
| ------------ | --------------------------------------------------------------- |
| **Continue** | Stay in the session. No context switch at all. |
| **`/clear`** | Empty the context window and start from nothing. |
| **`/handoff`** | Write a portable markdown file and seed a session anywhere with it. |
| **Subagent** | Send the task to its own context window and get a report back. |
| **`/compact`** | Compress this context and seed a fresh session with the summary. |
## The tree
Work top to bottom at the boundary. The first **yes** wins.
**1. Can you continue in this session?** Two things make the answer yes: the next phase needs this phase as a **primary source**, or you have enough [smart zone](https://www.aihero.dev/ai-coding-dictionary/smart-zone) left (~150k tokens) for the next phase to fit. Grilling → implementation is the standard yes: the implementation wants the reasoning verbatim, not a summary of it. Continue costs nothing and loses nothing, so rule it out before anything else.
**2. Is the context irrelevant to what comes next?** Is everything in this session — the exploration, the decisions, the dead ends — disposable? If so, **`/clear`**. It is the cheapest move on the board: it takes no time and hands back the whole window. `/clear` also isn't terminal — the old session stays resumable.
The cost of getting this wrong is one-way. Clear a *relevant* context and you lose the **why** behind what you built, and no amount of reading the diff back gets it returned.
**3. Do you need to hand off?** `/handoff` is narrow. You need it only when you are:
- swapping to a **new harness** (Claude → Codex),
- moving to a **new directory** or repo,
- sending the work to a **colleague**,
- or forking a side task you found **mid-phase** without derailing what you're doing.
That list is the whole clause. What `/handoff` buys is **portability** — a file that travels. If nothing is travelling, you don't need it.
**4. Can the task be done AFK?** Is it scoped tightly enough to run with you away from the keyboard, no steering? Then send it to a **subagent** and leave this session untouched. Automated review is the standard case: the agent reads the diff and reports, and you aren't needed while it does.
**5. Otherwise, `/compact`.** Relevant context, same harness, same directory, and you need to stay in the loop — this is where the tree lands, and it lands here often. Pass it an instruction (`/compact we're going to QA this area`) so the summary keeps what the next phase needs.
`/compact` is the **default, not the first reach**. It sits at the bottom because the four questions above it are all cheaper or more precise. The failure mode when people start here is a fresh session that is confidently wrong about a decision the summary flattened.
## Primary and secondary sources
Every move except **Continue** turns a **primary source** into a **secondary source** — the session as it happened, replaced by a summary of it. The trade is always the same shape:
| Source | Information | Noise | Room to move |
| --------------------------------- | ----------- | ----- | ------------ |
| Primary (Continue) | Full | Lots | Little |
| Secondary (`/compact`, `/handoff`) | Lossy | Less | Lots |
This is why question 1 comes first. You only pay the lossiness when staying costs more than it saves.
## These are judgement calls
The questions are not objective — each has taste in it, and the same boundary can go two ways on two days. The value is in asking them **in order**, at the boundary rather than in the middle of the work.
+6 -13
View File
@@ -15,12 +15,12 @@ A **flow** is a path through the skills. Most paths run along one **main flow**,
The route most work travels. You have an idea and want it built.
1. **`/grill-with-docs`** — sharpen the idea by interview. Start here when you **have a codebase**: it's stateful, retaining what it learns in `CONTEXT.md` and ADRs. (No codebase? Use `/grill-me` — see Standalone. Both run the same `/grilling` primitive; `grill-with-docs` is the one that leaves a paper trail.)
2. **Branch — can you settle every question in conversation?** If a question needs a runnable answer (state, business logic, a UI you have to see), detour through a prototype, bridged by **`/handoff`** in both directions (a prototype lives in its own directory, which is exactly what `/handoff` is for — see Phase boundaries):
2. **Branch — can you settle every question in conversation?** If a question needs a runnable answer (state, business logic, a UI you have to see), detour through a prototype, bridged by **`/handoff`** in both directions (see Crossing sessions):
- **`/handoff`** out, then open a fresh session against that file,
- **`/prototype`** to answer the question with throwaway code,
- **`/handoff`** back what you learned, and reference it from the original idea thread.
3. **Branch — is this a multi-session build?**
- **Yes** → **`/to-spec`** (turn the thread into a spec), then **`/to-tickets`** to split it into tracer-bullet tickets, each declaring its **blocking edges**. On a local tracker that's one file per ticket under `.scratch/<feature>/issues/`, worked blockers-first by hand; on a real tracker the edges become native blocking links, so any ticket whose blockers are done can be grabbed — kick off **`/implement`** per ticket, **`/clear`ing context between each one**. Each ticket is self-contained, so the last one's context is disposable.
- **Yes** → **`/to-spec`** (turn the thread into a spec), then **`/to-tickets`** to split it into tracer-bullet tickets, each declaring its **blocking edges**. On a local tracker that's one file per ticket under `.scratch/<feature>/issues/`, worked blockers-first by hand; on a real tracker the edges become native blocking links, so any ticket whose blockers are done can be grabbed — kick off **`/implement`** per ticket, **clearing context between each one**.
- **No** → **`/implement`** right here, in the same context window.
Either way, **`/implement`** builds each issue by driving **`/tdd`** internally — one red-green slice at a time — then closes out by running **`/code-review`**, a two-axis review (Standards + Spec) of the diff, before committing. Reach for **`/tdd`** on its own when you just want to build a concrete behaviour test-first without a full spec, and **`/code-review`** on its own whenever you want to review a branch or PR against a fixed point.
@@ -29,7 +29,7 @@ The route most work travels. You have an idea and want it built.
Keep steps 13 in **one unbroken context window** — don't compact or clear until after `/to-tickets` — so the grilling, spec, and tickets all build on the same thinking. Each `/implement` then starts fresh, working from the ticket.
The limit on this is the **[smart zone](https://www.aihero.dev/ai-coding-dictionary/smart-zone)**: the window (~150k tokens on state-of-the-art models) within which the model still reasons sharply. If a session approaches it before `/to-tickets`, don't push on degraded — `/compact` at the nearest phase boundary and carry on (see Phase boundaries).
The limit on this is the **[smart zone](https://www.aihero.dev/ai-coding-dictionary/smart-zone)**: the window (~120k tokens on state-of-the-art models) within which the model still reasons sharply. If a session approaches it before `/to-tickets`, don't push on degraded — `/handoff` and continue in a fresh thread.
## On-ramps
@@ -58,17 +58,10 @@ Two model-invoked references that run *beneath* the other skills — each the si
- **`/domain-modeling`** — sharpen the project's *domain* language: challenge a fuzzy term, resolve an overloaded word ("account" doing three jobs), record a hard-to-reverse decision as an ADR. It's the active discipline `/grill-with-docs` drives to keep `CONTEXT.md` a clean glossary.
- **`/codebase-design`** — the deep-module vocabulary (module, interface, depth, seam, adapter, leverage, locality) for designing a module's *shape*: a lot of behaviour behind a small interface at a clean seam. `/tdd` and `/improve-codebase-architecture` both speak it.
## Phase boundaries
## Crossing sessions
A **phase** is a chunk of work inside a session — the grilling, the implementation, the QA. At the **boundary** between two of them you have five options, and picking between them is the fuzziest decision in this whole map:
- **Continue** — stay put. Costs nothing, loses nothing.
- **`/clear`** — empty the window, when nothing here matters to what's next.
- **`/handoff`** — write a portable markdown file. Narrow: only for a **new harness**, a **new directory**, a **colleague**, or forking a side task **mid-phase**. What it buys is portability.
- **Subagent** — send a tightly-scoped task to its own window and get a report back.
- **`/compact`** — compress this context and seed a fresh session with it. The **default**, at the bottom of the tree rather than the first reach.
Read [PHASE-BOUNDARIES.md](PHASE-BOUNDARIES.md) for the ordered tree — the five questions, the reasoning behind each branch, and why the primary-source cost makes **Continue** the one to rule out first. Make the decision **at** a boundary; mid-phase, continue or split the rest into subagents.
- **`/handoff`** — when a thread is full or you need to branch off (e.g. into a `/prototype` session), this compacts the conversation into a markdown file. You don't continue in place — you **open a new session and reference that file** to carry the context across. It's the bridge between context windows, in either direction. Use it when you want a **fresh session** but need the **current conversation preserved**.
- **`/compact`** (built-in) — stay in the **same conversation**, letting the earlier turns be summarized. Use it at **intentional breaks between phases**, when you don't mind losing the verbatim history. Don't compact mid-phase — the agent can lose its way. `/handoff` forks; `/compact` continues.
## Standalone