> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mirage.strukto.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# FUSE

> Set up FUSE support for MIRAGE with the TypeScript SDK.

## Prerequisites

* Node.js 20+
* [pnpm](https://pnpm.io/) (recommended, `npm` and `yarn` also work, but the FUSE binding's install script needs extra configuration with pnpm).

## System FUSE

Install the OS-level FUSE kernel support first:

* [macOS FUSE Setup](/home/setup/macos), macFUSE + kernel extension + Apple Silicon recovery mode steps.
* [Linux FUSE Setup](/home/setup/linux), `fuse3` install and `/etc/fuse.conf`.

## Install the Node Binding

The Node package (`@struktoai/mirage-node`) ships FUSE support via an **optional peer dependency** on [`@zkochan/fuse-native`](https://www.npmjs.com/package/@zkochan/fuse-native), the pnpm author's actively-maintained fork that works on Node 20+ and supports both macOS and Linux (thanks to [@zkochan](https://github.com/fuse-friends/fuse-native/issues/36#issuecomment-3089754579)).

```bash theme={null}
pnpm add @struktoai/mirage-node @zkochan/fuse-native
```

<Tip>
  Non-FUSE users don't need `@zkochan/fuse-native`, the base `@struktoai/mirage-node` package works without it. Only install the binding when you want a real mountpoint.
</Tip>

### Allow pnpm to run the install script

`@zkochan/fuse-native` compiles native code on install. pnpm blocks install scripts by default, allow this one explicitly in `pnpm-workspace.yaml`:

```yaml theme={null}
onlyBuiltDependencies:
  - '@zkochan/fuse-native'
```

Or, if you're not using a pnpm workspace, in `package.json`:

```json theme={null}
{
  "pnpm": {
    "onlyBuiltDependencies": ["@zkochan/fuse-native"]
  }
}
```

## macOS 4+ Symlink Workaround

<Tabs>
  <Tab title="macOS">
    macFUSE 4 ships `libfuse.2.dylib` instead of the legacy `libosxfuse.2.dylib` that `@zkochan/fuse-native` was built against. Create a one-time symlink:

    ```bash theme={null}
    sudo ln -sf /usr/local/lib/libfuse.2.dylib /usr/local/lib/libosxfuse.2.dylib
    pnpm rebuild @zkochan/fuse-native
    ```
  </Tab>

  <Tab title="Linux">
    No workaround needed on Linux, `@zkochan/fuse-native` links against `libfuse3` directly.
  </Tab>
</Tabs>

## Verify

```ts theme={null}
import { Mount, MountMode, RAMResource, Workspace } from '@struktoai/mirage-node'

const ws = new Workspace({
  '/data': new Mount(new RAMResource(), { mode: MountMode.WRITE, fuse: true }),
})
await ws.fuseReady()

await ws.execute('echo hello | tee /data/x.txt')
console.log('mountpoints:', ws.fuseMountpoints)

// Any tool (ls, cat, external subprocess) can now see x.txt under the mountpoint.
await ws.close() // auto-unmounts
```

If `ws.fuseMountpoints` prints a `/tmp/mirage-fuse-XXXXXX` path and no error is thrown, the binding is wired up correctly.

Mounts are async, so `await ws.fuseReady()` once after constructing the workspace; it resolves when every `fuse` mount is live (and rejects if one fails to mount). Until then `ws.fuseMountpoints` may be empty. (In Python, where mounts are synchronous, the constructor blocks until ready 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):

```yaml theme={null}
mode: WRITE
mounts:
  /data:
    resource: ram
    fuse: /tmp/data-repo   # explicit path
  /s3:
    resource: s3
    fuse: true             # temp directory
```

Programmatically, set `fuse` per mount: `{ '/data': new Mount(dataResource, { fuse: '/tmp/data-repo' }), '/s3': new Mount(s3Resource, { fuse: true }) }`.
`ws.fuseMountpoints` returns a `{ prefix: path }` map of the live mountpoints.

<Note>
  FUSE on Node has a runtime constraint worth knowing, `fs-monkey` can't patch ESM `node:fs` imports. See [TypeScript Limitations](/typescript/limitations) for details and workarounds.
</Note>

<Warning>
  **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. Multiple per-mount FUSE mounts work on Linux; on macOS, enable
  `fuse` on a single mount per workspace (or run extra mounts in separate
  processes).
</Warning>
