Docs / Agents: CLI, MCP, skill
The same loop, with nothing installed
Everything in this skill is about what you do, not how you reach it. There are two ways to reach it, and they are the same surface:
- a terminal, where you run
a9script <command>and your files are on the disk that command can see; - a remote door, where a URL and a token are pasted into your harness and every command is a tool.
The loop, the folder model, the refusals and the exit codes are identical, because a tool call IS the command — the same words, parsed the same way, with the same answers. What follows is only what differs.
The tools are the commands
whoamifilestoreentityapplydescribelockrunprobesessionspositioncontinueaborthistoryinspectauthoring-pack
A tool’s arguments are that command’s own words and flags, by name: where a
terminal takes run on-order --debug, a tool call takes
{ "script": "on-order", "debug": true }. A flag that stands alone is a
boolean; everything else is text.
Spell a flag exactly as the flag is spelled. A flag of two words keeps its
hyphen — dry-run, no-wait, to-end, acknowledge-write — and a key that
matches no word and no flag is refused, naming the key and what that tool takes.
It is refused rather than ignored on purpose: writing dryRun where the flag is
dry-run would otherwise drop the very switch holding something back, and your
lint would have been a real apply.
Three commands are not tools
login— it stores a token in a profile file, and your connection already carries its token in the header it arrived on.setup— it turns a setup token into the first account, which is the one state a door behind a credential cannot be in.files— it moves bytes between the caller’s own disk and the store, and a remote caller’s disk is not the server’s. Both halves matter: bytes would cross this door as text, so anything that is not text would be corrupted without saying so, and a destination path would name a file on the server.
You can still see what an environment holds: the store list crosses, and reports every store with the number of files and bytes in it.
Your files are yours, so they travel
A terminal passes a path because the file is on the disk the command can read. Your disk is not the server’s, so where a terminal names a path, a tool call carries the content:
applytakes the folder itself — a list of{ "path": …, "content": … }, exactly the files you would have written out. There are caps on how much may travel at once, and crossing one is refused by name, saying which file and which cap, so you are told what to split rather than quietly truncated.runtakes the test input as the document itself, not a filename.
Nothing you send is written to the server’s filesystem, and nothing you name is read from it.
The authoring pack is already there
The pack this skill points at is served as a resource, so a harness that reads
resources on connect has it before you ask — at the version that environment is
running, which is the one that matters. You can also call authoring-pack as a
tool; it is the same document either way.
run starts the run and answers
Over a terminal run follows the run through any pause and exits on its
outcome. Over this door it does not: nobody is holding the call open, and the
harness on your side gives up long before a parked run comes back. So the tool
starts the run and answers with it — which is a success, not a failure — and you
read the outcome afterwards:
run { "script": "on-order", "debug": true } → the run, still going
history <run> → the calls it has made
Every answer says what to do next where there is something to do, so the exact
follow-up is in the reply rather than in your memory. If you want the tool to
wait after all, ask for it: { "script": "on-order", "wait": "30s" }.
Asking twice starts twice
A tool call is not a request you can safely repeat. There is no session and no
de-duplication key, so a run sent again starts a SECOND run, and a probe
with acknowledge-write fires a second write at the far end. If a call times
out or an answer goes missing, read what happened — sessions for a paused run,
history <run> for one you have an id for — before you send it again.
Everything else is the same
The token is still the context: it is bound to one environment, everything you do happens there, and a second environment means a second token. Reads are free, a write needs a full-scope token, and a credential’s VALUE is still entered by a person in the browser — your files leave a blank where it goes.