Official Python SDK for Common Compute — the batch AI bill you shouldn't be paying.
Project description
Common Compute — Python SDK
The official Python SDK + CLI for Common Compute — batch AI compute without the AWS tax, on Apple Silicon hardware AWS can't offer.
One SDK call replaces the IAM roles, compute environments, and job definitions. Every job returns its price and ETA before it runs, and you're only billed for successful jobs — each with a verifiable receipt.
pip install commoncompute # core: httpx + pydantic only
pip install "commoncompute[cli]" # + the `commoncompute` command line
commoncompute login # opens the browser — no key to copy-paste
The command is commoncompute. A short cc is not installed — that name
belongs to the system C compiler. Want the shorthand? alias cc="commoncompute".
commoncompute login (or commoncompute.connect() from a script or notebook) opens an
approval page in your browser; click Approve and a fresh API key is saved
to ~/.config/commoncompute/credentials, where the SDK finds it automatically.
Prefer explicit config? export CC_API_KEY=cc_live_... works everywhere and
takes precedence.
The 10-minute path
import commoncompute as cc
client = cc.Client() # reads CC_API_KEY, or the saved credentials file
job = client.submit("coreml_embed", {"input": ["what is the neural engine?"]},
model_id="bge-base")
print(job.job_id, job.locked_price_usd, job.eta_seconds) # price known BEFORE it runs
result = client.result(job) # waits, downloads, attaches the receipt
print(result.output)
print(result.receipt) # signed proof of what ran, where, for how much
Prefer the OpenAI-style surface? client.embeddings.create(input=[...], model="bge-base") returns vectors synchronously.
Examples — live today
1. OCR / document extraction — vs AWS Textract
job = client.ocr.extract("https://example.com/contracts.pdf", structured=True)
result = client.result(job) # blocks + bounding boxes as JSON
2. Embeddings in bulk
for result in client.submit_many(
"coreml_embed",
[{"input": chunked(doc)} for doc in corpus],
max_concurrent=16,
):
save(result.output) # results stream as they complete
3. Background removal
job = client.images.remove_background("product-shot.png")
Also live: speech synthesis, image classification/detection/pose, barcode
reading, HEIC conversion — plus the generic client.submit(workload_id, payload) for anything marked live in
the catalog.
In preview
client.translate(...) and client.video.transcode(...) run on preview
capacity — functional, not yet GA.
Not live yet
client.transcription.*, client.rerank(...), client.images.generate(...),
client.chat.*, and client.build.ios_test(...) target workloads still
marked coming soon: the API refuses them with a clear
workload_not_available error (HTTP 409) rather than queueing a job that
won't run. They activate automatically as those lanes go live — watch
the catalog.
Price before execution, hard caps, dry runs
quote = client.ocr.extract("scan.pdf", dry_run=True) # price + ETA, no job
job = client.ocr.extract("scan.pdf", max_spend_usd=1.0) # refused if it would exceed
Batches that stream back
for result in client.submit_many("vision_bgremove", images, max_concurrent=8):
save(result.output) # results stream as they complete
Receipts
Every successful job carries a receipt (job_id, cost, provider id,
timestamps, input/output hashes, signature):
client.receipts.list()
csv_blob = client.receipts.export(format="csv")
Account
client.account.balance() # card-on-file billing state (cash only)
client.account.spend(days=30) # spend summary by workload
client.account.tier() # your volume tier + the next threshold
Per-task prices step down automatically as your monthly usage grows — your current rate is always the one a quote returns.
Async
AsyncClient mirrors Client method-for-method — submit, wait, result,
and submit_many all have await-able twins. Use it as an async context
manager so the underlying HTTP pool is closed for you:
import asyncio
import commoncompute as cc
async def main():
async with cc.AsyncClient() as client: # closes the pool on exit
job = await client.submit("coreml_embed", {"input": ["hello world"]})
print(job.job_id, job.locked_price_usd, job.eta_seconds) # price BEFORE it runs
await client.wait(job) # poll until terminal
result = await client.result(job) # + download output & receipt
print(result.output)
asyncio.run(main())
Batches stream back the same way — submit_many is an async generator:
async with cc.AsyncClient() as client:
async for r in client.submit_many("coreml_embed", batches, max_concurrent=8):
save(r.output) # each result as it completes
The lower-level client.jobs.* namespace (jobs.submit, jobs.wait,
jobs.get, jobs.events, jobs.download) is async here too when you want the
raw request/response dicts instead of typed Job/TaskResult objects.
CLI
pip install "commoncompute[cli]" installs the commoncompute command.
Why not a short
cc? Becauseccis the Unix C compiler (/usr/bin/cc). Shipping a binary by that name puts it ahead of the real compiler onPATHfor anyone whose Python bin directory sorts first, and every build that shells out toccthen fails with a CLI usage error instead of compiling. Socommoncomputeis the only command installed. If you want the shorthand, opt in yourself:alias cc="commoncompute" # add to ~/.zshrc or ~/.bashrc
commoncompute login # stores the key locally
commoncompute quote vision_ocr --units 5 # price + ETA, no execution
commoncompute submit coreml_embed --payload '{"input":["hi"]}' --wait
commoncompute jobs list
commoncompute jobs get <id>
commoncompute balance
commoncompute receipts export --format csv --out receipts.csv
Commands
| Command | What it does |
|---|---|
commoncompute login / commoncompute logout |
Store / remove the API key (browser approval, or --api-key) |
commoncompute whoami |
Show the account behind the current key |
commoncompute balance |
Current workspace balance |
commoncompute usage |
Spend + call-count rollups over a date range (--start, --end, --group-by) |
commoncompute spend |
Total spend over the last --days N, grouped by workload |
commoncompute tier |
Current volume tier and the next threshold |
commoncompute workloads |
List available workloads |
commoncompute models |
List models (--workload to filter) |
commoncompute quote |
Price + ETA for a workload without submitting (--units, --priority, --model) |
commoncompute submit |
Submit one job (--payload/-f, --model, --priority, --wait, --timeout) |
commoncompute submit-many |
Submit a JSONL file of payloads; stream one result per line as NDJSON (--input/-i, --max-concurrent, --no-wait) |
commoncompute chat |
One-shot chat message to a model (--model, --stream/--no-stream) |
commoncompute embed |
Embed a single string (prints the vector length) |
commoncompute playground |
Open the web playground |
commoncompute jobs list |
Recent submissions, newest first (--limit/-n) |
commoncompute jobs get <id> |
Fetch one job |
commoncompute jobs wait <id> |
Poll a job to a terminal state (--timeout/-t) |
commoncompute jobs events <id> |
Event timeline for a job |
commoncompute jobs download <id> |
Download a job's result (--out/-o, else stdout) |
commoncompute keys list / create / revoke |
Manage API keys |
commoncompute receipts list |
Receipts for completed jobs (--limit/-n) |
commoncompute receipts get <id> |
Signed receipt for a single job |
commoncompute receipts export |
Export receipts as CSV or JSON (--format/-f, --out/-o, --limit/-n) |
commoncompute config path / show / set / unset |
Inspect and edit local settings (see below) |
commoncompute --version (or -V) prints the version. Every read command that renders a
table also accepts --json for plain, ANSI-free machine-readable output —
whoami, balance, usage, spend, tier, workloads, models, quote,
submit, jobs list/get/wait/events, keys list, and receipts list.
Shell completion
Typer ships completion for bash, zsh, fish, and PowerShell:
commoncompute --install-completion # install for the current shell
commoncompute --show-completion # print the script to inspect or customise
Exit codes
Scripts can branch on commoncompute's exit status:
| Code | Meaning |
|---|---|
0 |
Success |
1 |
API or runtime error (network, server, bad request) |
2 |
Usage error — missing/invalid arguments, or no credentials found |
3 |
The job reached a failed terminal state (failed / dead_letter / cancelled) — commoncompute jobs wait and commoncompute submit --wait only |
Migrating from OpenAI (optional)
Existing OpenAI-based pipelines (embeddings, chat, transcription) can point at Common Compute by swapping two env vars — or:
from commoncompute.compat import openai # sets OPENAI_BASE_URL / OPENAI_API_KEY
client = openai.OpenAI()
This is a migration path, not the recommended interface: the native client returns locked prices, ETAs, and receipts that the OpenAI wire format can't express.
Errors
Typed, always:
try:
client.ocr.extract("scan.pdf", max_spend_usd=0.01)
except cc.InsufficientFundsError: # quote exceeded the cap / no card
...
except cc.PermissionDeniedError: # key lacks scope for this workload
...
except cc.ConflictError: # idempotency-key or state conflict (409)
...
except cc.UnsupportedFormatError: # wrong file type for the workload
...
except cc.JobTimeoutError: # wait() expired; job still running
...
except cc.NetworkError: # no HTTP response after retries
...
except cc.CommonComputeError as e: # everything raises from this
print(e.request_id)
The full hierarchy — AuthenticationError, PermissionDeniedError,
NotFoundError, ConflictError, RateLimitError, InsufficientFundsError,
BadRequestError, ValidationError, UnsupportedFormatError, NetworkError,
JobTimeoutError, APIError — all subclass CommonComputeError.
Configuration
Credentials and settings live under one canonical directory (override the whole
directory with $CC_CONFIG_DIR):
~/.config/commoncompute/credentials # the API key (single line)
~/.config/commoncompute/config # settings: base_url, org (key = value)
Two legacy locations are still read (never written) so older installs keep
working: ~/.commoncompute/config and ~/.commoncompute/credentials.
Environment variables take precedence over both files at runtime:
| Setting | Env var | Resolution order (first match wins) |
|---|---|---|
| API key | CC_API_KEY |
env → ~/.config/commoncompute/credentials → ~/.commoncompute/config → ~/.commoncompute/credentials |
| Base URL | CC_BASE_URL |
env → config file base_url → https://api.commoncompute.ai |
| Org id | CC_ORG |
env → config file org → default workspace |
| Config dir | CC_CONFIG_DIR |
overrides the ~/.config/commoncompute location above |
Inspect and edit the local config from the CLI:
commoncompute config path # print the config directory
commoncompute config show # settings + active credential source (key masked)
commoncompute config set base_url https://api.commoncompute.ai
commoncompute config set org my-workspace
commoncompute config unset org
Env vars still win at runtime — commoncompute config set writes the file, but
CC_BASE_URL / CC_ORG override it for a given process.
Python 3.9+. Core dependencies: httpx, pydantic. MIT license.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file commoncompute-0.3.0.tar.gz.
File metadata
- Download URL: commoncompute-0.3.0.tar.gz
- Upload date:
- Size: 49.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8355f08063ab7204d6eadd4b9e929b0d7eff0a7bdbc43c6e1e1189063c040321
|
|
| MD5 |
c64358728b4c51bbe466e6cc31cc076a
|
|
| BLAKE2b-256 |
bee7f71f88f4dcb184396aaf19ac4341b6255bbc99f2449f958f2d80464dc813
|
File details
Details for the file commoncompute-0.3.0-py3-none-any.whl.
File metadata
- Download URL: commoncompute-0.3.0-py3-none-any.whl
- Upload date:
- Size: 58.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7ba246e8f439f7c4caf55570ec09fe5c78d772e3e3774022f5236ee2117f01a2
|
|
| MD5 |
6630090f4ee84dba4b931bc9ecc967c2
|
|
| BLAKE2b-256 |
b3474a8a353b18883d036aa63aba13afc9497a441d681eff8d37e7e38be37f71
|