CLI Reference
Every fcloud command, grouped by task.
Installation & authentication
curl -fsSL https://fcloud-home.vercel.app/install.sh | sh # install + sign in + agent skillsOr, with your own Python:
pip install fcloud-sdk
fcloud login # sign in via the browser; saves a key + installs agent skills
fcloud set_token <key> # already have a key (CI, agents)
fcloud setup # re-run the skill install / save a key you already have
fcloud health # verify connectivityHow the pieces fit
| Concept | What it is |
|---|---|
| session | A persistent /workspace filesystem, not a held GPU. Cold and $0 until used; exec/run/shell/upload bring it online with its files intact, and fcloud stop halts spend but keeps the files. Address an existing one with --on <SID> (or a bare s-... argument). |
| volume | A named folder you mount into a session with --volume — how data moves between sessions. Writes commit back as a new volume version when the session detaches or closes. See Volumes. |
| process | Work running inside a session. exec/run wait in the foreground; spawn returns a process id you then wait/logs/kill. |
| job | A run-to-completion session with no saved filesystem. Its only durable outputs are its volumes and its logs. See Batch. |
| sweep | fcloud map fans one command out over many argument bindings as a durable batch you inspect with fcloud sweep. See Batch. |
Global flags
| Flag | Description |
|---|---|
--json | Machine-readable JSON output on any command. Status messages go to stderr. |
Place --json before your remote command: flags after the command — or
after a -- — belong to your program. So fcloud exec --json -- python app.py
selects fcloud's JSON output, while fcloud exec -- python app.py --json passes
--json to app.py. Unknown flags are rejected (a typo'd --limitt is an
error, never silently ignored).
Find hardware
fcloud skus # list available GPU/CPU SKUs
fcloud health # check dispatcher connectivitySKUs follow the pattern gpu_<count>x_<model> (e.g. gpu_1x_l4,
gpu_8x_h100) or cpu_<...>. If a SKU has no free capacity, the session
queues until a host is provisioned. Browse the catalog.
Run code
| Command | Description |
|---|---|
fcloud exec [--sku SKU] [--on SID|SID] [--volume NAME[:MOUNT]] [--wait 30s] <cmd...> | Run a command on a GPU host |
fcloud run <file|dir> [--sku SKU] [--on SID|SID] [--script NAME] [-- args...] | Upload and run a script |
fcloud shell [--sku SKU] [--on SID|SID] [--volume NAME[:MOUNT]] | Interactive shell (fcloud-native PTY) |
fcloud ssh <SID> | SSH into a session (local OpenSSH client) |
fcloud tunnel <SID> [--port PORT] | SSH ProxyCommand / port tunnel |
Without --on, exec and run create a throwaway session, do the work, and
release it automatically — its filesystem is still saved and downloadable
afterwards. With --on <session-id> (or a positional s-... argument) they
attach to an existing session, run, and detach, leaving the session alive.
fcloud exec --sku gpu_1x_l4 nvidia-smi -L # one-off command
fcloud run train.py --sku gpu_1x_l4 # upload + run one file
fcloud run . --script train.py -- --epochs 50 # upload a dir, pass args
fcloud exec --on s-abc123 python train.py # attach to a session
fcloud exec s-abc123 -- python train.py # positional alias for --onWorking directory
Commands run from /workspace by default — the same place fcloud upload puts
your files. An uploaded train.py runs as python train.py; relative writes
land in /workspace and persist. To run elsewhere for one command, cd inside
it: sh -c 'cd /some/dir && ...'. This applies uniformly to exec, run,
spawn, and shell.
Waiting, detaching, and long commands
exec waits in the foreground for a budget (default 30s; set with --wait 10m
or the alias --timeout). If the command finishes in time, stdout/stderr are
printed and the CLI exits with the remote return code. If not, exec does
not kill it — it detaches and prints a process id:
Command is still running; use fcloud logs s-abc123 proc-456 --followIn --json mode a detached command returns status: "running" and
returncode: null plus session_id and process_id — treat that as
success-with-handle, then fcloud wait <sid> <pid> or
fcloud logs <sid> <pid> --follow. For jobs you expect to run long, prefer
spawn + wait from the start (see below).
Output is bounded by default so a noisy command can't flood the caller. If the
JSON response has stdout_truncated: true, don't rerun the command — fetch the
durable log instead: fcloud logs <sid> <pid> --output all.
Shell parsing
Pass commands as normal argv when you can. A single quoted string runs as shell
text (via bash -lc), and sh -c works for explicit shell syntax:
fcloud exec --on s-abc123 python train.py --epochs 10
fcloud exec --on s-abc123 'cd /workspace; ls'
fcloud exec --on s-abc123 -- sh -c 'sleep 45; echo done'Unquoted metacharacters are handled by your local shell first:
fcloud exec --on s-abc123 sleep 45; echo done runs sleep 45 remotely, then
echo done locally.
Background processes
| Command | Description |
|---|---|
fcloud spawn [--on SID|SID] [--volume NAME[:MOUNT]] [--emit-pid FILE] <cmd...> | Start a background process; prints a process id |
fcloud wait <SID> <PID> [--timeout DUR] | Block until the process exits; exits with its exit code |
fcloud logs <SID> [PID] [--follow] [--output MODE] [--stream stdout|stderr|combined] | Durable logs for a session or process |
fcloud kill <SID> <PID> | Kill a background process |
The reliable pattern for long jobs:
fcloud spawn --on s-abc123 python train.py # prints proc-456 immediately
fcloud logs s-abc123 proc-456 --follow # watch it live
fcloud wait s-abc123 proc-456 --timeout 0 # block; exits with its exit codewait reads durable logs, so it works after the host is gone, survives
checkpoint/migration, and exits 75 if a positive --timeout elapses while
the process is still running. Prefer it over hand-rolled logs | grep loops —
it distinguishes "still starting" from "already died".
The default log stream is combined (stdout + stderr) — prefer it. Most ML
tooling (tqdm, HuggingFace/TRL) writes progress to stderr, so --stream stdout
on a training job often looks empty even though it's producing output.
--emit-pid FILE (on spawn, exec, and run) writes
{"session_id": ..., "process_id": ...} JSON to a file the instant the process
starts — capture the handle even when stdout is piped or backgrounded. Never
pipe a live exec through | tail: it buffers everything until EOF and
swallows the detach line carrying the process id.
Sessions
| Command | Description |
|---|---|
fcloud create [--sku SKU] [--min-disk-gb N] [--keep-warm SECONDS] [--no-checkpoint] | Create a session (cold — $0 until used) |
fcloud config <show|get|set|unset> [KEY] [VALUE] | Per-user defaults, e.g. fcloud config set checkpoint off |
fcloud sessions [SID] [--all] [--limit N] | List sessions (--all includes cold/closed) |
fcloud history <SID> [--limit N] | Show a session's lifecycle timeline |
fcloud stop <SID> [--wait] [--timeout SECONDS] | Stop now: halt GPU spend, keep the files |
Session lifecycle
A session's state is reported by fcloud sessions:
| State | Meaning |
|---|---|
hot | Running on a host and spending. |
warm | Idle but holding its host, still spending. |
stopping | Finishing teardown. |
cold | Stopped — $0, no host. Comes back online automatically the next time you target it. |
preparing | Coming online (allocating a host / restoring state). |
A freshly created session is cold and costs nothing until its first
exec/run/upload. There is no resume command — targeting a cold
session brings it back transparently, on a fresh host with its /workspace
restored from cloud storage. fcloud stop exists only to halt spend
immediately; files are preserved either way.
stop --wait blocks until the workspace manifest is durable — use it before
anything that reads the manifest (fcloud ls, fcloud mount,
fcloud map --from <sid>) rather than polling fcloud sessions yourself.
Preemption: checkpoint/restore, or rebuild anywhere
Sessions run on spot capacity. When a host is reclaimed, fcloud by default
checkpoints the live sandbox (GPU state included) and restores it on a
fresh host, so running processes continue. The restore is pinned to the region
the checkpoint lives in, so it can wait for spot capacity there
(awaiting_restore_capacity).
Pass --no-checkpoint to create, exec, run or shell to turn that off
for a session: a preempted host then rebuilds it cold on any available host
in any region — /workspace is kept, running processes are lost, and
fcloud run/exec re-run your command (FCLOUD_MIGRATE_RESTART). Choose it
when capacity matters more than in-flight state, ideally with a script that
reloads its own checkpoints from /workspace or a volume.
fcloud run train.py --sku gpu_1x_h100 --no-checkpoint # this session
fcloud config set checkpoint off # my default
fcloud config unset checkpoint # back to onPrecedence: --checkpoint/--no-checkpoint → FCLOUD_CHECKPOINT=on|off →
fcloud.json "checkpoint": false → fcloud config set checkpoint → on. The
policy is fixed at create; --on <sid> keeps the session's own. Jobs never
checkpoint. fcloud sessions marks opted-out sessions [no-checkpoint].
Credits
fcloud is prepaid: you buy credit, and sessions draw it down as they run. At $0 new work is refused, running sessions are closed and queued jobs are canceled — so the balance is worth knowing before a long run.
| Command | Description |
|---|---|
fcloud credits | Balance, available, auto-refill and card |
fcloud credits buy <usd> [--yes] [--no-autorefill] | Buy credit through hosted checkout |
fcloud credits autorefill on|off|set [--threshold USD] [--amount USD] [--daily-cap USD] | Change the top-up rule |
fcloud credits statement [--limit N] | Recent ledger rows with a running balance |
Balance vs available. balance is what has posted to your ledger;
available subtracts usage that has been metered but not yet billed. Spend
decisions use available.
Auto-refill charges a saved card when the balance falls below your
threshold. It only fires when it is armed — enabled, consented to (which
happens on your first purchase) and backed by a saved card — so
fcloud credits reports armed rather than just on/off, and says which of
those is missing. Turning it off warns that work stops at $0 and needs a
confirmation.
fcloud credits buy opens a Stripe checkout page in your browser and waits
for the payment to post; the card never passes through the CLI. On a machine
with no browser the URL is printed to paste elsewhere.
Running out
A command refused for want of credit exits 4 and names the fix. It is not
retryable — the same refusal repeats until credit lands (about a minute after
it posts). Do not confuse it with exit 3 (a failed payment suspending the
account) or exit 75 (a transient blip, which is worth retrying).
fcloud exec --sku gpu_1x_l4 python3 train.py
# Out of credits: insufficient credit: your prepaid credit is exhausted...
# Add credit with `fcloud credits buy 25`, or let a saved card top you up
# with `fcloud credits autorefill on`.
echo $? # 4Before provisioning, the CLI warns once when the balance is low and nothing will top it up. The warning goes to stderr and never blocks the run.
Files
| Command | Description | Needs active session? |
|---|---|---|
fcloud upload [--on SID|SID] <local> [remote] | Upload files into /workspace/ | Yes |
fcloud download [--on SID|SID] <remote> [local] | Download a file | No — active or stopped |
fcloud ls <SID> [path] | List a stopped session's workspace manifest | No |
fcloud mount <SID> <mountpoint> | Mount a stopped session's files locally (read-only, via rclone) | No |
download uses the live host when the session is active (freshest bytes) and
falls back to the saved manifest otherwise. ls and mount read the manifest
the host writes when the session stops — use them after fcloud stop, the
common "grab my outputs later" case.
A stopped session's durable logs appear under a virtual _logs/ directory:
fcloud ls s-abc123 _logs # build.log, session.log, exec-<pid>.log, ...
fcloud download s-abc123 _logs/build.log # readable long after the session is gonemount uses rclone's NFS mount (brew install rclone) — no macFUSE or kernel
extension — and streams bytes directly from cloud storage. The mountpoint must
not exist yet; Ctrl-C unmounts.
Volumes
Named, manifest-backed folders that move data between sessions — mount with
--volume NAME[:MOUNT] on exec, run, shell, spawn, job run, and
map. Full guide: Volumes.
fcloud volume create checkpoints
fcloud exec --sku gpu_1x_l4 --volume checkpoints:/workspace/ckpt python train.py
fcloud volume files checkpoints # committed when the session detached
fcloud volume download checkpoints model.ptSubcommands: create · list · files · download [-r] · cat · delete ·
import.
Batch
Run-to-completion jobs and durable fan-outs. Full guide: Batch: jobs & sweeps.
fcloud job run --sku gpu_1x_l4 --volume results -- python train.py
fcloud map --sku gpu_1x_l4 -- python train.py --lr {lr} ::: lr=1e-4,3e-4
fcloud sweeps # list sweeps
fcloud sweep status <name> # counts + failures clustered by errorSSH & tunnels
fcloud shell is the fcloud-native PTY path — no SSH server required.
fcloud ssh <sid> uses your local OpenSSH client over fcloud tunnel; if the
image lacks sshd, the CLI bootstraps it on first connect (tens of seconds —
bake openssh-server into the image to skip that). fcloud tunnel <sid>
defaults to the session SSH port (2222) for use as a ProxyCommand; pass
--port to tunnel any other TCP service inside the session:
ssh -o ProxyCommand="fcloud tunnel %h" root@s-abc123
fcloud tunnel s-abc123 --port 8000 # e.g. reach a vLLM serverProject config (fcloud.json)
Drop an fcloud.json in your project root (auto-discovered by walking up from
cwd) to set defaults so you can skip the flags:
{
"sku": "gpu_1x_l4",
"volumes": [{ "name": "checkpoints", "mount": "/workspace/checkpoints" }],
"image": {
"base": "nvidia/cuda:12.8.1-devel-ubuntu24.04",
"apt": ["git", "build-essential"],
"pip": ["torch", "transformers"],
"env": { "PYTHONUNBUFFERED": "1" }
}
}Explicit --sku overrides the file; --volume flags merge with (and re-map by
name) the volumes defaults. Images are content-addressed — same config, same
cache, instant startup.
Help
fcloud help # grouped command list, concepts, recipes
fcloud help <command> # full flags and semantics for one command