# mcue documentation Every page from https://mcue.dev/docs, in reading order. Generated from the documentation sources; see https://mcue.dev/llms.txt for the index. --- # Documentation Pick up where the work actually left off. mcue saves what happened, what you decided, and what comes next as an explicit work record. A fresh connected AI chat reads that record and continues, without rebuilding the context from scratch. You can inspect the record, correct it, and choose which clients may change it. ## Getting started [Start with your existing conversation](/docs/getting-started): save where you are, open a fresh chat and carry on. Your first useful continuation comes before the deeper lessons. There are two ways in, and they share the same record: - **In the browser, with Hub.** Create a project, connect your AI app, and it can read and save straight away. Nothing to install. Hub is in invite-only alpha. - **On your machine, with the CLI.** The same loop runs locally, offline, in files you can read. Connect it to Hub later if you want the record reachable from other apps and machines. [Request alpha access](https://hub.mcue.dev/join) · [Read Getting started](/docs/getting-started) ## Start with the loop Every session follows the same loop: save where the work stands, check the record, and resume from it in the next session. Everything else in these docs exists to support it. In a connected chat, you ask your AI app to save or resume the project. In the terminal, the same loop is four commands: ```bash mcue init payments-api --name "Payments API" # register a project, anchored to this directory mcue closeout payments-api # capture intent, outcome, blockers, next action mcue resume payments-api # re-enter with a bounded context packet mcue index # see the whole portfolio at a glance ``` None of those touch the network. Locally, mcue works without an account. ## What mcue owns, and what it does not mcue holds **operating state**: the intent, outcomes, blockers, decisions, and resume points that let the work continue. Your source code stays in Git, untouched — mcue never writes to your repository and never copies it anywhere. That boundary is the reason the rest of the design looks the way it does, so it is worth reading [Operating state](/docs/concepts/operating-state) before the reference material. ## Where to go next - [Getting started](/docs/getting-started): Save, plan and continue real work across chats. Includes use cases and a Hub walkthrough. - [Use Hub](/docs/guides/publish-to-hub): Keep the record reachable from your connected AI apps, even while every machine is off. - [Install](/docs/install): Install the CLI with your alpha download key, then confirm with mcue doctor. - [Quickstart](/docs/quickstart): Run the loop once, end to end, in about five minutes. - [What mcue can do](/docs/features): The complete feature map, including every CLI namespace. - [Give agents your state](/docs/guides/agents-and-mcp): Expose the same validated surface to an MCP client. ## How these docs are arranged ### Getting started Continue real work in a fresh chat, then explore plans, Hub and local setup. - [Getting started](/docs/getting-started) — Save and resume your work, use plans and the Hub, and follow examples for writing, research and software. - [What mcue can do](/docs/features) — The complete feature map: local operating state, agents, Hub, BYO-S3 sync, and every CLI namespace. - [Install](/docs/install) — Install the CLI with your alpha download key, and confirm it with mcue doctor. - [Quickstart](/docs/quickstart) — Register a project, close out a session, and resume with bounded context. ### Guides Task-shaped walkthroughs for the things you will actually do. - [Close out and resume](/docs/guides/closeout-and-resume) — The two commands the whole product is built around, and how to write a closeout worth resuming from. - [A week with mcue](/docs/guides/a-week-with-mcue) — One project, three closeouts, one interruption, and the resume that pays for all of it — every command and its real output. - [Give agents your state](/docs/guides/agents-and-mcp) — Run the local MCP server and connect a client so agents read the same state you do. - [Publish to Hub](/docs/guides/publish-to-hub) — Log in, publish a project, and connect the hosted MCP endpoint. - [Read continuity graphs](/docs/guides/continuity-graphs) — Follow projects into their lanes, then read the cadence and coverage of accepted closeouts. - [Work offline and sync](/docs/guides/offline-and-sync) — What happens when a machine is offline, and how pending work reconciles on reconnect. - [Recover a broken session](/docs/guides/recovery) — Interrupted closeouts, degraded checkpoints, and retroactive capture. ### Concepts The model underneath the commands. Read these once and the rest follows. - [Operating state](/docs/concepts/operating-state) — The boundary between what mcue owns and what Git owns. - [Why not a notes file?](/docs/concepts/why-not-a-notes-file) — The obvious objection, answered without hedging — including the cases where a plain notes file really is the right answer. - [Projects, lanes, and plans](/docs/concepts/projects-lanes-plans) — How work is partitioned, and why a lane is not a branch. - [Authority and conflicts](/docs/concepts/authority-and-conflicts) — Sequences, pending operations, divergence, and why there is no last-write-wins. ### Reference Complete surfaces, kept in step with the shipped binary. - [CLI commands](/docs/reference/cli) — Every command, grouped by namespace. - [Files on disk](/docs/reference/files) — What lives under $MCUE_HOME and the shape of each file. - [MCP tools](/docs/reference/mcp) — The tool surface exposed to agents, locally and through Hub. ## A note on versions These pages track the current release. The command surface is generated from the shipped binary rather than transcribed, so if a flag here disagrees with `mcue --help`, trust the binary. --- # Get started with mcue: save, plan and use the Hub Pick a chat where you're already working on something. Save where you are, open a fresh chat, and carry on. You'll see the benefit in this sitting. Start with [save and resume](#1-save-where-you-are). Continue with [plans](#3-turn-the-next-piece-of-work-into-a-plan), [worked use cases](#examples-for-your-own-work), or [the Hub](#use-the-hub). The [CLI walkthrough](#using-mcue-plan-in-the-terminal) is on this page too. You can stop after your first useful continuation and return to the rest when you need it. ## Connect once Already connected to mcue? Go straight to step 1. Otherwise, [connect mcue to your chat app](/docs/reference/mcp#connecting-a-client-to-the-hosted-endpoint) and sign in with an account admitted to the alpha. Once signed in, the app can save work to your own projects; [you can restrict or revoke it](#connect-your-chat-app) at any time. The hosted route needs no terminal. If access is blocked, use the access request shown by Hub before continuing. ## 1. Save where you are Paste this into your existing conversation: > Help me continue this work in a fresh chat using mcue. Briefly show what we're doing, what we've decided, what's still open, and the next step. Keep suggestions separate from decisions. Reuse the right project if it exists; otherwise propose creating one. Show me where you'll save this and wait for my approval. Check that it got the work right. Correct anything missing or wrong, then reply: > Save it. Confirm the save with mcue and read it back to check it matches. Then give me one ready-to-paste prompt for a fresh chat that resumes this exact work and helps me take the next step. Fill in the saved project and lane for me. If anything fails, tell me what needs fixing. Wait for the confirmed save and your resume prompt. ## 2. Open a fresh chat and carry on Open a new conversation in the same connected app and paste the prompt it gave you. The new chat should pick up your next step and keep the decisions you've already made. Do the next small piece of work together. You shouldn't need to paste your old conversation or explain the project again. That's the first success: you're continuing real work in a new chat. If it gets something wrong or can't open a needed file, tell it what stopped you. mcue saves the work's state; files still need to be accessible in the new chat. ## 3. Turn the next piece of work into a plan A closeout records what happened and where to pick up. A plan keeps the steps you're working through and their progress. Use one when the next piece of work needs more than a single action. Continue in the same chat: > Read this project's current mcue state and active plan. If there's already a plan for this work, show me where we are in it. Otherwise, propose a short plan for the next useful result, with a clear finish condition for each step. Use the same project and lane. Show it to me before saving. For example, a plan for a one-page project brief could be: ```markdown # Write the project brief ## Objective Produce a one-page brief that makes the problem, scope and next action clear. ## Plan Steps - [ ] Agree the problem, audience and scope in an outline. - [ ] Draft the brief from the agreed outline. - [ ] Check the draft against the scope and resolve open comments. ``` Use your actual work; this is only an example. Adjust the steps, then say: > Save this approved plan in mcue and confirm it was created. Read back its progress and current step. Keep using our existing project and lane. You should see a saved plan with zero completed steps and the first step current. A checklist printed in chat is only a draft until mcue accepts it. Each lane holds one active plan; if one already exists, continue it or explicitly decide to replace it. If the agent says its connection cannot create plans, use the terminal route below or a client exposing the hosted plan-creation tool. Saving an ordinary closeout doesn't create an active plan. ## 4. Work a step, then save the progress Ask the agent to help with the current step. For the example, agree the outline before calling step 1 done. When that step's finish condition is met, say: > Prepare a closeout for the work we just did. Include the result, where to find it, anything unresolved and the next action. Propose marking the current plan step done only if its finish condition is met. Show me the closeout and plan change before saving. Check the proposal, then reply: > Save the closeout with that plan update. Read back the saved progress and current step, and give me an updated ready-to-paste resume prompt. For the example, completing the outline should leave **1 of 3 steps done**, with drafting current. The closeout carries the agreed outline or a reference the next chat can access. Use `in_progress` when you stop halfway through a step. Use `blocked` when you can't proceed, and record what would unblock it. Neither means done. For example: “The outline is blocked until we choose the audience; save that and make choosing the audience the next action.” Review and save the proposed update as above. ## 5. Resume the plan in another chat Open a fresh connected chat and paste the updated resume prompt. Then ask: > Read the saved plan progress and current step. Check the last closeout and the referenced work, then help me continue that step. Keep completed decisions unless I ask to revisit them. If something needed is missing, tell me before proceeding. In the example, the new chat should start drafting from the agreed outline, with step 1 still complete. You shouldn't need to explain the outline again. This is the plan's payoff: the sequence, progress and work stay connected across sessions. ## 6. Finish or change the plan Repeat work → reviewed closeout → progress update as you go. After the final check, save the final result and mark the last step done. All steps being checked doesn't automatically archive the plan. When you're ready to retire it, archive the plan as `done` using the terminal command below. If you change direction, archive it as `abandoned` with a reason before creating its replacement. Closed plans remain available as history; closing a plan doesn't close the project or its lane. In a chat-only client, finish the steps and record the outcome. Archiving the plan currently needs the CLI; ask the agent to prepare the exact command for the saved project and lane. You can keep working without archiving immediately. The current plan-update command changes progress, notes and blockers; it doesn't rewrite the step list. ## Examples for your own work The project-brief example above follows outline → draft → review. The same pattern works for research, code and projects that span many sessions. These are illustrative records: replace their results with what actually happened in your work. ### Research: compare papers without restarting the review You have a chat comparing papers on a research question. Some sources have been checked; others are still leads. **Plan:** agree the comparison question and criteria → extract evidence from selected papers → write the comparison and identify gaps. **Example closeout:** “Question and criteria agreed. Evidence extracted from papers A and B into the comparison table; paper C hasn't been checked. Step 1 is done; step 2 is in progress. Next: read C's methods section against the same criteria.” Include the table and source references, or accessible links. **Try this:** > Prepare a mcue plan for this comparison. Keep checked findings separate from unverified leads. Show which step we're on and what would count as finishing it. Let me review before saving. **Fresh-chat payoff:** the agent continues with paper C using your criteria. It doesn't treat a lead as an established result or ask you to reconstruct the comparison. ### Software: carry a bug investigation into a fresh coding session You reproduced a bug and ruled out one cause. The fix is still open. **Plan:** reproduce with a failing check → implement the fix → rerun the check and relevant regression tests. **Example closeout:** “Reproduced in `tests/refunds_test.go`; the empty-input case fails. Configuration mismatch ruled out. Step 1 done; step 2 current. Next: inspect the empty-input branch in `refunds.go`.” Record the actual command and result, plus the branch or working directory needed to continue. **Try this:** > Prepare a closeout and plan update for this investigation. Preserve the reproduction, what we ruled out, and the next code path to inspect. Don't mark the fix complete while verification is outstanding. Show me before saving. **Fresh-chat payoff:** the next agent opens the reproduction and investigates the remaining cause. It still needs access to the repository; Hub doesn't upload that code for it. ### Longer project: prepare a workshop across several sessions You've agreed the workshop audience and learning outcome. Exercises and timing still need work. **Plan:** agree audience and outcome → draft the session and exercises → rehearse and revise the timing. **Example closeout:** “Audience and outcome agreed. First exercise drafted; second still missing. Step 1 done; step 2 in progress. Keep the session to 45 minutes. Next: draft the second exercise using the same example.” Reference the working document. **Try this:** > Resume our workshop project and use its saved plan. Keep the agreed audience, learning outcome and time limit. Help me finish the current step, then propose a closeout for review. **Fresh-chat payoff:** you work on the second exercise immediately. When you're ready to rehearse, the plan advances without losing the constraints agreed in an earlier session. ## Use the Hub The [Hub](https://hub.mcue.dev) keeps saved project state reachable from connected clients and gives you a browser view of projects, plans and closeouts. Local-only CLI use is also available; connect to Hub when you want that state accessible across chats or machines. ### Open or create your project 1. Sign in to the Hub with your admitted alpha account. If it asks for access, complete the invitation/access step first. 2. Open [Projects](https://hub.mcue.dev/projects). If the earlier chat already created your project, open that one. 3. To start in the browser instead, choose **New project**. Enter a short **Project ID**, a **Name**, an **Objective** and a **Category**. For the worked example: `project-brief`, “Project brief”, “Produce a one-page brief with an agreed scope and next action”, and `work`. 4. Choose **Create project**. You can use it from connected chat clients immediately; no repository or CLI installation is required for this route. Use the existing default lane for your first sequence of work. A lane is a separately resumable stream inside a project; add another only when you have work with its own next action and progress to track. ### Connect your chat app Add mcue in your app's MCP/connector settings using `https://api.mcue.dev/mcp`, then complete the browser sign-in. The [client connection guide](/docs/reference/mcp#connecting-a-client-to-the-hosted-endpoint) covers the supported setup routes. Exact menus vary by client. Ask the connected agent to read your mcue projects, then return to the chat and save the reviewed closeout from step 1. A client you connect can read and write the projects you own, and create new ones, straight away; there is no separate step to allow saves. You narrow a client under [Connections](https://hub.mcue.dev/connections) → **Account access**: **Restrict to read** or **Revoke** stops it writing to your projects and creating new ones, while it can still read them. To narrow a client on one project only, or cut it off from that project entirely, open the project in Hub and use **MCP client grants**; a project setting takes precedence over account access. A write from a restricted client is refused with a message naming the client and where to change it. ### See your saved work and plan From Projects, open your project and then **Open lane** on the stream you're working on. Check: | In the Hub | What to look for | |---|---| | Objective and Next move | The goal and next action you just saved | | Active plan | The checklist, current step and completed count; after the outline example, 1 of 3 done | | Resume packet | A compact summary of where to pick up, with **Copy packet** | | Lane activity | The accepted writes that reached Hub | Use the connected-chat resume prompt to fetch current state in a new conversation. **Copy packet** is also useful when carrying a snapshot into a client without the connection; paste it and ask the agent to continue. A copied packet doesn't provide a live connection or save subsequent work back to mcue. Create plans through your connected agent or the CLI. The browser's **Active plan** panel shows progress; it isn't a plan editor. If a local change is missing in Hub, sync the project before expecting it to appear. ### Save a closeout directly in the browser You can record work done outside an AI chat. Open the lane and find **Close out this lane**. Fill in **Intent**, **Outcome**, **Blockers**, **Next action** and **Resume pointer**, then review and choose **Write closeout**. For example, after an offline workshop rehearsal: intent “Check the session fits”; outcome “Rehearsal took 52 minutes”; blocker “Need to cut seven minutes”; next action “Shorten the second exercise”; resume pointer to your rehearsal notes. Use your real observations. Wait for the success result and check the saved next move. The browser form records the closeout but doesn't offer plan-step controls; use the connected agent or CLI when you also need to advance a plan step. Save only to the lane the work belongs to. ### Move between Hub and local work For a project already in Hub, install the CLI, then run: ```bash mcue hub set https://api.mcue.dev mcue login mcue whoami mcue clone project-brief ``` Replace `project-brief` with your project's ID. If it's already local and linked, use `mcue sync project-brief` instead of cloning again. Run `mcue attach project-brief` from the working directory if you want that directory to identify the project automatically. Cloning brings mcue state locally; acquire source files separately. For an existing local project that hasn't been linked to Hub, configure the endpoint and log in as above, then run `mcue publish project-brief`. In mcue, this creates a **private Hub project** and sends its operating state, including plans and closeouts. It doesn't publish a public page or upload your source repository. Use this route only when you intend to send that project's state to Hub. Before changing machines or returning to a hosted chat, run `mcue sync project-brief` and check the result. `mcue sync status project-brief` shows the local cursor and pending changes; it doesn't contact Hub by itself. Keep unresolved local/Hub differences visible rather than assuming both sides match. ## Using mcue plan in the terminal These are the same operations expressed as commands. Use your existing local project and its actual lane. The example below assumes a project called `project-brief` with its `default` lane; replace those two names if yours differ. If your project only exists in Hub, follow the [local setup guide](/docs/quickstart) and bring that existing project locally first. Save the three-step Markdown example above as `brief-plan.md` in your working directory. Creating the plan imports that file into mcue; later edits to the source file don't update the saved plan. ```bash mcue plan create project-brief --lane default --from-file brief-plan.md --title "Write the project brief" mcue plan show project-brief --lane default ``` If an agent authors the plan, it adds `--provenance agent` to the create command. An existing active plan must be handled before creating another. Mark step 1 in progress when you begin: ```bash mcue plan update project-brief --lane default --step 1 --status in_progress ``` After you actually agree the outline, record both the outcome and progress together. Substitute your real result and artifact path: ```bash mcue closeout project-brief --lane default \ --intent "Agree the brief outline" \ --outcome "Problem, audience and scope agreed in outline.md" \ --next-action "Draft the brief from the agreed outline" \ --resume-pointer "outline.md" \ --plan-step 1 --plan-status done mcue plan show project-brief --lane default mcue resume project-brief --lane default --tier expanded ``` An agent-authored closeout adds `--provenance agent`. Expected result: 1/3 complete, step 2 current, with the outline available as the starting point. If step 2 becomes blocked, record the actual reason. This standalone update doesn't create a session closeout: ```bash mcue plan update project-brief --lane default --step 2 --status blocked \ --blocker "Need an agreed word limit before drafting" ``` Once resolved, select the step again and record the resolution: ```bash mcue plan update project-brief --lane default --step 2 --status in_progress \ --note "Word limit agreed: 500 words; previous blocker resolved" ``` Blocker entries are retained in the plan's history; this adds the resolution rather than erasing the old entry. Use a closeout when the change also needs to update the lane's next action and blockers. Continue the actual work, using closeouts with `--plan-step 2` and then `--plan-step 3` when those steps are done. Once all three steps are complete: ```bash mcue plan close project-brief --lane default --status done --note "Brief checked against agreed scope" mcue plan list project-brief --lane default --all ``` To retire a superseded plan, use `--status abandoned` and a note explaining the change. To inspect a closed plan, copy its plan ID from the list and run `mcue plan show project-brief --lane default --archived PLAN_ID`. For a Hub-linked local project, standalone plan commands leave changes pending for sync. Run `mcue sync project-brief` before switching to a hosted chat. A linked closeout attempts sync automatically; check its result. If sync fails, the local save and Hub state may differ. ## Keep using it Start a session by resuming the relevant work. Use the plan to choose the next step. End meaningful work with a reviewed closeout that records both the result and any plan progress. Ask the agent for the next chat's prompt whenever you switch. --- # What mcue can do This is the complete feature map for mcue v0.18. It describes the whole product, not only the everyday closeout-and-resume loop. For exact arguments and flags, use the [CLI reference](/docs/reference/cli) or `mcue <command> --help`. ## The local operating-state loop mcue records the operating state of a project's work: what you intended to do, what happened, the decisions and blockers that matter, and the next concrete action. A closeout writes an immutable checkpoint and refreshes the project's governed state; a resume turns that state into a bounded re-entry packet. ```bash mcue init payments-api --name "Payments API" mcue closeout payments-api mcue resume payments-api mcue index ``` The state is local by default. It lives as readable Markdown with YAML front matter under `$MCUE_HOME` (normally `~/.mcue`), outside the source repository. mcue does not copy, commit, or modify source code. ## Structure and lifecycle - **Projects** are the unit of registration, state, and resume. They can be anchored to a work tree with a `.mcue` footprint, updated, renamed, archived, or deliberately hard-deleted. - **Lanes** separate concurrent strands of attention within one project. Every project begins with a default lane; named lanes have their own state, plans, and checkpoint history. A lane is not a Git branch. - **Plans** are lane-scoped active sequences. They can be created, viewed, updated, closed into history, listed, or deliberately hard-deleted. - **Portfolio views** let you inspect all active projects or explicitly named projects; a named project remains visible even if it is archived or closed. ## Trust, recovery, and operator visibility mcue is designed to make its state inspectable and recoverable rather than magical. - Checkpoints are immutable and browseable through project history. - `review` provides an inspection surface without a new closeout. - `drift` reports warning-only changes in the recorded working environment. - `recover` turns an interrupted closeout into an explicit degraded checkpoint; it does not silently invent a normal one. - `audit` reads the append-only local write log. - `reconcile` resolves a lane that contains multiple unreconciled perspectives. - `doctor` diagnoses the local installation, while `identity` shows or overrides the operator and machine identity used in state. - Migration commands safely bring state written by older mcue releases forward. ## Agents and MCP Agents can use the same governed state rather than maintaining a separate memory file. `mcue serve` exposes the MCP read/write surface as a local stdio server or authenticated HTTP service. `mcue agents-snippet` emits the canonical access rules for an `AGENTS.md` or `CLAUDE.md`; `token` manages bearer tokens for the authenticated surface. Pass `--agent` (or set `MCUE_AGENT_MODE=1`) to scrub home-directory paths from CLI output before putting it into shared artifacts. ## Managed Hub Hub is optional: local mcue remains fully useful without an account or network. When connected, Hub keeps governed state available while this machine is off. - OAuth authorization-code login with PKCE; credentials stay in the operating system credential store. - Publish local projects to create a Hub replica, clone a Hub project onto a machine, and synchronize accepted state in either direction. - A durable local outbox records linked-project changes immediately, including while offline. `sync status` reads cursor and pending-operation state without a network request. - Sync uses cursors and explicit conflicts rather than last-write-wins. It advances the accepted replica and preserves still-pending local intentions for the next attempt. - `unlink` removes only this machine's Hub link and outbox; it leaves both local state and the Hub project intact. - `observe` collects Git evidence for a linked project's lanes and compares it with the checkpoints Hub has accepted. `--upload` submits that evidence to Hub; it never syncs pending operating state. Hub synchronizes only mcue state beneath `$MCUE_HOME`. It never uploads or mutates the source repository. ## BYO-S3 remote The `remote` namespace is a separate, account-free cross-machine path for an S3-compatible bucket you control. It can enable or disable a project remote, inspect its status, push and pull perspectives, rotate stored credentials, compare conflicting bytes, and force-push one confirmed perspective. It is independent of the managed Hub. ## Complete command coverage Every v0.18 command belongs to one of these groups. This section is deliberately exhaustive; the [CLI reference](/docs/reference/cli) supplies the per-command purpose and the binary supplies authoritative flags. | Area | Commands | |---|---| | Project lifecycle | `init`, `attach`, `detach`, `exists`, `update`, `project rename`, `project archive`, `project delete` | | Session loop and repair | `closeout`, `resume`, `index`, `review`, `history`, `drift`, `recover`, `reconcile` | | Lanes and plans | `lane create`, `lane close`, `lane update`, `lane delete`, `plan create`, `plan show`, `plan list`, `plan update`, `plan close`, `plan delete` | | Managed Hub | `hub set`, `hub status`, `login`, `logout`, `whoami`, `publish`, `clone`, `sync`, `sync status`, `unlink`, `observe` | | BYO-S3 remote | `remote enable`, `remote disable`, `remote status`, `remote push`, `remote pull`, `remote rotate`, `remote diff`, `remote force-push` | | Agents and MCP | `serve`, `agents-snippet`, `token issue`, `token list`, `token rotate`, `token revoke` | | Identity and diagnostics | `identity show`, `identity set`, `doctor`, `audit` | | Migrations | `migrate-lanes`, `migrate-objectives` | ## What mcue deliberately does not do mcue is not a project-management suite, a notes archive, a specification library, or a replacement for Git. It owns current operating state and bounded re-entry; source history stays in Git and durable project artifacts stay where the project already keeps them. Read [Operating state](/docs/concepts/operating-state) for that boundary, or [Why not a notes file?](/docs/concepts/why-not-a-notes-file) for when a plain file is the better tool. --- # Install mcue is a single static binary with no runtime dependencies, no daemon, and no configuration file to write before it works. During the alpha, downloads are unlocked with a personal key that comes with your invite. Once installed, mcue needs no account and contacts no server until you ask it to. If you would rather not install anything, start in the browser with Hub instead: the same invite gives you Hub access, and the CLI can join later. ## macOS and Linux Run the installer with the key from your invite: ```bash curl -fsSL https://mcue.dev/install.sh | MCUE_DOWNLOAD_KEY= sh ``` It installs the latest release for your machine into `~/.local/bin`. Set `MCUE_INSTALL_DIR` to put it somewhere else, and make sure that directory is on your `PATH`. To upgrade, run the same command again. ## Windows and direct downloads The [download page](/download) takes your key and offers the prebuilt binaries for macOS, Linux, and Windows directly. ## No key yet? Keys come with alpha invites. [Request alpha access](https://hub.mcue.dev/join), and you get Hub access and a download key together. The key is personal; please do not share it. ## Confirm the install ```bash mcue doctor ``` `doctor` prints install diagnostics: the resolved binary, the version, where `$MCUE_HOME` points, and whether the state directory is readable and writable. It makes no network request. Run it first whenever something behaves unexpectedly — it answers "is this even the binary I think it is?" faster than anything else. ## Where state lives By default mcue keeps everything under `~/.mcue`. Override it by exporting `MCUE_HOME` before running any command: ```bash export MCUE_HOME="$HOME/work/.mcue-state" ``` Point `MCUE_HOME` somewhere backed up and versioned if you want history beyond what mcue itself keeps. The full layout is documented in [Files on disk](/docs/reference/files). ## What installation does not do - It does not create an account. The download key unlocks the download only. - It does not make a network request. mcue stays offline until you explicitly run `mcue login`, `mcue publish`, or `mcue sync`, or configure a BYO-S3 remote. - It does not touch your repositories. mcue writes only beneath `$MCUE_HOME`, plus a small `.mcue` footprint file in a directory when you run `mcue attach`. - It does not send telemetry. There is none to disable. --- # Quickstart This runs the whole local loop once, end to end. It takes about five minutes, makes no network request, and leaves you with real state you can inspect in a text editor afterwards. You need mcue on your `PATH` — see [Install](/docs/install) if `mcue doctor` does not answer. ## 1. Register a project Change into a directory you actually work in, then: ```bash cd ~/work/payments-api mcue init payments-api --name "Payments API" ``` `init` registers the project, scaffolds its state files under `$MCUE_HOME`, and drops a small `.mcue` footprint in the current directory so later commands can tell which project you are in without being told. The positional argument (`payments-api`) is the stable project id; `--name` sets the display name ("Payments API" here). `--name` is optional from v0.14.1 and defaults to the id; before v0.14.1 it is required, and a bare `mcue init payments-api` fails with `required flag(s) "name" not set`. The project id is yours to choose. Keep it short and stable — it appears in every later command, and renaming later means `mcue project rename`. ## 2. Do some work Nothing to run here. Write code, break something, fix it, get interrupted. mcue is not watching; it only records what you tell it at the end. ## 3. Close out the session This is the command that matters: A closeout records five things: what you intended, what actually happened, anything blocking, the next action, and where to resume. They are flags, so a real one looks like this: ```bash mcue closeout payments-api \ --intent "Wire refunds to the ledger" \ --outcome "Ledger client assumes idempotency keys are UUIDs; ours are ULIDs, so every retry double-posts. Refund path itself is written but unusable until the key format is settled." \ --blockers "Whether to change our key format or wrap the ledger client" \ --next-action "Ask Sam which one the ledger team will support" \ --resume-pointer "internal/ledger/client.go:88, TestRefundRetry fails" ``` ```text Checkpoint written: ~/.mcue/projects/payments-api/checkpoints/20260817T173512Z.md Lane: default Project state refreshed for "payments-api" Scores: clarity high | cost low | trust medium | quality high (100/100) ``` If you would rather write prose than assemble flags, `mcue closeout payments-api --editor` opens your editor with the five fields laid out, and `--outcome-from-file ./notes.md` reads any of them from disk. Answer honestly and briefly — a closeout that says "fixed the thing" is worth nothing in three weeks, and the score on that last line will tell you so. The gap between intent and outcome is the most valuable part: this one records that the session did not do what it set out to do, and exactly why. A closeout writes a timestamped checkpoint and refreshes the project's governed state. It is the only routine way state advances. ## 4. Come back later Days pass. Come back and ask for a way in: ```bash mcue resume payments-api ``` You get a **resume packet**: a bounded brief capped at roughly 300 or 1000 tokens depending on the tier you ask for. Small enough to hand straight to an agent, big enough to re-enter without re-reading everything. That cap is deliberate. An unbounded dump of project history is exactly as useless as no history at all. ## 5. See everything at once ```bash mcue index ``` The derived portfolio view across every registered project — what is active, what is blocked, what has gone quiet. Name a project to scope it to that one: ```bash mcue index payments-api ``` ## 6. Read the state yourself Nothing here is opaque: ```bash ls ~/.mcue/projects/payments-api/ cat ~/.mcue/projects/payments-api/project_state.md ``` Markdown with YAML front matter. Diffable, greppable, and editable by hand when something needs repairing. If mcue vanished tomorrow, your state would still be readable. ## Where to go next - [Close out and resume](/docs/guides/closeout-and-resume) — how to write a closeout worth resuming from. - [Give agents your state](/docs/guides/agents-and-mcp) — expose this same surface over MCP. - [Operating state](/docs/concepts/operating-state) — the model underneath all of it. - [Publish to Hub](/docs/guides/publish-to-hub) — optional, when you want state reachable with the machine off. --- # Close out and resume Everything else in mcue is scaffolding around these two commands. A closeout is the only routine way state advances; a resume packet is the only thing you read when coming back. ## Closing out ```bash mcue closeout payments-api --editor ``` A closeout records five things, and each one earns its place: - **Intent** — what you set out to do. Not what you did; what you meant to. - **Outcome** — what actually happened, including the part that did not work. - **Blockers** — what is in the way, stated concretely enough to act on. - **Next action** — the single next thing, small enough to start cold. - **Resume pointer** — the file, the branch, the failing test, the open tab. The gap between intent and outcome is the most valuable field in the whole system. It is where "I meant to add caching but spent four hours on a connection-pool bug" gets recorded, and that sentence is worth more in three weeks than any diff. `closeout` does not interrogate you. `--editor` opens the five fields in your editor; otherwise pass them as flags (`--intent`, `--outcome`, `--blockers`, `--next-action`, `--resume-pointer`), read any of them from disk with `--intent-from-file` and friends, or pipe a whole payload with `--from-stdin-json`. [A week with mcue](/docs/guides/a-week-with-mcue) shows all of it against real output. ### Writing one worth reading A closeout is written for a stranger, and in three weeks you are that stranger. **Weak:** > Worked on refunds. Made progress. Continue tomorrow. **Useful:** > Intended to wire refunds to the ledger. Ledger client assumes idempotency keys > are UUIDs; ours are ULIDs, so every retry double-posts. Blocked on whether to > change our key format or wrap the client. Next: ask Sam which one the ledger team > will support. Resume at `internal/ledger/client.go:88`, test > `TestRefundRetry` currently fails. The second one takes ninety seconds longer to write and saves an afternoon. ### Partial and interrupted closeouts If a closeout is interrupted, mcue does not leave you with a half-written record. See [Recover a broken session](/docs/guides/recovery) — `mcue recover` produces a degraded checkpoint, and `closeout --retroactive` captures a session you already walked away from. ## Resuming ```bash mcue resume payments-api ``` You get a **resume packet**: a bounded brief capped at roughly 300 or 1000 tokens depending on the tier you ask for. The cap is the point. An unbounded dump of project history costs you the same re-reading you were trying to avoid, and it is useless to an agent with a context budget. A packet is meant to be small enough to paste into a conversation and complete enough to act on. A packet is derived on demand, never stored as truth. Improving how packets are assembled never rewrites your history. ## Looking without closing out Two commands read state without advancing it: ```bash mcue review payments-api # inspect state without a full closeout mcue history payments-api # browse the checkpoint history ``` `review` is the one to reach for mid-session when you want to see where things stand. It changes nothing. ## Updating metadata without a closeout ```bash mcue update payments-api ``` Changes mutable project metadata without writing a checkpoint. Use it for corrections — a wrong title, a stale description — not for recording work. Work belongs in a closeout. ## A rhythm that works - Close out when you stop, not when you finish. Most sessions do not finish. - Close out before a context switch, even a short one. The cost of writing it is lower than the cost of reconstructing it. - Resume before you open the editor. Reading the packet first is what stops you re-deriving yesterday's conclusion. - Run `mcue index` on Monday to see what has gone quiet. ## Next - [Give agents your state](/docs/guides/agents-and-mcp) — hand the same packet to an agent. - [Projects, lanes, and plans](/docs/concepts/projects-lanes-plans) — when one lane stops being enough. --- # A week with mcue Every other page here explains one command. This one runs a whole week on a single project and shows what each command actually prints. Nothing is elided and nothing is idealised — the Wednesday session gets interrupted, and you can see what that costs in the record. The project is `payments-api`. The work is wiring refunds to a ledger service. You can follow along in any directory; nothing here touches your repository. ## Monday — register and do the first real session ```bash cd ~/work/payments-api mcue init payments-api --name "Payments API" --category infrastructure ``` ```text Identity created: operator you@example.com on machine ed49f65e55866875997784799291f2a8 Project "payments-api" initialized at ~/.mcue/projects/payments-api anchored at ~/work/payments-api/.mcue ``` Then you work for four hours. You meant to wire refunds to the ledger. What actually happened is that the ledger client assumes idempotency keys are UUIDs and yours are ULIDs, so every retry double-posts. At the end of the session: ```bash mcue closeout payments-api \ --intent "Wire refunds to the ledger" \ --outcome "Ledger client assumes idempotency keys are UUIDs; ours are ULIDs, so every retry double-posts. Refund path itself is written but unusable until the key format is settled." \ --blockers "Whether to change our key format or wrap the ledger client" \ --next-action "Ask Sam which one the ledger team will support" \ --resume-pointer "internal/ledger/client.go:88, TestRefundRetry fails" ``` ```text Checkpoint written: ~/.mcue/projects/payments-api/checkpoints/20260817T173512Z.md Lane: default Project state refreshed for "payments-api" Scores: clarity high | cost low | trust medium | quality high (100/100) ``` `closeout` takes its five fields as flags. There is no interactive questionnaire — if you would rather write prose in your editor, `mcue closeout payments-api --editor` opens one, and `--intent-from-file` and friends read from disk. Note the last line. The checkpoint is scored as it is written, and this one scores 100 because every field was answered with something a stranger could act on. ## Wednesday — resume, then get interrupted Two days later you have forgotten the specifics. Do not open the editor first: ```bash mcue resume payments-api ``` ```text # Resume: payments-api **Lane:** default **Next:** Ask Sam which one the ledger team will support **Blockers:** Whether to change our key format or wrap the ledger client **Resume at:** internal/ledger/client.go:88, TestRefundRetry fails **Clarity:** high | **Cost:** low | **Fresh:** fresh | **Trust:** medium | **Quality:** high **Drift:** unknown - no Git repository observer configured ``` That is the default `minimal` tier — 98 tokens, and it is enough to start. You know the question to ask, the decision that is pending, and the line to open. Sam says the ledger team will not change the key format. So you write a wrapper. The targeted test passes. Then the checkout incident starts and you are gone for the rest of the day. The next morning you can record Wednesday honestly, but you cannot claim the work is verified, because you never ran the full suite: ```bash mcue closeout payments-api --degraded \ --intent "Wrap the ledger client so ULIDs survive a retry" \ --outcome "Wrapper exists and TestRefundRetry passes, but I was pulled into the checkout incident before running the full suite" \ --next-action "Run the full payments suite against the wrapper" \ --resume-pointer "internal/ledger/idempotency.go:24" ``` ```text Checkpoint written: ~/.mcue/projects/payments-api/checkpoints/20260819T164402Z.md Lane: default Project state refreshed for "payments-api" Scores: clarity high | cost medium | trust low | quality medium (51/100) ``` **This is the part worth reading twice.** The same command with `--degraded` scored 51 instead of 100, dropped trust to `low`, and raised resume cost to `medium`. That is not a punishment. It is the record telling the truth about itself, so that future-you does not treat a half-finished session as a finished one. Inventing "ran the suite, all green" would have scored better and been worth less than nothing. ## Friday — the packet warns you before you act ```bash mcue resume payments-api ``` ```text # Resume: payments-api **Lane:** default **Next:** Run the full payments suite against the wrapper **Blockers:** (none) **Resume at:** internal/ledger/idempotency.go:24 **Clarity:** high | **Cost:** medium | **Fresh:** fresh | **Trust:** low (degraded, low confidence) | **Quality:** medium **Drift:** unknown - no Git repository observer configured ``` `Trust: low (degraded, low confidence)` is the marker doing its job. Before you build on Wednesday's work, the packet has already told you Wednesday was partial. You run the suite. It is green. You also have a decision worth keeping, so you promote it: ```bash mcue closeout payments-api \ --intent "Run the full payments suite against the ledger wrapper" \ --outcome "Suite green. The wrapper normalises ULIDs to the ledger's UUID namespace at the boundary, so retries are idempotent end to end. Sam confirmed the ledger team will not change the key format, which settles Monday's blocker." \ --next-action "Delete the feature flag and ship the refund path" \ --resume-pointer "internal/ledger/idempotency.go:24, flag payments.refund_v2" \ --promotions "Ledger keys stay UUID; we normalise at the boundary rather than changing our ULID format" ``` ```text Checkpoint written: ~/.mcue/projects/payments-api/checkpoints/20260821T151130Z.md Lane: default Project state refreshed for "payments-api" Scores: clarity high | cost low | trust medium | quality high (85/100) ``` Trust returns to `medium` and cost falls back to `low`. The lane is healthy again because the latest session actually was. ## What the week left on disk ```bash ls ~/.mcue/projects/payments-api/ ``` ```text checkpoints decisions.log lanes project_state.md ``` ```bash ls ~/.mcue/projects/payments-api/checkpoints/ ``` ```text 20260817T173512Z.md 20260819T164402Z.md 20260821T151130Z.md ``` Three sessions, three append-only files. The Wednesday one still says what it is: ```bash cat ~/.mcue/projects/payments-api/checkpoints/20260819T164402Z.md ``` ```text --- project_id: payments-api lane_id: default timestamp: "2026-08-19T16:44:02Z" provenance: human confidence: low mode: degraded quality_score: 51 --- ## Intent Wrap the ledger client so ULIDs survive a retry ## Outcome Wrapper exists and TestRefundRetry passes, but I was pulled into the checkout incident before running the full suite ## Blockers (none) ## Next Action Run the full payments suite against the wrapper ## Resume Pointer internal/ledger/idempotency.go:24 ## Promotion Candidates (none) ``` `mode: degraded` is in the file itself, not in a database somewhere. Friday's promotion landed in its own log: ```bash cat ~/.mcue/projects/payments-api/decisions.log ``` ```text # Decisions Log: payments-api ## 2026-08-21T15:11:30Z - Promoted from checkpoint - project_id: payments-api - source_checkpoint: ~/.mcue/projects/payments-api/checkpoints/20260821T151130Z.md - lane_id: default - provenance: human - confidence: medium - decision: Ledger keys stay UUID; we normalise at the boundary rather than changing our ULID format ``` In three weeks, when someone asks why refund keys are normalised at the boundary, that line is the answer and it points at the session that produced it. ## Monday again ```bash mcue index ``` ```text PROJECT STATUS LANES NEXT ACTION CLARITY COST LAST TOUCHED STALE --------------------------------------------------------------------------------------------------------------------------- payments-api active 1 Delete the feature flag and ship the ... high low 2026-08-21T15:11:30Z ``` One project, so this is a small table. With fifteen it is the only view that tells you which work has gone quiet — the `STALE` column fills in for anything you have not touched, and that is usually the thing you were avoiding. ## What to take from the week - **The three closeouts cost about ninety seconds each.** The Wednesday resume saved an afternoon of re-deriving Monday's conclusion. - **The degraded checkpoint is the most valuable one.** It is the only record that admits uncertainty, and it is the one that stopped you building on unverified work on Friday. - **Nothing here required a network, an account, or a running daemon.** The whole week is files under `$MCUE_HOME`. - **The scores are feedback, not gamification.** A closeout that scores badly is usually telling you the next action is not small enough to start cold. ## Next - [Recover a broken session](/docs/guides/recovery) — the other two recovery paths, `recover` and `--retroactive`. - [Give agents your state](/docs/guides/agents-and-mcp) — hand that Friday packet to an agent instead of reading it yourself. - [Why not a notes file?](/docs/concepts/why-not-a-notes-file) — the honest version of the obvious objection. --- # Give agents your state An agent that cannot see what you were trying to do will confidently redo work you already abandoned. mcue exposes the same validated read and write surface over MCP that the CLI uses — not a second, looser path into your state. ## Run the local server ```bash mcue serve --mcp ``` That speaks MCP over stdio, which is what most desktop clients expect. It runs entirely locally and makes no outbound request. For clients that need HTTP instead of stdio, `mcue serve` also exposes an authenticated HTTP surface. Run `mcue serve --help` for the current flags — the address and transport options are the two you will care about. ## Connect a client to the local server Desktop clients launch the server themselves over stdio. Each one needs the same line: the command is `mcue`, the arguments are `serve --mcp`. **Claude Code.** ```bash claude mcp add mcue -- mcue serve --mcp ``` **Claude Desktop**, in `claude_desktop_config.json`, and **Cursor**, in `~/.cursor/mcp.json`: ```json { "mcpServers": { "mcue": { "command": "mcue", "args": ["serve", "--mcp"] } } } ``` Browser clients such as Claude.ai and ChatGPT cannot launch a process on your machine. They connect to Hub's hosted endpoint instead — see [Connecting a client to the hosted endpoint](/docs/reference/mcp#connecting-a-client-to-the-hosted-endpoint). ## Authenticating an HTTP client The HTTP surface is bearer-authenticated, and mcue manages those tokens for you: ```bash mcue token issue # issue a new bearer token mcue token list # ids, scopes, status — never the plaintext mcue token rotate # revoke and reissue with the same scope mcue token revoke # revoke by id ``` `mcue token list` deliberately never prints the plaintext token. If you lose one, rotate it rather than trying to recover it. ## Teaching the agent the rules Agents behave much better when the repository tells them how mcue is meant to be used. mcue emits that snippet for you: ```bash mcue agents-snippet >> AGENTS.md ``` The same snippet works in `CLAUDE.md` or any equivalent instruction file. It describes the access rules — what the agent may read, when it should close out, and what it must not invent. The snippet opens with a short procedure the agent must run before any project work: find the project, discover its lanes, select the lane by what you asked for now, read that lane's packet, and only then open the code. It also says that your current request decides the work — a recorded next action is context, not an instruction — and that local and Hub state are separate sources whose disagreement must stay visible. Two habits make lane fit visible without a checklist. The agent says in one line which lane it is using when it selects or switches, so a wrong assumption surfaces before the work. And before proposing a closeout it compares the work with the lane's objective: it does not stretch the objective to fit, it routes the closeout to the lane the work belongs to, and a session that produced work for two streams gets two closeouts. To make that selection cheap, `mcue review` and `mcue index --expand-lanes` print each lane's objective. **Where the file goes, and how to check it loaded.** Codex, Cursor, and Aider read `AGENTS.md`; Claude Code reads `CLAUDE.md`. Put the snippet in the file your client reads, at the root of the repository the agent starts in. A file at a workspace root is not loaded when the agent starts inside a child repository, so each repository that carries mcue state needs its own copy, or a one-line file that points at the root one. To verify, open a fresh chat and ask: "what is the first thing you do before project work here?" The answer should be the start-here procedure, given without a search. If the agent searches the repo to answer, the file is not being loaded. An agent connected over MCP does not need the file. Since v0.14.0 the server sends the same contract as MCP server instructions during the handshake and serves it as the `mcue://agents` resource, so a client that has never seen mcue learns the vocabulary and the read-first, close-out-at-ship rules before its first tool call. The hosted Hub endpoint carries the same instructions. Keep the repo file for agents that reach mcue through a shell rather than MCP tools, and for clients that ignore server instructions — `mcue agents-snippet --mcp` prints the MCP variant for those. ## What the agent can do The local server and Hub's hosted endpoint expose the same tools: | Tool | What it does | |---|---| | `index` | the portfolio view across projects | | `review` | one project's lanes as JSON, with signals, plan and drift per lane | | `resume` | fetch a bounded resume packet for a lane | | `project_state` | read current governed project state | | `checkpoint_latest` | read the most recent checkpoint | | `checkpoint_history` | list checkpoint headers, newest first, without bodies | | `checkpoint_read` | read one checkpoint verbatim, superseded ones included | | `drift` | check whether the repository moved since the lane's checkpoints | | `hub_status` | where this mcue connects to Hub, and each project's sync state | | `closeout` | write a checkpoint and advance state | | `init` | create a project with its state files | | `lane_create` | create a named lane | | `lane_close` | retire a lane as done or abandoned | | `plan_create` | create the active plan for a lane | | `reconcile` | resolve a lane whose perspectives diverged | Reads are the common case. `closeout` is the one write that matters, and it goes through the same validation the CLI uses — an agent cannot write state the CLI would have rejected. Full detail is in the [MCP tools reference](/docs/reference/mcp). ## Provenance Every write records which actor and which substrate produced it. When you later read a checkpoint, you can tell whether you wrote it or an agent did, and through which client. That is what makes it safe to let an agent close out at all: the record stays attributable. ```bash mcue audit ``` reads the local audit log. ## Local server or hosted endpoint The local server needs your machine to be on. If you want an agent to keep working against accepted state while your laptop is shut, that is what Hub's persistent endpoint is for — see [Publish to Hub](/docs/guides/publish-to-hub). The tools above are the same in both cases, so moving from one to the other does not change how the agent is configured beyond the endpoint and its credentials. The [MCP tools reference](/docs/reference/mcp) lists the few places the two behave differently. A release can add a tool. Clients take a server's tool list when a conversation starts and keep it for that conversation, so a tool added by a Hub deploy shows up in the next conversation, not the one already open — refresh the connector if your client caches the list across conversations. To see which contract a Hub serves, read its server version in the initialize handshake or the `hubcore` field of `GET /readyz`; both carry the mcue release it was built against. ## A caution worth stating An agent with write access can close out on your behalf. That is useful and it is also a way to fill your history with plausible, generic checkpoints that say nothing. Keep agent closeouts for genuine session boundaries, and read them occasionally to check they are worth keeping. --- # Publish to Hub Hub is optional. It exists for one thing: keeping accepted operating state — and a persistent MCP endpoint — reachable while every machine you own is switched off. Everything on this page is a deliberate, explicit step. Nothing here happens automatically. > Hub is an invite-only alpha. Signing in is open to anyone, but creating or using > Hub resources requires an invite. If you sign in and every call returns > `beta_access_required`, that is the allowlist, not a bug. ## 1. Point mcue at the Hub ```bash mcue hub set https://api.mcue.dev ``` This verifies the origin and stores it. `mcue hub status` shows the current configuration and your linked-project cursors at any time. ## 2. Log in ```bash mcue login ``` This opens your browser and runs OAuth authorization code with PKCE. mcue is a public client with no embedded secret; the refresh credential lands in your OS credential store — Keychain on macOS, Credential Manager on Windows, Secret Service on Linux. Tokens never touch project files, `$MCUE_HOME`, logs, or shell history. Confirm it worked: ```bash mcue whoami ``` ## 3. Publish a project ```bash mcue publish payments-api ``` Publishing: 1. creates a **private** Hub project with a server-generated UUID, 2. validates and submits your current state as an idempotent baseline import, 3. stores only the Hub project UUID, device id, and sync cursor locally, 4. prints the stable MCP endpoint and how to connect it. Your source repository is not sent. Only governed operating state is. The baseline upload accepts at most **500 files and 5 MiB** of governed state. A local project already above that size cannot connect to the Hub through `mcue publish` today: the command refuses with the limit named, and uploads nothing rather than part of the project. Lifting that ceiling needs both an upgraded Hub and an upgraded CLI; an installed CLI older than the release that carries it still refuses to capture a project above the budget, including for incremental sync. Never delete history to fit an upload. See [large-project recovery limits](/docs/guides/recovery#large-project-recovery-limits). Publish several at once, or everything: ```bash mcue publish payments-api ledger-svc mcue publish --all ``` ## 4. Connect the hosted MCP endpoint The endpoint is stable and the same for every project you publish: ```text https://api.mcue.dev/mcp ``` Project selection comes from tool arguments and your authorised membership, not from a per-project URL. Connect it once and it covers everything you publish afterwards. You do not need the CLI to connect. Claude.ai, ChatGPT, Claude Code, and Cursor each take the URL and run the sign-in in your browser — the per-client steps are in [Connecting a client to the hosted endpoint](/docs/reference/mcp#connecting-a-client-to-the-hosted-endpoint). **A client you connect can read and write your own projects.** You signed it in on your own account, so there is no separate step to allow saves. To narrow one, restrict it to read or revoke it in the Hub connection settings at [hub.mcue.dev](https://hub.mcue.dev). A restricted client that tries to write gets a clear refusal rather than a confusing permission error. ## 5. Verify ```bash mcue sync status payments-api ``` No network request — it reads your local cursor and outbox. A freshly published project should show a cursor and zero pending operations. ## Cloning onto a second machine Install mcue, point it at the same Hub, log in, then: ```bash mcue clone payments-api ``` That materialises the Hub project into local state. From there both machines are replicas of the same ordering — see [Work offline and sync](/docs/guides/offline-and-sync). ## Unpublishing, and what it does not do ```bash mcue unlink payments-api ``` `unlink` removes **only this machine's** Hub link and pending outbox. Your local project state stays. The Hub project stays. Other machines stay linked. Deleting the hosted project, exporting it, and deleting your account are browser-only operations in the Hub UI — they require an authenticated session and typed confirmation, and no OAuth client can perform them on your behalf. ## What Hub can and cannot see - **Can see:** operating state you explicitly published — checkpoints, decisions, plans, lane state — plus device records, client grants, and the technical metadata needed to run the service. - **Cannot see:** your source repository, anything in a project you have not published, or any project state on a machine that has not synced. ## Related - [Authority and conflicts](/docs/concepts/authority-and-conflicts) — what publishing changes about who decides ordering. - [MCP tools](/docs/reference/mcp) — the surface the hosted endpoint exposes. --- # Read continuity graphs {"A resume tells you where to pick up. A continuity graph shows how the work got there: which lanes carry its history, when closeouts arrived, and where the gaps are."} ## Start with the portfolio Choose **Project topology** in the Hub sidebar. Each project branches into its active lanes. A lane shows its recorded next action; select the project or lane to open its history. Drag the space between cards, or scroll, to pan. Use the zoom buttons, **Fit width**, or **Reset view** to find your place. With the graph focused, arrow keys pan, `+` and `-` zoom, and `0` resets. **List** keeps the same project and lane links in a layout that does not need panning. The portfolio shows membership. Its summary does not contain complete closeout history, so this view has no closeout timeline. A project whose state could not be loaded stays visible with an explanation. If the portfolio contains more projects than the current view can return, the page says so. ## Read a project's history On a project page, find **Closeout history** directly below the project heading. Each row is a lane that has accepted closeouts. Retired lanes keep their rows because their history still belongs to the project. - **Closeout chain** places marks between the oldest and newest accepted closeouts. Gaps show periods without a closeout. This span can cover months; the dashboard's portfolio pulse uses a shorter window. - **Lane coverage** shows each lane's share of the project's closeouts. Bar lengths are scaled to the busiest lane, and the percentage labels give each lane's share of the whole record. A lane page shows only that lane's chain. It has no coverage switch: a single lane would always carry its entire displayed record. ## Read a mark A mark groups closeouts into a time bucket. Longer histories use wider buckets to keep dense periods readable. The width is the history's span in days divided by 56, rounded up, with a minimum of one day. When buckets span several days, the footnote states their width. Larger marks mean more closeouts: one, two or three, then four or more. Each mark sits at the newest closeout in its bucket, so neighbouring buckets can occasionally appear close together. - A filled circle represents a human-majority bucket. - A ring represents a combined agent/tool majority. A tie between human and combined agent/tool counts uses the filled circle. - A diamond flags a bucket containing any checkpoint whose mode is not explicit. A busy bucket never hides that exception. Hover over a mark, or reach it with the keyboard, to read its count, date, writer split, and non-explicit count. The shape summarizes the bucket; the tooltip supplies the detail. ## Inspect a checkpoint Select a mark, or press Enter when it has keyboard focus, to open its records. The inspector shows the accepted timestamp, writer, mode, confidence, quality, and plan reference above the stored packet. The packet text is displayed verbatim. **Newer**, **Older**, and the record selector move through the records in that bucket. Close the inspector, or press Escape inside it, to return focus to the mark. An underline appears after every record in a bucket has been opened in the current view. Opening one record does not mark the rest as read. The indicator resets when you leave the page; it does not write to project state. Rings continue to mean agent or tool provenance. ## Change the colour encoding **Colour by** offers provenance, confidence, quality, and plan step. Shapes retain their meaning under every encoding, including non-explicit diamonds. - **Confidence** uses the recorded high, medium, or low value. Missing values stay visible as not recorded. - **Quality** groups recorded scores into 80–100, 50–79, and 0–49 bands. These are display bands, not a new assessment of the work. - **Plan step** groups records by plan ID and step. Colours repeat across the palette; the tooltip and inspector identify the exact plan and step. Striped marks indicate buckets containing different confidence levels, quality bands, or plan steps. A missing value mixed with recorded values also stays mixed. Open the bucket to inspect individual records. ## Use the table Open **View as table** for lane names, closeout counts, shares, and the age of the latest closeout. This gives the same row totals without relying on marks or colour. These views describe accepted closeouts. A gap does not prove that no work happened, and a lane's share is not a measure of its importance. The recorded objective, next action, and checkpoint text remain the context for reading the picture. Retired lanes open read-only history. The timeline ends at the latest accepted checkpoint, which may be older than today. Full stored packets and governed file bodies load when opened; the graph retains the complete history. --- # Work offline and sync Offline is the normal case, not the error case. mcue applies your work locally first and treats the network as something that eventually confirms it — so losing connectivity costs you nothing but confirmation. ## What happens when you are offline A local mutation: 1. is validated and applied **locally, immediately**, 2. is written to a durable outbox, 3. stays visibly **pending** until Hub accepts it. You keep working. Nothing blocks on the network, and nothing is queued in memory where a crash would lose it — the outbox survives restarts. ## Seeing what is pending ```bash mcue sync status payments-api ``` This makes **no network request**. It reads your cursor and outbox and reports what has not been accepted yet. Run it before you get on a plane and after you land; it is the honest answer to "did that go through?" Across every project at once: ```bash mcue hub status ``` ## Reconnecting ```bash mcue sync payments-api ``` On reconnect mcue exchanges pending operations and pulls accepted events after your cursor, then rebuilds the accepted base and replays anything still pending on top. Push and pull are one command because doing them separately is how replicas get subtly wrong. Sync several projects, or all of them: ```bash mcue sync payments-api ledger-svc mcue sync --all ``` ## The scenario worth understanding Two machines, both offline, both writing to the same lane. This is the case distributed systems usually handle badly. - **Both wrote checkpoints.** Checkpoints are append-only. Both survive. The lane becomes divergent and needs `mcue reconcile payments-api` — a human decision about which perspective is right. - **One wrote against stale mutable state.** That write is rejected with the current revision and a typed conflict. It is not silently overwritten, and it is not silently dropped from your outbox. - **A response was lost in flight.** Retrying is safe. Every operation carries an `operation_id`; replaying it returns the original result rather than appending a duplicate. The rule underneath all three: mcue never resolves a disagreement about what happened by comparing clocks. See [Authority and conflicts](/docs/concepts/authority-and-conflicts). ## The eight-hour test The scenario Hub exists to pass: 1. Publish a project from your laptop. 2. Connect an MCP client to the hosted endpoint and confirm read and write access. 3. **Shut the laptop down completely.** No tunnel, no daemon left running anywhere. 4. Hours later, resume the project and write a closeout through the hosted endpoint. 5. Start the laptop and run `mcue sync`. 6. The hosted write appears locally with the right actor, device, substrate, and ordering. If that fails, Hub is not doing its job. It is the acceptance test the whole hosted side is built around. ## BYO-S3, without Hub If you want cross-machine sync without a hosted service, the `mcue remote` namespace syncs perspectives through an S3-compatible bucket you control: ```bash mcue remote enable payments-api mcue remote push payments-api mcue remote pull payments-api mcue remote status payments-api ``` This is a separate path, part of the Apache-2.0 CLI — it is not renamed Hub commands, and it does not require an account. It gives you machine-to-machine sync but not a persistent endpoint that answers while every machine is off. ## If a sync looks wrong - `mcue sync status ` first — it is offline and tells you the actual cursor. - `mcue hub status` to confirm you are pointed at the Hub you think you are. - `mcue whoami` to confirm the session is still valid. - `mcue doctor` if the binary or `$MCUE_HOME` itself is in question. --- # Recover a broken session Sessions end badly. The machine sleeps mid-closeout, the terminal dies, or you simply walked away three days ago and never wrote anything down. mcue has a specific path for each, and none of them require editing state by hand. ## Picking the right path | What happened | Use | |---|---| | a closeout started and was interrupted | `mcue recover ` | | you can close out, but cannot answer everything | `mcue closeout --degraded` | | the session ended days ago with nothing recorded | `mcue closeout --retroactive` | | state looks wrong and you want to look before acting | `mcue review ` | When unsure, start with `review`. It reads state without advancing it, so it cannot make the situation worse. ## Interrupted closeout ```bash mcue recover payments-api ``` `recover` completes an interrupted closeout by writing a **degraded checkpoint** — one explicitly marked as incomplete rather than pretending to be a full record. That marking is the important part. A checkpoint that silently claims to be complete when half its fields were never answered is worse than no checkpoint, because you will trust it later. ## Closing out when you cannot answer everything ```bash mcue closeout payments-api --degraded ``` Use this when you genuinely do not know the outcome or the next action — the build is still running, you are being pulled into something else, the answer depends on someone else. It records what you do know and flags the rest as missing. A degraded checkpoint is honest. Inventing a plausible next action to satisfy the prompt is not. ## Capturing a session after the fact ```bash mcue closeout payments-api --retroactive ``` For the session that ended on Thursday when it is now Monday. Retroactive closeouts are marked as such, so the history distinguishes "recorded at the time" from "reconstructed later" — which matters when you are judging how much to trust the record. Write what you can actually remember. A retroactive closeout saying "cannot recall the blocker; the failing test was `TestRefundRetry`" is more useful than a confident reconstruction that is subtly wrong. ## Reading the result A resume packet built from a degraded or retroactive checkpoint says so. When you see that marker, treat the surrounding account as partial and check the repository state before acting on it. ```bash mcue resume payments-api mcue history payments-api # browse the checkpoint history ``` ## After a recovery Once you are back in a known state, close out normally at the end of the next real session. That writes a complete checkpoint and leaves the degraded one in history, where it stays as an accurate record that this period was messy. Do not try to retroactively "fix" a degraded checkpoint into a complete one. The gap is information. ## When the problem is distributed, not local If the trouble is two machines disagreeing rather than one session ending badly, this is the wrong page. See [Authority and conflicts](/docs/concepts/authority-and-conflicts) and `mcue reconcile `. ## When the problem is the install ```bash mcue doctor ``` Resolves which binary is running, its version, where `$MCUE_HOME` points, and whether that directory is readable and writable. Run it before assuming your state is corrupt — a surprising share of "my state is broken" turns out to be two installs or an unexpected `MCUE_HOME`. ## Hosted closeouts and uncertain acceptance The browser retains your draft and a request ID before submitting it. If the response is lost, use **Retry this request**: the same ID and exact fields resolve the original acceptance. **Download recovery copy** preserves the submitted fields before you clear browser data or change devices. Draft text remains in this browser for your account until accepted; it is not an accepted checkpoint. Hosted MCP `closeout`, `lane_create` and `lane_close` require a caller-retained `request_id`. A retry must reuse both the ID and identical fields. A different payload under that ID is refused. An unknown outcome never calls for a fresh ID. A conflict needs explicit reconciliation; an intentionally edited successor gets a new ID and links to the original closeout with `replaces_request_id`. `not_saved` means storage was not confirmed: keep the recovery fields returned to the caller. A `durable` pending attempt is separate from accepted history. Neither an error log nor an agent’s promise to remember is a durability guarantee. For coordinated incident recovery, pause competing writers, inventory overlapping work, and process eligible CLI queues before replaying any hosted record. Replay only the final hosted records not already covered by accepted work; retain unresolved conflicts for human reconciliation rather than forcing a winner. ## Large-project recovery limits These are the limits of the installed CLI today. They are transfer ceilings, not history ceilings: never delete accepted history to fit a transfer. - **First publish:** `mcue publish` accepts at most **500 files and 5 MiB**. A local project already above that size cannot first connect to the Hub. The refusal names the limit and uploads nothing. - **Whole-project reads:** the CLI reads at most **6 MiB** per Hub response. `mcue clone` and the pre-read refresh download a whole-project snapshot, so a project that has grown past that size on the Hub cannot be cloned or refreshed by the installed CLI. The failure is explicit, applies none of that response, and leaves pending local intent and the sync cursor untouched. - **Backups:** the project owner can download a streamed backup of accepted state from the Hub. Treat an interrupted download as incomplete; it cannot be verified or restored. Bounded, manifest-pinned transfers that remove the whole-project assumption from publish, clone, export and restore are implemented and under review. This page will document the commands when the CLI release that carries them is installable from the tap. Until then, an installed CLI reports the limits above. ## Resolving retained hosted requests The lane recovery panel lets you download submitted intent, retry an unresolved request, or explicitly mark it covered by an accepted checkpoint. Compare accepted history and all known CLI queues first. Discarding a recovery copy prevents replay of that ID and does not delete accepted history. Edited successors use a fresh ID linked to the original request. Unresolved copies have no automatic expiry and are capped at 100 requests / 32 MiB per actor/project. Identity and acceptance receipts remain until account/project deletion. Explicit copy deletion clears active recovery content; historical backup copies follow the deployment's backup retention. Downloaded files and browser storage are independent copies. Keep them private and clear them separately. ## Damaged local metadata Stop writers and preserve the original project directory, link and queue together. Do not hand-edit files under `~/.mcue` to bypass a recovery error, and do not force a queue through a conflict. To inspect accepted state without touching the damaged replica, clone the project into a separate empty `MCUE_HOME` and compare it against the original before reconciling selected edits. Unreadable local intent cannot be assumed to have reached the Hub; record that uncertainty for operator review instead of forcing a replay. --- # 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](/docs/concepts/projects-lanes-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](/docs/concepts/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`: ```bash 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](/docs/reference/files). ## 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](/docs/concepts/authority-and-conflicts) is about. --- # Why not a notes file? Everything mcue records could be typed into a `NOTES.md` at the bottom of your repository. That objection is correct, it is the first thing most people say, and it deserves a straight answer rather than a feature list. The short version: a notes file has no boundary, no derived view, and no way to admit it is unreliable. Those three gaps are what mcue closes. If none of them bite you, keep the notes file — the last section here says so plainly. ## "I already keep a NOTES.md" A notes file works until it is long. Then it fails in three specific ways. **It has no cap.** The whole point of re-entry is reading less than you wrote. A notes file grows monotonically, so coming back means skimming everything to find the part that still matters. A [resume packet](/docs/guides/closeout-and-resume) is bounded at roughly 300 or 1000 tokens and assembled on demand — it is *derived* from your history rather than being your history. That cap is the feature, and a file cannot have one. **It cannot tell you it is unreliable.** When you write notes while being pulled into an incident, the file looks exactly like notes written calmly with the test output in front of you. mcue marks that session `mode: degraded`, drops its trust score, and the resume packet leads with `Trust: low (degraded, low confidence)` before you act on it. You can *write* "I'm not sure about this" in a notes file, and you will not, because the moment you are least sure is the moment you are most rushed. See [a week with mcue](/docs/guides/a-week-with-mcue) for what that looks like in practice. **It stops at the project boundary.** A notes file cannot answer "which of my projects has gone quiet?" — that question needs a view across every project at once, which is what `mcue index` derives. With one project this does not matter. With twelve it is the only question that matters, and it is the one a per-repo file structurally cannot answer. There is also a quieter problem: a `NOTES.md` inside the repository is source control's business, so it shows up in diffs, conflicts on merge, and gets reviewed. Operating state is not source, and putting it under review changes what people are willing to write down. Honesty about a bad session is the most valuable thing in the record and the first thing to go when it is public to the team. ## "My todo app already does this" Todo apps hold **future** work: things to do, with a status. Operating state holds **past** intent and the gap between what you meant to do and what happened. That gap is the whole product. "Intended to wire refunds to the ledger; spent the session discovering our ULIDs double-post through their UUID-keyed client" is not a task. It has no status, it will never be checked off, and it is the single most valuable sentence you will read in three weeks. A todo app has nowhere to put it. The two are complementary rather than competing. Your todo app can keep the next action; it cannot keep the reason the last one failed. Practically: todo apps also store data in a service you do not control, in a format you cannot grep, and they cannot hand an agent a bounded brief. ## "That's what commit messages are for" Commit messages record what the code became. They are the closest real competitor here, and they still miss on three counts. **They only exist where there is a commit.** The four hours you spent ruling out an approach produce no commit. The afternoon lost to a connection-pool bug that turned out to be a misconfigured local environment produces no commit. Those are exactly the sessions whose lessons evaporate. **They are written for a different reader.** A commit message explains a diff to someone reviewing it. Re-entry needs something else entirely: what you were trying to do, what is blocking, and where to put your cursor. Those are not the same document, and writing one well does not produce the other. **They are attached to work that survived.** Abandon a branch and its messages go with it, along with the reason you abandoned it — which is the part worth keeping. mcue does not compete with any of this. Git records source history; mcue preserves the operating state needed to continue the work. That boundary is deliberate and is covered in [Operating state](/docs/concepts/operating-state). ## When a notes file really is enough It genuinely is enough, and pretending otherwise would be dishonest. Keep the notes file if **all** of these hold: - **One project**, or few enough that you never lose track of which has gone quiet. - **Working alone**, with no agent that needs your context in a bounded form. - **One machine**, so there is no question of state being reachable from elsewhere. - **Sessions close together**, so you rarely return cold enough to have forgotten the specifics. Under those conditions the overhead of a tool buys you very little. A file and some discipline will do. The conditions that break it are ordinary, though, and they arrive one at a time: | What changes | What breaks | |---|---| | a second and third project | you can no longer tell what has gone quiet | | an agent joins the work | prose notes are the wrong shape; a bounded packet is not | | a second machine, or a phone | the file is on the wrong computer | | a three-week gap | you re-read everything to find the part that matters | | a session that ends badly | nothing in the file marks it as unreliable | If you have hit two of those, the notes file has already stopped working and you are probably compensating by hand. ## The honest summary mcue is not a better notes file — it is continuity infrastructure that keeps what a file cannot: a **bound** on what you read back, a **derived view** across every project, and a **record that admits when it is unreliable**. If you do not need those three things, you do not need mcue, and the [quickstart](/docs/quickstart) takes five minutes to find out. ## Next - [A week with mcue](/docs/guides/a-week-with-mcue) — the same argument as a worked example. - [Operating state](/docs/concepts/operating-state) — the boundary between what mcue owns and what Git owns. - [Projects, lanes, and plans](/docs/concepts/projects-lanes-plans) — when one lane stops being enough. --- # 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: ```bash 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 ` moves the id across all local state rather than leaving you to fix references by hand. Projects have a lifecycle beyond deletion: ```bash 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. ```bash 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. ```bash 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 ```text 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 index` becomes 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. --- # 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: ```bash 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: ```bash 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](/docs/guides/offline-and-sync) — the same model, as a walkthrough. - [Recover a broken session](/docs/guides/recovery) — when the problem is local, not distributed. --- # CLI commands The complete command surface as shipped in the current release (`mcue --version` tells you which). Descriptions here are the binary's own. Flags change more often than commands do, so each entry points you at `--help` rather than transcribing a flag list that will drift. ```bash mcue --help # authoritative flags for any command ``` ## Project lifecycle | Command | Purpose | |---|---| | `mcue init --name "Display Name"` | Register a new project and scaffold its state files | | `mcue attach ` | Anchor an existing project to a directory via `.mcue` footprint | | `mcue detach` | Remove the `.mcue` footprint from a directory | | `mcue exists ` | Quietly check whether a project is registered | | `mcue update ` | Update mutable project metadata without a closeout | | `mcue project rename ` | Rename a project id across all of its local state | | `mcue project archive ` | Mark a project out of the active portfolio without removing state | | `mcue project delete ` | Hard-delete a project: remove its registry entry and state directory | ## The session loop | Command | Purpose | |---|---| | `mcue closeout ` | End a session and refresh governed project state | | `mcue resume ` | Generate a bounded resume packet for re-entry | | `mcue index [project-id...]` | Show the derived portfolio view, across projects or for named ones | | `mcue review ` | Inspect project state without full closeout | | `mcue history ` | Browse a project's checkpoint history | | `mcue drift ` | Show warning-only environment drift for a project or lane | | `mcue recover ` | Recover from an interrupted closeout with a degraded checkpoint | | `mcue reconcile ` | Resolve a lane with multiple unreconciled perspectives | ## Lanes and plans | Command | Purpose | |---|---| | `mcue lane create ` | Create a named operating lane inside a project | | `mcue lane update ` | Update a lane's objective, display name, or work tree without a closeout | | `mcue lane close ` | Retire a project operating lane | | `mcue lane delete ` | Hard-delete a lane and all its state | | `mcue plan create ` | Create the active plan for a lane | | `mcue plan show ` | Show the active or archived plan for a lane | | `mcue plan list ` | List active and archived plans | | `mcue plan update ` | Update the active plan outside closeout | | `mcue plan close ` | Archive the active plan on a lane | | `mcue plan delete ` | Hard-delete the active plan on a lane | ## Managed Hub | Command | Purpose | |---|---| | `mcue hub set ` | Set and verify the managed Hub origin | | `mcue hub status` | Show Hub configuration and linked-project cursors | | `mcue login` | Authorize mcue with the configured Hub using OAuth + PKCE | | `mcue logout` | Revoke the Hub OAuth session and remove it from the OS credential store | | `mcue whoami` | Show the authenticated Hub identity | | `mcue publish ...` | Publish one or more local projects to the managed Hub | | `mcue clone ` | Materialize a Hub project into local mcue state | | `mcue sync ...` | Push pending local state and pull accepted Hub events | | `mcue sync status [project-id]` | Show managed-Hub cursor and pending state **without network access** | | `mcue unlink ` | Remove only the local Hub link and pending outbox | | `mcue observe ` | Collect Git evidence against Hub-accepted checkpoints; `--upload` submits it to Hub | ## BYO-S3 remote A self-hosted cross-machine path that needs no account. Separate from Hub. | Command | Purpose | |---|---| | `mcue remote enable ` | Configure an S3-compatible remote for a project | | `mcue remote disable ` | Remove a project's remote configuration | | `mcue remote status ` | Show remote configuration and unpushed perspectives | | `mcue remote push ` | Upload local perspectives the bucket does not have | | `mcue remote pull ` | Download remote perspectives and recompute local state | | `mcue remote rotate ` | Replace the stored remote credential | | `mcue remote diff ` | Compare local and remote bytes for a perspective (byte-conflict check) | | `mcue remote force-push ` | Overwrite the remote bytes for one perspective with the local bytes | ## Agents and MCP | Command | Purpose | |---|---| | `mcue serve` | Run a mcue MCP server (stdio or authenticated HTTP) | | `mcue agents-snippet` | Emit the canonical mcue access-rules snippet for `AGENTS.md` / `CLAUDE.md` | | `mcue token issue` | Issue a new bearer token | | `mcue token list` | List issued tokens (ids, scopes, status — never the plaintext) | | `mcue token rotate ` | Revoke a token and issue a replacement with the same scope | | `mcue token revoke ` | Revoke a token by id | ## Identity and diagnostics | Command | Purpose | |---|---| | `mcue identity show` | Print the current operator and machine identity | | `mcue identity set` | Override identity fields or add aliases | | `mcue doctor` | Print install diagnostics for the local mcue setup | | `mcue audit` | Read entries from the local audit log | ## Migrations One-off commands for state written by older versions. Safe to ignore on a fresh install. | Command | Purpose | |---|---| | `mcue migrate-lanes` | Scaffold default lane state for pre-lane projects | | `mcue migrate-objectives` | Detect and clean up `project_state` objectives polluted by the pre-fix closeout bug | ## Scoping the portfolio view `mcue index` with no arguments is the cross-project glance. Name one or more projects to scope it: ```bash mcue index # every active project mcue index payments-api # just this one mcue index payments-api ledger-svc # several mcue index payments-api --expand-lanes # with its lanes ``` Two behaviours worth knowing: - A **named project is shown whatever its state**, including closed and archived ones that the unscoped view hides. Asking for a project by id means you want to see it. - An **unknown id is an error**, not an empty table — an empty table would read as "this project has nothing in it" rather than "no such project". For the fuller picture of one project, including checkpoint detail, use `mcue review ` instead. ## Commands that touch the network Worth knowing exactly which ones do, since everything else is guaranteed local: - `mcue hub set`, `mcue login`, `mcue logout`, `mcue whoami` - `mcue publish`, `mcue clone`, `mcue sync`, `mcue observe` - every `mcue remote` subcommand except `status` - `mcue serve` only when serving its HTTP surface, and only to clients that reach it Notably **`mcue sync status` does not** — it is deliberately offline so you can check pending work on a plane. --- # Files on disk Everything mcue knows is Markdown with YAML front matter under one directory. You can read it, diff it, grep it, and repair it by hand. This page is the map. ## Layout ```text $MCUE_HOME/ # ~/.mcue unless overridden ├── registry/ │ └── projects.yaml # every registered project └── projects/ └── / ├── project_state.md # governed project-level state ├── decisions.log # append-only decision record ├── checkpoints/ │ └── .md # one file per closeout └── lanes/ └── / ├── lane_state.md # governed lane-level state └── plan.md # the active plan for this lane ``` Publishing adds Hub link metadata and a pending-operation outbox beneath `$MCUE_HOME` as well. Hub synchronisation only ever reads and writes below `$MCUE_HOME` — it does not touch your source repository. ## Conventions Every governed file is Markdown with a YAML front-matter block. The front matter carries the machine-readable fields; the body carries the prose. That split is why the files stay useful to both a parser and a person. - Identifiers are lowercase, hyphen-separated, and stable. - Timestamps are the checkpoint filename as well as a field, so the directory sorts chronologically without parsing anything. - Append-only files are never rewritten in place; corrections are new entries. ## `registry/projects.yaml` The index of every registered project: its id, where it is anchored, and its lifecycle state. `mcue init` adds an entry, `mcue project archive` marks one out of the active portfolio, and `mcue project delete` removes it along with the state directory. This is the file `mcue index` reads first. If a project has vanished from `index` but its directory still exists, look here. ## `project_state.md` Project-level governed state: title, description, current objectives, and the derived status that `mcue index` surfaces. Refreshed by `mcue closeout`; editable for metadata via `mcue update`. ## `lanes//lane_state.md` The same idea, scoped to a lane: what this strand of work is doing, its current status, and the pointer to where to resume it. Every project has a default lane, so this file exists even if you never create one explicitly. ## `lanes//plan.md` The active plan: an ordered set of steps with their state. Closing a plan archives it rather than deleting it, so earlier plans stay answerable. ## `decisions.log` An append-only record of decisions and the reasoning behind them, newest entries appended at the end. This is the file that answers "why did we do it that way" eighteen months later, and it is the one most worth writing carefully. ## `checkpoints/.md` One file per closeout, named by timestamp. Each carries intent, outcome, blockers, next action, and the resume pointer, plus provenance — which actor and which substrate produced it. Checkpoints are append-only and never rewritten. Degraded and retroactive checkpoints are marked as such in front matter, so a later reader can tell how much to trust them. See [Recover a broken session](/docs/guides/recovery). ## Resume packets Not a file. A resume packet is assembled on demand from current state and capped at roughly 300 or 1000 tokens depending on the tier requested. This matters more than it sounds: because packets are derived rather than stored, improving how they are built never rewrites your history. ## The audit log A local record of what happened — reads, writes, which client, which substrate. Read it with: ```bash mcue audit ``` Provenance is what makes agent writes safe to allow. Every write is attributable to an actor and a substrate, so a checkpoint written by an agent through an MCP client is distinguishable from one you typed. ## Validation mcue validates state on read and on write, and the same validator runs behind the CLI, the local MCP server, and the hosted Hub endpoint. There is no looser path into your state — an operation an agent submits is checked exactly as one you type is. If you hand-edit a file into an invalid shape, the next command that reads it will say so rather than silently reinterpreting it. ## Backing it up `$MCUE_HOME` is a normal directory. Put it in a private Git repository, include it in your usual backups, or point `MCUE_HOME` at a synced folder: ```bash export MCUE_HOME="$HOME/work/.mcue-state" ``` Hub is not a backup — it holds accepted state for published projects only, which is a different thing from a copy of everything on this machine. --- # MCP tools mcue speaks MCP in two places: a local server on your machine, and a persistent hosted endpoint on Hub. Both serve the same tools with the same arguments and the same result shapes, so an agent configured against one works against the other. ## The two surfaces | | Local | Hosted | |---|---|---| | Command | `mcue serve --mcp` | none — always on | | Endpoint | stdio, or an authenticated HTTP address | `https://api.mcue.dev/mcp` | | Auth | bearer tokens from `mcue token` | OAuth via Hub | | Available when your machine is off | no | yes | | Reads | local state under `$MCUE_HOME` | accepted Hub state | | Requires an account | no | yes, invite-only | ## Tools | Tool | Kind | Local | Hosted | What it does | |---|---|---|---|---| | `index` | read | yes | yes | The derived portfolio view across projects; `sort`, `expand_lanes`, `focus` | | `review` | read | yes | yes | One project's lanes as JSON: status, objective, next action, blockers, signals, plan, drift and latest checkpoint per lane | | `resume` | read | yes | yes | Fetch a bounded resume packet for a project lane | | `project_state` | read | yes | yes | Read current governed project state | | `checkpoint_latest` | read | yes | yes | Read the most recent checkpoint | | `checkpoint_history` | read | yes | yes | List checkpoint headers newest first, no bodies; `lane` and `limit` (default 20, max 200) | | `checkpoint_read` | read | yes | yes | Read one checkpoint verbatim by the `file` a history row carries, superseded ones included | | `drift` | read | yes | yes | Repository drift per lane as JSON; missing or stale evidence reads unknown, never clean | | `hub_status` | read | yes | yes | The Hub API and web origins and, per project, its link, sync cursor and pending writes | | `closeout` | write | yes | yes | Write a checkpoint and advance governed state | | `init` | write | yes | yes | Create a project with project state, decisions log, and default lane | | `lane_create` | write | yes | yes | Create a named operating lane inside a project | | `lane_close` | write | yes | yes | Retire a lane as done or abandoned, keeping its history | | `plan_create` | write | yes | yes | Create the active plan for a lane from a Markdown body | | `reconcile` | write | yes | yes | Resolve a lane with multiple unreconciled perspectives | Reads are the common case. `closeout` is the write that matters — it is the same operation the CLI performs, through the same validator, with the same required fields. Both servers register their tools from one catalog in mcue's shared core, so a tool, an argument or a result shape cannot change on one without the other. Each server's test suite fails if it drifts from that catalog, and the table above is checked against the local server's live tool list by the site's own check before it ships. Where the two behave differently, the tool's own description says so: - **`drift`** — the local server observes each lane's attached repository on the spot; Hub reads the observations a host uploaded with `mcue observe --upload`, and never runs Git itself. - **`request_id`** on `closeout`, `lane_create` and `lane_close` — Hub requires it, so a retry after a lost response returns the original result instead of writing twice. The local server accepts it and honours it the same way, but does not require it. - **`hub_status`** — locally it reports the Hub this machine is configured for and each published project's sync cursor and pending writes; on Hub every project is linked and nothing is pending. `review`, `drift` and `hub_status` return JSON. A lane in `review` whose perspectives disagree carries `refusal: needs_reconcile` and lists them, instead of picking one; call `reconcile` to resolve it. Project selection comes from tool arguments and authorised membership, not from a per-project URL or a separate deployment. One endpoint covers everything you have published. ## Connecting a client to the hosted endpoint Every client asks for the same two things: the endpoint URL and a sign-in. Nothing is installed on the client side, and no token is copied by hand — the sign-in is an OAuth flow that Hub runs in your browser. Menu names move between client releases; the shape does not. **Claude.ai.** Open Settings, then Connectors, and add a custom connector. Give it a name, paste the endpoint URL, and save. The first time you enable it in a chat, Claude sends you to Hub to sign in and approve the client. **ChatGPT.** Open Settings, then Connectors (Apps in some releases), and create a new connector with the endpoint URL. Adding a remote MCP server currently requires developer mode on the account. ChatGPT sends you to Hub to sign in when you first use it. **Claude Code.** ```bash claude mcp add --transport http mcue https://api.mcue.dev/mcp ``` Then run `/mcp` inside a session and pick mcue to complete the sign-in. **Cursor, and other clients that read an `mcp.json`.** ```json { "mcpServers": { "mcue": { "url": "https://api.mcue.dev/mcp" } } } ``` The client detects OAuth from the endpoint's 401 response and opens the sign-in. Whichever client you use, once signed in it can read and write your own projects. The next section covers how to narrow or revoke it. ## Authorisation on the hosted endpoint **A client you connect can read and write your own projects.** You approved it at sign-in, on your own account, so it needs no further step before its first save. You can restrict any client to read, or revoke it, in the Hub connection settings at [hub.mcue.dev](https://hub.mcue.dev). The same default covers creating a new project with `init`; a client restricted to read or revoked under **Account access** cannot. A client you have restricted to read gets an explicit refusal telling it a write grant is required, rather than a vague permission error it might retry forever. Projects other people share with you work differently. The owner sets whether agents may write to the shared lane, and when you join you choose for your own agents: write where the share allows it, unless you pick read. Grants are per client, set on one project or across your account, and changes take effect immediately. Revoking a client on a project stops its access there; it does not delete project state. ## What the hosted endpoint will not do Some operations require an authenticated browser session and cannot be performed by any OAuth client, whatever its access: - deleting a hosted project - deleting your account - administering grants for other clients These live in the Hub UI behind typed confirmation. An agent cannot be talked into performing them. ## Authenticating a local HTTP client ```bash mcue token issue # issue a bearer token mcue token list # ids, scopes, status — never the plaintext mcue token rotate # revoke and reissue with the same scope mcue token revoke # revoke by id ``` The plaintext is shown once at issue. `list` never prints it — if you lose a token, rotate rather than trying to recover it. ## Provenance Every write through either surface records the actor, the device, and the substrate that produced it. That is what makes agent writes reviewable after the fact: ```bash mcue audit ``` A checkpoint written by an agent through an MCP client is distinguishable from one you typed, in the audit log and in the checkpoint's own front matter. ## Teaching an agent the rules ```bash mcue agents-snippet >> AGENTS.md ``` Emits the canonical access-rules snippet. It works equally in `CLAUDE.md` or any other instruction file your client reads, and it is worth adding — agents that know when to close out behave markedly better than agents guessing. Over MCP the server teaches this itself: both the local server and the hosted endpoint send the contract as server instructions in the initialize handshake and expose it as the `mcue://agents` resource (CLI v0.14.0 and later). The repo file remains useful for shell-based agents and for clients that discard server instructions; `mcue agents-snippet --mcp` prints the MCP variant. ## Related - [Give agents your state](/docs/guides/agents-and-mcp) — the walkthrough, including local client setup. - [Publish to Hub](/docs/guides/publish-to-hub) — getting the hosted endpoint. - [Authority and conflicts](/docs/concepts/authority-and-conflicts) — what happens when an agent and you write at once.