axon <agent>
Run one instruction against one agent. The agent boots, the instruction runs to completion, the agent exits.
axon <ref> -p "<instruction>" # ask the agent
axon <ref> -P <prompt> # run a prompt it declares
axon <ref> -s <script> # run one of its scripts
axon <ref> -a # open the terminal on it
There is no run verb — the reference is the command. See axon for
how the binary tells a reference from a verb.
Ask an agent something
The common case: a quoted string goes straight to the model.
axon . -p "what changed in the last commit?"
axon . -p "summarise the readme"
axon @cody/zeno -p "is the auth boundary sound?"
The answer streams to stdout, so it pipes:
axon . -p "list every TODO with its file" > todos.txt
axon . -p "what does this error mean?" | pbcopy
Nothing needs to be declared in advance — no prompt file, no config. Quoting is what makes
it a literal; see -p for the one rule.
The reference
axon . -p "audit the auth boundary" # the agent in this directory
axon ./agents/scout -p "what changed?" # a path
axon ~/work/zeno -p "what changed?" # home-relative
axon @cody/zeno -p "what changed?" # a package — installed, or fetched on a miss
. names the current directory. It is required rather than implied: a bare axon with no
reference opens the TUI.
Resolution never boots. A missing path fails immediately; a missing package is fetched, prepared and cached.
-p and -P
Two flags, distinguished by case. Nothing is inferred from the value.
| Flag | Input | Behaviour |
|---|---|---|
-p | -p "summarise the readme" | Used verbatim as the instruction |
-P | -P code-review | Looked up in the agent's declared prompts |
The case split is deliberate. A single flag would have to guess whether explain is a
prompt name or a one-word question — and either answer is wrong somewhere: guessing "name"
makes one-word instructions unreachable, guessing "instruction" means the command silently
changes meaning the day someone adds src/prompts/explain.vue. Case costs one keystroke
and removes the ambiguity.
Repeated -p composes into a single instruction:
axon . -p "review the diff" -p "focus on error handling"
A -P prompt written as .vue is rendered — <script setup> runs and declared props are
filled from the remaining flags. Installed prompts are namespaced by package
(-P @cody/eslint-scout:scout) and cannot shadow one you wrote.
-s — a script
Invokes one of the agent's own scripts, from src/scripts/. Every other flag arrives as
its args, -p included.
axon . -s triage
axon . -s triage -p "the login bug"
axon . -s close-plan --issueId bd-yiq
// src/scripts/triage.ts
const { prompt } = defineArgs<{ prompt: string }>()
await axon.request(prompt)
A script is not an instruction — it is the execution. The agent's code decides what to
do, including whether to invoke the loop at all, so -p alongside -s is a value the
script receives rather than a turn the CLI runs. Nothing is streamed for you; a script
writes its own output.
-a — open the terminal
-a says the conversation continues in the TERMINAL, so nothing runs here: the instruction
is handed over and delivered into the session the terminal opens.
axon @cody/zeno -p "summarise the readme" -a # opens the TUI with the message queued
Each -p becomes its own queued message, in the order given — they land in the pending
list above the input and are sent as the agent frees up, exactly as if you had typed them
one after another:
axon @cody/zeno -p "read the readme" -p "then summarise it" -a
That is the one place repeated -p does not compose into a single instruction. Without
-a there is one turn to run, so the parts join; with it there is a conversation to have,
so they stay separate.
-s is excluded — a script IS the execution, and there is no message for a session to
carry, so -a cannot mean "hand it over" there.
A reference with no instruction is already a destination, so -a is optional there —
there is nothing to run, and opening the terminal is the only thing it can mean:
axon @cody/zeno # opens the TUI on it
axon @cody/zeno -a # the same
axon "http://localhost:3101" # attaches to something already running
Either way this outranks the remembered last agent: naming one is an explicit instruction, and the terminal opens on what you asked for rather than what you were last on.
The turn runs before the terminal opens, so the transcript is already there when it does — one conversation, continued, rather than an answer in the shell and a fresh session in the UI.
A URL is verified before anything is recorded: a typo should not cost a whole terminal
boot to discover. A path or package is not, because there is nothing running to answer —
the terminal reports a bad reference the same way ~ does.
There is no axon attach. It was a verb for something that is not an action: it did no
work on the agent, it chose a destination.
Arguments
Any flag not listed under Options becomes a prompt argument.
axon . -P learn --domain tracing --depth 3
<script setup lang="ts">
defineProps<{ domain: string; depth?: string }>()
</script>
Ignored by -p, which is used verbatim and has nothing to render.
Options
| Flag | Default | Description |
|---|---|---|
-p, --prompt | — | A literal instruction, used verbatim. Repeats compose |
-P | — | A prompt the agent declares, resolved and rendered |
-s, --script | — | One of the agent's own scripts |
-a, --attach | false | Open the terminal when the work finishes. Implied when there is no instruction |
--context | — | Extra context for the turn |
--job | — | Tag the run with the job directory it belongs to |
--json | false | Print one line of JSON to stdout and nothing else |
--job is correlation only — it records the association in the run's liveness record and
changes nothing about what executes.
Output
Agent text streams to stdout. Boot progress, diagnostics and errors go to stderr.
That split is the whole automation story: a redirect or a pipe gets only the answer, while a person watching a terminal still sees the boot happen. There is no flag to remember.
axon @cody/zeno -p "…" > answer.txt # the file holds only the answer
axon @cody/zeno -s report | jq # nothing but the script's own output
Progress draws only when someone is watching — never under --json, --quiet, or when
stderr is not a terminal — and only once a boot has run long enough to be worth explaining.
A warm agent boots in under a second and says nothing.
-s prints nothing on the script's behalf: a script that wants to say something writes to
stdout itself.
Tool calls, kernel telemetry and the full causal record go to the session log under
.agent/data/sessions/.
axon.ui.ask() receives unavailable — there is no connected host to answer.
Errors
| Error | Meaning |
|---|---|
SCRIPT_NOT_FOUND | The agent declares no script by that name; the available ones are listed |
PROMPT_NOT_FOUND | No prompt by that name; the available ones are listed |
NOT_AN_AGENT | The reference resolved to a module, bench or cognet |
ATTACH_UNREACHABLE | -a on a URL that nothing answered |
ATTACH_URL_INVALID | The address has no scheme, or one that is not http(s) |
See prompts/ for authoring what -P resolves, and
Scripts for what -s invokes.