Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions .claude/skills/write-skill/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
name: write-skill
description: Scaffold a new Claude Code skill in this repo's house style — a `.claude/skills/<name>/SKILL.md` with correct frontmatter (name + a trigger-rich description), an intro, numbered `## Steps`, and a `## Do not` section — then register it in CLAUDE.md and log it. Use when the user wants to capture a repeatable procedure as a reusable skill ("make a skill for X", "turn this into a skill", "we keep doing X, let's skill-ify it"). First confirm it's actually a skill and not a note or code (see the skill-vs-note-vs-code knowledge note).
---

# write-skill

Skills in this repo share one shape, and a skill that doesn't match it either won't trigger when
it should (weak `description`) or won't be followable when it does (vague steps). This skill is the
recipe for writing a new one correctly, and it keeps the catalog self-propagating — the repo can
grow its own skills instead of being hand-copied.

## Steps

1. **Confirm it's really a skill.** A skill is a *repeatable procedure* with a trigger. If it's a
fact/decision it's a `note`; if it's deterministic testable logic it's `code`. When unsure, read
`knowledge/notes/skill-vs-note-vs-code.md` and decide before creating anything.
2. **Get the essentials** (ask if not supplied):
- **Name** — short, kebab-case (`review-signals`, `github-cli-setup`). Becomes the folder name.
- **When to use it** — the concrete triggers, ideally including the phrases a user would say.
- **The procedure** — the ordered steps, and any hard "never do this" rules.
3. **Check for duplication/overlap.** Look at the existing `.claude/skills/*/SKILL.md`. If a skill
already covers this, extend it rather than adding a near-duplicate (e.g. don't add a PR-flow
skill when `ship-loop-change` already owns verify→commit→PR).
4. **Write `.claude/skills/<name>/SKILL.md`** in the house style:
- **Frontmatter** — `name:` (matches the folder) and `description:`. The `description` is what
triggers the skill, so make it do double duty: *what* it does **and** *when* to use it,
including trigger phrases. Study the descriptions on `new-loop` and `review-signals` for the
length and specificity to match.
- **`# <name>`** heading, then a short intro: the problem this solves and when to reach for it.
- **`## Steps`** — numbered, imperative, concrete. Name the actual commands/paths/fields, not
"do the thing." Where a step is deterministic, point at code to call rather than prose to
re-derive.
- **`## Do not`** — the failure modes and hard boundaries. This is where hard-won lessons live;
don't skip it.
5. **Keep it generic** unless it's deliberately project-specific — a skill should read the same
regardless of which project pulled in this template.
6. **Register it in `CLAUDE.md`** — add a line to the `.claude/skills/` entry in the repo map so a
session knows the skill exists.
7. **Log it** — append one line to the root `LOG.md` (newest at top):
`YYYY-MM-DD HH:MM | scaffold | added <name> skill — <one-line purpose> | [[.claude/skills/<name>/SKILL.md]]`.
8. **Ship it** via `ship-loop-change` (branch → verify → commit → PR) rather than committing
directly, per this repo's convention.

## Do not

- Do not create a skill for a one-off — if it won't recur, it belongs in the run's `LOG.md`, not a
skill. Promote to a skill once it repeats (that's the `review-signals` pattern).
- Do not write a vague `description` — a skill that doesn't say *when* to use it silently never
triggers, which is worse than not existing.
- Do not duplicate an existing skill's territory; extend the incumbent instead.
- Do not embed deterministic logic (parsing, validation, dispatch) as prose steps when it could be
tested code the skill calls.
- Do not forget the `CLAUDE.md` registration and `LOG.md` line — an unregistered skill is hard to
discover.
6 changes: 4 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ know before touching code.}}
- `knowledge/` — the shared memory loops read and write between runs (`signals/`, `notes/`,
`domains/`). Read `knowledge/README.md` once; it's short.
- `.claude/skills/` — `new-loop` (scaffold a domain), `ship-loop-change` (verify-before-ship),
`review-signals` (promote piled-up signals), and generic GitHub playbooks `github-cli-setup`
(session/scope checks) and `github-project-tracking` (milestones + issues + Projects board).
`review-signals` (promote piled-up signals), `write-skill` (scaffold a new skill in the house
style), and generic GitHub playbooks `github-cli-setup` (session/scope checks) and
`github-project-tracking` (milestones + issues + Projects board). The rule for skill vs. note vs.
code is in `knowledge/notes/skill-vs-note-vs-code.md`.
- `LOG.md` — the global activity feed. Append one line here right before you commit a bulk of
work from any loop run.

Expand Down
1 change: 1 addition & 0 deletions LOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Format: `YYYY-MM-DD HH:MM | domain | one-line summary | link(s)`

## Entries

- 2026-07-26 23:05 | scaffold | documented the skill system: skill-vs-note-vs-code taxonomy note, write-skill meta-skill, github-project-tracking case study, and a README Skills index | [[knowledge/notes/skill-vs-note-vs-code.md]]
- 2026-07-26 22:51 | scaffold | added github-cli-setup + github-project-tracking skills (generic GitHub playbook: gh account/scope checks, milestones/issues/Projects-v2 board) | [[.claude/skills/github-project-tracking/SKILL.md]]
- 2026-06-22 16:00 | scaffold | stress-tested the orchestration/execution decision rule against opposite-shape domains (event+engine, scheduled+no-engine); rule held, fixed an implicit correlation in docs/loop-engineer-pattern.md's examples | [[docs/loop-engineer-pattern.md]]
- 2026-06-22 15:00 | review-signals | added review-signals skill + skill-writing recipe; dogfooded against a synthetic signal (correctly judged "leave open," then removed) | [[.claude/skills/review-signals/SKILL.md]]
Expand Down
30 changes: 27 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,39 @@ knowledge/
CLAUDE.md template every session reads — fill in the {{PLACEHOLDER}}s for your project
LOG.md global one-line-per-run activity feed
.claude/skills/
new-loop/ scaffold a new knowledge/domains/<name>/README.md
ship-loop-change/ verify (test/lint), then commit + PR — never ship unverified
review-signals/ periodically promote signals that have built up enough evidence to act on
new-loop/ scaffold a new knowledge/domains/<name>/README.md
ship-loop-change/ verify (test/lint), then commit + PR — never ship unverified
review-signals/ periodically promote signals that have built up enough evidence to act on
write-skill/ scaffold a new skill in the house style, then register + log it
github-cli-setup/ pre-flight the gh session: right account, repo visibility, token scopes
github-project-tracking/ turn a roadmap into milestones + issues + a Projects (v2) board
```

Copy either example domain as a starting point, or run the `new-loop` skill to scaffold a blank
one. Triggers (cron/webhook) aren't reimplemented here — wire a domain's cadence to Claude Code's
own `/schedule` or `/loop` skill; see [`docs/loop-engineer-pattern.md`](docs/loop-engineer-pattern.md).

## Skills

The `.claude/skills/` directory is the reusable-procedure catalog — each is a `SKILL.md` an agent
follows when its `description` matches the moment. Some drive this template's own loop workflow;
others are generic playbooks (like the GitHub ones) that any project built from the template
inherits. The rule for what becomes a skill vs. a `knowledge/notes/` note vs. tested code is in
[`knowledge/notes/skill-vs-note-vs-code.md`](knowledge/notes/skill-vs-note-vs-code.md); use
`write-skill` to add a new one in the house style.

| Skill | What it does |
|---|---|
| [`new-loop`](.claude/skills/new-loop/SKILL.md) | Scaffold a new `knowledge/domains/<name>/` charter for a loop. |
| [`review-signals`](.claude/skills/review-signals/SKILL.md) | Promote signals that have built up enough evidence into notes or backlog items. |
| [`ship-loop-change`](.claude/skills/ship-loop-change/SKILL.md) | Verify (lint/type/test) → commit → PR. Never ship unverified. |
| [`write-skill`](.claude/skills/write-skill/SKILL.md) | Scaffold a new skill in the house style, then register and log it. |
| [`github-cli-setup`](.claude/skills/github-cli-setup/SKILL.md) | Pre-flight the `gh` session: right account active, repo visible, token scopes present. |
| [`github-project-tracking`](.claude/skills/github-project-tracking/SKILL.md) | Turn a roadmap into milestones + issues + a Projects (v2) board. |

For a worked example of the GitHub skills on a real project, see
[`knowledge/notes/case-study-github-project-tracking.md`](knowledge/notes/case-study-github-project-tracking.md).

## Using this as a template

Click **"Use this template"** on GitHub, or:
Expand Down
52 changes: 52 additions & 0 deletions knowledge/notes/case-study-github-project-tracking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
title: "Case study: scaffolding a project roadmap with github-project-tracking"
type: note
domain: []
status: adopted
links: [[skill-vs-note-vs-code]]
---

A worked example of the `github-project-tracking` and `github-cli-setup` skills on a real project,
kept as provenance: it shows the skills doing end-to-end work, and it's where the skills were
generalized *from* (the reusable version was extracted after doing this once by hand).

## What happened

Starting point: a written architecture/roadmap for a mobile app, with the work already divided
into six phases (M0–M5). Goal: make that roadmap trackable on GitHub instead of living in a doc.

The run, in order:

1. **`github-cli-setup` first.** `gh auth status` showed two logged-in accounts; the one that
*owned* the target repo wasn't the active one, and its token was missing the `project` scope.
Switched accounts, and — because scope grants are interactive — handed the user the exact
`gh auth refresh -s project` command to run. This is precisely the failure the skill exists to
front-load: without it, the board step would have died halfway through.
2. **Milestones.** Six milestones (M0–M5) created via `gh api`, one per roadmap phase. Only needs
`repo` scope, so this ran before the `project` scope was even granted.
3. **Issues.** 24 task issues created with `gh issue create --milestone`, each body pointing back
at the roadmap section it came from, so an issue is self-explanatory without the doc.
4. **Board.** A Projects (v2) board created, linked to the repo, all 24 issues added, and each set
to `Todo` — laid out by Status for day-to-day work.

## What this validated about the skills

- **The scope split is real and load-bearing.** Milestones and issues (18-plus artifacts) were
created under `repo` scope while the board waited on an interactive `project`-scope grant.
Blocking everything on `project` would have stalled the whole run for no reason.
- **A 404 meant "wrong account," not "no repo."** The private repo was invisible to the initially
active account; the reflex to treat a 404 as "doesn't exist" would have been wrong. This lesson
is now written into `github-cli-setup`'s "Do not."
- **Eventual consistency is observable.** Right after bulk-adding, the board's item *count* lagged
the actual items. Verifying by listing issue numbers (not trusting the count) is now a step in
`github-project-tracking`.

## Reusable takeaway

The general shape — *check the session → create the cheap-scope artifacts → grant the extra scope →
create the expensive-scope artifacts → set initial state → verify by enumeration* — is what got
lifted into the two skills. Doing it once by hand, then extracting the skill, is the intended path
(see [[skill-vs-note-vs-code]]: promote to a skill once it recurs, not on the first occurrence).

## Timeline
- 2026-07-26 | created — recorded the first end-to-end run that the github-* skills were generalized from
61 changes: 61 additions & 0 deletions knowledge/notes/skill-vs-note-vs-code.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
title: When to write a skill vs. a knowledge note vs. code
type: note
domain: []
status: adopted
links: []
---

This template gives an agent three different places to put something it figures out. Choosing the
wrong one is the most common way the system rots: reusable procedures get buried in chat, one-off
facts get promoted to skills nobody triggers, and logic that belongs in tested code ends up
re-derived in prose every run. This note is the decision rule.

## The three homes

| You have… | It goes in… | Because |
|---|---|---|
| A **repeatable procedure** — "when X, do these steps" | a **skill** (`.claude/skills/<name>/SKILL.md`) | Skills are *instructions an agent follows*. They're triggered by a description match and re-run the same way each time. |
| **Durable knowledge** — a decision, an analysis, something learned that should outlive the task | a **note** (`knowledge/notes/<slug>.md`) | Notes are *things that are true*, read by a human or agent for context. They don't "run." |
| **Deterministic logic** — parsing, control flow, anything with a right answer you can test | **code** (`src/`) | Code is *executed, not interpreted by a model*. If it can be unit-tested, it shouldn't live in a prompt. |

## The decision rule

Ask, in order:

1. **Does it run the same way every time and can I write a test for it?** → **code.** Model
tokens are the wrong tool for deterministic work (JSON parsing, date math, dispatch). Put it in
`src/` behind a test. Skills and notes *call* code; they don't reimplement it.
2. **Is it a procedure an agent should follow when some trigger fires?** → **skill.** The tell is
that you can write a `## Steps` list and a `description` that says *when* to use it. If you find
yourself re-explaining the same steps to the agent across sessions, that's a missing skill.
3. **Is it a fact, a decision, or something learned — true whether or not anyone acts on it?** →
**note.** The tell is there are no "steps," just "here's what's true and why." Decisions
especially: capture what was chosen *and what was rejected and why*, so it isn't relitigated.

## Boundary cases (where it's tempting to get it wrong)

- **A skill that hardcodes a fact** → split it. The procedure is the skill; the fact it depends on
is a note the skill *reads*. Otherwise the fact is invisible to everything except that one skill.
- **A note that lists steps** → that's a skill wearing a note's clothes. If the point is "do this,"
it's a skill, even if you also want prose around it.
- **A skill re-deriving logic every run** (parsing output, validating a schema in prose) → that
logic wants to be code the skill calls, so it's tested once instead of improvised each run.
- **"It's just this once"** → then it's neither; leave it in the run's `LOG.md`/Timeline. Promote
to a skill or note only when it recurs (this is exactly what `review-signals` is for).

## Options considered, and why not

- **One folder for everything ("just markdown").** Rejected: losing the skill/note distinction
loses the trigger. Skills are found by description-match at the moment they're needed; notes are
read for context. Collapsing them means either everything tries to "run" or nothing does.
- **Everything as a skill.** Rejected: notes don't have a trigger or steps, and forcing a `## Steps`
shape onto a decision record makes it worse to read and tempts re-running something that
shouldn't run.
- **Put procedures in code too.** Rejected for *agent* procedures: the value of a skill is that a
model adapts the steps to context (which files, which account, which repo). Hardcoding that in
Python removes the judgment that made a skill the right tool. Deterministic sub-steps still drop
down into code the skill calls.

## Timeline
- 2026-07-26 | created — codifying the skill/note/code split after the knowledge base grew to five skills, so new artifacts land in the right home
Loading