# strukto-ai/mirage: A Unified Virtual Filesystem for AI Agents

> Mirage mounts S3, Google Drive, Slack, Redis and dozens of other backends as one filesystem that an agent drives with ordinary bash. The idea is strong; the ecosystem is early and the filetype layer is deliberately empty.

**strukto-ai/mirage** — The Unified Virtual Filesystem For AI Agents. **Embeddable:** the Python and TypeScript SDKs run in-process inside FastAPI, Express, browser apps, or any async runtime; no separate process required.

- Repository: https://github.com/strukto-ai/mirage
- Website: https://www.strukto.ai/mirage
- Stars: 3,663 · Forks: 270
- Language: TypeScript
- License: Apache-2.0
- Published: 2026-08-04 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/strukto-ai-mirage

## The problem: N SDKs and M MCP servers for one agent

An agent that needs to read a Slack thread, pull a CSV out of S3, and write a summary into Redis usually ends up with three client libraries, three credential stories, and three different notions of what a "file" is. Each new backend adds another tool definition the model has to learn, and tool definitions cost context. Mirage's answer is to stop adding tools. It mounts every backend under a single root and exposes POSIX operations over them, so the agent keeps using the vocabulary it already has: ls, cat, grep, cp, and pipes. The README frames this as "one interface instead of N SDKs and M MCPs." The target user is not someone building a file browser. It is someone whose agent loop is already bash-shaped and who wants Slack channels and S3 prefixes to look like directories. The README claims around 50 built-in backends, spanning object storage (S3, R2, OCI, Supabase, GCS), documents and mail (Gmail, GDrive, GDocs, GSheets, GSlides), trackers (GitHub, Linear, Notion, Trello), chat (Slack, Discord, Email), databases (MongoDB, GridFS, Postgres, LanceDB, Qdrant), and SSH. That breadth is the pitch, and it is also the first thing to be skeptical about, because a backend that exists is not the same as a backend whose semantics survive a cp.

## How the mount model actually works

A Workspace is constructed from a mapping of mount path to resource plus a MountMode. In the Python example the README gives, /tmp is a RAMResource mounted EXEC, /redis is a RedisResource mounted WRITE, and /slack is a SlackResource mounted EXEC. The mode is the interesting part, because it tells you the authors expect the same underlying service to be usable in different ways depending on what you want the agent to do with it. Read, write, and execute are separate grants rather than one blanket permission.

The second piece is runtimes. The same example passes runtimes=[MontyRuntime(captures=["python", "python3"]), "vfs"]. Monty captures the python and python3 commands, so a script invoked inside the workspace runs sandboxed rather than on the host. The "vfs" runtime handles the filesystem verbs. This is what makes the README's demo work: a Python script that lives in a Slack channel can be executed and its output filed into Redis, in one execute call, without the script ever touching the host interpreter.

Commands are dispatched per resource, and per filetype. The README states that POSIX operations such as read can be customized per resource and filetype, and that Mirage ships no filetype renderers, so a format renders however you register it. A command registered for one resource and extension wins over the generic one. That is a clean override rule. It also means the default experience for, say, reading a .docx out of Google Drive is whatever the generic path does, not a rendered document. The empty renderer set is a design decision, not an oversight, but it shifts work onto you.

## Installing Mirage and running a first cross-backend command

The README lists Python 3.11 or newer for the mirage-ai package and the mirage CLI, Node.js 20 or newer for the TypeScript SDK, and macOS or Linux, noting that FUSE-based mounts require platform support. Windows is not in that list.

For Python, the documented install is a single uv command. It pulls in both the library and the CLI binary:

```bash
uv add mirage-ai
```

For TypeScript there are three packages, split by runtime. A Node server or CLI wants the node package, a browser or edge runtime wants the browser package, and the agent adapters are separate:

```bash
npm install @struktoai/mirage-node
npm install @struktoai/mirage-browser
npm install @struktoai/mirage-agents
```

The README notes both runtime packages pull in @struktoai/mirage-core automatically, so you should not need to install the core package by hand.

A first workspace needs two mounts that cannot fail on credentials. RAM and S3 is the pairing the quickstart uses, and it is the right one to start with because RAM has nothing to authenticate:

```python
from mirage import Workspace
from mirage.resource.ram import RAMResource
from mirage.resource.s3 import S3Config, S3Resource

ws = Workspace({
    "/data": RAMResource(),
    "/s3":   S3Resource(S3Config(bucket="my-bucket")),
})

await ws.execute("cp /s3/report.csv /data/report.csv")
await ws.execute("grep alert /s3/data/log.jsonl | wc -l")
```

The first execute copies an object out of the bucket into RAM. The second pipes grep into wc, which is the shape Mirage is built around: ordinary shell composition across a network backend and a memory backend. The TypeScript API mirrors it almost token for token, with the same Workspace constructor taking a path-keyed object of resource instances. If you prefer the CLI, the documented flow is create, execute, snapshot, load:

```bash
mirage workspace create ws.yaml --id demo
mirage execute   --workspace_id demo --command "cp /s3/report.csv /data/report.csv"
mirage workspace snapshot demo demo.tar
mirage workspace load demo.tar --id demo-restored
```

Credentials come from the environment. The repository ships an .env.example with keys for R2, AWS, Box, Trello, Notion, Slack, IMAP and SMTP, Dropbox, Daytona, Hugging Face, Nextcloud, and Upstash Redis, so the expected workflow is to fill in the backends you actually mount and leave the rest blank.

## Snapshots are the feature to test before you commit

Portable workspaces are the claim that separates Mirage from a thin wrapper over cloud SDKs. The README says you can clone, snapshot, and version a workspace, and that agent runs move between machines without restarting or reconfiguring the system. The quickstart shows the mechanism as a single call, await ws.snapshot("demo.tar"), and the CLI equivalent writes demo.tar and later loads it under a new id.

What the documentation does not spell out is what lands in that tar. A RAM mount has bytes to serialize. An S3 mount does not, and a Slack mount certainly does not. Whether a snapshot stores the mount definitions, the credentials, the materialized contents, or some combination is the single most important thing to verify on your own setup, because the answer determines whether a snapshot is a portable artifact or a recipe that only works while the original credentials remain valid. The README does not document rollback either, so versioning a workspace and reverting one are not the same thing here. Treat snapshot and load as the pair to exercise first, with a RAM-only workspace, before you build a workflow on top of them.

## Where Mirage is the wrong tool

The filetype renderer gap is the sharpest limitation. Mirage ships no filetype renderers, and the README is explicit that a format renders however you register it. If your workload is "read this PDF and answer questions about it," you are not getting a PDF reader. You are getting a byte stream and an extension, plus whatever you write to turn one into the other. The per-resource, per-extension override rule is good design, but it is a hook, not a library.

Platform support is the second boundary. FUSE-based mounts require platform support, and the install section lists macOS and Linux only. If your deployment target includes Windows hosts, the FUSE path is not available to you, and the README does not describe a Windows substitute.

Third, the release history is short. The most recent release, v0.0.5, was published on 2026-08-15, following v0.0.4 on 2026-07-23 and v0.0.3 on 2026-06-30. The last push to the default branch was on 2026-08-15. Three releases in roughly six weeks is a fast-moving pre-1.0 project, and the version numbers say so. Anything you build against these APIs should assume breakage between minor versions. If you need a filesystem abstraction that will not move under you, this is not it yet. If your agent needs a single-purpose integration with one service, a plain SDK is less machinery than a mount table, a runtime list, and a snapshot format.

## What it replaces, and what it does not

The obvious alternative is the direct SDK approach: call boto3 for S3, the Slack Web API for channels, and a Redis client for the cache, each behind its own tool definition. That approach has no new abstraction to learn and no mount semantics to reason about, and every operation maps to a documented vendor call. Its cost is exactly what Mirage is trying to remove: the agent needs a tool per service, the credentials live in three places, and cross-service work has to be orchestrated in application code rather than in a pipeline.

A closer comparison is a FUSE-based virtual filesystem such as rclone mount or a generic VFS layer. Those also present remote storage as paths, and they are far more mature at the filesystem part. The difference is the agent-facing layer. Mirage adds MountMode grants, a runtime list that captures interpreters so scripts execute inside the workspace, per-resource command overrides, and workspace snapshots. rclone gives you a mount and expects the process on the other side to be a normal program. Mirage expects the process on the other side to be an LLM that writes bash. That is a narrower bet, and it is the reason the project exists. If your consumers are humans or ordinary daemons, a plain mount is the better fit.

## Licence and the cost of keeping up

Mirage is licensed under Apache-2.0, according to the repository's LICENSE file and the licence identifier on the project. Apache-2.0 is a permissive licence with an explicit patent grant and a requirement to preserve notices, which matters if you embed the SDKs in a product. It does not impose copyleft on your application code. The repository also carries a licenses/ directory alongside the top-level LICENSE, which is worth reading before you ship, since bundled backends can carry their own terms. None of this is legal advice; if you are redistributing, have counsel read the notices rather than a review of the README.

The upgrade cost is the part to plan for. Three releases between 2026-06-30 and 2026-08-15, all at 0.0.x, means the API surface is still settling. The repository layout suggests the maintainers take compatibility seriously enough to ship a conformance/ directory and a spec/ directory, which is a good sign for anyone pinning versions, but the README does not make a stability promise. Pin your version, run the examples in examples/python/ and examples/typescript/ against it after each bump, and keep your mount definitions in one place so a rename in the Workspace constructor is a single edit.

## Conclusion

Adopt Mirage if your agent already reasons in shell commands and you need several backends behind one path namespace, and start from a RAM mount plus one real backend before adding more. Skip it if you need a stable API today, since the latest release is v0.0.5 and the filetype rendering layer ships empty, or if FUSE mounts on Windows are part of your plan. Verify three things first: that your Python is 3.11 or newer or your Node.js is 20 or newer, that each backend you mount has working credentials, and that a snapshot taken with ws.snapshot restores into a workspace whose paths you actually expect.

## FAQ

### What is Mirage in simple terms?

It is a virtual filesystem that mounts services such as S3, Google Drive, Slack, and Redis under one root, so an agent can read, grep, and pipe across them with ordinary bash commands instead of a separate SDK per service.

### How do I install Mirage for Python?

The README documents uv add mirage-ai, which installs both the mirage library and the mirage CLI binary. Python 3.11 or newer is required, and the supported platforms are macOS and Linux.

### Does Mirage work in the browser?

Yes, via the separate @struktoai/mirage-browser package, which the README lists for browser and edge runtimes alongside the Node package. Both pull in @struktoai/mirage-core automatically.

### Can Mirage read document formats like PDF or DOCX?

Not out of the box. The README states that Mirage ships no filetype renderers, so a format renders however you register it, and a command registered for one resource and extension wins over the generic one.

## Sources

- [Official documentation](https://www.strukto.ai/mirage)
- [Official README](https://github.com/strukto-ai/mirage#readme)
- [Project repository](https://github.com/strukto-ai/mirage)
- [Release notes](https://github.com/strukto-ai/mirage/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/strukto-ai-mirage
