Skip to main content
Mesa works best when you have a clear notion of:
  • Which data lives in each repository
  • When to branch and checkpoint work
  • When you will promote to the main line of version history

Repositories

A repository is just a folder with independent version history and permissions. Generally, you documents should be grouped into the same repository if they need to evolve together and share the same owner. For example, all of the code for an application would typically live in a single repository. But apps belonging to different tenants should live in separate repositories. You can always add metadata to repositories to help you track which repositories belong to different teams or tenants. Here are recommendations for common cases:
  • Applications: One repo per application
  • Knowledge bases: One repo per team or project
  • n8n-style workflows: One repo per workflow
  • Skills: One repo per skill. It is also feasible to create one skills repo per tenant, but repo-per-skill plus metadata tags typically provides the most flexibility.

Branching and checkpointing

Generally, you should treat main bookmark as the canonical state that users or production systems trust. Treat other bookmarks as markers of the tips of different “timelines” — work-in-progress modifications that are not yet ready to be merged into the canonical state of the repository. When an agent or human wants to draft some work, you typically create a new change forked off of the main bookmark, and optionally create a new bookmark pointing at that change. When you want to checkpoint your draft, you can chain a new change on top and advance the bookmark. When you’re happy with that draft work, you can merge it into the canonical state with the mesa.merge method. Below is guidance on using Mesa for agent sessions.

Timeline-per-session

Create one bookmark per user session/workflow run instead of mixing multiple sessions on main. Each session can evolve independently, and you can merge or discard without affecting parallel work.
await mesa.bookmarks.create({
  repo: "my-repo",
  name: `session/${sessionId}`,
  change_id: repo.head_change_id,
});
Recommended naming: session/<session-id> or proposal/<feature-name>-<run-id>.

Checkpoint-per-prompt

Create a new change (and move the session bookmark to it) after each user prompt. This gives you a clean timeline of intent, makes undo/redo straightforward, and lets you restore the repository to a known good state if a later step goes wrong.
const change = await mesa.changes.create({
  repo: "my-repo",
  base_change_id: sessionBookmark.change_id,
  message: `prompt: ${userPrompt}`,
  author: { name: "Agent", email: "agent@acme.dev" },
  files: agentEdits,
});

// To accept the changes, move the bookmark to the new change, making it the new head of the timeline.
await mesa.bookmarks.move({
  repo: "my-repo",
  bookmark: sessionBookmark.name,
  change_id: change.id,
});
To undo the last prompt, move the bookmark back to the previous change. Recommended for:
  • conversational coding agents,
  • iterative content generation,
  • any workflow where users expect “undo last prompt” behavior.

Short-lived bookmarks

Keep session/proposal bookmarks temporary. Merge approved work quickly and delete abandoned bookmarks. Short-lived bookmarks reduce drift from main, lower conflict rates, and make reviews easier because diffs stay small.
// Delete an abandoned bookmark
await mesa.bookmarks.delete({ repo: "my-repo", bookmark: `session/${sessionId}` });
Good rule of thumb: if a bookmark has been idle for a while, either merge it into main or delete it.

Approvals (proposal bookmark + diff)

Use a proposal bookmark for all non-trivial changes, then show users a diff before merge:
  1. Agent writes changes on a proposal bookmark.
  2. Fetch the diff between main and the proposal bookmark.
  3. Render the diff in your UI in a way that makes sense for your app.
  4. On user approval, merge the proposal into main.
  5. On reject, keep the bookmark for iteration or delete it.
This pattern gives users explicit control and creates a clear audit trail of what was proposed and accepted.
// 1. Create a proposal bookmark at the current main
const bookmarks = await mesa.bookmarks.list({ repo: "my-repo" });
const main = bookmarks.bookmarks.find((bookmark) => bookmark.name === "main")!;

await mesa.bookmarks.create({
  repo: "my-repo",
  name: "proposal/add-forecast-widget",
  change_id: main.change_id,
});

// 2. Agent writes changes on the proposal bookmark (via the filesystem or changes API),
// advancing it to `proposalHead`.

// 3. Diff main vs. the proposal
const diff = await mesa.diffs.get({
  repo: "my-repo",
  base_change_id: main.change_id,
  head_change_id: proposalHead,
});

renderApprovalUI(diff);

if (userApproved) {
  // 4. Merge the proposal into main
  await mesa.bookmarks.merge({
    repo: "my-repo",
    target: "main",
    source: "proposal/add-forecast-widget",
    delete_source: true,
  });
} else {
  // 5. Clean up (if you didn't use the `delete_source` option in the merge)
  await mesa.bookmarks.delete({
    repo: "my-repo",
    bookmark: "proposal/add-forecast-widget",
  });
}

General

  • Treat main as canonical state, not a scratchpad.
  • Add metadata in commit messages so runs are traceable.
  • Keep API/JWT scopes as tight as possible
  • Track write, diff, and merge latency in your critical paths.
  • Enforce repository naming conventions and lifecycle policies.
  • Delete abandoned proposal bookmarks after a retention window.
  • Keep human review workflows for high-impact changes.