afui CLI reference
Create, validate, trust, inspect, and compare Provider-owned UI frontends.
afui 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 | afui only | Name, version, and build identity as one protocol result. |
--docs | afui 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
afui frontend check— Validate one frontend and report its trust state.afui frontend dev— Prepare a validated frontend for Provider-owned development.afui frontend diff— Compare workspace and global frontend files.afui frontend disable— Remove explicit trust for one frontend.afui frontend enable— Explicitly trust the current contents of one frontend.afui frontend init— Create a frontend directory and manifest.afui frontend preview— Prepare a validated frontend for Provider-owned preview.afui session close— End a running UI session from outside the process that created it. Whoever created it getsOutcome::Closed, the same as if a person had closed its window.afui session list— List every UI session running on this machine.afui session open— Open a window onto one running session.afui session serve— Serve every running session to a browser on another device. Binds a port and stops there: getting to that port is an SSH tunnel, WireGuard, Tailscale, or a TLS reverse proxy, none of which this is.afui skill install— Install the Agent-First UI skill.afui skill status— Show whether the Agent-First UI skill is installed, valid, and up to date.afui skill uninstall— Remove an afui-managed Agent-First UI skill.
afui frontend check
Validate one frontend and report its trust state.
afui frontend check <PROVIDER_ID> <UI_KIND> [--scope <workspace|global>] [--safe-mode]
| Argument | Meaning |
|---|---|
PROVIDER_ID | Stable Provider identifier |
UI_KIND | Stable UI kind identifier |
--scope | Frontend scope |
--safe-mode | Ignore user frontend code before reading its manifest |
afui frontend dev
Prepare a validated frontend for Provider-owned development.
afui frontend dev <PROVIDER_ID> <UI_KIND> [--scope <workspace|global>] [--safe-mode]
| Argument | Meaning |
|---|---|
PROVIDER_ID | Stable Provider identifier |
UI_KIND | Stable UI kind identifier |
--scope | Frontend scope |
--safe-mode | Ignore user frontend code before reading its manifest |
afui frontend diff
Compare workspace and global frontend files.
afui frontend diff <PROVIDER_ID> <UI_KIND> [--scope <workspace|global>]
| Argument | Meaning |
|---|---|
PROVIDER_ID | Stable Provider identifier |
UI_KIND | Stable UI kind identifier |
--scope | Frontend scope |
afui frontend disable
Remove explicit trust for one frontend.
afui frontend disable <PROVIDER_ID> <UI_KIND> [--scope <workspace|global>]
| Argument | Meaning |
|---|---|
PROVIDER_ID | Stable Provider identifier |
UI_KIND | Stable UI kind identifier |
--scope | Frontend scope |
afui frontend enable
Explicitly trust the current contents of one frontend.
afui frontend enable <PROVIDER_ID> <UI_KIND> [--scope <workspace|global>]
| Argument | Meaning |
|---|---|
PROVIDER_ID | Stable Provider identifier |
UI_KIND | Stable UI kind identifier |
--scope | Frontend scope |
afui frontend init
Create a frontend directory and manifest.
afui frontend init <PROVIDER_ID> <UI_KIND> [--scope <workspace|global>] --frontend-id <FRONTEND_ID> [--ui-api-version <VERSION>]
| Argument | Meaning |
|---|---|
PROVIDER_ID | Stable Provider identifier |
UI_KIND | Stable UI kind identifier |
--scope | Frontend scope |
--frontend-id | Stable identifier for this frontend implementation |
--ui-api-version | Provider-defined typed UI API version |
afui frontend preview
Prepare a validated frontend for Provider-owned preview.
afui frontend preview <PROVIDER_ID> <UI_KIND> [--scope <workspace|global>] [--safe-mode]
| Argument | Meaning |
|---|---|
PROVIDER_ID | Stable Provider identifier |
UI_KIND | Stable UI kind identifier |
--scope | Frontend scope |
--safe-mode | Ignore user frontend code before reading its manifest |
afui session close
End a running UI session from outside the process that created it. Whoever created it gets Outcome::Closed, the same as if a person had closed its window.
afui session close <SESSION_ID>
| Argument | Meaning |
|---|---|
SESSION_ID | Session identifier from afui session list |
afui session list
List every UI session running on this machine.
afui session list
afui session open
Open a window onto one running session.
afui session open <SESSION_ID>
| Argument | Meaning |
|---|---|
SESSION_ID | Session identifier from afui session list |
afui session serve
Serve every running session to a browser on another device. Binds a port and stops there: getting to that port is an SSH tunnel, WireGuard, Tailscale, or a TLS reverse proxy, none of which this is.
afui session serve [--listen <ADDRESS>] [--advertise-host <HOST>] [--idle-minutes <MINUTES>] [--grace-minutes <MINUTES>] [--session-origin-host <HOST>]
Output: protocol events; --output json/yaml/plain (default json), --output-to stdout/stderr (default stdout).
| Argument | Meaning |
|---|---|
--listen | Address to bind. Loopback by default; widen it only behind a tunnel or VPN you trust |
--advertise-host | Authority to put in the URL when the bound address is not one anybody can open |
--idle-minutes | Stop answering this long after nobody is attending the page: no visible tab, no traffic through a session. Overrides AFUI’s global attention.idle_timeout_s; 0 never stops |
--grace-minutes | How long the page warns first, still fully working, with a button that renews it. Overrides AFUI’s global attention.grace_period_s; 0 lapses without warning |
--session-origin-host | Give every session an origin of its own, s-<credential>.<HOST>, so a framed UI keeps browser storage. Needs *.<HOST> to resolve here, and a wildcard certificate behind TLS; localhost needs neither, because browsers resolve *.localhost to this machine. Also the host the page itself is served on |
When neither override is supplied, AFUI reads attention.idle_timeout_s (default 900) and attention.grace_period_s (default 300) from the global AFUI config.json: ~/Library/Application Support/afui/config.json on macOS, $XDG_CONFIG_HOME/afui/config.json on Linux (or ~/.config/afui/config.json when XDG_CONFIG_HOME is unset), or %APPDATA%\afui\config.json on Windows. AFUI_CONFIG_DIR replaces that file’s parent directory. The same policy controls direct link delivery.
The serving progress event reports the resolved values as idle_timeout_s and grace_period_s; idle_timeout_s is null when expiry is disabled.
afui skill install
Install the Agent-First UI skill.
skill-install-every-agent — Target every agent that supports the scope
afui skill install [--agent all] [--scope <personal|workspace>] [--force]
skill-install-one-agent — Target one named agent; only this shape accepts –skills-dir
afui 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 UI skill at the target path |
afui skill status
Show whether the Agent-First UI skill is installed, valid, and up to date.
skill-status-every-agent — Target every agent that supports the scope
afui skill status [--agent all] [--scope <personal|workspace>]
skill-status-one-agent — Target one named agent; only this shape accepts –skills-dir
afui 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 |
afui skill uninstall
Remove an afui-managed Agent-First UI skill.
skill-uninstall-every-agent — Target every agent that supports the scope
afui skill uninstall [--agent all] [--scope <personal|workspace>] [--force]
skill-uninstall-one-agent — Target one named agent; only this shape accepts –skills-dir
afui 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 UI skill at the target path |
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.