rafa pages
- rafa
- rafa agent
rafa agent
Copy an agent definition into the project, and list, show and search the agent definitions a loop session can see.
A plan task can be routed to a Claude Code subagent with agent= on its line. rafa agent shows which agent definitions a loop session sees, and copies one into the project when it lives only where a session cannot see it.
Spends: 🪙 search, one haiku session reading the best-ranked files, unless --no-model. Changes: vendor writes into .claude/agents/; the rest read only.
Things to know before you use it:
- Agents come from three tiers: the project, the copies rafa ships, and
~/.claude/agents. A loop session sees the user tier only whenloop.settingSourcesincludesuser, which the default does not;vendorcopies an agent into the project instead. - Two tiers holding different agents under one name are refused until a
tiers.agentspin names the tier to use.
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 |
|---|---|
vendor | copy an agent definition from the rafa tier or ~/.claude/agents into this project |
list | list every agent definition with its source, its state and whether the loop sees it |
show | show one agent definition: its record, frontmatter, other holders and headings |
search | find the agent definitions that answer a question, each with a quote from its file 🪙 unless --no-model |
rafa agent vendor
Copy an agent definition from the rafa tier or ~/.claude/agents into this project.
rafa agent vendor <name> [--force]
Copies each named definition from the rafa tier (bundled/agents beside the running entry) or, when rafa ships no definition of that name, from ~/.claude/agents into <root>/.claude/agents, naming the tier each copy came from, keeping the source file's own name and writing one HTML comment after its frontmatter naming the file it came from and the day. A name is a definition's frontmatter name, which is what --agent resolves by, not its file stem. Under the loop's default loop.settingSources of project,local the home is out of reach, so a task routed agent=<name> exits 1 before any model call until the definition sits in the project: this is the fix rafa loop start and rafa plan validate name when they refuse one. Every name is checked before the first byte is copied, and the command refuses a name neither tier carries and a destination already there, which --force replaces whole. With --output=json the copies are the data of the terminal result event.
| Argument | Type | What it is |
|---|---|---|
name | string, required | The frontmatter name of a definition the rafa tier or ~/.claude/agents holds; more than one may be named. |
| Flag | Type and default | What it does |
|---|---|---|
--force | boolean | Replace a definition of the same file name already in the project, whole, instead of refusing it. |
Examples:
rafa agent vendor tdd-guide: Copies~/.claude/agents/tdd-guide.mdinto.claude/agents/, so a task routed to it dispatches.rafa agent vendor tdd-guide code-reviewer --force: Vendors both names, replacing the project definitions already there.
Output formats: text, json.
rafa agent list
List every agent definition with its source, its state and whether the loop sees it.
rafa agent list [--tier|--source=<string>] [--state=<string>]
[--hidden-from-loop] [-i|--interactive]
Lists every agent definition the inventory holds — the project's .claude/agents, the bundled/agents directory beside the running rafa, ~/.claude/agents, each loaded add-on's and each installed plugin's — one row each, under the frontmatter name a task routes to: 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 definitions under the name and a tiers.agents pin must settle it, shadowed-by:<source> when another source serves the name, or disabled:<how>) and its own description as the summary. The Claude Code built-ins are not listed. --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. When ~/.claude/agents holds a name no visible row answers, a trailing line names it and points at rafa agent vendor. It spawns no session and exits 0 whatever the rows say. With --output=json the rows, the vendor names and the warnings 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 agent list: Lists every agent definition, each with its source, its state and whether the loop sees it.rafa agent list --hidden-from-loop --source=user: Lists the~/.claude/agentsdefinitions a loop session does not resolve.rafa agent list --state=collision: Lists the holders of every name two loaded tiers hold different definitions under, which a pin settles.rafa agent list -i: Browses every agent definition: Enter shows one,fits whole file, Escape goes back,qquits.rafa agent list --output=json: Writes a start event, then a result event whose data holds every row and the vendor names.
Output formats: text, json.
rafa agent show
Show one agent definition: its record, frontmatter, other holders and headings.
rafa agent show <name> [--full]
Shows the agent definition a name resolves to, from the same inventory rafa agent list reads, the name being the frontmatter name a task routes to: its record (path, state, whether a session the loop spawns resolves it, summary, stack and tags), its frontmatter as written, every other agent 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. The Claude Code built-ins are not inventory rows and are not shown. --full prints the whole file in place of the frontmatter and the headings. A name no agent 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 agent's name, as rafa agent 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 agent show code-reviewer: Shows the definition that answers to the name, what it shadows, its frontmatter and its headings.rafa agent show code-reviewer --full: Shows its record and other holders, then the whole file.rafa agent show code-reviewer --output=json: Writes a start event, then a result event whose data holds every part of the view.
Output formats: text, json.
rafa agent search
Find the agent definitions that answer a question, each with a quote from its file.
rafa agent search <question> [--all] [--no-model]
Finds the agent definitions that answer a question. First, in code, the inventory rafa agent 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 skills 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 skills 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 agent search "which agent reviews a diff for security": Ranks the agent definitions, asks one session which answer, and prints each match with its quote.rafa agent search "which agent reviews a diff for security" --no-model: Prints the keyword ranking alone and starts no session.rafa agent search "which agent reviews a diff for security" --all: Searches agent definitions and skills, one session each.rafa agent search "which agent reviews a diff for security" --output=json: Writes a start event, then a result event holding the ranking, the kept matches and the dropped count.
Output formats: text, json.