Skip to main content

fcloud

Python SDK and CLI for the fcloud GPU compute platform: provision GPU or CPU hosts, run commands and scripts on them, keep a persistent workspace between runs, move files in and out, and drive long-running or batch jobs — from a terminal, from Python, or from an AI coding agent.

Requires Python 3.9+ (see Python versions).

Install

curl -fsSL https://fcloud-home.vercel.app/install.sh | sh

That installs the CLI from PyPI (via uv or pipx), signs you in through the browser, and installs the fcloud skill for coding agents on your machine. With your own Python:

pip install fcloud-sdk
fcloud login

fcloud is prepaid — fcloud credits buy 25 before your first run, and fcloud credits to see the balance.

Python versions

Every row runs the full test suite in CI on every push (the matrix in .github/workflows/unit-tests.yml is the source of truth; a CI check fails if pyproject.toml's classifiers drift from it).

Python Status
3.14 supported
3.13 supported
3.12 supported
3.11 supported
3.10 supported
3.9 supported (macOS command-line-tools Python, Debian 11)
3.8 and older not supported; the installer script bootstraps uv, which fetches a supported Python

The installer only uses your system Python (pipx/pip) when it is 3.9 or newer; otherwise it installs uv, which brings its own.

Setup

fcloud login opens https://fcloud-home.vercel.app to sign in (Google or email) and add a card, then saves a key minted for this machine. Running any fcloud command on a fresh install starts the same login.

fcloud login [--no-browser] [--agents auto|all|cursor|claude|codex|none]
fcloud set_token <key>  # already have a key (CI, agents, a second machine)
fcloud setup            # save a key you already have; install agent skills
fcloud health           # verify connectivity

fcloud login installs the fcloud skill file for the coding agents it finds (Cursor, Claude Code, Codex — --agents all for every one) so an agent can drive fcloud for you. fcloud setup --agents none skips that.

Quick start

# Run a one-off command on a GPU
fcloud exec --sku gpu_1x_l4 nvidia-smi -L

# Upload a script and run it
fcloud run train.py --sku gpu_1x_l4

# Upload a project directory, run one script in it, pass arguments through
fcloud run . --script train.py --sku gpu_1x_l4 -- --epochs 50

# See what hardware is available
fcloud skus

fcloud run <dir> uploads the whole directory. Keep secrets, virtualenvs and large data out of the tree you point it at.

How the pieces fit

  • session — a persistent /workspace filesystem, not a held GPU. It costs nothing 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>.
  • volume — a named folder you mount into a session with --volume; this is how data moves between sessions. Writes commit back as a new version when the session detaches or closes.
  • 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 durable outputs are its volumes and its logs.
  • sweepfcloud map fans one command out over many argument bindings as a durable batch you inspect with fcloud sweep.

CLI

fcloud help prints the full grouped list; fcloud help <command> prints details.

Find hardware
  fcloud skus                                          List SKUs and prices
  fcloud health                                        Check API connectivity

Run code
  fcloud exec [--sku SKU] [--on SID] <cmd...>          Run a command on a host
  fcloud run <file|dir> [--sku SKU] [--on SID]         Upload and run a script
  fcloud shell [--sku SKU] [--on SID] [--volume NAME]  Interactive shell
  fcloud ssh <SID>                                     SSH into a session
  fcloud tunnel <SID> [--port PORT]                    SSH ProxyCommand tunnel

Background processes (inside a session)
  fcloud spawn --on SID <cmd...>                       Start a background process
  fcloud wait <SID> <PID> [--timeout DUR]              Wait for it; exit with its code
  fcloud logs <SID> [PID] [--follow]                   Show process output
  fcloud kill <SID> <PID>                              Kill it

Sessions (the persistent filesystem)
  fcloud create [--sku SKU] [--min-disk-gb N]          Create a session ($0 until used)
  fcloud sessions [SID] [--all] [--limit N]            List sessions
  fcloud history <SID> [--limit N]                     Session event history
  fcloud stop <SID>                                    Stop now (files kept)

Files
  fcloud upload [--on SID] <local> [remote]            Upload files
  fcloud download [--on SID] <remote> [local]          Download a file
  fcloud ls <SID> [path]                               List a session's files
  fcloud mount <SID> <mountpoint>                      Mount session files read-only (needs rclone)

Volumes (data that outlives a session)
  fcloud volume <create|list|files|download|cat|import|delete> ...

Batch
  fcloud job <run|ls|logs|wait|kill> ...               Run-to-completion jobs
  fcloud map [--sku SKU] -- <cmd {}> ::: v1,v2...      Fan a command out over bindings
  fcloud sweeps / fcloud sweep <status|logs|retry|cancel|wait> <name>

Setup
  fcloud login [--no-browser] [--agents auto|all|cursor|claude|codex|none]
  fcloud setup [--token KEY] [--agents all|cursor|claude|codex|none]
  fcloud set_token <api-key>
  fcloud --version

All commands accept --json for machine-readable output.

fcloud exec returns bounded stdout by default. If --json reports stdout_truncated: true, fetch the full log instead of rerunning:

fcloud logs <session-id> <process-id> --output all
fcloud logs <session-id> <process-id> --stream stderr --output all

Python SDK

import fcloud

client = fcloud.Client()

image = fcloud.Image.debian_slim().pip_install(["torch", "numpy"])
project = client.project("my-run", image=image)

with project.session(sku="gpu_1x_l4") as s:
    s.upload("./data", "data/")
    result = s.run(["python3", "/workspace/data/train.py"])
    print(result.stdout)
    if result.stdout_truncated:
        print(s.logs(result.process_id, output_range="all").output)
    weights = s.download("model.pt")

Errors raise fcloud.FcloudError (or a subclass such as PaymentOverdueError).

Porting from Modal

fcloud exposes a Modal-compatible surface, so most Modal scripts port with an import rename:

import fcloud as modal  # was: import modal

app = modal.App("demo")
image = modal.Image.debian_slim().pip_install("torch", "numpy")

@app.function(image=image, gpu="H100", timeout=600)
def train(steps: int) -> float:
    ...

@app.cls(gpu="L4", volumes={"/data": modal.Volume.from_name("weights", create_if_missing=True)})
class Model:
    @modal.enter()
    def load(self): ...
    @modal.method()
    def predict(self, x): ...

@app.local_entrypoint()
def main(steps: int = 100):
    print(train.remote(steps))
    print(Model().predict.remote(1))

Run it with fcloud run demo.py [--steps 500] (the Modal-style demo.py::name picks an entrypoint or function). Each (gpu, image, volumes) combination gets one warm session; .remote() pickles the args, runs the function on the host and returns the pickled result, streaming stdout back live.

Supported: App, @app.function / @app.cls / @app.local_entrypoint, .remote() / .spawn() / .map(), Image.* (varargs or list), Volume.from_name, Secret.from_dict / from_dotenv / from_local_environ, gpu="H100", "A100-80GB:8", etc. cpu=, memory=, retries= and similar options are accepted and ignored with a warning.

Not supported: web endpoints, Dict / Queue, schedules, sandboxes, Secret.from_name (no hosted secret store), modal deploy. .map() runs inputs sequentially on one session; use fcloud map for real fan-out.

Configuration

API key, in order of precedence:

  1. api_key= passed to Client()
  2. FCLOUD_API_KEY exported in the shell
  3. Saved token in ~/.fcloud/token (from fcloud setup / fcloud set_token)
  4. FCLOUD_API_KEY in the nearest .env file (searched upward from the cwd)

API URL, in order of precedence:

  1. url= passed to Client()
  2. FCLOUD_URL exported in the shell
  3. Saved URL in ~/.fcloud/url
  4. FCLOUD_URL in the nearest .env — only honoured when that same .env is also supplying the API key, so a checked-out repo can't redirect a saved token elsewhere
  5. https://fcloud-dispatcher.fly.dev

Other environment switches:

Variable Effect
FCLOUD_QUIET=1 Suppress "still waiting" progress lines while a host is provisioned
FCLOUD_QUEUE_TIMEOUT=<seconds> How long to wait for capacity before giving up (default 1200)
FCLOUD_MIGRATE_RESTART=never Don't automatically re-run a command after a host rebuild (default auto)
FCLOUD_CHECKPOINT=off Default checkpoint/restore policy for new sessions. off: a preempted session rebuilds cold on any available host (/workspace kept, processes lost) instead of restoring pinned to its checkpoint's region. Per-session: --checkpoint/--no-checkpoint; per-user: fcloud config set checkpoint off; per-project: fcloud.json "checkpoint": false
FCLOUD_INSECURE_HTTP=1 Allow a plaintext http:// API URL to a non-loopback host (refused by default — the API key would travel unencrypted). Loopback URLs never need this
FCLOUD_TELEMETRY=0 Disable all client telemetry. When enabled (the default), the client reports failures the backend cannot otherwise see — an uncaught CLI error, a queue-wait timeout, exhausted connect retries — as a fixed-allowlist payload (session id, event type, error class, truncated message, SKU/timing fields); never file contents, paths from OS errors, or credentials

A fcloud.json at the project root can set defaults (image build steps, default volumes, checkpoint policy); fcloud config stores per-user defaults in ~/.fcloud/config.json. Note that fcloud will run the build steps it finds there, so treat a cloned repo's fcloud.json the way you would its Dockerfile.

Agent skill

fcloud setup installs SKILL.md by default (--agents none to skip) for supported coding agents. It is the long-form, agent-oriented guide: workflow patterns, monitoring loops, and anti-patterns.

Development

pip install -e ".[dev]"
pytest
ruff check src tests

License

Apache License 2.0 — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fcloud_sdk-0.3.0.tar.gz (421.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fcloud_sdk-0.3.0-py3-none-any.whl (303.7 kB view details)

Uploaded Python 3

File details

Details for the file fcloud_sdk-0.3.0.tar.gz.

File metadata

  • Download URL: fcloud_sdk-0.3.0.tar.gz
  • Upload date:
  • Size: 421.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for fcloud_sdk-0.3.0.tar.gz
Algorithm Hash digest
SHA256 48bd07fd7f994065133b4dced4d144d786c058fcc4084e210be345f1e11f4f83
MD5 602d5e8edea44c98f183d1c7b7ba9039
BLAKE2b-256 1aba0222c512c2a89fdba37b600e8f0427decc4327e0af6ab0422213f40c6c9d

See more details on using hashes here.

File details

Details for the file fcloud_sdk-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: fcloud_sdk-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 303.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for fcloud_sdk-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 218fa257ced15e5bacfc7bf536b1853f34be40c358e49259603988d88c4fefd6
MD5 f4238909d91a5188e9d6a92584acf77e
BLAKE2b-256 fa5719cd032a9cd82ea8b14f5446aa4428280689f31775800fb1baed8c715760

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 files

0.2.1

2 files

0.2.0

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page