Session artifacts
stella can hand you a session you can carry to another machine, but it won't carry it there for you. Why that line is drawn there, what stella still owes you, and what it won't take on.
stella already survives a crash. If you kill the process mid-turn, the next run picks up right where it left off, with the no-clobber guarantee still intact, because both live in a durable git store stella keeps in its own directory.
What it doesn't survive is a machine. If your laptop dies, or you want to hand a half-finished session to a coworker, or start something on your desktop and finish it on a plane, none of that works today. The reason is worth being precise about, because it shows exactly where the line belongs.
Heads up: this describes a planned design, not shipped behavior. The checkpoint and replay APIs below don't exist yet. What is real today: the local store and the remote-call model described in "Why not build sync in" are both live. The fingerprint check described below is not: it depends on a mechanism that hasn't been built yet.
Why state stays local
stella's durable store is keyed to a workspace id that only means something
on one machine. That id lives in .stella/private/, which is gitignored by
default, so cloning a project never carries it along. stella decides
identity by comparing absolute paths, and that comparison means nothing
across machines. If stella sees the same id at a path where another copy
is still running, it creates a fresh id instead, so two copies of a
project can never silently write into each other's history.
Every one of these choices is right for the question this part of stella is answering: is this the same working copy I saw last time? And every one of them rules out resuming somewhere else.
The obvious fix is to give stella a portable identity: an account, a project id, a login. stella doesn't do this, and that choice is the whole point of this page.
The line
stella provides a checkpoint API and a replay API. Checkpoint returns a self-contained artifact. Replay accepts one. Identifying a workspace, storing the artifact, moving it around, authenticating it, and deciding who can read it are all up to whatever calls these APIs.
This isn't a line invented just for this feature. It's the same line stella draws everywhere else.
When stella runs headlessly behind a host, using the stella-serve crate,
every governed side effect goes back to the host. Model calls and tool
calls are requests the host answers. The engine never has authority of
its own, so a turn running this way literally cannot read one of your
files on its own. It can only ask, and something else decides. In this
setup, the workspace was never stella's to begin with.
Why not sync
Building sync in would mean one integration instead of two, which is a real advantage if you're one person with two machines. But it loses anyway, for three reasons.
It needs an identity nobody can derive. stella only sees a directory.
It has no way to know that ~/src/api on your laptop and /work/api on a
build machine are the same project. Only something with a concept of
project can know that. Any scheme that tries to guess will eventually
link two unrelated codebases together, which is worse than just missing
the match.
It contradicts what this project promises. Local-first state, BYOK credentials, and zero telemetry egress by default are claims the project's whole premise depends on, with exactly two explicit opt-in exceptions. A first-party upload path makes them conditional, and the condition is precisely the thing people choose stella to avoid. An artifact API adds no third path: producing an artifact writes bytes locally, and stella still uploads nothing.
It builds the easy half twice. Storage, auth, tenancy, retention, audit — these are solved problems, and they don't get better for being rebuilt inside a CLI.
What stella still owes you
"Identity is the caller's problem" is the right line. "Any artifact can be replayed into any tree" is not.
Replay an artifact into the wrong checkout, and you get a session whose transcript describes files that were never there. The model reasons confidently from content that doesn't exist in the tree it's about to edit, and nothing reports it. That's worse than the failure the no-clobber guard exists to prevent, for the same reason it's worse to be quietly misinformed than loudly blocked.
So the artifact carries a fingerprint of the tree it came from, and replay checks it and refuses by default if it doesn't match. stella isn't naming your workspace. It's checking that this artifact belongs to this tree.
This fingerprint would need to build on the same kind of tracking the no-clobber guard uses: every path a session touched, and a fingerprint of what it saw there. That tracking doesn't currently exist in a form the fingerprint could use, so what follows describes the intended design, not something built yet.
Checking it means re-hashing those paths in the tree being replayed into. A mismatch names the exact files, the same way a refused write does, and nothing is lost. It can be overridden, but only by passing an explicit argument. It's never automatic, and never a fallback stella takes for you when the check fails.
This tracking would only cover the files the session actually touched, nothing else. So it can't cry wolf over unrelated changes elsewhere in the project, and it can't catch a tree that differs only in files the session never read. That's the same reasoning as the guard it's based on: a check that fires on noise gets overridden out of habit, and then it protects nothing.
Two ways to land
Replaying into a tree you already have and building a tree from scratch are different operations with different failure modes. So they're two different modes you choose, never guessed from what happens to be on disk.
- Apply (the default) replays against a checkout you already have, checked against the fingerprint. This is the same-laptop-the-next-morning case.
- Materialize writes the session's files out first. The cross-machine case.
Materialize has a real limit: the artifact holds the files the agent touched, not your whole project. stella records the base commit so a caller can name it, but it doesn't carry that base, and never will. Bundling your whole project into an artifact would move files the agent never even read, and that's a decision about what leaves your machine that stella has no business making for you.
Fetching the base commit is exactly the kind of thing a control plane is for. It already has the repository, the credentials, and the policy about who can use them.
What's in the artifact
The conversation, word for word. That means the full content of every
file the agent read, including whatever was in those files: the
credentials in the .env you asked it to debug, customer rows in a test
fixture, a key in a test file.
Keep that in mind every time — it's not a one-time warning in a release note.
stella doesn't encrypt it, redact it, classify it, or expire it. Doing any of that requires knowing whose data it is, what jurisdiction it's under, and who's allowed to read it, and stella knows none of that. Its only job here is to say exactly what's in the artifact, so you can make an informed decision. That's not a gap. It's the boundary working as intended.
Forks stay visible
Two machines replay the same artifact. Which one wins is a policy question, and stella does not answer it.
What stella guarantees is that the split is visible. Every replay starts its own session, with its own reference in the durable store, and where the artifact came from is kept on record. You get two histories with a common starting point you can point to, not one history with two sessions tangled together, which you could never untangle afterward.
Where the line falls
| stella owns | Your control plane owns |
|---|---|
| what is in the artifact | naming a workspace or project |
| an exact round trip | storing artifacts, and keeping them |
| refusing a tree the artifact did not come from | moving it, checking who it's from, keeping customers separate |
| the version rules, and how long old artifacts stay readable | encryption, at rest and in transit |
| making a fork visible | how long it's kept, deleting it, and auditing it |
| telling you what the artifact contains | who wins a conflict, and when |
Oxagen is that control plane at enterprise scale: accounts and projects as the portable identity stella won't invent on its own, plus storage, access control, auditing, and resuming a session right from a browser.
This is a layer on top, not a dependency, and that difference is the test of whether the line sits in the right place. stella has to stay fully usable and fully durable on its own. The work journal, crash resume, and the no-clobber guarantee are local mechanisms, and they stay local mechanisms. If a future change ever made one of them depend on a control plane existing, that change would be the mistake, not this design.
What this does not claim
- This is not sync. There's no
stella login, no stella-hosted store, and no built-in upload path. This isn't a "later" feature. It's a hard no. - Old artifacts don't stay readable forever. A stored artifact stays replayable for a stated support window, not forever. When a build genuinely can't read an old one, it tells you and names what can, instead of guessing at a format it only half understands, which would resume your session subtly wrong.
- stella doesn't merge forks. It just makes them visible. Resolving a fork means knowing which one matters, and that's exactly what stella doesn't know.
- The artifact isn't a backup of your project. It's a record of what the agent did, plus a fingerprint of what it did it to.
Where this sits
The same rule shows up everywhere in stella: where something can be decided by a mechanism, the mechanism decides it. Whether an artifact belongs to a tree is checkable, so it gets checked, and the check refuses rather than just warning. Anything genuinely not checkable from inside a directory, like whose project this is, who may read it, or which copy wins, gets handed to a layer that can actually answer it, instead of being guessed at by a layer that can't.
No silent overwrites
stella refuses to write over a change it never saw, with no lock, no background service, and no need to know who else is working on the file. How this works, what it doesn't promise, and what happens after a crash.
Configuration
How stella is configured: settings.json, credentials, workspace files, and the scope hierarchy.