stella cloud

Read and set the org and workspace identity that scopes replicated telemetry, and send that telemetry to an org intake you configure.

Every row stella usage copies to the hub carries an identity: which organization it reports to, which workspace it came from, and which repository that workspace maps to. stella cloud is where you read that identity, set it, and, if you configure an endpoint, upload data under it.

Login is still a work in progress: register saves ids locally and creates a durable workspace id, and the login step that will attach a token will write to the same file later. Registration alone doesn't upload anything and doesn't change what telemetry is collected, only which ids get stamped on it.

Synopsis

stella cloud status
stella cloud register --org <ORG_ID> [--workspace-id <ID>]
stella cloud sync
stella cloud logout
stella cloud deregister

A subcommand is required. None of them needs a provider or an API key.

What it does

Four ids describe an installation, and each answers a different question:

org_id

The organization this installation reports to. NULL until you register. STELLA_ORG_ID wins if set; otherwise it comes from the org_id in ~/.stella/cloud.json, written by stella cloud register.

workspace_id

A durable id at <root>/.stella/workspace.json, written only by registration and never created automatically. An unregistered workspace reports NULL. It lives outside .stella/private/, so committing it gives every clone and every machine one shared workspace identity.

repo_id

A workspace is only usually a repository. repo_id is built from the normalized origin remote URL (the SSH and HTTPS forms of the same repo count as the same one), and falls back to the folder path when there is no git remote. Rows carry it separately so a multi-repo workspace still reports per repository.

project_id

A hash of the workspace's own path. Always present, registration or not, and it is the key replication runs on. This is what makes stella usage work on a machine that has never heard of a cloud org.

Resolving these ids never fails: telemetry scoping must never break a turn, so unregistered ids resolve to NULL, and a missing git remote falls back to the path-based id instead of erroring.

stella cloud status

Print this installation's identity for the current workspace, and, once an org is set, any rows the cloud intake permanently rejected.

stella cloud status

Unregistered:

org_id:   (not registered)
workspace:   (not registered)
repo_id:   9f2c1ad4e7b03518
project:   4b81c0e2f39a77de

register with `stella cloud register --org <org-id>` — telemetry replicates locally either way; org scoping gates what a future cloud sync would ship

Registered:

org_id:   acme
workspace:   6f1d8a20-4c3e-4a71-9a55-2d0be1c7f5aa
repo_id:   9f2c1ad4e7b03518
project:   4b81c0e2f39a77de

Quarantined rows

Once an org is registered, status also reports rows the cloud intake rejected permanently. This is the only place they show up. The drain sets these rows aside and moves past them so newer rows keep flowing, which means everything downstream can look healthy while a rejected row sits in the hub unnoticed.

quarantined:   3 row(s) the cloud intake permanently rejected
              2 x HTTP 422: model slug not in the intake catalog
              1 x HTTP 413: payload too large
              retained in the hub for inspection; the cursor advanced past them

At most three reason groups are listed before the rest fold into a +N more reason(s) line. The rows themselves stay in place; nothing is deleted. Since status answers about identity first, this check does its best: if the hub can't be opened, it prints a one-line note instead of failing the command.

stella cloud register

Save an org id and register this workspace.

--org <ORG_ID>Required

The cloud organization id telemetry reports under. Saved to ~/.stella/cloud.json, the same file that will hold your login token later, so registration and login stay in one file. Cannot be empty.

--workspace-id <ID>

Use a workspace id issued elsewhere instead of creating a new one. Ignored if this workspace is already registered. Registration only runs once, and an existing id always wins, because one workspace must never end up with two identities.

stella cloud register --org acme
registered to org acme (stub — OAuth login lands later)
workspace id 6f1d8a20-4c3e-4a71-9a55-2d0be1c7f5aa written to .stella/workspace.json
commit .stella/workspace.json so every clone reports as this workspace

Commit .stella/workspace.json. It lives outside .stella/private/ for exactly that reason. Without it, a clone has no workspace id until someone registers there, and if they do, the same project ends up reporting under two identities.

The file it writes is small and easy to read:

.stella/workspace.json
{"workspace_id": "6f1d8a20-4c3e-4a71-9a55-2d0be1c7f5aa"}

stella cloud sync

Send staged hub telemetry to the org intake set in ~/.stella/cloud.json's drain block. This is the one command in this group that uses the network.

stella cloud sync

It does nothing unless both an org_id (from register) and a drain block are present. No block, no network traffic. The block also carries the intake credential, which is why cloud.json is saved so only you can read it:

~/.stella/cloud.json
{
  "org_id": "acme",
  "drain": {
    "url": "https://intake.example.com/v1/telemetry",
    "format": "stella",
    "token": "…",
    "batch_size": 200
  }
}
FieldDefaultMeaning
urlrequiredThe HTTPS org intake batches are sent to
formatstellaWire format: stella (the native schema-versioned batch) or otel (OTLP). An unknown value fails and stops
tokennoneBearer credential for the intake. oauth_token wins when both exist
batch_size200Rows per request

Rows the intake rejects permanently are set aside, and the cursor moves past them so newer rows keep flowing. They show up under status. A temporary failure is reported as something you can retry, so just re-run the command.

This is a second, separate export path from the Oxagen Enterprise managed export. It has its own wire format, its own endpoint, and its own opt-in: a drain block in a file you write yourself, pointed at an intake you run. Enterprise enrollment does not turn this on, and this does not turn on enterprise enrollment.

stella cloud logout

Delete the stored credentials and remove the drain block, which stops uploads. Registration and local hub telemetry stay in place.

stella cloud deregister

Does what logout does, plus clears the org id, returning the installation to unregistered. Hub rows keep the org they were captured under; unsent rows for the old org stop sending and stay local. Delete them with stella usage prune --force if that's what you want.

What registration alone does not do

  • It does not upload anything by itself. register writes two local files. Uploading needs a drain block and running stella cloud sync. Telemetry is copied into ~/.stella/usage.db whether you register or not.
  • It does not change what is collected. Only the ids stamped onto each row change, from NULL org and workspace to yours.
  • It does not relabel history. Rows written before registration keep their NULL org, which is why stella usage report --org <id> leaves them out.

It does change one thing worth knowing about: once rows carry an org, stella usage prune will not drop rows a cloud drain hasn't acknowledged yet, unless you pass --force.

Examples

Check what identity this workspace reports under before wiring up CI:

stella cloud status

Register a machine to an org and use a workspace id issued elsewhere:

stella cloud register --org acme --workspace-id 6f1d8a20-4c3e-4a71-9a55-2d0be1c7f5aa

Scope an org to one shell session without touching cloud.json. The environment variable wins over the file:

STELLA_ORG_ID=acme-staging stella cloud status

Register, then confirm the hub is stamping rows the way you expect:

stella cloud register --org acme
stella usage sync
stella usage report --org acme