fcloud
Guides

Python SDK

Complete guide to the fcloud Python SDK.

Everything the CLI does is available programmatically. The SDK is the right tool when GPU work is embedded in a larger program — a training harness, an agent loop, a pipeline.

Installation

pip install fcloud-sdk

Authentication

Authenticate once via the CLI (fcloud setup or fcloud set_token), or pass a token explicitly:

import fcloud

client = fcloud.Client()                      # uses the saved token / env var
client = fcloud.Client(token="fcloud_sk_...") # explicit

Token resolution order: Client(token=...)FCLOUD_API_KEY env var → saved token in ~/.fcloud/tokenFCLOUD_API_KEY from the nearest .env.

Session-based workflow

Sessions persist state across commands. Use the context manager so the session closes (and stops spending) even on exceptions:

import fcloud

client = fcloud.Client()
project = client.project("my-experiment")

with project.session(sku="gpu_1x_a10g") as s:
    s.run(["pip", "install", "transformers"])
    s.upload("./data", "data/")
    result = s.run(["python", "train.py"])
    print(result.stdout)

    weights = s.download("model.pt")     # bytes
    open("model.pt", "wb").write(weights)

Commands run from /workspace — the same place upload puts files — so uploaded scripts run by relative path.

Custom images

Declare the environment once; layers are content-addressed, so the same spec is a cache hit and starts instantly:

from fcloud import Image

image = (
    Image.from_registry("nvidia/cuda:12.8.1-devel-ubuntu24.04")
    .apt_install(["git", "build-essential"])
    .pip_install(["torch", "transformers"])
    .env({"PYTHONUNBUFFERED": "1"})
)
project = client.project("my-experiment", image=image)

Image.debian_slim() is the lightweight default; named images like Image.from_name("agent-gpu") ship a pinned GPU training stack (torch, transformers, flash-attn, vLLM).

Background processes

Start long-running work without blocking:

with project.session(sku="gpu_1x_a10g") as s:
    proc = s.spawn(["python", "train.py", "--epochs=100"])
    proc.poll()        # refresh status
    print(proc.output) # read output so far
    proc.wait()        # block until done
    print(proc.exit_code)

Stream output live with s.watch(proc) — see Logs & streaming.

Session lifecycle

Sessions are cold ($0, no host) until first used, then hot while running. A cold session comes back online automatically the next time you target it — there is no explicit resume step. s.close() (or fcloud stop from the CLI) returns it to cold and halts spend; /workspace is preserved either way.

with project.session(sku="gpu_1x_l4") as s:
    s.run(["python", "train.py"])
    sid = s.session_id

# Later — even days later, on a fresh host, files restored:
s2 = client.attach_session(sid)
s2.run(["ls", "/workspace/"])        # original files are here
s2.close()

When a spot host is reclaimed, a session is by default checkpointed and restored on a fresh host in the same region. Pass checkpoint=False to project.session(...) / project.cold_session(...) to opt out: the session is instead rebuilt cold on any available host (/workspace kept, processes lost, SessionInfo.checkpoint == False). None (the default) defers to FCLOUD_CHECKPOINT, fcloud.json "checkpoint", then fcloud config set checkpoint.

with project.session(sku="gpu_1x_h100", checkpoint=False) as s:
    s.run(["python", "train.py", "--resume-from", "/workspace/ckpt"])

Jobs and sweeps

For run-to-completion batch work, project.job(...) runs a command on an ephemeral session (no saved filesystem; outputs go to volumes), and client.map(...) fans a command out over argument bindings as a durable sweep. See Batch: jobs & sweeps for both.

Volumes

client.list_volume_files("results")                       # [{path, size, ...}]
data = client.read_volume_file("results", "model.pt")     # bytes, no session
client.download_volume_file("results", "model.pt", "./model.pt")
client.delete_volume("results")

Mount into a session at creation with volume_mounts=[{"name": ..., "mount_path": ...}] — semantics match the CLI's --volume (Volumes).

Mixing CLI and SDK

Both talk to the same sessions. A common pattern: provision and iterate from the CLI, then follow the work programmatically (or vice versa) — any session id printed by fcloud create works with client.attach_session(sid), and any SDK session shows up in fcloud sessions.

On this page