afterminal CLI reference
Run and expose the Agent-First Terminal PTY runtime.
afterminal is compiled from a closed cli-spec-v1 registry: one source for argv parsing, typed invocation values, which parameter combinations are legal, output contracts, and help. An invocation runs only when it matches exactly one registered combination.
Global arguments
AFDATA registers these itself, so the syntax in Commands leaves them out.
| Argument | Where | What it does |
|---|---|---|
--help | every command | Every legal shape of that command, complete, plus its subcommands. JSON by default; --output plain for a terminal. |
--version | afterminal only | Name, version, and build identity as one protocol result. |
--docs | afterminal only | This document, rendered from the registry. |
--output <FORMAT> | per output contract | Render as json, yaml, plain (default json). |
--output-to <DESTINATION> | per output contract | Route results and diagnostics to split, stdout, stderr (default split). |
--stdout-file <PATH>, --stderr-file <PATH> | per output contract | Append that stream to a file instead. |
Success output is protocol events, on those terms, unless a command’s own Output line says otherwise.
A shape is one legal set of arguments that may appear together, under a stable id. Where a command has more than one, each id is a heading below. --help returns them all at once, so discovering a command costs one call; there is no recursive mode across commands, and this document is that view.
Commands
afterminal api export— Write the generated OpenAPI document.afterminal api serve— Serve the bearer-protected terminal API.afterminal skill install— Install the Agent-First Terminal skill.afterminal skill status— Show whether the Agent-First Terminal skill is installed, valid, and up to date.afterminal skill uninstall— Remove an afterminal-managed Agent-First Terminal skill.afterminal ui— Deliver a UI over a new or already-running terminal runtime.
afterminal api export
Write the generated OpenAPI document.
afterminal api export [--directory <PATH>] [--force]
| Argument | Meaning |
|---|---|
--directory | Destination directory |
--force | Replace an existing generated document |
afterminal api serve
Serve the bearer-protected terminal API.
afterminal api serve [--port <PORT>] [--mode <local|lan>] [--access-token-secret <SOURCE>]
Output: protocol events; --output json/yaml/plain (default json), --output-to stdout/stderr (default stdout).
| Argument | Meaning |
|---|---|
--port | TCP port; use 0 to let the operating system choose |
--mode | Network exposure: local binds 127.0.0.1; lan binds 0.0.0.0 and publishes the LAN address |
--access-token-secret | Bearer credential; falls back to AFTERMINAL_API_ACCESS_TOKEN_SECRET (the value, or where to read it: env:NAME, file[+FORMAT]:PATH#DOT_PATH, literal:VALUE) |
afterminal skill install
Install the Agent-First Terminal skill.
skill-install-every-agent — Target every agent that supports the scope
afterminal skill install [--agent all] [--scope <personal|workspace>] [--force]
skill-install-one-agent — Target one named agent; only this shape accepts –skills-dir
afterminal skill install --agent <codex|claude-code|opencode|hermes> [--scope <personal|workspace>] [--skills-dir <DIR>] [--force]
Arguments across every shape above:
| Argument | Meaning |
|---|---|
--agent | Agent to manage |
--scope | Skill scope |
--skills-dir | Directory that contains skill folders |
--force | Overwrite or remove an unmanaged Agent-First Terminal skill at the target path |
afterminal skill status
Show whether the Agent-First Terminal skill is installed, valid, and up to date.
skill-status-every-agent — Target every agent that supports the scope
afterminal skill status [--agent all] [--scope <personal|workspace>]
skill-status-one-agent — Target one named agent; only this shape accepts –skills-dir
afterminal skill status --agent <codex|claude-code|opencode|hermes> [--scope <personal|workspace>] [--skills-dir <DIR>]
Arguments across every shape above:
| Argument | Meaning |
|---|---|
--agent | Agent to manage |
--scope | Skill scope |
--skills-dir | Directory that contains skill folders |
afterminal skill uninstall
Remove an afterminal-managed Agent-First Terminal skill.
skill-uninstall-every-agent — Target every agent that supports the scope
afterminal skill uninstall [--agent all] [--scope <personal|workspace>] [--force]
skill-uninstall-one-agent — Target one named agent; only this shape accepts –skills-dir
afterminal skill uninstall --agent <codex|claude-code|opencode|hermes> [--scope <personal|workspace>] [--skills-dir <DIR>] [--force]
Arguments across every shape above:
| Argument | Meaning |
|---|---|
--agent | Agent to manage |
--scope | Skill scope |
--skills-dir | Directory that contains skill folders |
--force | Overwrite or remove an unmanaged Agent-First Terminal skill at the target path |
afterminal ui
Deliver a UI over a new or already-running terminal runtime.
ui-attach — Attach to a running terminal API instead of starting one
afterminal ui [<SESSION_ID>] --api-url <URL> [--access-token-secret <SOURCE>] [--mode <window|link|session>]
ui-serve — Start and deliver a runtime with no initial terminal session
afterminal ui [--port <PORT>] [--access-token-secret <SOURCE>] [--mode <window|link|session>]
ui-serve-session — Start and deliver a runtime with one configured terminal session
afterminal ui <SESSION_ID> [--port <PORT>] [--access-token-secret <SOURCE>] [--program <PROGRAM>] [--arg <ARG>...] [--cwd-path <PATH>] [--rows <ROWS>] [--cols <COLS>] [--title <TITLE>] [--mode <window|link|session>]
Output: protocol events; --output json/yaml/plain (default json), --output-to stdout/stderr (default stdout).
Arguments across every shape above:
| Argument | Meaning |
|---|---|
SESSION_ID | Session to open, or to select when attaching through –api-url |
--api-url | Existing terminal API to attach without creating a new runtime |
--port | TCP port; use 0 to let the operating system choose |
--access-token-secret | Bearer credential; falls back to AFTERMINAL_API_ACCESS_TOKEN_SECRET (the value, or where to read it: env:NAME, file[+FORMAT]:PATH#DOT_PATH, literal:VALUE) |
--program | Program for the initial session. Defaults to the user’s shell |
--arg | Argument passed directly to the initial program; may be repeated |
--cwd-path | Working directory for the initial session |
--rows | Initial terminal rows |
--cols | Initial terminal columns |
--title | Advisory title for the initial session |
--mode | How this reaches the person: window a browser window is open on this machine; link the page is reachable from this machine’s network at the link URL; session the session is registered only; open it with afui session open or reach it through afui session serve. Falls back to AFUI_DELIVERY, then window |
Exit codes
| Code | Meaning |
|---|---|
| 0 | The command ran and succeeded. |
| 1 | The command ran and failed. The event carries a domain error.code. |
| 2 | The invocation was rejected before anything ran. error.code is one of the cli_* codes below. |
The split is the useful one for a caller: exit 2 means the call was never made, so retrying it unchanged cannot help, while exit 1 means it was.
CLI errors
Every structural failure emits one strict JSON kind:"error" event on stderr, leaves stdout empty, and exits 2. The code names the failure — cli_unknown_argument for an unknown spelling, cli_unregistered_combination for registered arguments in a mixture that is not, and one each for cli_unknown_command, cli_missing_argument_value, cli_invalid_argument_value, cli_duplicate_argument, cli_unexpected_positional, and cli_invalid_utf8. message identifies a safe argument spelling or the failure category and hint gives the command to run next; neither ever quotes a raw value, including secrets. These are decided before any config, secret source, filesystem, network, or domain I/O.
Two exit-1 codes describe the tool itself rather than the call: cli_invocation_invalid means the program misread its own resolved invocation — an unknown action id, or an argument id the selected combination cannot produce — and output_setup_failed means an output sink (--stdout-file, --stderr-file, stream redirection) could not be established. Both are defects to report, not inputs to correct; retrying the same command cannot help.
Domain failures (exit 1) carry their own stable error.code instead, drawn from whatever this tool defines rather than from the cli_* set. Error events are routinely logged, so a message never quotes a value that came from an argument able to carry a credential — a header, a cookie, a token, a password, a proxy URL, an environment value, a form field. Such an error names the argument and the shape that was wrong, and stops there. A value that cannot be a secret — a path, a dot-path, a session name — is quoted, because an error that cannot say which one it means is not worth logging either.