Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.mesa.dev/llms.txt

Use this file to discover all available pages before exploring further.

This guide captures the baseline operating model we recommend for production usage.
  • Create a timeline-per-session for non-trivial agent tasks.
  • Treat main as promoted, reviewed state.
  • Scope API keys to the minimum required permissions.
  • Add metadata in commit messages so runs are traceable.

Operational practices

  • Track commit and merge latency in your critical paths.
  • Enforce repository naming conventions and limits.
  • Keep human review workflows for high-impact changes.

Repo-per-project

Use a separate repository for each project or similar concept in your application. This keeps history focused, reduces noisy diffs, and lets you apply permissions and retention policies per project. Use this when projects are logically independent and typically reviewed/deployed separately. Some examples of how to decide what’s a repo and what isn’t:
  • n8n-style workflows: each workflow is a separate repo
  • app builder: each user app is a separate repo
  • coding agents: each user codebase is a separate repo
  • VMs & infra: each user volume is a separate repo

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.

Timeline-per-session

Create one bookmark per user session/chat/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>.

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",
  });
}