Terminal and providers
Each terminal card is a real process from a provider — Claude, Codex, Cursor, Antigravity, OpenCode, Cline, Command Code or a plain shell.
Each terminal card is a real PTY, running a provider or a plain shell. Stellar does not simulate a terminal: what appears in the card is the process.
Providers
| Provider | What runs |
|---|---|
claude |
Claude Code |
codex |
Codex |
cursor |
Cursor |
antigravity |
Antigravity (Gemini) |
opencode |
OpenCode |
cline |
Cline |
commandcode |
Command Code |
bash |
a shell, with no agent behind it |
The last two are not code: they are data. The built-in catalog declares
the binary, how the session id comes in, which flag carries the system
prompt, where the MCP config lives, effort and model — and the arguments are
synthesized from that declaration. It is what lets you declare your own: a
providers.json in the configuration folder registers a new CLI without
restarting the app (see Where data lives).
The provider is chosen at card creation. It is not inherited from whoever dispatched: a task that does not declare a provider is refused, on purpose — pinning the whole chain to the provider that started would be too silent a decision.
Installed is not ready
The binary resolving on the PATH answers one question only. Availability
has four answers, and each one is as large as the proof behind it:
| Answer | What backs it |
|---|---|
missing |
the binary does not resolve on the PATH |
not-ready |
installed, and the declared probe answered that it is not ready (a missing credential, for example) |
ready |
installed, and the probe answered that it is |
unknown |
installed, and the app does not know — no probe was declared, or it never answered |
unknown is the default of a provider that declares nothing, and it never
becomes “ready” out of optimism. The case that forced this is measured: a
CLI installed and without a credential showed as available, the spawn
“succeeded” and the card stayed silent forever. The probe lives in the
provider declaration because “ready” varies per harness — and what the app
reads is the field the tool itself prints, not the exit code.
Zoom without reflow
The canvas zoom is optical: the text scales like an image, without firing
fit() or reflowing columns and rows mid-session. The PTY is resized only
when you drag the card’s physical edge.
Session and resume
Every card can be resumed with the provider’s session id, but not the same way — and the difference that matters is between imposing and resuming.
Imposing is creating the session already with the id Stellar chose. Only
two providers know how: claude, with --session-id, and cursor, with
--new-session-id. On cursor the imposing flag does not show in --help,
and for a while the app used --resume for both roles — which asked to
resume a session that did not exist yet.
Resuming is pointing at a session that already exists, discovered in the
provider’s store: cline (--id), codex (resume <id> — a subcommand,
not a flag), opencode (--session), commandcode (--resume) and
antigravity (--conversation). None of these accepts an unknown id: an
imposed id would be ignored silently.
The registry keeps two distinct ids: the resumeId requested at spawn and
the sessionId discovered at runtime. When the provider imposes an id
different from the requested one, the second is the one that counts.
And the imposition is checked, not presumed. After the spawn, the app
reads the store declared by the provider and looks for the imposed id there.
If it does not find it, the declaration was contradicted by measurement and
the session watcher takes over again — instead of the card pointing forever
at a session that does not exist. The check exists because
canImposeSessionId: true is a claim in a configuration file, and nothing
checked it: that is how the cline defect (the flag was for resuming) and the
cursor one (the flag was wrong) got through.
Where there is neither imposition nor a discoverable session, the registry stays absent, honestly, instead of inventing an id.
Quota and agent death
Providers die from quota in the middle of the work. Before concluding that the agent failed, read the card’s scrollback: a quota death looks like a bug death when nobody looks.