Docs / CLI

CLI

Install the hosted CLI, ship with aft deploy — no login — then manage claimed sites after aft login: rename, secrets, visibility, rollback, update.

Install

Requires Node.js ≥ 20. Puts aft in ~/.local/bin.

curl -fsSL https://aft.page/install | sh
aft --help

If aft is not found, add export PATH="$HOME/.local/bin:$PATH" and reopen the terminal. Working from the repo instead: node apps/cli/bin/aft.js.

The CLI checks for a newer version once a day and nudges you if you're behind — see Troubleshooting if you'd rather turn that off.

Ship (no login)

Only shipping is anonymous. aft deploy and aft init don't need an account. Same durable URL you'd get from Drop or MCP.

# Plain HTML — folder with index.html
aft deploy

# Vite / React / Vue — build first; CLI auto-picks dist/
npm run build
aft deploy

# Or point at the output folder directly
aft deploy dist
aft deploy out     # Next static export

On first deploy in a project root, the CLI writes aft.json (slug from package.json's name, or the folder name) if one doesn't exist yet. Redeploys reuse .aft/state.json — the slug and edit token stored there — so the URL stays put.

Success prints the live URL and a claim link. Keep that link — unclaimed sites are deleted after 30 days idle. See the claim guide.

After claim + login

Claim on the live URL (or on the preview page with ?token=), then:

aft login
aft whoami
aft sites

aft login opens your browser to sign in, then hands the CLI a session token over a short-lived local server — no password ever touches the terminal. The session is stored in ~/.config/aft.page/credentials.json; override the lookup with the AFT_TOKEN environment variable (handy in CI). From here, management commands mirror the project dashboard: rename, secrets, visibility, rollback.

aft.json

Written by aft init or your first deploy. Example:

{
  "name": "my-app",
  "slug": "my-app",
  "runtime": "static"
}

Optional capabilities.secrets / egress lets an app declare what it needs so an owner can approve it on deploy — see the Capabilities guide. Next / Worker runtimes add runtime + upstream — see Frameworks.

Output folders

From a project with package.json and no root index.html, aft deploy looks for dist/, then out/, then build/ — whichever contains an index.html first. If it instead sees src/ or app/ with no build output, it stops and tells you to run npm run build first rather than guessing.

State (.aft/state.json) always stays in the project root, even when you deploy from dist/ — so redeploys keep finding the same slug and edit token no matter which folder you point the CLI at.

Command reference

Command Login? What
aft deploy [dir] no Upload a static site
aft init no Write aft.json
aft update no Reinstall the latest CLI
aft login / logout / whoami Browser session
aft sites (aft ls) yes List claimed projects
aft open yes Open this project's live URL
aft rename <slug> yes Change the *.aft.page URL
aft env list|set|unset (aft secrets) yes Secrets vault — same as the project UI
aft visibility public|private (aft vis) yes Who can open the live site
aft rollback [deployId] yes List or restore prior deploys
aft plugins add Install the Agent Plugin (deploy Skill + MCP)

Examples

aft rename include-xi
aft env set ANTHROPIC_API_KEY=sk-…
aft env list
aft visibility private
aft rollback
aft rollback dep_abc123def456

Rename and secrets need a claimed site you own. The preview UI can also rename with the deploy edit token before claim — see Claim.

Troubleshooting

"command not found: aft" — the installer puts aft in ~/.local/bin, which isn't always on PATH by default. Add export PATH="$HOME/.local/bin:$PATH" to your shell profile and open a new terminal.

"run npm run build first"aft deploy saw a src/ or app/ folder but no dist/, out/, or build/ with an index.html in it. Build the project, or point the CLI straight at the output folder: aft deploy dist.

Commands that need login fail with an auth error — run aft whoami to check the session. Sessions live in ~/.config/aft.page/credentials.json; delete that file (or run aft logout) and aft login again if it's stuck. In CI, skip the browser flow entirely by setting AFT_TOKEN.

CLI feels out of date — run aft update to reinstall the latest build. To turn off the daily version check (for example in CI), set AFT_NO_UPDATE=1.