Skip to main content

Prerequisites

  • Python 3.11+
  • uv package manager (optional)

System FUSE

Install the OS-level FUSE driver first (see the support matrix for the full OS overview):

Install Mirage with the FUSE Extra

Or with uv:

Verify

If the printed path exists under /tmp/mirage-*, FUSE is wired up correctly. The Workspace constructor blocks until every fuse mount is live, so the mountpoint is ready to read as soon as the with block is entered, no sleep needed. (In TypeScript, where mounts are async, you await ws.fuseReady() instead.)

Per-mount FUSE

FUSE is configured per mount. Each mount whose fuse is set is exposed at its own mountpoint, showing only that mount’s subtree. The value is either true (mount at a fresh temp directory) or a path string (mount there, creating the directory if missing):
ws.fuse_mountpoints returns a {prefix: path} map of the live mountpoints.

Size semantics for API-backed files

Some resources (Linear, Trello, Slack, …) cannot report a file’s size without fetching its content, so stat returns an unknown size. Over the FUSE mount these files behave like Linux /proc files: they stat as 0 bytes until first open, and become fully readable the moment anything opens them. Mirage mounts with direct_io (the kernel reads to EOF regardless of the reported size) and attr_timeout=0 (post-open fstat returns the real size of the now-fetched content, kept warm in a 30-second cache). What that means per tool: Mirage never reports a fake size and never fetches content during stat: returning real sizes eagerly would fire one API call per file on every ls -l.
Windows differs: it cannot query attributes without opening a handle, so a per-file stat of a size-unknown file fetches the content and shows the real size immediately. Directory listings stay cheap. See Windows FUSE Setup for the other Windows-specific behaviors (unmount at process exit, mount-level ownership).
macOS allows only one in-process FUSE mount. macFUSE registers a process-global signal source, so a second simultaneous mount in the same process fails with fuse: cannot register signal source. Multiple per-mount FUSE mounts work on Linux and Windows; on macOS, enable fuse on a single mount per workspace (or run additional mounts in separate processes).
Symlinks live in Mirage’s namespace, not in any backend. Links created with ln -s in the Mirage shell (or with ln -s inside the mountpoint) appear as real symlinks over FUSE: ls -l shows lrwxrwxrwx, readlink prints the target, and reads follow the link. Absolute targets are displayed relative to the link’s directory so they always resolve inside the mountpoint. Permission bits shown over FUSE come from Mirage’s metadata (chmod, chown, touch results), and they are display only: access control is enforced by Mirage mount modes, not by the kernel. For that reason, never mount with the default_permissions FUSE option. It would make the kernel enforce the displayed bits, and a chmod 000 could lock Mirage out of its own files.