The akter CLI
Responsibility: document the akter command-line tool: its commands, flags, output, and exit statuses.Authority: normative CLI interface.
Owner role: API/SDK.
Change policy: a changed command, flag, or exit status updates this page, the runbooks, and the guides that use it.
akter is the apps/cli bin, named durable before ADR 0085. It parses its arguments with Effect’s effect/cli module: one root akter command whose subcommands are the groups below, each flag typed and described, so akter --help and akter <command> --help print the same reference as this page. Flags take their value as --flag value or --flag=value, and -- ends flag parsing.
Exit statuses
Global flags
Every command takes--help (-h), --version (-v), --completions <bash|zsh|fish|sh>, which prints a shell completion script, --log-level <level>, and --wizard, which builds a command interactively.
akter --help
Operator commands
defects list, inspect, export, receipts show, dead-letters, and subscriptions call a runner’s Operators.serve routes. Each reads its bearer token from DURABLE_OPERATOR_TOKEN, or from the environment variable --token-env names. --url repeats; defects list reads every runner named, and the single-actor commands use the first. See ADR 0050 for the grants each command needs and the runbooks for when to use them.
Akter Cloud commands
login, logout, whoami and deploy talk to a control plane (apps/api) through its CloudApi client (ADR 0085). login signs in through Better Auth’s device authorization grant and stores the session in credentials.json in the CLI’s configuration directory: AKTER_CONFIG_DIR when set, else ~/Library/Application Support/akter on macOS, %APPDATA%\akter on Windows and $XDG_CONFIG_HOME/akter (default ~/.config/akter) elsewhere. The file is 0600 in a 0700 directory, written under a random temporary name that must not already exist and renamed into place, and a file the group or others can read is refused until it is fixed or replaced by another login. The other commands send the stored session as a bearer token to the control plane it came from, which must be https, or http only on a loopback host (localhost, *.localhost, 127.0.0.0/8, [::1]); login --api-url refuses any other URL with exit 2, and stored credentials naming one are refused as unreadable. A session acts in every organization its user belongs to, like gh or vercel; the control plane checks membership on every request.
Commands
akter login
Sign in to Akter Cloud through the browser and store the session for deploy
/device page and a code written XXXX-XXXX (never a link that carries the code), then polls at the interval the control plane names, five seconds slower after each slow_down, until the code is approved, denied or past its own expiry. Approving the code saves the session, which starts in the approver’s active organization, and prints who it signs in as; a denied or expired code exits 1 and saves nothing. If the control plane will not say who the new session belongs to, login signs the session out again and saves nothing.
akter logout
Sign out of Akter Cloud and delete the stored session
akter whoami
Show who the stored Akter Cloud session signs in as
akter login.
akter deploy
Upload the build context, build and roll it out on Akter Cloud, and follow it until it is live
docker build would send it (<Dockerfile>.dockerignore, else .dockerignore; the Dockerfile always included): symbolic links are sent as links and never followed, files keep their permission bits, and owners and times are zeroed so the same files give the same digest. --dockerfile is cleaned (./a//Dockerfile is a/Dockerfile), and a path starting at / or containing .. is refused with exit 2 before anything is read. It uploads it to POST /api/projects/:projectId/sources, creates the deployment from the returned digest, and prints each rollout step as it starts and ends. It exits 0 once the deployment is live, and 1 when it fails, naming the failed step and, for a failed build, printing the build’s last 20 lines. Outside a git repository the deployment is labeled with the archive digest’s first 40 hex digits; a dirty working tree marks the message (with uncommitted changes). A control plane without a builder refuses the upload with NotImplemented, and one past 64 MiB is refused with PayloadTooLarge.
akter billing setup
Create or reconcile products, meters and prices using the configured provisional pricing. Every provider creation has a stable identity; repeating setup does not duplicate catalog objects.
STRIPE_API_KEY from the environment; it is not a command-line argument. API, edge and setup consume the same optional BILLING_PRICING_CONFIG JSON configuration. Setup does not publish the planning prices or establish live tax/provider support.