Status: Authoritative current behavior. Verified through: v0.4.0.
calque has one workload shape (a Modal-decorated script's warm unit, driven
over real or synthetic items) but several ways to acquire and drive
hardware for it. This page is purely "which one, when" — for the why
behind each design, follow the links into docs/.
| You want to... | Use | Why not the others |
|---|---|---|
| Just see if my script parses / would run, no spend | calque analyze then calque run --dry-run |
Nothing else is free. |
| Confirm the AWS plumbing (acquire/bring-up/collect/terminate) works before trusting it with real money | calque smoke |
real/ramp/pool/spawn-run all assume the plumbing already works — smoke is the thing that proves it, cheaply. |
| Run one real job, once, on its own dedicated instance | calque real (no --shards, no --pool) |
ramp holds the instance for MULTIPLE N values, which you don't need for one run; pool is for repeat/shared use, which adds setup cost for a single run. |
| Run the same script at several different N values without re-paying acquisition each time | calque ramp |
real acquires fresh (and pays acquisition cost) every invocation; ramp acquires once, holds, and drives every rung over SSM. Use this for "try N=1, then N=100, then N=1000" testing. |
Fan a .map()-shaped workload out across many items faster than one instance can serial-drain them |
calque real --shards N |
This is real's own fleet mode — N single-node instances acquired in parallel, sharded by item index, collected back into one ordered result set. Not a separate command. |
| Serve MANY separate runs/claims against the SAME warm model without reloading it each time | calque pool create, then calque real --pool |
real (without --pool) reloads the model fresh (@enter's cost) every single invocation; a pool keeps resident workers warm across claims via a model-scoped SQS queue. Worth the setup cost once you have more than a handful of runs against the same model. See ../pool-queue-contract.md. |
Run a script whose Modal code uses .spawn()/.get() to fan out across DIFFERENT callables (not one .map()'d callable over many items) |
calque spawn-run |
real --shards shards ONE callable's item list across instances; spawn-run instead gives each DISTINCT .spawn()-classified callable in the script its own instance — a different fan-out shape entirely. |
| Give multiple users their own isolated (or cooperative) slice of ONE already-running GPU instance | calque session checkout |
Nothing else touches an instance after it's already up — session is the only verb that doesn't itself acquire or terminate EC2 instances; it operates on hardware real/ramp/pool/smoke already stood up. See ../tenancy-vs-session.md. |
--script /path/to/your_script.py makes real (and ramp) parse and drive
a real script's own body instead of the hardcoded vLLM reference. From
there:
- Script has 0 or 1
@app.local_entrypoint()s, or you're fine with whichever callable calque's automatic scan picks: do nothing extra. - Script has 2+ entrypoints and you need a specific one: add
--entrypoint NAME. - The callable you actually want isn't reachable through ANY
entrypoint — e.g. it's a sibling function only a different
entrypoint invokes, the exact shape AI-Almanac's
run_benchmark_localhit (its only entrypoint calls a different, GCS-backed sibling) — use--function NAMEto select it directly, by name.--functionwins over--entrypointwhenever both are given. - Your target function's real signature takes a single
bytesarg (e.g.def f(input_bundle: bytes)): use--item-file PATH. - Your target function's real signature mixes
byteswith other typed args (e.g.def f(job_id: str, config: dict, bundle: bytes)): use--arg-file IDX=PATHfor the bytes position(s) and--arg-json IDX=JSONfor everything else — every position must be covered by exactly one of the two. - The script needs env vars / secrets before
@enterruns:--secret NAME=VALUE, repeatable. - The script's own
pip_install(...)chain wasn't statically resolvable (e.g. built via a factory function calque can't trace through):--pip PACKAGE(repeatable, accepts git-URL specs too) + optionally--python-version. - The script's body shells out to a hardcoded absolute path its
original Docker image would have put something at (e.g. a generator
script baked into a base image):
--stage-file URL=PATHdownloads it there first.
Full flag-by-flag detail: cli-reference.md.
ramp and real --shards both acquire and own the EC2 instance(s)
they use for exactly one command's lifetime. pool and session are the
two primitives built for hardware that OUTLIVES a single invocation —
pool keeps a set of workers warm across many separate claims over time;
session lets several users share one already-running instance
concurrently. If you're reaching for ramp/real --shards and find
yourself wanting the instance to still be around for your NEXT invocation
too, that's the signal you actually want pool or session instead. See
../m12-m13-boundary.md for how these two layer
on top of the base acquire/release primitive.