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.