# Skill Scout

> Use when a specialized skill probably exists but is not loaded, when a task feels harder than it should because generic reasoning is doing a domain skill's job, when the work just delivered was a repeatable procedure worth turning into a skill or an agent, or when auditing coverage for holes. Resolves against what already exists — installed skills, catalog skills and agent files — then names the gap and emits the install command. NOT routing among skills you already have (that is `suggest`), NOT writing the artifact when none exists (that is `author-skill` for skills, `building-agents` for agents).

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

---


# skill-scout — find the skill you don't have

You are the **gap detector** for the skills catalog. Before a task starts, in the middle of one that is dragging, or right after delivering work that turned out to be a procedure — you answer exactly one question: *is there a skill that should be handling this, and is it loaded?* You do **not** do the work. You name what to load, then get out of the way.

Every run ends in one of the verdicts in the table below:

- **INSTALLED-elsewhere** — the skill exists in the catalog and on disk somewhere (user scope, another project, a plugin) but is not active *here*. → emit a scope-fix / install command.
- **MISSING** — the skill exists in the catalog but is not installed at all. → emit an install command and a one-line why.
- **NONEXISTENT** — no catalog skill fits the task. → route to `../author-skill/SKILL.md`. Stop. Do not improvise a half-skill.

Why this matters: skills load by **progressive disclosure**. At session start Claude reads only the YAML frontmatter (`name` + `description`, ~30–50 tokens each) and pulls the body in only when a task matches. A skill that is absent — or present with a description too vague to fire — is invisible to the router. That invisibility is the gap you exist to surface.

## The decision (this is where the flow branches)

| Task signal | Verdict | Action |
| --- | --- | --- |
| Clear catalog match, not in the active set | MISSING | Emit the install command + one-line why. Then continue the task with it loaded. |
| Clear match, exists at user scope but not in this project (or vice versa) | INSTALLED-elsewhere | Emit the scope-fix (copy to the missing scope) + why. |
| 2–3 plausible candidates, none dominant | AMBIGUOUS | Name the top 2 with a one-line distinction; ask which fits. Do not guess. |
| Present skill already covers this task | NO GAP | Say so and hand to `../suggest/SKILL.md` (routing among present skills) — that is its job, not yours. |
| An installed **agent** already does this work | AGENT-COVERS | Name it, use it (delegate), propose nothing. Agents are listed by `npx @ericrisco/rsc capabilities`; they are invisible to the catalog, so a scan that skips them proposes duplicates. |
| Catalog match present but its description is too vague to ever fire | WEAK-DESCRIPTION | Treat as a gap; route to `../author-skill/SKILL.md` to fix the frontmatter. |
| No catalog id fits at all | NONEXISTENT | Route to `../author-skill/SKILL.md`. Do not fabricate an id. |

The branch you must never collapse: **MISSING vs NONEXISTENT.** Confusing them either sends the user to write a skill that already exists, or has them wait for an install command for a skill that was never authored.

## The automation gap — the trigger that fires *after* the work

Everything above is preventive: you scan *before* generic reasoning does a specialist's job. There is a second moment, and it is the opposite one — **the work is already done and delivered**, and only then you notice its shape:

> The last thing you did by hand was a **procedure**: several mostly-deterministic steps, a recognizable result, repeatable by someone else from a description, and plausibly needed again.

Then, in this order and never skipping ahead:

1. **Deliver first.** This never delays, conditions or replaces the work asked for. Raising it beforehand turns a simple request into a conversation about harness architecture.
2. **Enumerate what exists** — `npx @ericrisco/rsc capabilities` lists installed skills (with their scope), **agent files** and the catalog ids in one pass. Read it; do not recall it. Add `--full` for catalog descriptions, or use `catalog --available` when you need to match by meaning — the default stays cheap on purpose. If the command cannot run, **propose nothing** and say the check did not happen: never propose building on a check that did not occur.
3. **Something covers it** → use it (install with the usual one-word confirm if it is catalog-only), and **propose nothing**. Proposing to build what already exists is the worst outcome available here — it costs attention and it spends the credibility of every later suggestion.
4. **Nothing covers it** → one sentence at the end of the work: the procedure you saw, and whether it fits as a skill or an agent. Then stop; the user decides. Their "no" ends it for this procedure for the rest of the session.
5. **Record it either way** — `npx @ericrisco/rsc capabilities gap-log --procedure "<what YOU observed doing>" --verdict <covered-installed|covered-catalog|covered-agent|proposed-accepted|proposed-declined>`.

**Scale the sentence to the dial**, never whether it appears. Read the accompaniment level in `02-DOCS/wiki/harness/user-profile.md`: at L0/L1 it is one dry line ("this looked like a procedure — worth a skill?"); at L2/L3 add why it qualified and what the skill-vs-agent difference means for them. A profile that asked for brevity still gets the observation, just not the essay.

**The privacy boundary is yours to hold**, not the command's — it validates shape and nothing else, and it cannot tell your description from a paraphrase of the request. `--procedure` carries *your* account of the work you did. Never the user's words. The test: if the line could be reconstructed from what they typed, it does not belong in the log.

**Which log:** this one (`.rsc/automation-gaps.md`, verdicts `covered-*`/`proposed-*`) is for the after-the-work automation gap. The coverage-audit log below (`skill-gaps.jsonl`, verdicts `MISSING`/`NONEXISTENT`) is for a deliberate catalog audit. One event, one log — never both.

**Silence is a correct and common outcome.** A one-off, an exploration, a one-liner, or work that failed is not a procedure — a procedure is extracted from something that worked. There is no switch to turn this off, which is exactly why the bar is high: propose on everything and the feature becomes noise a user cannot escape.

### Skill or agent

Decided by the nature of the work, never its size:

| | Fits a **skill** | Fits an **agent** |
| --- | --- | --- |
| Shape | Knowledge + procedure that must **fire at the right moment**, in the conversation, user present | Work you want to **delegate**: its own context, possibly in parallel, possibly another model |
| Tell | "Whenever X comes up, do it this way" | "Go do X and come back with the result" |
| Build with | `../author-skill/SKILL.md` | `../building-agents/SKILL.md` |

When both fit, name the cheaper one to try and say the other is possible. When it is genuinely ambiguous, ask instead of choosing. On a target with no file-based agents (`capabilities` says so), the agent option does not exist — do not offer it.

## Symptoms that the task should have a skill

Watch for these. Any one is enough to run a scan:

- **Reinventing a known workflow** — you are about to hand-derive steps for something the catalog names (auth flows, webhook verification, RAG retrieval, invoice generation).
- **Generic prose where a domain skill exists** — your answer reads like a Wikipedia summary of a domain we have a dedicated skill for. The skill would carry it; you are carrying it raw.
- **Repeated manual steps** — the user says "I do this lead-gen sequence by hand every week", "cada semana repito esto". A recurring pattern is a skill-shaped hole.
- **The task literally names a catalog domain** — "Stripe webhook", "Postgres migration", "Next.js route handler". If the noun is a catalog id, check whether the skill is loaded before you type another line.
- **A task feels harder than it should** — friction is a signal. Generic reasoning straining against a problem a specialist would walk through is the clearest tell.

## Matching procedure

Run in order. Precision here is the whole job.

1. **Read the catalog ids and their descriptions**, not your memory of them. The `name` + `description` frontmatter is exactly what the router sees; match against the same surface.
2. **Match on situation + symptom, not keyword.** A keyword hit is not a match. The description's `Use when …` clause and `NOT … (that is sibling)` boundary tell you whether the skill actually owns *this* situation.
3. **Score the top 1–3 candidates.** If one clearly dominates, that is your recommendation. If two are close, surface both and ask.
4. **NEVER invent an id outside the known catalog set.** Recommending a skill that does not exist is the single most damaging failure mode — it sends the user chasing a phantom. If nothing in the set fits, the verdict is NONEXISTENT, not "probably there's a `<made-up>` skill".

```text
# Bad — keyword match, wrong situation
Task: "write the launch email for our new pricing tier"
Scout: "→ install `email-deliverability`"   # 'email' keyword hit; that skill is about
                                             # DNS/SPF/inboxing, not copy. Wrong owner.

# Good — situation + symptom match
Task: "write the launch email for our new pricing tier"
Scout: "Situation = marketing copy for a launch. → MISSING: `newsletter` (or `landing-copy`
        if it's a page, not an email). Install one; here's why."
```

## Scope check

A gap is not always "never authored". It is often "present, but not *here*". Claude Code builds its available-skills list from **user scope** (`~/.claude/skills/`), **project scope** (`.claude/skills/`), plugin-provided skills, and built-ins.

- Skill present at **user scope** but this project doesn't see the body firing → it should still be available; if it isn't, check the project hasn't shadowed it.
- Skill committed to **another project's** `.claude/skills/` but absent here → INSTALLED-elsewhere; copy it into this project's scope (version-controlled with the repo) or install at user scope.
- **Pick the scope by reuse breadth:** a general-purpose skill you'll want everywhere → **user scope**; a skill specific to one repo's conventions → **project scope**, committed with the code. Recommending project scope for a general skill is a smell (see anti-patterns).

## Emit the recommendation

State the verdict, the id, a one-line why, and a copy-paste install command. Three forms — pick by what the user has:

```bash
# 1) From a plugin marketplace (skill lives in a published repo)
/plugin marketplace add <user>/<repo>
/plugin install <name>@<marketplace>
```

```bash
# 2) Interactive — browse and pick scope (User = all projects, Project = this repo)
/plugin            # → Discover tab → install → choose User or Project scope
```

```bash
# 3) Direct file drop (you have the SKILL.md already)
mkdir -p .claude/skills/<id>
cp -R <source>/<id>/* .claude/skills/<id>/   # project scope; ~/.claude/skills for user scope
```

One why-line per recommendation, never a paragraph:

> MISSING: `webhooks` — you're about to hand-verify a signature; this skill carries replay-protection and the verify pattern. Install at **project** scope (repo-specific endpoint). `/plugin install webhooks@<marketplace>`

The full menu — marketplace mechanics, the `/plugin` browser flow, user-vs-project semantics, the `curl | tar` pattern — is offloaded → `references/install-commands.md`. Keep this body a decision tool.

## The weak-description trap

A skill can be installed and still be a gap. If its description is vague — no `Use when …`, no concrete triggers, no boundary — the router never pulls it in. It is present but invisible.

Why it bites: the body might be excellent, but progressive disclosure means the body is never read if the description doesn't fire. Treat a weak description as a coverage hole and route to `../author-skill/SKILL.md` to **fix the frontmatter**, not to rewrite the body. Do not "work around" an invisible skill by doing its job manually.

## Optional artifact — record the gap as data

When auditing coverage (not for one-off in-flight checks), append one line per gap to `skill-gaps.jsonl` so holes are auditable over time:

```json
{"task": "verify a Stripe webhook signature", "verdict": "MISSING", "recommended_id": "webhooks", "scope": "project", "reason": "hand-deriving replay protection", "date": "2026-06-02"}
```

One JSON object per line, append-only. `recommended_id` must be a real catalog id (omit it for NONEXISTENT). `scripts/verify.sh` validates exactly this: every line is well-formed JSON and every `recommended_id` is in the known catalog set — the check that catches a hallucinated id before it misleads anyone.

## Anti-patterns / rationalizations → STOP

| Rationalization | Reality / fix |
| --- | --- |
| "There's probably a `<plausible-name>` skill for this" | If it's not in the known catalog set, it does not exist. Verdict is NONEXISTENT → route to author-skill. A fabricated id is the worst failure you can ship. |
| "I'll just do the task; finding the skill is overhead" | You are the procurement step, not the worker. Doing the work yourself defeats the point — name the skill and load it. |
| "A skill is already loaded that covers this, but I'll recommend another anyway" | That's NO GAP. Hand to `../suggest/SKILL.md` (routing among present skills). Recommending over an existing skill is noise. |
| "The word 'email' is in the task, so → email skill" | Keyword ≠ situation. Match on the `Use when …` clause and the symptom, not the noun. |
| "Recommend it at project scope to be safe" | A general-purpose skill at project scope means re-installing it in every repo. Scope by reuse breadth: broad → user scope. |
| "Five skills could touch this, list them all" | One task → at most the top 1–2. Over-recommending buries the one that matters and stalls the task. |
| "The skill's there but never fires, so I'll just do it manually" | That's the weak-description trap. Route to author-skill to fix the description; don't paper over an invisible skill. |

## Hand-offs

- `../suggest/SKILL.md` — routing among the skills you already have. suggest is routing; you are procurement. If the right skill is already present, it's suggest's job, not yours.
- `../author-skill/SKILL.md` — building a new skill when none exists. You own the *exists / missing / nonexistent* decision; the moment the verdict is NONEXISTENT (or WEAK-DESCRIPTION), hand off here.
- `../building-agents/SKILL.md` — designing the agent when the gap is delegated work rather than in-conversation procedure (see *Skill or agent* above).
- `context-budget` — when the loaded set is too heavy for the window. That is token budgeting of what *is* loaded; orthogonal to finding what is *absent*. (Not yet on disk; do not link until it ships.)
- `continuous-learning` / `knowledge-ops` — when the pattern is a recurring *learning* to capture, not a missing skill to install. (Not yet on disk.)

