Command reference
This page is generated from the af contract (version 2026-10-31), so it always matches the af you install. Agents: pass --json to every command and parse the result.
Every command takes --json, --timeout <s> (default 300), and --quiet. With --json, stdout is exactly one JSON object:
{"ok": true, "data": {…}}on success;{"ok": false, "error": {"code", "message", "hint", "retryAfterSeconds"?}}on failure.
Logs go to stderr.
A Machine object always has name, kind, size, state (starting · running · stopped · error), ip, vcpu, memoryGiB, diskGiB and createdAt. Depending on kind it may also have ttlExpiresAt, ssh, hostKeyFingerprint, authorizedKeys (af box show: the fingerprints a running Box accepts, null when it is not running or cannot be read), api, registered, ephemeral and cpus (Runners: registered is null when it cannot be read; cpus is the CPUs it runs on). size is S, M, L, CI (Runners) or custom; a Runner’s is read from its live limits (GitHub Actions runners).
Commands
Section titled “Commands”| Command | Does | Notes |
|---|---|---|
af whoami |
Your Lane, Tailscale login, limits | github is null when your Lane has no GitHub user |
af doctor |
Client checks: Tailscale up, certificate valid, platform reachable, clock, and lane-network: this device reaches your Lane’s addresses (a running Box’s SSH port; warn with none running) |
Every line ok, warn or fail. A lane-network fail usually means the subnet routes are not accepted on this device (Getting started) |
af sizes |
The sizes (Overview) | CI’s vcpu is null: your Lane’s CI CPU setting decides it (GitHub Actions runners) |
af usage |
Caps and use, per Machine | |
af list [--kind] |
Your Machines | |
af box create <name> [--size S|M|L] |
New Box, or the existing one (created: false) |
Name: [a-z][a-z0-9-]{1,30} |
af box show <name> |
One Box | |
af box ssh <name> · af box ssh-config <name> |
Open SSH · print a pinned config entry | |
af box resize <name> --size <S|M|L> [--restart] |
Grow or shrink CPU and RAM; grow disk | RESTART_REQUIRED on pinned cores. A smaller size shrinks CPU and RAM and keeps the larger disk, which diskGiB shows, so a size change never returns CANT_SHRINK_DISK |
af box snapshots <name> · af box snapshot <name> · af box restore <name> <snap> --confirm <name> |
List · take one now · restore | Nightly snapshots and yours are kept 7 days. Restore restarts the Box |
af box stop <name> · af box start <name> |
Stop or start a Box | A stopped Box keeps its disk and frees the server’s CPU and RAM; it still counts against your Lane’s caps |
af box delete <name> --confirm <name> |
Delete a Box and its snapshots | Irreversible. Without --json, it asks for the name instead |
af box encrypt-home <name> |
The steps to make an encrypted directory in the Box with your own passphrase | Prints steps; runs nothing |
af keys add <public-key-file> · af keys list · af keys remove <fingerprint> |
Your Lane’s SSH public keys: add, list, remove; every running Box updated in the same call (SSH keys) | At most 10. add of a key already there is a no-op |
af runner create <name> [--size S|M|L|CI] [--kvm] [--ephemeral] |
A VM from the Runner image, not registered (GitHub Actions runners) | Default S. Safe to retry. Counts against your Lane’s caps and asks the RAM check, like a Box. Pinned to your Lane’s cores; --size CI follows your Lane’s CI CPU policy and holds no core. A kept Runner gets or reuses its cache disk |
af runner register <name> (--jit-config - | --token - --url <repo-or-org> [--labels a,b]) |
Registers it with GitHub, inside the VM, and starts its service | The secret on stdin only: one on the command line is USAGE. af stores nothing |
af runner list |
Your Runners, with their live size and cpus, registered, busy and cacheGiB |
The last three are null when the Runner is not running or cannot be read |
af runner logs <name> [--lines <n>] |
The runner service’s last lines (default 100, at most 1000) | |
af runner delete <name> --confirm <name> [--removal-token -] [--with-cache] |
Deletes the VM, keeping its cache disk unless --with-cache |
Irreversible. --removal-token - reads a GitHub removal token on stdin and deregisters first; if that fails, nothing is deleted and the Runner goes back to listening. Deregistering stops the runner’s service first, so a job it was running is cancelled, even when the token then fails |
af login |
Store the client certificate | Token on stdin. You run this yourself, not your agent. next is the af keys add step when the Lane has no SSH key yet |
af ui [--passphrase -] |
Your certificate as a browser file (PKCS#12) and the steps to open the web console with it (Web console) | Prints the passphrase once; --passphrase - reads one you choose on stdin instead. Sends nothing. For the user: agents use af |
af version |
af and contract versions |
Starting a Machine (box create, box start, and box resize when it grows memory; a restore’s restart takes back the memory it just freed, so it is not asked) first asks the server how much memory it has free for new starts, and stops with HOST_FULL if the Machine needs more. The answer is one number, the server’s free total; it never says whose Machines use the rest.
af box ssh <name> --json prints the ssh command instead of opening it. A Box’s user is your Lane’s name, and af pins the Box’s host key in ~/.config/af/known_hosts.
What data holds
Section titled “What data holds”af is tested against this table: each command’s data has exactly these keys.
| Command | data keys |
|---|---|
af whoami |
lane, project, github, tailscale, limits (memoryGiB, diskGiB, machines, cores) |
af doctor |
checks (each name, status, detail), healthy |
af sizes |
sizes (each size, vcpu, memoryGiB, diskGiB) |
af usage |
lane, caps (memoryGiB, diskGiB, machines, cores), used (memoryGiB, diskGiB, machines), machines |
af list |
machines |
af box create |
created, machine |
af box show |
machine |
af box ssh |
command |
af box ssh-config |
host, config |
af box resize |
machine, restarted |
af box snapshots |
snapshots (each name, createdAt, expiresAt) |
af box snapshot |
snapshot |
af box restore |
machine, snapshot |
af box stop |
machine |
af box start |
machine |
af box delete |
deleted |
af box encrypt-home |
steps |
af keys add |
added (the new keys’ fingerprints), keys, boxes |
af keys list |
keys (each fingerprint, type, bits, comment) |
af keys remove |
removed, keys, boxes (each name, status, detail) |
af runner create |
created, machine |
af runner register |
name, registered, ephemeral |
af runner list |
runners (each a Machine plus busy, cacheGiB) |
af runner logs |
name, lines |
af runner delete |
deleted, deregistered, cacheKept |
af login |
lane, project, fingerprint, next |
af ui |
path, url, passphrase (null with --passphrase -), steps |
af version |
af, contract |
af doctor’s healthy is true when no check is fail; it exits 0 either way, because it reports rather than acts.