# New Skill

> Take a NEW Claude Code skill from idea to published-and-live, the way Felix ships them: grill the idea into a crisp skill-spec, scaffold a dedicated repo (skills/<name>/SKILL.md), author the SKILL.md, TEST that it actually triggers correctly (fires on the right prompts, stays quiet on decoys) and works end-to-end, present one review brief, then on approval publish it (gh repo create + npx skills add -g). Use when the user says "new skill: X", "make/build/create a skill that…", "author a skill", "ship a skill", or "/new-skill". This is the full authoring+testing+publishing loop — not just scaffolding, and not for editing or debugging an existing skill (that's skill-doctor).

- Skill: `sunfmin/new-skill` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add sunfmin/new-skill`
- Raw SKILL.md: https://api.skillmd.com/api/skills/sunfmin/new-skill/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: sunfmin (https://skillmd.com/u/sunfmin)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/sunfmin/new-skill

---


# new-skill — idea → tested → published

Ships a **new** Claude Code skill end to end. The reason this beats hand-scaffolding is the
middle and the end: it **tests that the skill triggers correctly and works**, and it
**publishes cleanly** via Felix's exact convention. One human checkpoint, deferred as late
as possible (just before the irreversible publish).

**Scope:** brand-new skills only. Improving/debugging an existing skill → `skill-doctor`.

**Conventions (non-negotiable):**
- Layout: a dedicated repo `~/Developments/<name>/` → GitHub `sunfmin/<name>`, skill at
  **`skills/<name>/SKILL.md`** (a `skills/` subdir — NEVER repo root). Monorepo variant:
  `~/Developments/felix-skills/skills/<name>/` on a branch.
- Publish + install **globally** (`npx skills add … -g`). Never hand-edit `~/.claude/skills/`
  — `npx skills update` clobbers it; the source of truth is `~/Developments/<name>`.
- Need a credential? Get it via the `mytokens` skill — never prompt for a raw token.

Run the phases in order. Do NOT publish (Phase 5) without the Phase 4 approval.

---

## Phase 0 — Intake grilling → skill-spec

Grill the user **one question at a time, each with a recommended answer** (the loop-me /
grilling discipline). Don't scaffold until every field below is filled. Capture the answers
into a **skill-spec** and write it to `skills/<name>/.skill-spec.md` (it seeds authoring and
future `skill-doctor` regression tests):

| Field | What to pin down |
|---|---|
| `name` | kebab-case. **Collision-check** it (Phase 0.1) before continuing. |
| `description` | One-line purpose + the trigger phrasing that goes in frontmatter. |
| `should_fire` | 3+ concrete prompts/situations where it MUST activate. |
| `decoys` | Nearby prompts where it must NOT activate. User adds; you also derive near-misses. |
| `examples` | 2–3 concrete invocations. |
| `needs` | Tools / scripts / CLIs / MCP tools / assets the skill depends on. |
| `functional_test` | ONE representative task **+ a checkable success condition** (concrete input, and how to know the output is right). Required — Phase 3.2 runs it. |
| `target` | dedicated repo (default) or `felix-skills` monorepo. |
| `visibility` | `public` (default) or `private`. |

### Phase 0.1 — Collision check
```bash
rg -q "\"$NAME\"|/$NAME\b|$NAME ->" ~/.agents/.skill-lock.json && echo "COLLISION: lockfile"
[ -e ~/Developments/$NAME ] && echo "COLLISION: ~/Developments/$NAME"
```
Any collision → have the user rename before proceeding.

---

## Phase 1 — Scaffold

Create the real repo dir so the checkpoint reviews real files:
```bash
mkdir -p ~/Developments/$NAME/skills/$NAME/{scripts,references}   # drop empty subdirs later
```
Write `skills/$NAME/.skill-spec.md` from Phase 0.

## Phase 2 — Author

Write `skills/$NAME/SKILL.md` and any assets from the skill-spec. Follow **`writing-great-skills`**
for description shape, discoverability, and rule clarity, and reuse **`skill-creator`** patterns.
Bundle any scripts the spec's `needs` calls for. Keep the frontmatter `description` explicit
about trigger situations — that is what Phase 3.1 measures.

## Phase 3 — Test (both dimensions)

### 3.0 Frontmatter gate — automatic, runs first
`trigger_test.py` now refuses to start unless `SKILL.md`'s frontmatter parses as **strict**
YAML with a non-empty `name`/`description` matching `--name`; `publish.sh` re-checks before
pushing. Do not skip or work around it: `npx skills add` parses strictly and **silently skips**
a skill that fails, so the repo gets created and *nothing installs* — while this harness and
the agent runtime both read SKILL.md leniently and report everything green. The bug that
motivated it: a description containing `: ` (colon-space) inside an unquoted scalar →
`Nested mappings are not allowed in compact mappings`, discovered only at publish time after a
7/7 trigger pass. When writing descriptions, prefer ` — ` over `: `.

The gate needs PyYAML, which system `python3` usually lacks. Both scripts now borrow it via
`uv run --no-project --with pyyaml`, and `publish.sh` **refuses to publish** if no parser can
be found. Previously it printed `pyyaml missing, skipping strict check` and published anyway —
a gate that waves the skill through when the parser is absent is worse than no gate, because
the reassuring line hides that nothing was checked.

### 3.1 Trigger test (discovery) — REQUIRED
Write the spec's prompts to a cases file and run the validated harness:
```bash
echo '{"should_fire": [...], "decoys": [...]}' > /tmp/${NAME}_cases.json
python3 SKILL_DIR/scripts/trigger_test.py \
  --name "$NAME" --skill-dir ~/Developments/$NAME/skills/$NAME \
  --cases /tmp/${NAME}_cases.json --jobs 3
```
It installs the candidate as a project skill among all of Felix's real skills, runs a real
headless `claude -p` probe per prompt with execution tools disabled (zero side effects), and
detects whether the `Skill` tool fired for this candidate. **Pass = every should_fire
activated AND no decoy did.** A miss usually means the `description` needs sharpening (or a
decoy legitimately belongs to another skill — note it).

**Before you rewrite a description to chase a miss, check `first_tool` in the output.**
Probes run `--max-turns 4` (was 1) because `Read`/`Glob` are *not* disallowed: for a prompt
like *"fix the type errors in src/models.py"* the model's first move is to look at the file,
and at one turn the probe ended right there and scored a miss — even though the skill loads
on turn 2. Measured on a real skill, the same prompts scored **2/6 at one turn and 6/6 at
five**. Decoys run at the same limit, so the extra room cannot hide over-firing. A miss whose
`first_tool` is `Read`/`Glob` is a measurement artifact; one with no tool call at all is a
real description problem.

Prompts that name real files also need those files to exist, or the model burns its turns
hunting. Point `--project-dir` at a fixture repo for those (the candidate is symlinked in and
removed afterwards; the fixture is left untouched); the default empty throwaway project only
suits from-scratch authoring prompts.

### 3.2 Functional test — REQUIRED
Execute the skill on the spec's `functional_test` task and evaluate its success condition;
capture the output. If running it fully would cause side effects (publishing, sending,
writing to shared state), run it in the skill's own dry-run / sandbox mode. **Pass = success
condition met.**

Record every miss (which prompt, expected vs actual) for the brief.

## Phase 4 — Brief + checkpoint (the one gate)

Present a tight brief and stop:
- name · one-line purpose · target repo · visibility;
- link to `skills/$NAME/SKILL.md` + the asset list;
- **test scoreboard**: `trigger: fired N/N, decoys N/N clean` · `functional: PASS/FAIL (+output)`;
- the exact publish commands Phase 5 will run.

Then the user chooses:
- **approve** → Phase 5;
- **revise** → they say what to change; re-author (Phase 2) and **re-test** (Phase 3), present a fresh brief;
- **discard** → `rm -rf ~/Developments/$NAME` (nothing was ever pushed).

## Phase 5 — Publish (only on approve)

```bash
bash SKILL_DIR/scripts/publish.sh "$NAME" "<visibility>"
```
It commits, creates `sunfmin/$NAME` and pushes, `npx skills add sunfmin/$NAME -g -y`, and
verifies with `skills list`. On any step failing it stops loudly without half-registering.
Monorepo target instead: commit the new `skills/$NAME/` folder to `~/Developments/felix-skills`,
push, then `npx skills update felix-skills`.

Close out with one line: `Published sunfmin/$NAME, installed globally, live.`

---

## Guardrails
- The publish in Phase 5 is outward-facing and hard to undo (public repo, mutates the live
  skill env). Never run it before the Phase 4 approval.
- `SKILL_DIR` above = this skill's own directory (`.../skills/new-skill`).
- If `mytokens` is needed for a credential during a functional test, use it — don't prompt.

