The mcue model: what survives between sessions
Your tools preserve artefacts. The state you need to continue the work — what you were trying to do, what you ruled out, what is blocked, where to pick up, and whether the last account of it can be trusted — usually does not survive the session, the agent, or the machine that produced it. That is continuity loss, and it is the problem mcue exists to solve. This page is the whole mcue model in one sitting — what operating state is, how it is structured, and what happens when more than one machine writes it. Ten minutes, no installation required.
Operating state
Your repository records what the code became. It does not record what you were trying to do, what you ruled out, what blocked you, or where you meant to pick up. That second category is operating state: the governed state about active work that makes continuing it possible. It is the only thing mcue holds.
The boundary
Git records source history. mcue preserves the governed operating state needed to continue the work.
| Git records | mcue preserves |
|---|---|
| files, diffs, history | intent, outcome, blockers |
| branches and merges | decisions and the reasons behind them |
| who changed which line | where to resume, and with how much context |
| the artefact | the continuity state required to continue producing it |
A repository is an attachment to a project, not its definition. A project can have
one repository, several, or none at all — a project created in Hub with no source
attached is a complete project, with lanes, plans, checkpoints, and resume views.
When a repository joins later, mcue attach connects it to the same project.
mcue never writes to your repository and never copies it anywhere. The only file
it places outside $MCUE_HOME is a small .mcue footprint dropped by
mcue attach, which exists so commands can tell which project a directory belongs
to. Publishing to Hub sends operating state and nothing else — your source never
leaves your machine through mcue.
Why this is a boundary and not a feature
It would be easy to make mcue a little bit smarter by letting it read your diffs, watch your editor, or infer intent from commit messages. Each of those would quietly convert mcue from a tool you can reason about into a tool you have to trust.
What mcue does observe is bounded and warning-only: the current branch, HEAD,
and whether the tree is dirty, so mcue drift can tell you the environment has
moved since the last checkpoint. It does not read diffs, and it never infers a new
objective, resolves a blocker, or changes a decision because the repository
changed. Environment evidence can warn; only an explicit closeout can change
operating state.
The boundary is what makes the rest of the guarantees possible:
- It can work offline, because it never needed your network in the first place.
- It can be inspected, because the state is small enough to read by hand.
- It can be repaired, because Markdown with YAML front matter survives its own tooling.
- It can be handed to an agent, because a bounded packet of intent is useful in a way that a repository dump is not.
What the state is made of
Everything mcue stores reduces to a few kinds of thing:
- Projects — a governed intent with a stable id: the durable identity and ownership boundary for a body of work. Repositories attach to it; it is not defined by one.
- Lanes — independently resumable streams of work inside a project, each with its own state, plan, blockers, and next action. Not branches; see Projects, lanes, and plans.
- Checkpoints — timestamped records written by
mcue closeout. Append-only. - Decisions — a running log of what was chosen and why.
- Plans — the current intended sequence of steps on a lane.
- Perspectives — origin-tagged accounts of a lane (this machine, that agent, the Hub web surface). More than one can be live at once; see Authority and conflicts.
- Resume packets — derived, bounded briefs assembled on demand. Never stored as truth.
The first six are durable. The last is computed, which matters: a resume packet is a view over governed state, so improving how packets are built never requires rewriting history.
Human-readable on purpose
State is Markdown with YAML front matter, on disk, under $MCUE_HOME:
cat ~/.mcue/projects/payments-api/project_state.md
You can diff it, grep it, put it in a private repository, and fix it in a text editor when something is wrong. That is a deliberate durability property rather than a convenience: if mcue stopped existing tomorrow, nothing you recorded would become unreadable.
The complete layout is in Files on disk.
Where Hub fits
Hub does not change the model. It holds accepted operating state so that the persistent MCP endpoint can answer while your machines are off, and so a second machine can clone a project and carry on.
mcue stays authoritative for anything you have not published. Hub becomes authoritative for the ordering of operations on projects you have published — which is what Authority and conflicts is about.
The boundary says what mcue holds. The next question is how that state is shaped — because "a pile of notes" would survive between sessions and still be useless. The structure is three nested ideas, and each one earns its place.
Projects, lanes, and plans
Three nested ideas carry all of mcue's structure. Understanding what each one is for — and what it deliberately is not — makes the command surface obvious.
Projects
A project is a governed intent: the durable identity for a body of work whose continuity mcue governs. It has a stable id, a registry entry, and a state directory. From the CLI, it is usually created where the code lives:
mcue init payments-api --name "Payments API" # register and scaffold
mcue attach payments-api # anchor an existing project to this directory
mcue detach # remove the footprint, keep the state
The directory is an attachment, not the project. A project can have several
repositories attached or none; one created in Hub with no CLI involved is the same
kind of thing, and mcue attach joins a repository to it later. The project is the
boundary for identity, ownership, membership, shared decisions, and portfolio
visibility. It is not the smallest thing you resume — that is a lane.
The id is yours to choose and appears in every later command. Keep it short and
stable; if you must change it, mcue project rename <old-id> <new-id> moves the id
across all local state rather than leaving you to fix references by hand.
Projects have a lifecycle beyond deletion:
mcue project archive payments-api # out of the active portfolio, state retained
mcue project delete payments-api # hard delete: registry entry and state
Archiving is the one you usually want. mcue index stops showing archived
projects without destroying anything.
Lanes
A lane is an independently resumable stream of work inside a project. It has its
own objective, blockers, next action, resume pointer, plan, and checkpoint history
— and its own freshness, trust, and drift signals. mcue closeout writes to a
lane; mcue resume reads from one. The lane is the primary continuity unit.
mcue lane create payments-api refunds
mcue lane close payments-api
mcue lane delete payments-api
A lane is not a Git branch. The distinction matters:
- A branch partitions code. A lane partitions attention.
- A branch merges. A lane reconciles — and only when two perspectives on the same lane diverge.
- You can work one lane across several branches, or several lanes on one branch. mcue does not care what your VCS is doing.
Every project starts with a default lane, so you can ignore lanes entirely until you are genuinely running two strands of work and find their closeouts polluting each other.
Plans
A plan is the current intended sequence of steps on a lane. It is scoped to the lane, not the project, because two lanes have two different next actions.
mcue plan create payments-api
mcue plan show payments-api
mcue plan update payments-api # change it outside a closeout
mcue plan close payments-api # archive the active plan
mcue plan list payments-api # active and archived
Plans are archived rather than deleted when closed, so "what did we think the sequence was in March" stays answerable.
How they compose
project payments-api
├── lane default
│ ├── plan (active)
│ └── checkpoints/
└── lane refunds
├── plan (active)
└── checkpoints/
mcue closeout writes to a lane. mcue resume reads from a lane. mcue index
aggregates across projects. When a lane accumulates two unreconciled perspectives —
usually because two machines wrote to it independently — mcue reconcile is how
you resolve it.
Choosing a granularity
The failure mode at both ends is real:
- Too many projects. A project is one governed intent — the body of work you
would describe as a single thing with one owner and one set of decisions. Often
that maps to a repository; sometimes it spans several, or has none yet. One per
feature means
mcue indexbecomes noise and nothing is ever resumed. - Too many lanes. Create a lane when two strands genuinely have different next actions and different blockers. Otherwise a single lane with good closeouts beats five with sparse ones.
When in doubt, fewer. Splitting later is cheap; merging a fragmented history is not.
Structure settles how one machine organizes the work. The moment a project exists on more than one machine — a laptop and a desktop, you and an agent, you and a colleague — something has to decide what order things happened in. That is the last piece of the model, and the one where most tools quietly cheat.
Authority and conflicts
The moment a project exists on more than one machine, something has to decide what order things happened in. mcue answers that with an explicit sequence and typed conflicts — never with a clock comparison.
Before you publish
There is no question to answer. Your machine holds the state, your machine is authoritative, and nothing else can write to it.
After you publish
Publishing changes the authority model for that project. Hub orders accepted operations; every mcue installation becomes an offline-capable replica of that ordering.
Each accepted operation gets a monotonically increasing per-project sequence. That sequence — not a timestamp — is what "after" means. Wall-clock time is recorded as evidence and is never the arbiter, because two machines disagreeing about the time is a normal condition, not an exceptional one.
The four fields that make it work
Every operation carries:
operation_id— unique per operation. Retries are safe: replaying an operation id returns the original result rather than appending a second copy. This is what makes a dropped response harmless.base_entity_revision— what the operation was written against. If the entity has moved on, the write is stale.project_event_sequence— assigned on acceptance. Your sync cursor.entity_revision— assigned on acceptance. Detects the next stale write.
Pending work
A local mutation applies locally first, then goes into a durable outbox. Until Hub accepts it, it is pending and mcue says so:
mcue sync status payments-api
That command makes no network request. It reads your cursor and your outbox and tells you what has not been accepted yet. Pending work is never silently discarded — not on reconnect, not on conflict, not on unlink.
What happens on reconnect
mcue sync exchanges pending operations and pulls events after your cursor, then
rebuilds the accepted base and replays anything still pending on top.
| Situation | Result |
|---|---|
the same operation_id arrives twice | original result returned; nothing appended twice |
| two append-only writes to one lane | both accepted; the lane becomes divergent and needs reconciliation |
| a mutable write against a stale revision | rejected with the current revision and a typed conflict |
| a delete against a changed entity | rejected; never cascades from stale state |
| an accepted remote write while you were offline | applied on your next pull |
| an invalid operation from any source | rejected by the shared validator |
Divergence is not failure
Append-only writes — checkpoints, perspectives — never conflict in the destructive sense. Both survive. The lane is marked divergent, and:
mcue reconcile payments-api
is how you resolve it. Reconciliation is a human judgement about which perspective is right, so mcue asks rather than guesses. That is the whole reason there is no last-write-wins: the later write is not more correct, it is just later.
Why no automatic merge
An automatic merge of operating state would have to decide that one person's account of what happened supersedes another's. It cannot know that. The honest options are to keep both and ask, or to reject the stale one and say why — which is exactly what the table above describes.
The cost is that you occasionally have to reconcile by hand. The benefit is that mcue never quietly loses the record of what you were doing.
Revocation is not deletion
Revoking a device or an OAuth client stops further access. It does not delete
project state, on Hub or locally. Similarly, mcue unlink removes only this
machine's link and outbox — the local state and the Hub project both remain.
Related
- Work offline and sync — the same model, as a walkthrough.
- Recover a broken session — when the problem is local, not distributed.
Where this leaves you
That is the model: a hard boundary around operating state, three nested ideas that structure it, and an authority rule that never guesses. Read together, they are one commitment — continuity. mcue preserves the minimum trustworthy state required for the next person or agent to continue the right work from the right state, and it prefers visible disagreement to a confidently wrong merge. Everything else — the command surface, the MCP tools, the Hub — is these three sections made operational.
What mcue is, and the vocabulary every surface shares, is fixed in one contract,
CONTINUITY.md, which ships with the source repository.