Skip to main content

extro-sim — Python client

Install

pip install extro-sim
# or from a checkout of the repo
pip install ./clients/python

Not on PyPI yet — the hosted zip is the install path until pip install extro-sim lands there (the distribution name; it imports as extro_sim).

Do NOT pip install extropic — the PyPI package by that name is an unrelated squatted package (no client API, no console script). Always install from the repo as above. Post-install smoke check: python -c "import extro_sim; print(extro_sim.DEFAULT_API_URL)"

Defaults are baked for the production deployment (api.extropic.dev); no configuration needed. Auth is extro-sim auth (browser login, stored session) — and a job submitted from an interactive terminal without a session triggers the same flow automatically. Set STAGING=1 to target the staging deployment (api.staging.extropic.dev) instead.

A first-class Python interface to the Extropic thermodynamic compute cloud. Decorate a function, then run it on the cloud with .remote() / .submit().

import extro_sim as xtr

xtr.configure(api_url="https://api.extropic.dev", token="<supabase-jwt>")

@xtr.job(tier="cpu", timeout_s=120)
def add(a, b):
    return {"sum": a + b}

add(2, 3)            # {"sum": 5}  — runs locally, like any function
add.local(2, 3)      # {"sum": 5}  — explicit local run
add.remote(2, 3)     # {"sum": 5}  — runs on Extropic, blocks for the result

job = add.submit(2, 3)   # fire-and-forget, returns a handle
job.state                # "running" | "succeeded" | ...
job.result()             # blocks, returns {"sum": 5}
job.cancel()

Configuration

xtr.configure(...) or environment variables:

env notes
api_url EXTROPIC_API_URL default https://api.extropic.dev
— STAGING STAGING=1 targets staging (api.staging.extropic.dev) as a set
token EXTROPIC_TOKEN Supabase JWT — overrides the extro-sim auth session (CI/staging)
user_id EXTROPIC_USER_ID dev identity (local, X-User-Id)

Hardware

Pass tier= to @xtr.job — labels state the hardware explicitly:

cpu (1 vCPU · 4 GB) · l4 (4 vCPU · 16 GB · 1×L4) · a100 (8 vCPU · 64 GB · 1×A100 80GB) · h100 (8 vCPU · 64 GB · 1×H100)

GPU tiers: JAX must be the CUDA build

A plain pip install thrml (or jax) pulls CPU-only jaxlib — on the GPU tiers the GPU sits idle and JAX silently runs on cpu:0. Install the CUDA 13 extra explicitly:

pip install "jax[cuda13]" thrml

Avoid jax[cuda12]: on newer GPUs it runs, but cuBLAS < 13.2 has a known concurrent-kernel TMEM bug (silent data corruption warning at import). Sanity check inside the job before doing real work:

import jax
assert jax.default_backend() == "gpu", jax.devices()

API contract notes

  • Rate limits: submit bursts can 429 — raised as typed RateLimited with .retry_after (seconds). Submits are never retried automatically (a blind retry could double-submit); honor retry_after when fanning out.
  • Auth expiry: if the stored session can't be refreshed the client raises extro_sim.auth.AuthExpired before any request — run extro-sim auth login.
  • GET /jobs/{id}/result currently returns the full job record (not a narrow result view); Job.result() handles either shape.
  • DELETE /jobs/{id} means cancellation requested — the response may still show pending/running; poll until terminal (cancelled).
  • /healthz requires auth by design; there is no anonymous health probe.
  • output & tracebacks: stdout, stderr and result are artifacts — durable objects in the store, synced while the job runs and always flushed before the runner exits (a failed flush errors the job rather than losing bytes). Job.follow() subscribes to all three from the store (chunks a few seconds behind live; ends with the result / raises the terminal error); Job.stream_logs(stream=...) follows one stream and uses the live per-job tunnel (runner_url on the view) when present for lower latency, artifact polling otherwise. On failure the full Python traceback is an artifact and rides in the JobFailed message (e.traceback).
  • status polling never false-fails: Job.result()/.wait() treat a 429 during polling as retry-after-and-continue, never as a job failure — a rate-limited poll of a healthy running job must not report it dead.
  • You are never billed before compute starts: a job stays pending (unbilled, hold only) until its sandbox is actually allocated. If the backend can't provide capacity within the start deadline the job ends at_capacity — retryable, $0 charged. timeout_s counts from when your code's sandbox exists, not from submit.

Errors

.result() raises a typed error for non-success states: JobFailed, OutOfCredits, AtCapacity (retry later), JobCancelled — all subclasses of ExtropicError. A 503 on submit also raises AtCapacity.

CLI

Installing the client (from the repo — see Install above) also installs the extro-sim command — submit · supervise · collect:

submit/run ship the file's source into the sandbox — keep the file plain (no top-level import extro_sim, no decorator; the base image doesn't have the package). The decorated @xtr.job + .remote() form is the SDK path and never goes through extro-sim run.

extro-sim auth                            # log in via the browser (reuses your console session)
extro-sim submit job.py --entrypoint main --tier cpu --arg 2 --arg 3 --wait
extro-sim run job.py --arg 2 --arg 3     # submit + supervise + collect in one shot
extro-sim jobs                            # list your jobs
extro-sim supervise <id>                  # stream state/progress until it finishes
extro-sim collect <id>                    # wait for + print the result
extro-sim logs <id> -f                    # follow a job's stdout live
extro-sim cancel <id>
extro-sim balance                         # credit balance + holds
extro-sim recharge 25                     # start a top-up (finish the card in the web console)

extro-sim auth opens the web console, which signs you in with Supabase (instantly if you're already logged in there) and hands the session back to the CLI; it's stored under ~/.config/extropic/credentials.json and auto-refreshed. auth status / auth logout manage it. Point the CLI at your console + API with EXTROPIC_FRONTEND_URL and EXTROPIC_API_URL (or --api-url); the edge/WAF secret must be supplied at runtime as EXTROPIC_EDGE_SECRET and is never baked into the package. --arg/--kwarg values parse as JSON when possible, else as strings.

Constraints (v1)

Functions ship via cloudpickle: closures, objects, and non-JSON args/results all work. The pickle carries interpreter bytecode, so the sandbox runs a matching Python/cloudpickle (the SDK ships both versions in the job envelope); the function's imports must exist in the sandbox image for its tier.

Metadata

Release files for extro-sim 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for extro-sim 0.5.0
File Size Uploaded
extro_sim-0.5.0.tar.gz 58.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for extro-sim 0.5.0
File Interpreter ABI Platform
extro_sim-0.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 117.7 kB

Release files / extro_sim-0.5.0.tar.gz

Download URL extro_sim-0.5.0.tar.gz
Size 58.4 kB
Tags Source
SHA-256 checksum
How to use checksums
9ffd89a643d5eb144df004d385ea3f3a50e96d52619477ac3d7db75c4c4fd1bc
BLAKE2b-256 checksum
How to use checksums
46483c9ec636de92049837fd9044629d051dc938d2bbdee8d252c2e5a5e3c134
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 4, 2026.

Transparency log

Release files / extro_sim-0.5.0-py3-none-any.whl

Download URL extro_sim-0.5.0-py3-none-any.whl
Size 59.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
58501690d60dbabf58abab77e913c409162da58e53bc93b481f16a5098d7a0e5
BLAKE2b-256 checksum
How to use checksums
8d827c6555d3ebaffcd2b6a825fefc48b57973bfd5fcc91d1bd11796ac617a33
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 4, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.5.0 This release

2 release files

0.4.0

2 release 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