docs
Commands

stella usage

Report, replicate, and prune the cross-project telemetry hub at ~/.stella/usage.db — the same cost numbers as stella stats, across every project on this machine.

stella stats answers "what did this workspace cost." stella usage answers the same question across every project on this machine, by reading the usage hub — one SQLite database per developer at ~/.stella/usage.db. It needs no provider and no API key, and nothing it does sends anything anywhere.

Synopsis

stella usage
stella usage report [--format <table|json|csv>] [--org <id>]
stella usage sync [--all]
stella usage prune [--older-than <AGE>] [--max-rows <N>] [--gc-deleted] [--force] [--vacuum] [--dry-run]

A bare stella usage is stella usage report with the defaults. The flags belong to the subcommand, so name report explicitly when you pass one.

What it does

Every project keeps its own source of truth at <workspace>/.stella/private/store.db — that is the store stella stats and stella inspect read. The hub is derived from those stores: each finished turn rolls its telemetry up into ~/.stella/usage.db so a cross-project question can be answered without opening every project database in turn.

Two properties fall out of that design, and they are the reason the command exists:

  • It reads even when the project stores are busy. A report from the hub does not contend with a live session holding store.db.
  • It outlives the checkout. A project you deleted six months ago still contributes to the totals, because its rows were replicated before the directory went away.

Flow is strictly one way — store.dbusage.db. Nothing here writes back into a project store, and a hub that is missing or briefly unopenable never fails a turn; replication is best-effort by design.

The hub stores metadata and rollups, never source code or tool output. Prompts are reduced to a digest plus a short preview. Registration with stella cloud changes which ids the rows carry, not what is in them, and does not upload anything today.

Subcommands

report

Per (org, provider, model) totals across every replicated project: calls, tokens, cache reads, cost, and how many distinct projects contributed. The default.

sync

Replicate this workspace's telemetry into the hub from a cursor. Safe to re-run; --all heals every project the hub has ever seen.

prune

Bound the hub's growth — by age, by a row ceiling, and by GC of projects whose checkout is gone.

stella usage report

Group every hub row by org, provider, and model, and total it. Rows are ordered by cost, descending.

--format <table|json|csv>

table prints aligned columns with a TOTAL row; json and csv are for piping into other tools. The three text columns in CSV are RFC-4180 escaped, so an org id or a model slug containing a comma cannot shift the following columns.

Default table

--org <id>

Only rows replicated under this org id. Rows written before you registered carry no org and are excluded by any --org filter.

stella usage
stella usage report --format json
stella usage report --org acme --format csv > acme-spend.csv

Representative table output (illustrative):

ORG            PROVIDER   MODEL                           CALLS        INPUT       OUTPUT   CACHE-READ       COST  PROJECTS
(local)        anthropic  claude-fable-5                    412      8214003       411220      6120884    31.4188         7
(local)        zai        glm-5.2                           268      3901556       288104      1902330     4.9071         4
TOTAL                                                       680     12115559       699324      8023214    36.3259

An unregistered installation reports its rows under (local) — the display for a NULL org id. An empty hub says so and points you at stella usage sync.

stella usage sync

Replication normally happens on its own: each finished turn ships its telemetry into the hub best-effort. sync is the explicit and the repair path — it walks the hub's per-project cursor forward, so re-running it is safe and only ever ships rows the hub does not already have.

--all

Walk every project in the hub's registry instead of just the current directory. This is the repair path: a project whose best-effort sync failed mid-turn has a cursor that fell behind, and --all heals all of them in one pass. A registered project with no local store.db is reported as skipped rather than treated as an error.

# This workspace only.
stella usage sync

# Every project the hub knows about — the repair pass.
stella usage sync --all

The single-workspace form reports one number; --all reports per project first:

acme-api                 128 row(s)
acme-web                 0 row(s)
old-prototype            skipped (no local store)
replicated 128 telemetry row(s) across 3 project(s)

stella usage prune

The hub keeps one telemetry row per model call, across every project, forever — including rows from checkouts that no longer exist. prune is the retention control. It refuses to run with none of --older-than, --max-rows, or --gc-deleted set, so a bare stella usage prune can never mean "delete something."

--older-than <AGE>

Drop rows older than this window. N followed by d, w, h, mo, or y90d, 12w, 720h, 3mo, 1y. A bare number means days. The window must be positive: 0 would prune everything older than now, which is almost always a typo.

--max-rows <N>

Hard ceiling on retained telemetry rows; the oldest prunable ones are evicted until the hub is at or under it.

--gc-deleted

Also drop everything the hub holds for a project whose checkout is gone and that was never org-registered — its telemetry, its rollups, its sync cursor, and its registry row. "Gone" means the project root is missing while its parent directory still exists, which is a deletion. A whole volume being absent — an unplugged drive, a down network share — is deliberately not a deletion, so an unmounted disk never GCs your local history. A project that does come back re-replicates on its next sync.

--dry-run

Compute the report and delete nothing. Worth running first.

--vacuum

VACUUM afterwards, handing freed pages back to the filesystem, and re-anchor the cloud cursors across it. Also runs automatically after a large prune.

--force

Also drop un-acked cloud rows, breaking a pending drain. Off by default.

# What would go, without touching anything.
stella usage prune --older-than 1y --dry-run

# A year of history, plus everything held for repos you have since deleted.
stella usage prune --older-than 1y --gc-deleted --vacuum

# Or bound it by row count instead of age.
stella usage prune --max-rows 100000

Prune is cloud-safe by default: a row belonging to a registered org that the cloud drain has not yet acknowledged is never dropped, even when it falls inside the age window. Those rows are reported back to you as kept — --force is the deliberate override, and it breaks the pending drain permanently. Rollup rows never drain, so they age out unconditionally.

If the ceiling could not be met because the excess rows were un-acked, prune says so rather than silently leaving the hub over budget: drain them, or re-run with --force.

Relationship to stella stats

stella stats

One workspace. Reads <workspace>/.stella/private/store.db, the source of truth, with the per-run cache-economics columns. Its prune bounds that store.

stella usage

Every workspace. Reads ~/.stella/usage.db, derived from the above. Its prune bounds the hub, and the two retention commands are independent — pruning one never touches the other.

The two --older-than vocabularies are shared code precisely so --older-than 3mo cannot work on one command and fail on the other.

Examples

Your five most expensive models across every project — the rows already arrive sorted by cost:

stella usage report --format json | jq '.[0:5] | .[] | {provider, model, cost_usd}'

Find the models you use across the most projects:

stella usage report --format json | jq '.[] | select(.projects > 2) | {provider, model, projects, cost_usd}'

Heal every stale cursor after a stretch of interrupted sessions, then report:

stella usage sync --all
stella usage report

Keep the hub bounded on a schedule, safely:

stella usage prune --older-than 6mo --gc-deleted --vacuum

The hub is a real SQLite file at ~/.stella/usage.db (STELLA_DATA_DIR overrides the directory). Beyond this command you can query it with any SQLite client — see Telemetry & budget.

Stella is totally free and open source, licensed AGPL 3.0 — use it, fork it, ship it; if you distribute a modified Stella or run one as a service, you publish your changes too. Writing closed-source code with Stella is unaffected. Need to embed it in a proprietary product? A commercial license is available. No account and no Community/default telemetry egress. An explicitly enrolled Oxagen Enterprise managed seat has one signed, content-free operational exception. Enterprise telemetry boundary → What that means →

On this page