rafa pages
- rafa
- rafa skill
rafa skill
Check a skills directory, list and show the skills a loop session sees, search them, and demote or backfill a directory.
Skills are offered to plan tasks by the resolver task.skills names. rafa skill checks that a skills directory is one an agent can follow, shows which skills a loop session sees, and tidies a directory through a reviewed report.
Spends: 🪙 search (one haiku session unless --no-model) and backfill --propose (one session per batch of skills). Changes: demote applies a reviewed report; backfill writes the fields a directory lacks; the rest read only.
Things to know before you use it:
rafa skill check .claude/skills --project=.refuses a skill an agent could not follow, such as a path that does not resolve or a missing field, before it costs a task.
In the target layout this code lives in the private package rafa-inventory, bundled into @open-tomato/rafa (Repository layout). In 0.47.0 it is already a package, @open-tomato/rafa-inventory in packages/rafa-inventory, but only as a facade: it re-exports this code from the root package's src/, where the files still live until their move. You install and type the same either way. [verify: the release the move lands in]
Actions
| Action | Does |
|---|---|
check | check every skill under a skills directory for layout, schema, resolution and locality |
list | list every skill with its source, its state and whether the loop sees it |
show | show one skill: its record, frontmatter, other holders and headings |
search | find the skills that answer a question, each with a quote from its file 🪙 unless --no-model |
demote | classify a skills directory into the demotion report, and apply a reviewed one |
backfill | fill in the fields a skills directory lacks, by proposal and by derivation 🪙 with --propose |
rafa skill check
Check every skill under a skills directory for layout, schema, resolution and locality.
rafa skill check <dir> [--fix] [--project=<string>]
Runs the five checks over a skills directory, in order and all of them on every file, so one run names every rule a file breaks: layout (the two shapes that parse and silently register nothing, <dir>/<group>/<name>.md and <dir>/<group>/<name>/SKILL.md), schema (the required fields, the enums, the description and when_to_use caps, the stack vocabulary and the paths globs), resolution (every path the body names, every script under the skill's own directory and every tool named in a fenced shell command) and locality (an absolute path that is one machine's home). The exit code is the number of failing files, capped at 255; warnings, such as a project path in a run given no --project, never count. --project=<root> is the checkout the bodies are consumed in, and without it a project-looking path is left unchecked. --fix fills tags and stack by inference on a file whose only failures are those two missing fields, and never touches a body. With --output=json a clean run gives the reports as the data of the terminal result event.
| Argument | Type | What it is |
|---|---|---|
dir | string, required | The skills directory to check: ~/.claude/skills, a project's .claude/skills, or rafa's own. |
| Flag | Type and default | What it does |
|---|---|---|
--fix | boolean | Fill tags and stack by inference on a file whose only failures are those two missing fields. |
--project | string | The project root the bodies are consumed in, which their paths resolve against. |
Examples:
rafa skill check .claude/skills --project=.: Checks this project's tier against this checkout, exiting with the number of failing files.rafa skill check ~/.claude/skills --fix: Fillstagsandstackon every user skill that lacks only those, leaving each body unchanged.
Output formats: text, json.
rafa skill list
List every skill with its source, its state and whether the loop sees it.
rafa skill list [--tier|--source=<string>] [--state=<string>]
[--hidden-from-loop] [-i|--interactive]
Lists every skill the inventory holds — the project's .claude/skills, the bundled/skills directory beside the running rafa, ~/.claude/skills, each loaded add-on's and each installed plugin's — one row each: a mark saying whether a session the loop spawns under loop.settingSources resolves it or is served it from the rafa tier, its name, its source, its state (enabled, collision when two loaded tiers hold different skills under the name and a tiers.skills pin must settle it, shadowed-by:<source> when another source serves the name, or disabled:<how>) and its own description as the summary. --source=<source> keeps one source, plugin:<name> and addon:<name> included; --state=<state> keeps enabled, collision, shadowed or disabled rows; --hidden-from-loop keeps the rows no loop session resolves. The filters combine. A skills directory that is not there says so, and a source that does not read is a warning. The exit code is 0 whatever the rows say: this command reports and rafa skill check gates. With --output=json the rows, each with its checker verdict, are the data of the terminal result event. -i browses the listed rows in the terminal instead of printing them, and refuses without one.
| Flag | Type and default | What it does |
|---|---|---|
--tier, --source | string | List one source alone: project, rafa, user, plugin:<name> or addon:<name>. --tier is an alias, removed after one release. |
--state | string | List the rows in one state alone: enabled, collision, shadowed, disabled. |
--hidden-from-loop | boolean | List the rows no session the loop spawns resolves. |
-i, --interactive | boolean | Browse the listed rows in the terminal: Enter shows one, f its full context, Escape goes back, q quits. Refused without a terminal and with --output=json. |
Examples:
rafa skill list: Lists every skill, each with its source, its state and whether the loop sees it.rafa skill list --source=user --state=shadowed: Lists the~/.claude/skillsskills a nearer source holds the name of.rafa skill list --state=collision: Lists the holders of every name two loaded tiers hold different skills under, which a pin settles.rafa skill list --hidden-from-loop: Lists the skills a loop session does not resolve underloop.settingSources.rafa skill list -i --source=project: Browses the project's skills: Enter shows one,fits whole file, Escape goes back,qquits.rafa skill list --output=json: Writes a start event, then a result event whose data holds every row with its checker verdict.
Output formats: text, json.
rafa skill show
Show one skill: its record, frontmatter, other holders and headings.
rafa skill show <name> [--full]
Shows the skill a name resolves to, from the same inventory rafa skill list reads: its record (path, state, whether a session the loop spawns resolves it, checker verdict, summary, stack and tags), its frontmatter as written, every other skill of that name with its source and state, and the headings of its body with their lines in the file. The name shows its nearest holder — project, then rafa, user, add-ons and plugins — so a shadowed copy is listed under the other holders. --full prints the whole file in place of the frontmatter and the headings. A name no skill holds is refused with exit code 1. With --output=json every part of the view is the data of the terminal result event, the file text included under --full.
| Argument | Type | What it is |
|---|---|---|
name | string, required | The skill's name, as rafa skill list prints it. |
| Flag | Type and default | What it does |
|---|---|---|
--full | boolean | Print the whole file in place of the frontmatter and the headings; type it after the name. |
Examples:
rafa skill show verification-loop: Shows the skill that answers to the name, what it shadows, its frontmatter and its headings.rafa skill show verification-loop --full: Shows its record and other holders, then the whole file.rafa skill show verification-loop --output=json: Writes a start event, then a result event whose data holds every part of the view.
Output formats: text, json.
rafa skill search
Find the skills that answer a question, each with a quote from its file.
rafa skill search <question> [--all] [--no-model]
Finds the skills that answer a question. First, in code, the inventory rafa skill list reads is ranked by the question's words against each item's tags, prevents, when_to_use, description and body, and the top twelve are kept. Then one haiku session, given the tools Read, Grep and Glob and nothing else and run in a scratch copy of those twelve files, says which of them answer, each with a quote from its file. Then, in code, a match whose quote is not in its file within three lines of the line given is dropped and counted. A session that gives no usable answer prints the ranking with a notice. Each session stores one effort row of kind search. --no-model prints the ranking and starts no session. --all searches agent definitions too, one session per kind. The exit code is 0 whatever is found. With --output=json each kind's ranking, kept matches and dropped count are the data of the terminal result event.
Spends: 🪙 unless --no-model: one search session
| Argument | Type | What it is |
|---|---|---|
question | string, required | The question, quoted as one word. |
| Flag | Type and default | What it does |
|---|---|---|
--all | boolean | Search agent definitions as well, one session per kind; type it after the question. |
--model | boolean, default true | Run the search session; --no-model prints the keyword ranking and starts none. |
Examples:
rafa skill search "who writes TSDoc for exported symbols": Ranks the skills, asks one session which answer, and prints each match with its quote.rafa skill search "who writes TSDoc for exported symbols" --no-model: Prints the keyword ranking alone and starts no session.rafa skill search "who writes TSDoc for exported symbols" --all: Searches skills and agent definitions, one session each.rafa skill search "who writes TSDoc for exported symbols" --output=json: Writes a start event, then a result event holding the ranking, the kept matches and the dropped count.
Output formats: text, json.
rafa skill demote
Classify a skills directory into the demotion report, and apply a reviewed one.
rafa skill demote <dir> [--apply]
Runs the demotion pass over one skills directory. Without --apply it classifies every skill the directory registers, and every learned/ file it holds, as observation-shaped, procedure-shaped or unclassified, and writes <base>/.rafa/demoted/report.md with one row per file carrying its hash, its verdict, the rule that decided it and two empty override columns — moving nothing at all, since every verdict is a proposal a person settles. With --apply it reads that report back and refuses it unless the review marked it status: reviewed: each observation becomes an instinct under <base>/.rafa/instincts/, checked by the same checker rafa instinct check runs BEFORE it is written, with the original kept under <base>/.rafa/demoted/ so a wrong verdict is a mv; each procedure stays a skill; and an unclassified row the review did not decide is left alone. A row whose file changed since the report, and a record the checker fails, are refused one row at a time, and the exit code is the number of rows refused, capped at 255. <dir> is ~/.claude/skills or a project's .claude/skills, and anything else is refused. A second --apply over an applied report changes nothing. With --output=json the counts, or the per-row actions, are the data of the terminal result event.
| Argument | Type | What it is |
|---|---|---|
dir | string, required | The skills directory to pass over: ~/.claude/skills or a project's .claude/skills. |
| Flag | Type and default | What it does |
|---|---|---|
--apply | boolean | Carry out a reviewed report: write the instincts, and move the originals under .rafa/demoted/. |
Examples:
rafa skill demote ~/.claude/skills: Classifies the user tier into~/.rafa/demoted/report.md, moving nothing.rafa skill demote ~/.claude/skills --apply: Applies that report once its header saysstatus: reviewed, refusing any row whose file changed.
Output formats: text, json.
rafa skill backfill
Fill in the fields a skills directory lacks, by proposal and by derivation.
rafa skill backfill <dir> [--propose] [--apply] [--project=<string>]
Runs the backfill over one skills directory, in the three halves the pass separates. With no flag it PLANS: it answers what the deterministic derivation would write — stack for a directory the ECC table names, paths from the glob table for a non-agnostic stack, and when_to_use from "<trigger sentence>. Prevents: <prevents>" trimmed to the listing cap — and how many files a proposal pass would ask about, writing nothing. With --propose it asks one claude -p session per batch of twenty files for the prevents, signal, trigger sentence and over-cap description no table can derive, and writes one proposals-<nn>.yaml per batch under <base>/.rafa/backfill/, each status: draft and each row of a session that answered nothing readable marked unanswered rather than guessed. With --apply it writes every reviewed row into its skill and then runs the derivation over the result, refusing a file still marked draft, a skill that changed since its proposal was written, and any write that fails a check the file passed before. Every file an apply rewrites outside the checkout the command runs in is copied to <base>/.rafa/backfill/backup/ first, and no body is ever written. The exit code of an apply is the number of rows and files it refused, capped at 255. <dir> is ~/.claude/skills or a project's .claude/skills, and anything else is refused. With --output=json the actions and their counts are the data of the terminal result event.
Spends: 🪙 with --propose: one session per batch of skills
| Argument | Type | What it is |
|---|---|---|
dir | string, required | The skills directory to backfill: ~/.claude/skills or a project's .claude/skills. |
| Flag | Type and default | What it does |
|---|---|---|
--propose | boolean | Ask one session per batch of twenty for what no table derives, and write the draft proposals. |
--apply | boolean | Write every reviewed proposal row into its skill, then run the derivation over the result. |
--project | string | The project root the bodies are consumed in, which their paths resolve against. |
Examples:
rafa skill backfill ~/.claude/skills: Says what the derivation would write and how many files a proposal pass would ask about.rafa skill backfill ~/.claude/skills --propose: Asks one session per twenty files and writes the draft proposals under~/.rafa/backfill/.rafa skill backfill .claude/skills --apply --project=.: Writes the reviewed rows, derives, and copies each rewritten file outside the checkout first.
Output formats: text, json.