Compare commits

...
Author SHA1 Message Date
Matt PocockandGitHub 66898f60e8 Merge pull request #536 from mattpocock/task/claude-codex-plugin
feat: ship the skill set as a native Claude Code plugin (v1.2)
2026-07-13 14:36:01 +01:00
Matt PocockandGitHub 0ac3f3fbf1 Merge pull request #551 from mattpocock/codex-skill-metadata
feat: add Codex agents/openai.yaml metadata to every skill
2026-07-13 13:00:38 +01:00
697d4ce974 feat: add Codex agents/openai.yaml metadata to every skill
Adds an `agents/openai.yaml` beside each `SKILL.md` so the skills work in
Codex as well as Claude Code, without generated copies:

- `interface.display_name` + `interface.short_description` for the Codex
  skill picker, hand-written for all 39 skills.
- `policy.allow_implicit_invocation: false` on the 22 user-invoked skills —
  the Codex analog of `disable-model-invocation: true`, so Codex excludes
  them from implicit invocation while explicit `$skill` 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
  instructions; note Codex as a `link-skills.sh` install target.

Slimmed-down rework of the approach prototyped in #522: keeps the essential
cross-harness metadata, drops the Ruby validator, the runtime-detector test,
per-skill `default_prompt`s, and the unrelated promotion changes.

Co-authored-by: gabimoncha <gabimoncha@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 12:57:18 +01:00
Matt PocockandGitHub 8f4952b6a3 Merge pull request #539 from mattpocock/fix/finish-promoted-wiring
fix: finish promoted-bucket wiring for resolving-merge-conflicts and implement
2026-07-13 12:42:15 +01:00
Matt PocockandClaude Opus 4.8 d3275456a4 fix: finish promoted-bucket wiring for resolving-merge-conflicts and implement
Close a standing CLAUDE.md-invariant gap where two promoted skills were
not fully wired into the plugin manifest and READMEs.

- resolving-merge-conflicts (model-invoked): add to .claude-plugin/plugin.json,
  top-level README.md, and skills/engineering/README.md.
- implement (user-invoked): add the missing line to skills/engineering/README.md
  (already present in plugin.json and the top README).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 12:00:09 +01:00
Matt PocockandGitHub 04fee67571 Merge pull request #533 from mattpocock/yagni-scope-improve-architecture
improve-codebase-architecture: scope the scan to where change is landing (YAGNI)
2026-07-13 11:27:15 +01:00
Matt PocockandGitHub 33dfc9b28f Merge pull request #538 from mattpocock/wayfinder/research-subagents
wayfinder: burn research tickets down with subagents
2026-07-13 11:18:20 +01:00
Matt PocockandGitHub 8eb8f58f0f Merge pull request #532 from mattpocock/grill-me-general-use
grilling: reword the primitive for general use
2026-07-13 11:14:03 +01:00
Matt PocockandClaude Opus 4.8 2602257241 feat(wayfinder): burn research tickets down with subagents
Research stays a real ticket type — it's a shared blocker downstream
decisions hang on, which the frontier's blocking edges exist to render.
What changes is resolution: because research is AFK, charting doesn't
stop and read. After creating the tickets, the charting session fires a
/research subagent for each research ticket to burn it down in parallel,
capturing findings on a throwaway research/<name> branch with a context
pointer.

Charting's "fire the research subagents" step owns how research is
handled; the Ticket Types bullet just names the resolver, and the
one-ticket-per-session rule carries the research exception.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 11:10:46 +01:00
Matt PocockandClaude Opus 4.8 45afd8074a improve-codebase-architecture: scope the scan to where change is landing (YAGNI)
Before scanning, decide where to look. If the user named a direction, take
it; otherwise read the last ~20 commit messages to bias exploration toward
actively-developed paths. A deepening opportunity in code nobody touches is a
refactor you'll never cash in — leverage only pays off where you keep editing.

Syncs the docs page and adds a changeset.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 11:01:18 +01:00
Matt PocockandClaude Opus 4.8 42a5b70fca feat: ship the skill set as a native Claude Code plugin
Add a Claude Code plugin marketplace so the promoted skills can be
installed as a managed, read-only bundle (subscribe rather than fork),
alongside the existing skills.sh installer.

- Enrich .claude-plugin/plugin.json with marketplace metadata (version,
  description, author, license, keywords); keep the curated promoted-only
  skills array.
- Add .claude-plugin/marketplace.json making the repo its own
  single-plugin marketplace (mattpocock-skills@mattpocock).
- README: document /plugin install alongside skills.sh, and the
  subscribe-vs-fork tradeoff.
- CLAUDE.md: extend the promoted-set invariant to cover marketplace.json
  and plugin.json/package.json version sync.
- ADR 0002: record why Claude ships now and a native Codex plugin is
  deferred (Codex skills field is single-path + drops symlinks, which
  can't express a curated subset of a bucketed repo without a restructure).

Verified: 'claude plugin validate . --strict' passes, and marketplace
add -> install resolves all 21 promoted skills at v1.2.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 10:14:22 +01:00
57 changed files with 321 additions and 13 deletions
@@ -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.
+5 -3
View File
@@ -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:
- **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…").
- **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.)
- **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` 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**.
+10
View File
@@ -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.
+12
View File
@@ -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": 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
---
Add a YAGNI scoping filter to the **`improve-codebase-architecture`** skill's Explore step. Instead of scanning the whole repo evenly, it now scopes to where change is actually landing: if you name a direction it takes it, otherwise it reads the last ~20 commit messages to bias exploration toward actively-developed paths. A deepening opportunity in code nobody touches is a refactor you'll never cash in — the leverage only pays off where you keep editing — so the report stops tidying dormant corners of the repo.
+23
View File
@@ -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"
]
}
]
}
+19
View File
@@ -1,5 +1,23 @@
{
"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/engineering/ask-matt",
"./skills/engineering/diagnosing-bugs",
@@ -17,6 +35,7 @@
"./skills/engineering/domain-modeling",
"./skills/engineering/codebase-design",
"./skills/engineering/code-review",
"./skills/engineering/resolving-merge-conflicts",
"./skills/productivity/grill-me",
"./skills/productivity/grilling",
"./skills/productivity/handoff",
Symlink
+1
View File
@@ -0,0 +1 @@
CLAUDE.md
+4 -2
View File
@@ -7,7 +7,9 @@ Skills are organized into bucket folders under `skills/`:
- `in-progress/` — drafts not yet ready to ship
- `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`.
@@ -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.
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.
+28
View File
@@ -39,6 +39,33 @@ npx skills@latest add mattpocock/skills
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
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.
- **[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.
- **[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
@@ -16,6 +16,8 @@ npx skills update improve-codebase-architecture
It does **not** hand you a flat list of refactors. Every candidate has to pass the **deletion test** — would removing this module *concentrate* complexity behind a smaller interface, or just move it around? Only the "concentrates" cases earn a card. That filter is what stops the report from becoming generic cleanup advice.
Unless you point it at a specific area, it also scopes itself to where development is actually landing — reading the recent commits to bias toward the code you're still changing. Deepening a module pays off by making future changes to it easier, so it puts extra weight on the parts of the repo that have recently changed.
## When to reach for it
You invoke this by typing `/improve-codebase-architecture` — the agent won't reach for it on its own.
+2 -2
View File
@@ -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.
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
- 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`.
- 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.
## Where it fits
+1 -1
View File
@@ -8,7 +8,7 @@ set -euo pipefail
# Links all skills in the repository into the local skill directories used by
# each agent harness:
# - ~/.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
# to keep installed skills up to date.
@@ -0,0 +1,3 @@
interface:
display_name: "Design an Interface"
short_description: "Explore alternative module interfaces"
+3
View File
@@ -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
+3 -1
View File
@@ -4,7 +4,7 @@ Skills I use daily for code work.
## 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.
- **[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,6 +13,7 @@ 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.
- **[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.
- **[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
@@ -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.
- **[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.
- **[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`.
@@ -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
@@ -17,6 +17,11 @@ This command is _informed_ by the project's domain model and built on a shared d
### 1. Explore
**Scope before you scan — YAGNI.** Deepening a module pays off by making future changes to it easier, so put extra weight on the parts of the codebase that have recently changed. Decide *where* to look before you look:
- If the user named a direction — a module, a subsystem, a pain point — take it, and skip the inference below.
- Otherwise, walk back a good stretch of the commit history (`git log --oneline`) to find the codebase's hot spots — the files and areas that keep coming up — and let those paths pull your attention first. If the changes are scattered with no clear hot spot, widen the net.
Read the project's domain glossary (`CONTEXT.md`) and any ADRs in the area you're touching first.
Then use the Agent tool with `subagent_type=Explore` to walk the codebase. Don't follow rigid heuristics — explore organically and note where you experience friction:
@@ -0,0 +1,5 @@
interface:
display_name: "Improve Codebase Architecture"
short_description: "Find and grill architecture improvements"
policy:
allow_implicit_invocation: false
@@ -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
+4 -3
View File
@@ -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).
- **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.
- **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.
@@ -102,7 +102,7 @@ Ruling something out of scope is a scoping act, not a step on the route. When a
## 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
@@ -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.
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.
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
@@ -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"
+1 -1
View File
@@ -4,7 +4,7 @@ General workflow tools, not code-specific.
## 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.
- **[handoff](./handoff/SKILL.md)** — Compact the current conversation into a handoff document so another agent can continue the work.
@@ -0,0 +1,5 @@
interface:
display_name: "Grill Me"
short_description: "Sharpen a plan through interview"
policy:
allow_implicit_invocation: false
@@ -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,5 @@
interface:
display_name: "Writing Great Skills"
short_description: "Principles for predictable skills"
policy:
allow_implicit_invocation: false