Skip to main content
In this quickstart, you will create a repo, read and write files with MesaFS, and experiment with versioning. The goal is to show the primitives Mesa provides that can be used for any of your agent workflows.
1

Sign up and create an API key

  1. Create an account at app.mesa.dev.
  2. Create an organization for your product (example: acme).
  3. Generate an API key with admin scope.
Store the key as an environment variable:
export MESA_API_KEY="mesa_..."
API keys are only shown once. Save them in your secrets manager before leaving the dashboard.
See Auth & Permissions for key management and scope details.
2

Install the SDK or CLI

npm install @mesadev/sdk
Using MesaFS through the CLI requires FUSE which is not a straightforward process on MacOS (yet). If testing with the CLI we recommend using a FUSE-enabled Sandbox. See Integration Guides for more.
3

Create a repo

In Mesa, you organize resources using a special type of directory called a repository. A repository has a completely unique version history in Mesa and its own permissions and access controls.Repositories are free to create on Mesa. You should use them liberally to isolate resources that belong to different tenants, different internal teams, and even different projects or workspaces within a single tenant.Use the SDK to create repositories on-demand and edit their contents through Mesa.
import { Mesa } from "@mesadev/sdk";

const mesa = new Mesa({ apiKey: process.env.MESA_API_KEY, org: "acme" });

const repo = await mesa.repos.create({ name: "project-1" });
To retrieve an existing repo later:
const repo = await mesa.repos.get({ repo: "project-1" });
4

Read and write your first files

Once created, the easiest way to read and write to a repository is by mounting MesaFS, either through our SDKs or through a FUSE mount with our CLI.
import { Mesa } from "@mesadev/sdk";

const mesa = new Mesa({ apiKey: process.env.MESA_API_KEY, org: "acme" });
const repo = await mesa.repos.create({ name: "project-1" });

// Open the repository locally as a virtual filesystem
const fs = await mesa.fs.mount({
  repos: [{ name: repo.name, bookmark: "main" }],
  mode: "rw",
});

// Use explicit filesystem operations
await fs.mkdir("/acme/project-1/memories", { recursive: true });
await fs.writeFile("/acme/project-1/memories/run-1.md", "Hello, world!");
const content = await fs.readFile("/acme/project-1/memories/run-1.md", "utf8");

// Or use the emulated bash environment
const { stdout } = await fs.bash({ cwd: "/acme/project-1" }).exec("echo memories/run-1.md");
5

Experiment with versioning

A repository is a directed acyclic graph of Changes or snapshots of the repository at that point in time. You can always go back and view the state of files at older Changes and even restore the current state of a file from an older Change version.See more in Versioning.Every time you make file edits in Mesa, those writes are going to a specific change. Your first change is created automatically when you mount an empty repo in MesaFS. All subsequent changes must be explicitly created.
// The first Change that holds our previous writes
const firstChange = await fs.change.current({ repo: "project-1" });

// Create a new Change on top of the first using MesaFS
await fs.change.new({ repo: "project-1", changeId: firstChange.changeId });

// All writes go to the new change
await fs.bash({ cwd: "/acme/project-1" }).exec('echo "Hello, Mesa!" > memories/run-1.md');
const secondChange = await fs.change.current({ repo: "project-1" });
You can easily roll back to a previous version by switching to an old Change.
// Roll back to the first change
await fs.change.edit({ repo: "project-1", changeId: firstChange.changeId });
const original = await fs.readFile("/acme/project-1/memories/run-1.md", "utf8");
console.log("Content:", original); // "Hello, world!"

// Continue with the new change
await fs.change.edit({ repo: "project-1", changeId: secondChange.changeId });
const updated = await fs.readFile("/acme/project-1/memories/run-1.md", "utf8");
console.log("Content:", updated); // "Hello, Mesa!"
6

Diff two changes

Now you have two changes in your repo: the first Change with the default main bookmark, and the second Change with the feature-changes bookmark.You can imagine having many different changes and many different bookmarks with different agents doing work. Once an agent is done with their work, you may want to show a UI for users to review the changes and approve or reject them.
const diffResult = await mesa.diffs.get({
  repo: repo.name,
  base_change_id: firstChange.changeId,
  head_change_id: secondChange.changeId,
});

diffResult.entries.forEach((entry) => {
  // render file diff
});
7

Bookmark changes

By default, Changes are “anonymous”. If you want to create a named checkpoint or merge one change into another, you should Bookmark the change. By default, the first change on a repo is automatically bookmarked as main (or whatever you set as defaultBookmark when creating the repo).
await mesa.bookmarks.create({
  repo: repo.name,
  name: "feature-changes",
  change_id: secondChange.changeId,
});
8

Merge two changes

You will eventually have lots of different changes and bookmarks and you’ll want to merge the changes from one bookmark into another.Merge your source bookmark (feature-changes) into your target bookmark (main). This process creates a new Change on top of main that contains the merged changes and moves the main bookmark to the new Change.
const mergedChange = await mesa.bookmarks.merge({
  repo: repo.name,
  target: "main",
  source: "feature-changes",
});

console.log("Merged Change:", mergedChange.change_id);
Now you have 3 changes in your repo. You can use these patterns to effectively have staged changes. Your main bookmark holds the canonical version of your documents, agents and humans create changes on separate Changes with named Bookmarks. You render UI for human-in-the-loop approvals, and when you’re ready you can merge one set of experimental changes into your main line of Change history.
You’re now ready to start building complex agent workflows with Mesa.

Next steps