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.48.1 - 2026-09-15

Added

  • Answer grep and rg with server side search capability

Fixed

  • Fix filesystem checkpoint on empty repositories by initializing the first change before saving and advancing bookmarks

0.48.0 - 2026-09-10

Changed

  • Breaking: Rename FsLayoutAuthor to Author for commit attribution across commit-producing operations
  • Breaking: Rename the access-token-only MesaFileSystemConfig.credential field to accessToken and report an empty value with MissingAccessTokenError (MISSING_ACCESS_TOKEN)
  • Breaking: Rename MissingCredentialError to MissingPrivateKeyError and its code from MISSING_CREDENTIAL to MISSING_PRIVATE_KEY
  • Breaking: Consolidate LayoutSpec and the prepared Layout wrapper into a validated, plain Layout map; serialize it with JSON.stringify()

Added

  • Add authors and authored_at to change.created and change.evolved webhook events; email is null when none was supplied
  • Add authors and authored_at to change results

Removed

  • Breaking: Remove the deprecated singular author from change results and from normalized change.created / change.evolved webhook events; read authors and authored_at instead. Raw @mesadev/rest responses keep author for API compatibility
  • Breaking: Remove MesaFileSystem.create() and stop exporting MesaFileSystem as a value; it remains exported as a type for annotating the result of mesa.fs({ layout, authors }).mount(), which is now the only way to open a filesystem. MesaFileSystem.createAsync() and MesaFileSystem.validateLayout() are no longer reachable from the package entry point
  • Breaking: Remove legacy comma-separated repository tag filters from mesa.repos.list(); pass a structured RepoTagFilter object instead
  • Breaking: Remove positional private-key, nested auth, and access-token construction from Mesa; construct with new Mesa() or new Mesa({ privateKey, ...options }), and pass scoped tokens to the CLI, mounted MesaFS environments, or direct REST calls instead
  • Breaking: Remove API-key management methods and the deprecated MesaFS apiKey configuration alias
  • Breaking: Remove mesa.tokens.create(). Mint through a layout definition instead: mesa.fs({ layout, ttl }).token(), which scopes the token to the repositories the layout declares

[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.