Skip to content

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).

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.

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.