Agent-ergonomic wrapper around the official vast.ai CLI (vastai), following the AXI principles: TOON output, minimal schemas, structured errors, no prompts, next-step hints.
- Fewer tokens. For 10 GPU offers,
vastai search offers --rawreturns 95 fields per offer and costs about 12,000 tokens.vast-axi search --limit 10costs about 400 (o200k tokenizer, measured live).--fullbrings back every field. - Errors an agent can act on. Upstream reports auth failures with exit code 0. vast-axi maps them to structured errors with exit 1 and a fix hint, and an empty result says so instead of printing
[]. - A spend guard.
rentrefuses offers above your price cap.--hours Nshows the estimated total and its share of your balance, andrentrefuses (exit 2) when N hours of your current burn plus the new offer would cost more than your balance, unless you pass--confirm. Rentals are always on-demand, never interruptible. - A destroy timer that outlives your session.
rent --max-hours Nschedules the destroy on vast.ai's servers, so the instance goes away even if your machine or agent session dies. Your API key never goes on the instance. - A job lifecycle.
runstarts a detached job,jobreports its state and log tail, andfinish --wait --fetch ... --destroydestroys the instance only after every fetched file has arrived and is non-empty. - An upload secret guard.
copyrefuses to upload files that look like keys or credentials unless you pass--allow-secrets. - Works on Windows. Tested on Windows 11 and Linux, including Git Bash path handling.
- Node.js 20 or newer
vastai1.8.3, the tested version. Install it withuv tool install vastai, or pointVAST_AXI_BINat a project venv (.venv/Scripts/vastai.exe).- A vast.ai API key, set with
vastai set api-key <key>orVAST_API_KEY. vast-axi never reads or prints it. sshandscpon PATH forssh --execandcopy. rsync is not needed.
Each release has a prebuilt tarball attached. Install it straight from the release; no build runs on install:
npm i -g https://github.com/jeffrymahbuubi/vast-axi/releases/download/v0.2.0/vast-axi-0.2.0.tgzvast-axi update installs the newest release (it uses the gh CLI, logged in). Add --pre to include pre-releases.
npm i -g github:jeffrymahbuubi/vast-axi#<tag> does not work. npm's global git install never installs the build tools in its clone.
Development, from this folder:
pnpm install
pnpm dev -- search --limit 5| Command | What it does |
|---|---|
vast-axi |
Dashboard: balance, instances, burn per hour, 24h projection, runway in hours, idle flags |
search [--hours N] [--sort value|flops] [--precision fp32|tf32|fp16] |
Cheapest offers, 7 fields, sorted by price; --full for every field. --hours N adds max_h, est_cost and pct_balance, and hides offers whose contract ends within N hours. --sort value ranks by vast.ai's DLPerf per $/hr, and --sort flops by TFLOPS per $/hr. --precision ranks by a static table of vendor datasheet peak TFLOPS (dense) per $/hr |
rent <offer> --image <img> [--hours N] [--max-hours N] [--pip "pkgs"] [--onstart file] |
Rent an on-demand instance behind the spend guard. --max-hours N (2 to 23) has vast.ai destroy it on a server-side timer. --pip and --onstart install and set up at boot as the job onstart, and status --wait waits for it |
status <id> [--wait] |
Instance state; --wait stops on terminal states |
ssh <id> [--exec -- <cmd>] |
Print the ssh command, or run one remote command |
logs <id> |
Container logs, truncated with size hints (for a program started with run, use job) |
stop <id> / destroy <id> |
Idempotent; destroying an already destroyed id is a no-op |
copy <src> <dst> [--allow-secrets] |
scp for local and instance transfers, vastai copy between remotes. Uploads that contain secrets are refused |
run <id> [--cwd] [--log] [--name] -- <cmd> |
Start a detached job (nohup, setsid); the log ends with a __VAST_AXI_EXIT__ line |
job <id> [--name] [--tail] [--list] |
Job state (running, finished, failed, lost), exit code, elapsed time, log tail |
finish <id> --wait --fetch <remote>:<local> [--destroy] |
Wait for the exit line, fetch and verify results, destroy only if every fetch verified and the job exited 0 |
raw <vastai args> |
Any other vastai command, rendered as TOON |
setup hooks / setup key <key> |
Opt-in Claude Code SessionStart hook; store the API key |
update [--check] |
Update from the latest GitHub release |
Run vast-axi <command> --help for the flags of each command.
rent refuses with exit 2 when the offer exceeds maxDph (default 1.00 USD/hr) or when current burn plus the offer exceeds maxBurn (default 2x maxDph). --confirm overrides both. If current burn cannot be read, rent refuses and --confirm does not override it.
With --hours N, rent also refuses (OVER_BALANCE) when N x (current burn + offer price) is more than the account balance. --confirm overrides that. If the balance cannot be read, it refuses and --confirm does not override it.
rent always creates an on-demand instance and prints type: on-demand. It never passes a bid price, so it never creates an interruptible instance.
rent --max-hours N (N from 2 to 23) creates a vast.ai scheduled job that destroys the instance on vast.ai's servers. It runs even when this machine is off or the agent session has ended. The API key never goes onto the instance.
- The job is a DAILY job set to the destroy hour (UTC). The destroy time is rounded down to the hour, so the rental never lasts longer than N hours; it can be up to 59 minutes shorter. The output prints
destroy_atandruns_for_h. If the delete fails, vast.ai runs the job again 24 hours later. rentreads the job back after creating it. If the job is missing or doesn't match, or it cannot be created, the new instance is destroyed straight away andrentexits 1.- N is capped at 23 because a daily job cannot be set further ahead. For longer runs, end with
vast-axi finish <id> --wait --fetch <remote>:<local> --destroy. - If the offer's rental contract ends before
destroy_at,rentrefuses with exit 2 (--confirmoverrides). vast.ai stops an instance at contract end, and a stopped instance still bills storage. destroyandfinish --destroyalso delete the timer.status <id>and the dashboard showdestroy_at.--max-hours Nimplies--hours Nfor the balance check.- Legacy timers: v0.1.4 to v0.1.6 created HOURLY jobs. vast.ai fires those at the next top of the hour, ignoring the planned time.
statusand the dashboard flag them asLEGACYand print the command to delete them.
Set the limits in ~/.config/vast-axi/config.json (maxDph, maxBurn, idleMinutes) or with VAST_AXI_MAX_DPH and VAST_AXI_MAX_BURN.
--pip "pkg pkg==1.2"runspython3 -m pip installat boot.--onstart setup.shthen runs the script. Both run as one detached job namedonstart, using the same exit-line mechanism asrun.vast-axi job <id> --name onstartshows its log.status <id> --waitkeeps waiting until the onstart job finishes. A failed onstart exits 1 with the log tail and keeps the instance.- vast.ai stores the onstart text on the instance record, where the host can read it. Scripts containing key-shaped strings (
hf_…,sk-…,ghp_…,AKIA…, private-key blocks) are refused unless you pass--allow-secrets. The text is limited to 4,048 characters, which leaves about 1.7 KB of script (1.5 KB with--pip). For longer setup,copya script and start it withrun. - vast.ai re-runs onstart on every container start, so
statusreports the latest boot.
copy local:<path> C.<id>:<path> checks the upload before scp starts. Files or folders named .env/.env.* (examples, samples and templates are allowed), *.pem, *.key, *.p12, *.pfx, id_rsa/id_ed25519-style private keys, .git-credentials, .netrc, .pypirc, .npmrc, credentials.json, kaggle.json, .aws/credentials, anything under .ssh/, or a vast.ai key file are refused with exit 2. So are text files containing key-shaped strings. --allow-secrets uploads them anyway and lists them. Downloads are not checked.
gpu_utilcomes from vast.ai and lags real GPU usage by several minutes; about 10 minutes has been observed. The API gives no timestamp for it.- The dashboard's
idleflag is thereforeno,unknownorlikely, never a definite yes. - Before stopping or destroying anything, run
vast-axi status <id> --live, which readsnvidia-smiover ssh. Or runvast-axi ssh <id> --exec -- nvidia-smi. destroydeletes data andstopkeeps billing for disk. Copy results out first.- For long training jobs, use
run, thenjob, thenfinish. A job is finished only when its log has the exit line with that run's token, never because of echoed command text. finish --waitcan run for hours, longer than most agent tool timeouts. Run it in the background, or callfinishwithout--waitin a loop. It prints one progress line per poll to stderr; stdout holds only the result.jobshows the tail of the job's log, so the program has to write to stdout while it runs. Run Python unbuffered (python -u). Notebook runners print nothing until they finish unless told to stream, e.g.papermill in.ipynb out.ipynb --log-output.statusshowsssh_direct, the endpointsshandcopyconnect to, next to vast.ai's proxy endpoint. Use the direct one for a manualssh -Ltunnel.rentprices the offer for the--diskyou asked for and printspriced_for_disk_gb.searchlists prices for vast.ai's default disk, so the two can differ by a little.finish --destroykeeps the instance when the job failed or was lost, or when any fetched file is missing or its size differs from the remote copy. The output says why.
pnpm testreplays recorded vastai output throughtests/helpers/fake-vastai.cjs. It needs no network and no API key.VAST_AXI_LIVE=1 pnpm test:liveruns the full lifecycle against the real service: it rents the cheapest reliable offer under 0.30 USD/hr, then destroys it. A run costs a few cents.