Skip to main content
All notable changes to this project will be documented in this file. The format is based on Common Changelog, and this project adheres to Semantic Versioning.

[0.47.1] - 2026-08-16

Fixed

  • Fix slow mount() initialization for layouts that specify a checked-out revision with at, and allow concurrent mount() calls to initialize in parallel

[0.47.0] - 2026-08-14

Changed

  • Breaking: Change the app-mount Bash default working directory from /home/user to /

[0.46.0] - 2026-08-13

Changed

  • Breaking: Replace the mesa.fs.mount({ repos }) mount syntax with the new mesa.fs({ layout, ... }).mount(...) syntax
  • Breaking: Remove FsMountReposOptions. mount() now only accepts cache and telemetry; pass ttl and authors to mesa.fs() instead
  • Breaking: Change repo() to select a checkout revision with the at field instead of bookmark / changeId

Added

  • Add branchedFrom to repo() to fork a new change the first time the mount opens the repo

Removed

  • Breaking: Removed the async mesa.resolveOrg() method. The organization slug is now available synchronously via mesa.org.slug.
  • Breaking: Remove org from the TypeScript SDK constructor and resource methods; the SDK derives the organization from the credential
  • Breaking: Remove vcsUrl option from the client configuration
  • Breaking: Replace all singular author options with a plural authors

Fixed

  • Fix repo() at pins being overridden when the organization’s configuration forks the repo on open

[0.45.0] - 2026-08-11

Changed

  • Point package source and issue links to the public SDK repository
  • Breaking: Remove top-level RepoConfig.bookmark, RepoConfig.changeId, and RepoConfig.readOnly (and the deprecated FromRevision type). Use at / branchedFrom and mode instead
  • Breaking: Resolve fs.change.new({ bookmark }) (and edit / mount at.bookmark) strictly against refs/heads/<name>. A string that is not a bookmark no longer falls through server-side revspec resolution to a change id; pass changeId to fork from a change

Added

  • Add mount RepoConfig fields mode, at, and branchedFrom to open an existing revision or fork a new revision at mount time (create change → optional as.bookmark → publish checkout; omit as.bookmark for an anonymous tip)

Removed

  • Breaking: Remove API-key authentication from the SDK, including apiKey, MESA_API_KEY, legacy HS256 token minting, and MissingApiKeyError; use privateKey or auth.accessToken instead

[0.44.1] - 2026-08-09

Changed

  • Split native filesystem write batches to the server-advertised VCS operation and message-size limits

[0.44.0] - 2026-08-07

Changed

  • Resolve the organization for auth.accessToken locally from its JWT issuer and reject opaque or malformed tokens instead of making an implicit /whoami request
  • Limit signing-key token and commit attribution to 100 ordered authors
  • Deprecate the apiKey client option, the MESA_API_KEY environment fallback, and the apiKeys resource in favor of private keys, and the org client option (the organization is derived from the credential); API keys remain supported
  • Change native addon loading to fail with the actionable Unable to load mesafs-napi native addon error (original failure attached as cause) when the package is installed but no platform binary is present

Added

  • Allow private-key authentication to carry ordered commit authors, with explicit authors required for token creation, commit writes, and mounts
  • Add custom mount layouts, created by calling mesa.fs({ layout, ttl })
  • Add token() and layout() on the FS mount definition for serializing a token and layout file that can be passed into a sandbox
  • Add fs.change.checkpoint({ repo, message? }) to flush pending writes (serializing concurrent writes and tree mutations in the same repo), optionally describe the current change, create a new descendant change, and advance bookmarks onto that descendant (requires the checkout to already be on a bookmark). Concurrent bookmark-tip races raise a retryable conflict (distinct from not-on-a-bookmark and from a half-applied checkout failure). Omit message to preserve the existing description; pass message: '' to clear it; any other string overwrites. Returns CheckpointResult with savedChangeOid (saved change) and activeChangeOid (now-active empty descendant)

[0.43.0] - 2026-08-02

Added

  • Allow private keys to authenticate normal SDK requests and MesaFS mounts with new Mesa({ privateKey }). Private-key clients can also mint scoped access tokens locally with tokens.create(), and those tokens can authenticate another client through auth.accessToken
  • Add repository ID restrictions to locally signed access tokens with mesa.tokens.create({ repo_ids: [...] })

Changed

  • Breaking: Require REST and native filesystem bookmark moves to advance history by default; pass allow_backwards or allowBackwards to permit intentional backward or sideways moves
  • Breaking: Change Mesa.apiKey from string to string | undefined; it remains a string for API-key clients and is undefined for private-key and access-token clients

[0.39.0] - 2026-07-08

Added

  • Add structured tag filter objects to mesa.repos.list(), with $-prefixed case-insensitive operators ($and, $or, $not, $eq, $in, $contains, $starts_with, $ends_with, $exists) and case-insensitive tag matching

Deprecated

  • Deprecate legacy comma-separated repo tag filters in favor of structured tag filter objects

[0.38.0] - 2026-06-22

Fixed

  • Fix files written through the SDK transiently disappearing during bursts of writes

[0.37.0] - 2026-06-17

Fixed

  • Repeated filesystem operations on the same repository are now dramatically faster

[0.36.0] - 2026-06-09

Added

  • Add mesa.tokens.create() to sign a self-expiring access token (JWT) locally from an API key, scoped to a subset of the key’s scopes and to repositories given as full org/repo names. Signing is local with no network call; a ttl_seconds outside 1 second to 24 hours raises InvalidOptionsError
  • Add a ttl option (seconds) to fs.mount() to set how long the mount lasts. The mount signs one access token for that lifetime and expires with it. Defaults to 1 hour, capped at 24 hours
  • Add MesaFileSystemConfig.credential as the preferred name for the bearer-credential field, which accepts an access token (JWT) or an API key
  • Add MissingCredentialError as the preferred name for the error thrown when the Mesa constructor is given no API key (and MESA_API_KEY is unset)

Changed

  • fs.mount() now signs a short-lived access token locally from your API key instead of creating an ephemeral API key on the server. No server-side credential is created or left behind, and the mount expires on its own when the token does

Deprecated

  • Deprecate MesaFileSystemConfig.apiKey in favor of credential. The apiKey field is still accepted; supply exactly one (credential wins if both are set)
  • Deprecate MissingApiKeyError in favor of MissingCredentialError. The old name is retained as an alias of the same class, so instanceof checks under either name keep working

Removed

  • Remove the automatic API key cleanup that ran on process exit; fs.mount() no longer creates server-side keys

[0.35.0] - 2026-06-07

Changed

  • Change mesa.fs.mount() native addon loading to use the @mesadev/mesafs-napi package while keeping MESA_NAPI_PATH as a local override

[0.34.0] - 2026-06-01

Added

  • Changes in Mesa are now realtime by default. Concurrent editors mounted on the same change will see one another’s modifications within a few seconds.
  • Add MesaFileSystem.subscribe(handler) for filesystem invalidation callbacks across mounted changes. Call unsubscribe() on the returned subscription to stop.

Removed

  • Remove the experimental multiplayer filesystem APIs.

[0.33.0] - 2026-05-26

Added

  • Add per-repo readOnly?: boolean to RepoConfig in fs.mount(...). When true, the mesa daemon rejects writes to that repo with EROFS, so a single mount can carry a mix of writable and read-only repos.

Changed

  • Change responses now report parent change IDs instead of commit SHAs of prior versions of the same change.

Removed

  • Breaking: Remove the mount-wide mode?: 'ro' | 'rw' option from fs.mount(...) and MesaFileSystem.create(...). Set readOnly on each RepoConfig instead. The minted API key always carries read and write scopes; read-only enforcement is performed client-side by the mesa daemon

[0.32.0] - 2026-05-22

Added

  • Add multiplayer.subscribe() for event-emitter style multiplayer event streaming. Returns a MultiplayerSubscription that emits remote-change (with generation) and peers-changed (with count) events. Call .unsubscribe() to stop.
  • Add multiplayer.watch() for AsyncIterable-based multiplayer event streaming. Yields MultiplayerEvent objects and supports AbortSignal for cancellation.

[0.31.0] - 2026-05-21

Added

  • Add setMetadata / getMetadata / clearMetadata on MesaFileSystem for reading and writing per-file metadata as plain key/value pairs (e.g. { origin: 'notion:page_foo' }). setMetadata merges per key; passing null or an empty string as a value deletes that key, so one call can mix sets and deletes. getMetadata returns all keys including the read-only org/repo. clearMetadata removes every key on a path.

Changed

  • Breaking: Rename the client.repos.content.get(...) metadata surface from xattrs to metadata. Responses now expose metadata?: Record<string, string> instead of xattrs?, and directory listings filter via metadata key/value pairs instead of xattr pairs.

[0.30.0] - 2026-05-19

Added

  • Respond to client.repos.content.get(...) with optional xattrs?: Record<string, string> metadata for files, symlinks, directories, and directory entries when present.
  • Add xattr filters to client.repos.content.get(...) directory listings, returning entries that match all supplied xattr name:value pairs.
  • Add message support to fs.change.new(...) for setting the description of a newly created mounted-filesystem change.

Changed

  • mesa.changes.create(...) and mesa.changes.patch(...) now accept empty string descriptions. Omit message on create to create a change with no description, or omit it on patch to preserve the existing description; pass "" to create or update a change with no description.
  • mesa.bookmarks.merge(...) now accepts message; omit it to use the generated merge description, or pass "" to create the merge with no description.

[0.29.3] - 2026-05-18

Fixed

  • Make every mesa.fs write durable before the operation returns

[0.29.2] - 2026-05-17

Added

  • Add mesa.bookmarks.get({ repo, bookmark }) for direct bookmark lookup by name, and add glob filtering to mesa.bookmarks.list({ repo, glob })
  • Add optional ref_globs filters to mesa.repos.syncUpstream(...): omit it to sync all supported branches and tags, or pass branch/tag glob strings such as { branches: "main" }

[0.29.1] - 2026-05-16

Fixed

  • Fix mesa.fs.mount() native addon loading by restoring platform package entrypoints and falling back to direct mesa-napi.node resolution

[0.29.0] - 2026-05-15

Added

  • Add VIRTUAL_ROOT_CHANGE_ID export for referencing the virtual-root sentinel change id from @mesadev/sdk
  • Add mesa.repos.syncUpstream({ repo, direction }) for triggering an sync with a repository’s upstream. Returns the sync row; the worker processes it asynchronously. Read repo.upstream.latest_sync, call mesa.repos.getUpstreamSync({ repo, syncId }), list mesa.repos.listUpstreamSyncs({ repo }), or subscribe to sync.{queued,in_progress,completed,failed} webhooks
  • Add mesa.repos.{getUpstreamSync, listUpstreamSyncs} for reading repository upstream sync history
  • mesa.repos.create and mesa.repos.update accept an upstream: { url, auth? } field to add or replace the repository upstream. The auth payload is inline: { kind: 'token', token, token_username? } or { kind: 'username_password', username, password }. mesa.repos.update accepts upstream: null to remove. Repository responses include the upstream configuration with latest_sync; secrets are never returned
  • Surface sync.queued, sync.in_progress, sync.completed, and sync.failed webhook event types

Changed

  • Resolving the default bookmark of a freshly created (never-written-to) repo continues to return the virtual root sentinel change_id. The server-side lazy-seed behavior is transparent to SDK consumers — the first write through any path advances the bookmark to a real change (MES-1387)

Fixed

  • Fix REST API errors to throw human-readable MesaApiError instances while preserving structured response metadata

Removed

  • Breaking: Remove the public mesa.raw generated REST operation namespace; use @mesadev/rest directly for low-level REST access

[0.28.2] - 2026-05-07

Added

  • Add fs.change.current({ repo }) to query the currently active change on a mounted repo. Returns ChangeInfo with changeId and commitOid.

[0.28.1] - 2026-05-06

Changed

  • Rename SIGNATURE_HEADER export from x-depot-signature to x-mesa-signature. Consumers verifying webhook signatures must update to match the new header name.
  • Coordinate MesaFileSystem cache budgets across instances in a single process; disk_cache.max_size_bytes: null now auto-sizes against system resources instead of being unbounded

Fixed

  • Fix rg and other tools that resolve /.. by clamping resolve_path at the filesystem root.

[0.28.0] - 2026-05-03

Added

  • Added support for conflicts in the FS interfaces. Conflicting files render jj-style conflict semantics.

Fixed

  • Surface LOCK_CONFLICT instead of INTERNAL_ERROR on concurrent bookmark writes.
  • Fixed race condition in cache deallocation theoretically causing crashes.

[0.27.0] - 2026-04-30

No user-facing changes.

[0.26.0] - 2026-04-29

Changed

  • Breaking: Rename “upstreams” to “remotes” across all SDK interfaces.

Fixed

  • Fix repo list cache not being exercised through the SDK codepath, hitting an uncached API on every call.