---
title: "CLI reference"
description: "Every promigence command and flag."
url: "https://www.promigence.ai/docs/cli"
site: "Promigence"
---

# promigence CLI reference

Install: `npm i -g ./promigence-<version>.tgz` (the file sent with your invite; not on npm), then `promigence signup`

## Global flags
- `--json`, one JSON document on stdout; the default whenever stdout is not a TTY, except for exec --sandbox
- `--text`, human-readable text
- `--api-key KEY`, precedence: --api-key > PROMIGENCE_API_KEY > ~/.config/promigence/credentials
- `--version`, print the version
- `--help`, help; `promigence <command> --help` for one command

## Setup

Sign up, check the install, and get an agent oriented in about 1,200 tokens.

### `promigence login` 
sign up or sign in (email; GitHub/Google where enabled); stores a new API key
- `--provider NAME`, a sign-in method the API offers (email; github|google where enabled): skip the chooser
- `--no-browser`, headless: print the URL, paste the code back
- `--key-name N`, label for the key this login mints (default cli@<host>)
- `--api-url URL`, sign in to this API instead of the default (no prompt)
- `--yes`, accept a non-default API from PROMIGENCE_API_URL without the prompt
- `--ref CODE`, a referral code (new accounts)
- `--json`, force the JSON envelope

### `promigence signup` 
create an account (asks for an invite code first while invite-only)
- `--invite CODE`, the code (prefer the prompt; argv is visible)
- `--provider NAME`, a sign-in method the API offers (email; github|google where enabled): skip the chooser
- `--no-browser`, headless: print the URL, paste the code back
- `--key-name N`, label for the key this sign-in mints (default cli@<host>)
- `--api-url URL`, sign up on this API instead of the default (no prompt)
- `--yes`, accept a non-default API from PROMIGENCE_API_URL without the prompt
- `--ref CODE`, a referral code (new accounts)
- `--json`, force the JSON envelope

### `promigence logout` 
forget this CLI's key (revoked when `promigence login` minted it)
- `--keep-key`, only forget it locally; the key keeps working
- `--json`, force the JSON envelope

### `promigence auth login` 
store an API key (--from-env VAR | stdin; never on argv)
- `--from-env VAR`, read the key from an environment variable
- `--api-key K`, accepted but warns: key on argv

### `promigence keys list` 
your org's API keys
- `--all`, include revoked keys
- `--project P`, another project's
- `--org ORG`, with --project: in this org
- `--no-browser`, sign in headless (or PROMIGENCE_ID_TOKEN)
- `--yes`, sign in to PROMIGENCE_API_URL without the prompt
- `--json`, force the JSON envelope

### `promigence keys create` 
mint a key (secret printed once)
- `--name N`, label, e.g. ci-prod
- `--org ORG`, in this org (default: this key's)
- `--project P`, in this project
- `--service`, owners: outlives your membership (CI)
- `--expires WHEN`, 30d, 1y, a date; default never
- `--no-browser`, sign in headless (or PROMIGENCE_ID_TOKEN)
- `--yes`, sign in to PROMIGENCE_API_URL without the prompt
- `--json`, force the JSON envelope

### `promigence keys revoke KEY_ID` 
revoke a key
- `--project P`, a key in another project
- `--org ORG`, with --project: in this org
- `--no-browser`, sign in headless (or PROMIGENCE_ID_TOKEN)
- `--yes`, sign in to PROMIGENCE_API_URL without the prompt
- `--json`, force the JSON envelope

### `promigence org list` 
your organizations (* = default)
- `--all`, every one
- `--no-browser`, sign in headless (or PROMIGENCE_ID_TOKEN)
- `--yes`, sign in to PROMIGENCE_API_URL without the prompt
- `--json`, force the JSON envelope

### `promigence org create NAME` 
create one you own (no trial credit)
- `--no-browser`, sign in headless (or PROMIGENCE_ID_TOKEN)
- `--yes`, sign in to PROMIGENCE_API_URL without the prompt
- `--json`, force the JSON envelope

### `promigence org switch ORG` 
sign in, make ORG the default, store a key for it
- `--project P`, the new key's project
- `--keep-old-key`, keep the replaced key working
- `--no-browser`, sign in headless (or PROMIGENCE_ID_TOKEN)
- `--yes`, sign in to PROMIGENCE_API_URL without the prompt
- `--json`, force the JSON envelope

### `promigence org members` 
members and roles
- `--org ORG`, another org than this key's
- `--no-browser`, sign in headless (or PROMIGENCE_ID_TOKEN)
- `--yes`, sign in to PROMIGENCE_API_URL without the prompt
- `--json`, force the JSON envelope

### `promigence org invite EMAIL` 
invite an email (owners)
- `--role R`, owner|member (member)
- `--org ORG`, another org than this key's
- `--no-browser`, sign in headless (or PROMIGENCE_ID_TOKEN)
- `--yes`, sign in to PROMIGENCE_API_URL without the prompt
- `--json`, force the JSON envelope

### `promigence org invites` 
pending invites (14-day expiry)
- `--mine`, sent to you
- `--org ORG`, another org than this key's
- `--no-browser`, sign in headless (or PROMIGENCE_ID_TOKEN)
- `--yes`, sign in to PROMIGENCE_API_URL without the prompt
- `--json`, force the JSON envelope

### `promigence org uninvite INVITE_ID` 
revoke an invite (owners)
- `--org ORG`, another org than this key's
- `--no-browser`, sign in headless (or PROMIGENCE_ID_TOKEN)
- `--yes`, sign in to PROMIGENCE_API_URL without the prompt
- `--json`, force the JSON envelope

### `promigence org role USER_ID ROLE` 
set owner|member (owners)
- `--org ORG`, another org than this key's
- `--no-browser`, sign in headless (or PROMIGENCE_ID_TOKEN)
- `--yes`, sign in to PROMIGENCE_API_URL without the prompt
- `--json`, force the JSON envelope

### `promigence org remove USER_ID` 
remove a member; their keys die (owners)
- `--org ORG`, another org than this key's
- `--no-browser`, sign in headless (or PROMIGENCE_ID_TOKEN)
- `--yes`, sign in to PROMIGENCE_API_URL without the prompt
- `--json`, force the JSON envelope

### `promigence org leave [ORG]` 
leave an organization
- `--no-browser`, sign in headless (or PROMIGENCE_ID_TOKEN)
- `--yes`, sign in to PROMIGENCE_API_URL without the prompt
- `--json`, force the JSON envelope

### `promigence org join INVITE_ID` 
accept an invite sent to you
- `--decline`, decline it instead
- `--no-browser`, sign in headless (or PROMIGENCE_ID_TOKEN)
- `--yes`, sign in to PROMIGENCE_API_URL without the prompt
- `--json`, force the JSON envelope

### `promigence org audit` 
who did what (owners; needs --sign-in)
- `--before SEQ`, older entries
- `--limit N`, how many (100)
- `--org ORG`, another org than this key's
- `--sign-in`, sign in in your browser: the log is read as you, never with a key
- `--no-browser`, sign in headless (or PROMIGENCE_ID_TOKEN)
- `--yes`, sign in to PROMIGENCE_API_URL without the prompt
- `--json`, force the JSON envelope

### `promigence org delete ORG` 
delete it; keys die (owners)
- `--confirm NAME`, its name (required)
- `--no-browser`, sign in headless (or PROMIGENCE_ID_TOKEN)
- `--yes`, sign in to PROMIGENCE_API_URL without the prompt
- `--json`, force the JSON envelope

### `promigence project list` 
projects (keys belong to one)
- `--org ORG`, another org than this key's
- `--no-browser`, sign in headless (or PROMIGENCE_ID_TOKEN)
- `--yes`, sign in to PROMIGENCE_API_URL without the prompt
- `--json`, force the JSON envelope

### `promigence project create NAME` 
create a project
- `--org ORG`, another org than this key's
- `--no-browser`, sign in headless (or PROMIGENCE_ID_TOKEN)
- `--yes`, sign in to PROMIGENCE_API_URL without the prompt
- `--json`, force the JSON envelope

### `promigence project rename PROJECT NAME` 
rename (not `default`)
- `--org ORG`, another org than this key's
- `--no-browser`, sign in headless (or PROMIGENCE_ID_TOKEN)
- `--yes`, sign in to PROMIGENCE_API_URL without the prompt
- `--json`, force the JSON envelope

### `promigence project delete PROJECT` 
delete an empty one (owners)
- `--org ORG`, another org than this key's
- `--no-browser`, sign in headless (or PROMIGENCE_ID_TOKEN)
- `--yes`, sign in to PROMIGENCE_API_URL without the prompt
- `--json`, force the JSON envelope

### `promigence project cap PROJECT USD|off` 
monthly USD cap, or off (owners)
- `--org ORG`, another org than this key's
- `--no-browser`, sign in headless (or PROMIGENCE_ID_TOKEN)
- `--yes`, sign in to PROMIGENCE_API_URL without the prompt
- `--json`, force the JSON envelope

### `promigence project move PROJECT` 
to another org; keys die (owners)
- `--to ORG`, yours, with a card
- `--org ORG`, another org than this key's
- `--no-browser`, sign in headless (or PROMIGENCE_ID_TOKEN)
- `--yes`, sign in to PROMIGENCE_API_URL without the prompt
- `--json`, force the JSON envelope

### `promigence me` 
plan, concurrency in use, trial credit, spend, limits
- `--json`, force the JSON envelope

### `promigence billing card` 
add a card: prints a checkout URL (trial credits kept)
- `--json`, force the JSON envelope

### `promigence doctor` 
check client, auth and API
- `--json`, force the JSON envelope

### `promigence init` 
write promigence.toml
- `--repo U`, git URL (default: the `origin` remote)
- `--commit SHA`, commit to pin (default: HEAD)
- `--setup CMD`, override the inferred setup step
- `--verify CMD`, override the inferred verify command
- `--tier xsmall|small|medium|large|xlarge|2xlarge`, default medium
- `--force`, overwrite an existing promigence.toml
- `--print`, write nothing; print what it would write
- `--json`, force the JSON envelope

### `promigence examples` 
what forks with no build (no auth)
- `--limit N`, how many to list (default 20)
- `--bundle`, write each public snapshot as a .promigence file (none yet)
- `--json`, force the JSON envelope

### `promigence agent-guide` 
~1.2k-token guide for agents (--section commands|errors|cost)
- `--section commands|errors|cost`, one section instead of the core
- `--code C`, the entry for one error code
- `--format md|json`, default md
- `--install`, write the fence into AGENTS.md/CLAUDE.md, .claude/skills, .cursor/rules
- `--create`, with --install: create AGENTS.md if neither file exists
- `--check`, report what --install would change; write nothing

### `promigence mcp` 
MCP server on stdio: `claude mcp add promigence -- promigence mcp` (Windows: `-- cmd /c promigence mcp`)
- `--read-only`, offer only the tools that read: list, read a file, fetch output, a report
- `--allow-tools A,B`, offer only these tools (comma-separated names)
- `--cap USD`, spend cap for every sandbox and batch it starts (else PROMIGENCE_SPEND_CAP, else the org default)
- `--keep`, leave the sandboxes this session created running at shutdown

### `promigence status` 
regions · your concurrency in use vs your limit
- `--json`, force the JSON envelope

### `promigence billing usage` 
this month's spend: plan, usage by tier, credits, next invoice
- `--ledger`, also print this key's project's metered rows
- `--limit N`, with --ledger: how many rows (default 20)
- `--cursor C`, with --ledger: the next_cursor of an earlier page
- `--json`, force the JSON envelope

### `promigence referrals` 
your referral code, its offer, your referrals
- `--json`, force the JSON envelope

### `promigence referrals apply <code>` 
apply a code (owner, before the first paid invoice)
- `--json`, force the JSON envelope

### `promigence pricing` 
the price list, live (yours with a key)
- `--new-account`, what a new account gets
- `--json`, force the JSON envelope

### `promigence credits` 
your free-credit offer: state, credit, expiry, campaign
- `--json`, force the JSON envelope

### `promigence credits claim` 
open the claim page (accept the terms in the browser); prints its URL
- `--no-open`, print the URL, open nothing
- `--json`, force the JSON envelope

### `promigence billing portal` 
manage the card on file and past invoices: prints a portal URL
- `--json`, force the JSON envelope

## Snapshots

Build a verified environment once. Everything after this is a fork of it.

### `promigence snapshot create` 
build + verify a snapshot (--image | --dockerfile | --devcontainer)
- `--repo R`, owner/name (connected GitHub) or a git URL
- `--ref R`, with owner/name: branch|tag|sha
- `--commit SHA`, 40-char sha, never a branch
- `--image REF`, a tag (we pin it) or REF@sha256:D
- `--dockerfile PATH`, a Dockerfile we build
- `--context DIR|URL@SHA`, default: the Dockerfile's dir
- `--devcontainer PATH`, a devcontainer.json (default: the one here)
- `--no-devcontainer`, ignore the repo's devcontainer.json
- `--dir PATH`, upload the files git tracks there
- `--from SNAP`, owner/name|--dir: start from (base)
- `--track`, owner/name: rebuild on every push
- `--setup CMD`, setup step (ordered)
- `--verify CMD`, must exit 0 or nothing is stored
- `--start CMD`, background process kept running
- `--tier xsmall|small|medium|large|xlarge|2xlarge`, build and fork size
- `--alias N`, unique per org
- `--grade CMD`, score the work in a clean env
- `--fresh`, no 10-min replay (identical inputs still reuse their snapshot)
- `--wait`, bounded by --wait-timeout (default 100s)
- `--wait-timeout DUR`, bound (100s); expiry = exit 11, nothing killed
- `--idempotency-key K`, a key you pick (24 h)
- `--json`, force the JSON envelope

### `promigence snapshot status <build_id>` 
poll a build by build_id
- `--wait`, bounded by --wait-timeout (default 100s)
- `--wait-timeout DUR`, bound (100s); expiry = exit 11, nothing killed
- `--log N`, print the last N lines of the build log
- `--json`, force the JSON envelope

### `promigence snapshot list` 
list snapshots in your org
- `--json`, force the JSON envelope

### `promigence snapshot inspect <hash>` 
show a snapshot manifest
- `--json`, force the JSON envelope

### `promigence snapshot verify <hash>` 
re-verify a snapshot in a fork
- `--json`, force the JSON envelope

### `promigence snapshot export <hash>` 
write a portable .promigence bundle (commit it, cite it, mail it)
- `--out FILE`, default <alias>.promigence; `-` or a pipe writes stdout
- `--no-layers`, citation form: identity + provenance + verification, no chunk table
- `--layers`, keep the chunk table however large (default: drop it above 100 kB)
- `--json`, force the JSON envelope

### `promigence image resolve REF` 
resolve REF (python:3.12) to REF@sha256:… without a local container runtime
- `--registry-secret NAME`, stored secret holding user:password for a private registry
- `--json`, force the JSON envelope

### `promigence github connect` 
install the GitHub App (browser); waits for it
- `--no-open`, print the link, open nothing
- `--no-wait`, print the link and return
- `--wait-timeout DUR`, for the install (10m); expiry = exit 11
- `--json`, force the JSON envelope

### `promigence github status` 
connected accounts, pending installs, tracked branches
- `--json`, force the JSON envelope

### `promigence github disconnect <installation_id|account>` 
stop building from a GitHub account
- `--json`, force the JSON envelope

### `promigence github untrack <track_id|alias>` 
stop rebuilding on push (the snapshot stays)
- `--json`, force the JSON envelope

### `promigence repos` 
repos your GitHub connection reads (for --repo)
- `--page N`, page (100 a page)
- `--json`, force the JSON envelope

### `promigence snapshot delete <hash|alias>` 
remove one of your snapshots (refused while a fork of it is alive)
- `--json`, force the JSON envelope

### `promigence snapshot builds` 
your builds, newest first (a rejected build keeps its reason)
- `--limit N`, how many (default 20)
- `--state S`, only this state, e.g. running | rejected
- `--cursor C`, the next_cursor of an earlier page
- `--json`, force the JSON envelope

### `promigence snapshot alias <hash> [NAME]` 
name a snapshot, or clear its name (unique per org)
- `--clear`, remove the alias instead
- `--json`, force the JSON envelope

## Runs

Quote, cap, fork N copies, execute, and read which copies were valid.

### `promigence run -- CMD` 
fork N, exec CMD in each, print the validity report
- `--snapshot H`, id | alias[@commit7] | ./env.promigence (default promigence/base)
- `--image REF`, not with --snapshot: a tag or REF@sha256:D
- `--count N` **(required)**, sandboxes; each has PROMIGENCE_INDEX (0..N-1) and PROMIGENCE_SEED
- `--timeout DUR`, sandbox timeout (15m)
- `--cap USD` **(required)**, spend cap; refused above it (exit 5)
- `--allow-partial`, start what the cap allows; the rest not_started
- `--secret NAME`, stored secret as an env var
- `--verify-each`, verify forks before hand-over
- `--network none|egress`, default egress
- `--allow HOST`, outbound allow-list
- `--optimize-for start|compute`, default start
- `--keep-delta`, keep the writable delta
- `--label K=V`, run label
- `--wait-timeout DUR`, bound (100s); expiry = exit 11, nothing killed
- `--grade CMD`, score the work in a clean env
- `--holdout CMD`, second test set; gap reported
- `--grade-score M`, exit|last_line_json|tap (exit); JSON: {"score":0.8,"pass":true}
- `--grade-timeout DUR`, per grader (10m)
- `--grade-output`, keep last 16 KiB
- `--fail-on task|env|none`, what exits non-zero (task)
- `--keep`, keep sandboxes after CMD
- `--stream`, live output (auto on a TTY)
- `--no-stream`, one envelope even on a TTY
- `--max-output BYTES`, output cap (64k)
- `--idempotency-key K`, a key you pick (24 h)
- `--verbose`, text: fork timings and totals too

### `promigence run quote` 
price a run before launch
- `--snapshot H`, id | alias[@commit7] | ./env.promigence (default promigence/base)
- `--count N` **(required)**, number of sandboxes
- `--timeout DUR`, sandbox timeout (15m)
- `--tier T`, must match the snapshot's assigned tier
- `--cap USD`, price it against this cap; spends nothing
- `--json`, force the JSON envelope

### `promigence run report ID` 
validity report: env vs task failures
- `--json`, force the JSON envelope
- `--sandboxes all|failed`, default: summary + non-completed sandboxes
- `--sandbox SID`, one sandbox
- `--repro`, print the repro command for --sandbox
- `--limit N`, text rows before '… N more' (50; 0 = all). --json is never paged

### `promigence run status ID` 
poll a run
- `--wait`, bounded by --wait-timeout (default 100s)
- `--wait-timeout DUR`, bound (100s); expiry = exit 11, nothing killed
- `--json`, force the JSON envelope

### `promigence run cancel ID` 
stop queued starts
- `--json`, force the JSON envelope

### `promigence run kill ID` 
kill every sandbox of a run
- `--json`, force the JSON envelope

### `promigence run replay ID` 
replay sandboxes (client-triggered, never automatic)
- `--sandbox SID`, only these sandboxes
- `--json`, force the JSON envelope

### `promigence run open ID` 
reopen a failed sandbox as a live one, at the moment it failed
- `--sandbox SID`, which failure (default: the only one)
- `--cap USD`, what the reopened sandbox may spend
- `--timeout DUR`, how long it may run (default: the run's)
- `--json`, force the JSON envelope

### `promigence run captures ID` 
what of this run is preserved, and when it expires
- `--delete SNAPSHOT_ID`, destroy one now, before it expires
- `--json`, force the JSON envelope

### `promigence run list` 
your runs, newest first
- `--limit N`, how many (default 20)
- `--state S`, only this state
- `--cursor C`, the next_cursor of an earlier page
- `--json`, force the JSON envelope

## Sandboxes

Long-lived sandboxes you drive command by command: exec, files, pause, resume, fork.

### `promigence fork` 
fork N sandboxes from a snapshot (--count --cap)
- `--snapshot H`, snap_<id> | alias[@commit7] | ./env.promigence (default promigence/base)
- `--count N` **(required)**, number of sandboxes
- `--timeout DUR`, sandbox timeout (15m)
- `--cap USD` **(required)**, spend cap; refused above it (exit 5)
- `--allow-partial`, start what the cap allows; the rest not_started
- `--secret NAME`, stored secret as an env var
- `--verify-each`, verify forks before hand-over
- `--network none|egress`, default egress
- `--allow HOST`, outbound allow-list
- `--optimize-for start|compute`, default start
- `--keep-delta`, keep the writable delta
- `--label K=V`, run label
- `--wait-timeout DUR`, bound (100s); expiry = exit 11, nothing killed
- `--no-wait`, return after POST /runs
- `--fresh`, skip idempotent replay
- `--stream`, live output (auto on a TTY)
- `--no-stream`, one envelope even on a TTY
- `--idempotency-key K`, a key you pick (24 h)
- `--verbose`, text: fork timings and totals too
- `--json`, force the JSON envelope

### `promigence exec -- CMD` 
run CMD in a sandbox (--sandbox SID) or a run (--run ID --all)
- `--sandbox SID`, stdout is the child's own bytes (JSON only with --json or PROMIGENCE_OUTPUT=json); its exit code passes through; not found 127; Promigence's own failures 125
- `--run ID`, with --all: every ready sandbox; queued reported skipped unless --wait
- `--all`, 0 if every child exits 0, else 4
- `--no-passthrough`, return 0–12 instead of the child's code
- `--background`, with --sandbox: start it, print its exec_id, return now
- `--stdin`, with --background: keep stdin open for `promigence exec stdin`
- `--secret NAME`, stored secret as an env var
- `--stream`, live output (auto on a TTY)
- `--no-stream`, one envelope even on a TTY
- `--max-output BYTES`, per stream (64k; 32m, the most, into a pipe or file); past it the rest is cut, and text exits 12
- `--timeout DUR`, child timeout (default 15m)
- `--wait`, bounded by --wait-timeout (default 100s)
- `--wait-timeout DUR`, bound (100s); expiry = exit 11, nothing killed
- `--idempotency-key K`, a key you pick (24 h)

### `promigence exec output EXEC_ID` 
an exec's output by id (background x_…: --follow)
- `--range A-B`, byte range, 0-based and B inclusive; `A-` runs to the end
- `--sandbox SID`, resolve the exec inside this sandbox (required for x_…)
- `--run ID`, resolve the exec inside this run
- `--stderr`, the child's stderr instead of its stdout
- `--follow`, background exec: stream until it exits, pass its code through
- `--json`, force the JSON envelope

### `promigence exec ps` 
list a sandbox's background execs
- `--sandbox SID` **(required)**, the sandbox
- `--json`, force the JSON envelope

### `promigence exec stdin EXEC_ID` 
write to a background exec's stdin (needs `exec --background --stdin`)
- `--sandbox SID` **(required)**, the sandbox it runs in
- `--data TEXT`, write this (default: read stdin to EOF)
- `--file P`, write this local file's bytes
- `--eof`, close stdin after writing (implied when reading a pipe)
- `--no-eof`, keep it open after piped input
- `--json`, force the JSON envelope

### `promigence exec kill EXEC_ID` 
signal a background exec (default SIGKILL)
- `--sandbox SID` **(required)**, the sandbox it runs in
- `--signal SIG`, TERM | INT | HUP | KILL | a number
- `--forget`, then drop its handle and buffered output
- `--json`, force the JSON envelope

### `promigence files put SRC DST` 
copy a local file into a sandbox (--recursive: a directory)
- `--sandbox SID` **(required)**, target sandbox
- `--recursive`, SRC is a local directory; DST is a directory in the sandbox
- `--json`, force the JSON envelope

### `promigence files get SRC DST` 
copy a file out of a sandbox (--recursive: a directory)
- `--sandbox SID` **(required)**, source sandbox
- `--recursive`, SRC is a directory in the sandbox; DST a local directory
- `--exclude GLOB`, with --recursive: leave these out, e.g. .git
- `--keep-links`, with --recursive: keep links leaving DST
- `--json`, force the JSON envelope

### `promigence files ls [PATH]` 
list a directory in a sandbox (lstat per entry)
- `--sandbox SID` **(required)**, the sandbox
- `--recursive`, walk below PATH, not one level
- `--depth N`, with --recursive: how many levels
- `--limit N`, stop after N entries (truncated is reported)
- `--no-hidden`, drop dotfiles (they are listed by default)
- `--json`, force the JSON envelope

### `promigence files search [PATH]` 
find files by name glob and/or text inside them
- `--sandbox SID` **(required)**, the sandbox
- `--name GLOB`, name glob, e.g. '*.py'
- `--contains TEXT`, literal text to find inside matching files
- `--ignore-case`, case-insensitive --contains
- `--limit N`, stop after N hits (truncated is reported)
- `--no-hidden`, skip dotfiles and dot-directories
- `--json`, force the JSON envelope

### `promigence files mkdir PATH` 
create a directory in a sandbox
- `--sandbox SID` **(required)**, the sandbox
- `--parents`, mkdir -p: intermediate directories, and no error if it exists
- `--mode OCTAL`, e.g. 755
- `--json`, force the JSON envelope

### `promigence files mv SRC DST` 
move or rename a path inside a sandbox
- `--sandbox SID` **(required)**, the sandbox
- `--overwrite`, replace DST if it is already there
- `--json`, force the JSON envelope

### `promigence files cp SRC DST` 
copy a path inside a sandbox (both ends are in the sandbox)
- `--sandbox SID` **(required)**, the sandbox
- `--recursive`, a directory and everything under it
- `--overwrite`, replace DST if it is already there
- `--json`, force the JSON envelope

### `promigence files chmod PATH` 
change mode and/or owner of a path in a sandbox
- `--sandbox SID` **(required)**, the sandbox
- `--mode OCTAL`, e.g. 755
- `--uid N`, owner
- `--gid N`, group
- `--recursive`, the directory and everything under it
- `--json`, force the JSON envelope

### `promigence agent start claude|codex|opencode` 
a coding agent in a new sandbox
- `--key-secret NAME[=VAR]`, stored secret with the model key (default ANTHROPIC_API_KEY; codex: OPENAI_API_KEY)
- `--key-from-env VAR`, store the key from this variable first (never argv)
- `--snapshot H`, start from this snapshot (default promigence/base; the agent is installed if missing)
- `--image REF@sha256:D`, instead of --snapshot
- `--repo URL`, clone this public repository and start the agent in it
- `--prompt TEXT`, work on this task headless, in the background
- `--attach`, open the agent's terminal now
- `--timeout DUR`, sandbox lifetime (default 1h)
- `--cap USD`, spend cap (else PROMIGENCE_SPEND_CAP, else the org default)
- `--wait-timeout DUR`, bound (100s); expiry = exit 11, nothing killed
- `--json`, force the JSON envelope

### `promigence sandbox kill SID` 
kill one sandbox
- `--json`, force the JSON envelope

### `promigence sandbox network SID` 
what this sandbox may reach, and every host it was refused
- `--cut`, cut this sandbox's egress now; it cannot be turned back on
- `--json`, force the JSON envelope

### `promigence sandbox shell SID [-- CMD]` 
interactive terminal (raw TTY, follows window size)
- `--cmd CMD`, run this instead of the login shell (sh -c)
- `--cwd DIR`, start in this directory
- `--env K=V`, environment variable
- `--secret NAME[=VAR]`, stored secret in the terminal's environment; NAME=VAR binds it to VAR

### `promigence sandbox ssh SID [-- CMD]` 
log in over SSH (scp, sftp and -L work too)
- `--config`, print an ssh config block instead of logging in
- `--print`, print the connection details instead of logging in
- `--key PATH`, use this key pair instead of making one
- `--ttl S`, how long the access lasts (default 3600, max 3600)
- `--idle S`, close a session after this long with no activity
- `--proxy`, carry one connection on stdin/stdout (used by ssh itself)
- `--list`, the keys that have access, then exit
- `--revoke KEY_ID`, end one key's access (and its tunnel credential), then exit
- `--json`, force the JSON envelope

### `promigence port expose PORT` 
publish a port as a preview URL (anyone with it can reach it)
- `--sandbox SID` **(required)**, the sandbox
- `--json`, force the JSON envelope

### `promigence port list` 
list a sandbox's preview URLs
- `--sandbox SID` **(required)**, the sandbox
- `--json`, force the JSON envelope

### `promigence port revoke TOKEN|PORT` 
take a preview URL down (a token, or every URL for a port)
- `--sandbox SID` **(required)**, the sandbox
- `--json`, force the JSON envelope

### `promigence secrets set NAME` 
store secret NAME (env/file/stdin, never argv)
- `--from-env VAR`, read the value from an environment variable
- `--from-file P`, read the value from a file
- `--host HOST`, bind it to a host: sandboxes get a placeholder, replaced by the value only in requests sent to the address this command prints for HOST
- `--header NAME`, with --host: the request header the key is sent in (default: the usual key headers)
- `--no-raw`, with --host: the value itself can never be given to a sandbox
- `--list`, list stored secret names (no values, ever)
- `--delete`, remove NAME
- `--json`, force the JSON envelope

### `promigence sandbox list` 
your sandboxes, newest first
- `--limit N`, how many (default 50)
- `--state S`, only these states, e.g. running,ready
- `--label K=V`, only sandboxes whose run carries every label given
- `--cursor C`, the next_cursor of an earlier page
- `--json`, force the JSON envelope

### `promigence sandbox pause SID` 
park a sandbox: it holds no capacity and bills no seconds
- `--json`, force the JSON envelope

### `promigence sandbox resume SID` 
bring a paused sandbox back and restart its clock
- `--optimize-for start|compute`, default: as created
- `--json`, force the JSON envelope

### `promigence sandbox snapshot SID` 
snapshot it without stopping it
- `--json`, force the JSON envelope
- `--alias NAME`, name it
- `--move-alias`, take the alias from the snapshot that has it
- `--force`, take it even though the sandbox was given a secret; the snapshot, and what starts from it, can then contain that value

### `promigence secrets list` 
stored secret names (never a value)
- `--json`, force the JSON envelope

### `promigence secrets delete NAME` 
remove a stored secret
- `--json`, force the JSON envelope

### `promigence sandbox info SID` 
one sandbox: state, tier, time left, cost so far, and its execs
- `--json`, force the JSON envelope

### `promigence sandbox extend SID` 
give a live sandbox more time, within its run's quote and --cap (exit 5 past them)
- `--timeout DUR` **(required)**, the new total timeout
- `--json`, force the JSON envelope

### `promigence sandbox autopause SID` 
pause it once it has sat idle, or read the rule it is under
- `--after DUR`, idle this long and it pauses itself (2s or more)
- `--off`, never pause it on idle; only its timeout ends it
- `--mode MODE`, requests (default) | activity: also no CPU, no bytes, no open connection inside
- `--json`, force the JSON envelope

### `promigence sandbox probe SID` 
is this still the verified environment? (its recorded paths, or --path)
- `--path P`, check these paths instead; PATH=blake3:<hex> where the snapshot recorded none (base, --image)
- `--json`, force the JSON envelope

### `promigence files rm PATH` 
delete a path in a sandbox
- `--sandbox SID` **(required)**, the sandbox
- `--recursive`, a directory and everything under it
- `--json`, force the JSON envelope

## Ops

Accounts, keys, billing, organisations, connections and CI runners.

### `promigence bench burst` 
N sandboxes at once: hand-off percentiles + success rate
- `--snapshot H` **(required)**, snap_<id> | alias[@commit7] | ./env.promigence
- `--count N` **(required)**, number of sandboxes
- `--timeout D`, per-sandbox timeout (default 120s, the public burst harness's)
- `--cap USD`, spend cap for the burst (required unless PROMIGENCE_SPEND_CAP is set)
- `--keep`, leave the sandboxes running (default: killed once measured)
- `--json`, force the JSON envelope

### `promigence runners github` 
GitHub Actions jobs in sandboxes: `runs-on: promigence` (until Ctrl-C)
- `--repo OWNER/REPO`, take this repository's jobs
- `--org ORG`, or every repository's of an organization
- `--runner-group NAME`, with --org: the runner group (Default)
- `--token-env VAR`, variable holding a GitHub token (GH_TOKEN, then GITHUB_TOKEN)
- `--labels A,B`, the runs-on labels (promigence); promigence-small|medium|large pick a size
- `--tier small|medium|large`, size of a job that names none (small)
- `--warm N`, keep N runners waiting: instant pickup, billed while idle
- `--max M`, sandboxes at once (10)
- `--cap USD`, most one job may cost (default: its timeout at its size)
- `--timeout DUR`, longest job (default: your plan's longest sandbox)
- `--idle-timeout DUR`, stop an on-demand runner no job took (90s)
- `--kill-on-exit`, Ctrl-C cancels running jobs instead of waiting
- `--prepare`, build the --tier runner snapshot, then exit
- `--yes`, build a missing runner snapshot (the build price, per size) without asking
- `--github-api URL`, GitHub Enterprise Server's API URL
- `--json`, force the JSON envelope

### `promigence runners gitlab` 
GitLab CI jobs in sandboxes, as a runner with your tags (until Ctrl-C)
- `--url URL`, your GitLab (https://gitlab.com)
- `--token-env VAR`, variable holding the runner authentication token (GITLAB_RUNNER_TOKEN)
- `--executor docker|shell`, jobs in containers (docker) or in the sandbox
- `--default-image REF`, docker: image of a job with no image: (ubuntu:24.04)
- `--pool N`, runners kept up, billed while idle (1)
- `--api-token-env VAR`, read_api token: start runners only for pending jobs
- `--max M`, sandboxes at once (10)
- `--tier small|medium|large`, runner size (small)
- `--cap USD`, most one job may cost (default: its timeout at its size)
- `--timeout DUR`, longest job (default: your plan's longest sandbox)
- `--idle-timeout DUR`, with --api-token-env: a runner no job took exits (90s)
- `--kill-on-exit`, Ctrl-C cancels running jobs instead of waiting
- `--prepare`, build the --tier runner snapshot, then exit
- `--yes`, build a missing runner snapshot (the build price) without asking
- `--json`, force the JSON envelope

