Skip to main content

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 `cc` command line
cc login                           # opens the browser — no key to copy-paste

cc 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.transcription.create("s3://my-bucket/meeting.mp3", timestamps=True)
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

Examples

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. Transcription in bulk

jobs = client.transcription.create_many(
    [f"s3://recordings/call-{i}.mp3" for i in range(200)],
    language="en",
    max_concurrent=16,
)

3. Reranking — sharpen RAG retrieval

job = client.rerank("what is the neural engine?", documents, top_n=5)
top = client.result(job).output

4. Translation

job = client.translate(catalog_descriptions, target_lang="de")

5. Background removal

job = client.images.remove_background("product-shot.png")

Also available: client.video.transcode(...), client.build.ios_test(...), client.images.generate(...), client.embeddings.create(...), and the generic client.submit(workload_id, payload) for anything in 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 cc command.

cc login                              # stores the key locally
cc quote vision_ocr --units 5         # price + ETA, no execution
cc submit coreml_embed --payload '{"input":["hi"]}' --wait
cc jobs list
cc jobs get <id>
cc balance
cc receipts export --format csv --out receipts.csv

Commands

Command What it does
cc login / cc logout Store / remove the API key (browser approval, or --api-key)
cc whoami Show the account behind the current key
cc balance Current workspace balance
cc usage Spend + call-count rollups over a date range (--start, --end, --group-by)
cc spend Total spend over the last --days N, grouped by workload
cc tier Current volume tier and the next threshold
cc workloads List available workloads
cc models List models (--workload to filter)
cc quote Price + ETA for a workload without submitting (--units, --priority, --model)
cc submit Submit one job (--payload/-f, --model, --priority, --wait, --timeout)
cc submit-many Submit a JSONL file of payloads; stream one result per line as NDJSON (--input/-i, --max-concurrent, --no-wait)
cc chat One-shot chat message to a model (--model, --stream/--no-stream)
cc embed Embed a single string (prints the vector length)
cc playground Open the web playground
cc jobs list Recent submissions, newest first (--limit/-n)
cc jobs get <id> Fetch one job
cc jobs wait <id> Poll a job to a terminal state (--timeout/-t)
cc jobs events <id> Event timeline for a job
cc jobs download <id> Download a job's result (--out/-o, else stdout)
cc keys list / create / revoke Manage API keys
cc receipts list Receipts for completed jobs (--limit/-n)
cc receipts get <id> Signed receipt for a single job
cc receipts export Export receipts as CSV or JSON (--format/-f, --out/-o, --limit/-n)
cc config path / show / set / unset Inspect and edit local settings (see below)

cc --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:

cc --install-completion        # install for the current shell
cc --show-completion           # print the script to inspect or customise

Exit codes

Scripts can branch on cc'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) — cc jobs wait and cc 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_urlhttps://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:

cc config path                        # print the config directory
cc config show                        # settings + active credential source (key masked)
cc config set base_url https://api.commoncompute.ai
cc config set org my-workspace
cc config unset org

Env vars still win at runtime — cc 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

commoncompute-0.2.0.tar.gz (48.4 kB view details)

Uploaded Source

Built Distribution

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

commoncompute-0.2.0-py3-none-any.whl (57.4 kB view details)

Uploaded Python 3

File details

Details for the file commoncompute-0.2.0.tar.gz.

File metadata

  • Download URL: commoncompute-0.2.0.tar.gz
  • Upload date:
  • Size: 48.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for commoncompute-0.2.0.tar.gz
Algorithm Hash digest
SHA256 ccea4d5ad2a729a14299caab3bf03c4a2b94d7c57068a0be9a76e273af4bb097
MD5 8bc50bfc77cbc13dd38f48c9c756a7ec
BLAKE2b-256 844c512483e01ce454b647e994752d3b25103f92a1e5ba45b2f2230f25e4090e

See more details on using hashes here.

File details

Details for the file commoncompute-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: commoncompute-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 57.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for commoncompute-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4fa9c5aedc383e11e603d6055c32469fe1ac6f8ead818d4b02f94bb4c8240508
MD5 4fe8db8dece9fe64b5475c058fa83258
BLAKE2b-256 9105760aa48793a845456d453e6e57d9ca76e3adcc62037f1adf6314ae7b6852

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page