Skip to content

Releases: strukto-ai/mirage

Mirage 0.0.6

Choose a tag to compare

@zechengz zechengz released this 03 Sep 16:25
5678c94

We are excited to announce the release of Mirage 0.0.6 🎉🎉🎉

Mirage 0.0.6 is a permissions release. 0.0.5 gave an agent typed programs to act with; 0.0.6 decides what it may do with them. A permissions document replaces the old guard list: allow, ask and deny rules, one role per session, mounts that narrow rather than gate, hidden subtrees that stay hidden through a mutation, an approval door where an asked line reaches a person, and a decision ledger you can query and explain. A policy can now be a program, written in Python or JavaScript and judged at the command, op and session doors. Credentials move behind a secrets plane instead of sitting in a config block. Underneath, a long deduplication pass collapses the backends onto shared HTTP, object-store, hierarchy and render kits, the integration fakes become one TypeScript and Prisma kit that runs off a laptop, bash grows most of tiers 2 and 3, guests see one filesystem through a single stat struct, and Hugging Face Hub arrives as both a mount and a CLI. Python and TypeScript stay mirrored throughout.

pip install mirage-ai==0.0.6 · npm install @struktoai/mirage-core@0.0.6 (and -node, -browser, -server, -cli, -agents)

@struktoai/mirage-dsh joins the shared version line at 0.0.6. It was published once as 0.0.1; the versions between were never released.

Highlights

  • Permissions are a document, not a guard list. A permissions document with profiles replaces the guards (#857), carrying allow, ask and deny rules with an approval door where an asked line reaches a person (#865). A session holds one role, and a mount narrows what that role may reach instead of gating it (#876). The path axis gained show entries, per-subtree modes and hide reasons (#896), and a mutation below a hidden path resolves without revealing it (#901). Every decision lands in a ledger with explain and whole-line judging (#880), reachable through an asks door and workspace-level list-asks, allow and deny (#899). Documented, with (approval <id>) renamed (ask <id>) (#900).
  • A profile's policy can be a program. A profile takes a script rather than only coded rules (#884), and the policy block's program defines which gate hooks exist: pre_command, pre_ops and pre_session, probed once per program text, with a hook left out meaning silence and none at all failing closed (#997). The op-door boundary is stated and pinned (#908), coded pre_ops binds on the command tier (#909), and dsh routes allow, ask and deny through its own approval channel (#890).
  • Credentials live on a secrets plane. Env-plane managed credentials arrive first (#960), then a config plane and a 1Password source (#973), and finally a mount or CLI credential that reads from that plane rather than holding the value (#978). Alongside it, every TypeScript mount config now validates through one door, with the two languages' field sets gated against each other (#994).
  • The backends collapse onto shared kits. One HTTP client kit with notion and discord as exemplars (#835), then every hand-rolled client onto it (#841). One JSON render kit for .json and .jsonl bodies (#823). An object-store kit and a hierarchy kit (#848), taking hf and opfs (#858), postgres, mongodb and the google trio (#868), trello, linear, notion and gcal (#870), discord, slack, gmail and email (#874), and lancedb and qdrant with per-mount routes (#875). The 42 S3-alias resources collapse onto a shared base (#866), and a TypeScript backend is assembled from one CommandIO table (#883).
  • The integration fakes are one TypeScript and Prisma kit. The mock servers unify (#916) and the services follow: dropbox, box and onedrive (#919), slack, notion and mem0 (#925), the hf buckets (#927), databricks, dify and http (#928), and github (#935). They can run somewhere other than a developer's laptop (#905), a run axis rides the URL so two hosts stop sharing one world (#945, #946, #947), and one launcher hosts them all behind pooled sessions (#965).
  • Hugging Face Hub is a mount and a CLI. A Hub repo mounts, with the hf CLI beside it (#931), exercised against a fake in CI (#934), read-only by default (#937), and serving Hub metadata and search (#939). The fake answers hf_fs errors the way the live server does (#974), advertises the discovery scopes it claims (#982), serves hf://README.md because the tool document tells the model to read it (#976) and /raw/ (#979).
  • bash tiers 2 and 3. The export attribute and identifier validation (#816); associative arrays, declare attributes, readonly -f and the jobs flags (#824); then let, umask, shopt, alias, mapfile, the read flags, declare -g/-n, disown/wait and exec (#833).
  • Guests see one filesystem. Every path-taking os verb routes through the workspace (#877), symlink, readlink and setattr are served (#879), a readdir row carries the link mark (#881), and one stat struct sits at the runtime door with each surface projecting it (#882). Engines and sandbox SDKs are upgraded with the monty Python and TypeScript guest-behavior gaps closed (#904), and the history view and root anchor are withheld from runtimes (#932). Two new providers: a smolvm microVM and a confined sandlock Python runtime (#834), and ssh (#852).
  • Errors say what the kernel would say. A prefix holding no keys is ENOENT rather than an empty directory (#809, #815), a path under a file is ENOTDIR rather than ENOENT (#813), a directory read carries GNU's errno and exit code (#895), rmdir refuses a non-empty directory at the op rather than only in the builder (#854), and every refusal now speaks bash's Permission denied instead of each command's own wording (#993).
  • Redis reaches the browser through Upstash's REST API, so a browser workspace can use the same cache and store as node (#992).

Breaking Changes

  • Guards are gone. The permissions document and its profiles replace them (#857); a session holds one role and a mount narrows rather than gates (#876).
  • build_resource is synchronous again (#820), reversing the 0.0.5 change; github hydrates lazily instead. Code written against 0.0.5's await build_resource(...) drops the await.
  • FileType is the node kind, and content type is its own axis (#878).
  • core is imported by module path. index.ts drops from 1589 lines to 102, so a deep import replaces the barrel (#805), and the dead exports around it are swept (#814).
  • Builtin commands are per-command packages behind a BUILTINS table with tiers (#853).
  • ls -l reports the workspace user as owner and the session profile as group (#985).
  • A Hub mount is read-only (#937).
  • /dev/null and /dev/zero are character devices, not regular files (#910).
  • getState/loadState sit on the TypeScript Resource contract, mirroring Python's base (#800).
  • Routing is renamed and execution passes through an ExecContext seam (#944).
  • @struktoai/mirage-dsh moves from its own version line onto the shared one, from 0.0.1 to 0.0.6 (#998).

Features

  • permissions: the document and profiles (#857); allow, ask and deny with an approval door (#865); one role per session (#876); the path axis, per-subtree modes and hide reasons (#896); the asks door and workspace list-asks/allow/deny (#899).
  • policy: decision ledger, explain and whole-line judging (#880); profiles written by a script (#884); a policy block whose program defines the gate's hooks (#997).
  • secrets: env-plane managed credentials (#960); config plane and 1Password source (#973); mount and CLI credentials read from the plane (#978).
  • cli: virtual gh workflows (#915); builtin command catalogs (#929); custom authoring made first-class (#950) with an example (#940) and specs validated at construction (#933); the hf CLI (#931).
  • shell: bash tier 2 stage 1 (#816); associative arrays, declare attributes, readonly -f, jobs flags (#824); let, umask, shopt, alias, mapfile, read flags, declare -g/-n, disown/wait, exec (#833).
  • runtime: smolvm microVM and confined sandlock Python (#834); the ssh sandbox provider (#852); every engine and sandbox SDK upgraded (#904).
  • resource: a Hugging Face Hub mount (#931, #937, #939); Redis in the browser over Upstash (#992); mount parents, kit backend ops and a resource class reference (#887).
  • core: optional byte-range reads across backends (#810).
  • watch: delta_hook for ten more backends (#811); push event mapping and subtree invalidation (#817).
  • integ: a restricted-token GitHub fake, gh api --jq and notion retrieve-block (#819); branch history recorded when a ref moves (#969); the kit migration (#916, #919, #925, #927, #928, #935) and the run axis (#945, #946, #947, #965).

Bugfixes

  • cache: a rename evicts the destination's own listing, across thirteen backends, with disk Windows separators and databricks copy invalidation (#802); a recursive delete or directory rename evicts its subtree (#864, #863); the cache manager walks the ancestor chain (#838); the Redis file cache add is atomic (#830).
  • errors: a prefix with no keys is ENOENT (#809, #815); a path under a file is ENOTDIR (#813); a directory read uses GNU's errno and exit code (#895); rmdir refuses at the op (#854).
  • ls: a cross-mount listing is relayed so GNU headers and the global sort survive (#844); a nested mount's root is listed in its parent's -R listing (#847).
  • rename: directories move whole, on every backend that fakes them (#808).
  • search: the grep and rg push-downs are gated on operand count (#851), and the remaining find push-downs with them (#856).
  • shell: an orphaned $var expands in a redirect target, and record is forwarded through the daemon (#926); the tree-sitter engine boots once (#912).
  • naming: every <label>__<id> name is budgeted in bytes, not characters (#885); the gmail excerpt and daemon des...
Read more

Mirage 0.0.5

Choose a tag to compare

@zechengz zechengz released this 15 Aug 00:45
d4f2ff5

We are excited to announce the release of Mirage 0.0.5 🎉🎉🎉

Mirage 0.0.5 is a control-surface release. An agent no longer only reads a workspace, it acts on one through typed programs: a CLI tier turns git, gh, slack, ntn, himalaya, gws, linear, discord and anything you author into installed head words dispatched by name, and a policy layer sits at every door those programs pass through. Underneath, the workspace grows one door per state plane, the runtimes collapse onto a single mount-op vocabulary, background commands stream through a job console instead of arriving whole, and a new @struktoai/mirage-dsh package puts a mirage workspace under DeepSeek Harness as its filesystem and shell. Alongside that, a long conformance sweep pins commands, flags and error text against GNU and the real upstream CLIs. Python and TypeScript stay mirrored throughout, now with a layout parity gate that fails when they drift.

pip install mirage-ai==0.0.5 · npm install @struktoai/mirage-core@0.0.5 (and -node, -browser, -server, -cli, -agents)

New in this release: npm install @struktoai/mirage-dsh@0.0.1, the DeepSeek Harness adapter, on its own version line.

Highlights

  • CLIs are a first-class tier. A recursive CLISpec built on CommandSpec gives a program a typed verb tree (#682), installed host-side into a registry and dispatched by name rather than by operand path, with a clis: section in YAML (#691) and file-reference installs (#798). Builtin families land in waves: himalaya and gws (#699), slack, discord, ntn and linear (#703), git over any mount (#710), and gh with the write half of the GitHub fake (#768). You can author your own in code, by pointer, or as a script (#712), and every install is discoverable through man, type and which (#707) because help renders from the spec.
  • A CLI that mimics a real program is gated against that program. ntn runs every shared-battery case a second time against the real npm binary pointed at the same fake, so the grammar cannot drift from upstream without a red build (#740, #747, #756, #794), and himalaya was realigned to the upstream pimalaya grammar the same way (#709, #723, #761).
  • A policy layer with hooks at every door. route becomes policy and gains a deny verdict (#659), then a real package with pre_command absorbing the old command guards (#690), pre_ops/post_ops at the op doors (#692), ParsedCommand plus a cli fact and registry snapshot (#693), and output safeguards folded in as Limit (#694). Session writes join it: every expansion-time writer (${X:=d}, $((X=5)), printf -v, for ((...))) now passes through SessionView.set instead of around it (#791).
  • One door per state plane. Mount structure merges into the door's readdir and stat (#739), VFS and FUSE ops route through a single door in both languages (#753), and state doors with per-plane views (data, name, session) replace the ad-hoc threading (#771), with a shared FileHandle/FileTable behind the buffered handle tables (#760) and per-session hidden paths and vars via SessionProfile (#778).
  • Runtimes consolidate onto one vocabulary. A uniform runtime interface and one integ suite for all runtimes (#655), evaluator as a capability with PythonRuntime dropped (#657), a tiered taxonomy and TS runtime package layout (#726), one mount op vocabulary for the Python (#730) and TypeScript (#732) sandbox runtimes, a resolver protocol (#749), and guest op parity behind one Ops facade (#767). pyodide now serves from a custom Emscripten filesystem (#732), flushes without JSPI (#720), and routes guest mutations to the mount with appends staying additive (#728); monty moved to pydantic-monty 0.0.19 (#717); python3 parses CPython's real option table (#743).
  • Background commands stream. A JobConsole records a job's output as timestamped chunks on stdout/stderr/control channels, so a reader can follow a running command from any cursor (#611), with a Redis store and cross-language streaming integ beside the RAM one (#795).
  • DeepSeek Harness runs on mounted data. The new @struktoai/mirage-dsh package provides ctx.fs and ctx.shell over one workspace (#774), with session binding for the shell executor (#784), a bundle manifest that installs into a stock dsh profile with declarative mounts (#787), and streaming background output, sandbox facts and spill files (#796).
  • Archivers grew up. tar and zip plan every member from one shared traversal that merges the backend walk, the namespace's symlinks and the mount table, so a directory operand is walked rather than read, a symlink is stored as a symlink, and a nested mount is refused rather than silently archived (#738); tar accepts GNU's old option style (#734), unzip selects members and exits 11 on unmatched filespecs (#725), and the GPL bzip2 dependency is gone in favor of modern-tar plus MIT seek-bzip (#741).
  • Conformance as a gate, not a claim. A layout parity check diffs the Python and TypeScript module namespaces and fails on drift in either direction (#759), the integ runner fails on zero work rather than passing vacuously (#737), resource capabilities and CommandIO slots are spec-gated (#742), and the Python test tree moved onto the source layout so a source module without a test is visible (#763).

Breaking Changes

  • The bundled filetype renderers are gone. Parquet, ORC, feather/arrow/ipc and hdf5 rendering, the parquet/hdf5/pdf extras and the hyparquet/apache-arrow/h5wasm dependencies are removed; a file with an unregistered extension reads as raw bytes. Registration on a mount survives as the extension point (#651).
  • du has one backend contract. du_size and du_entries replace the flat-list du_multi; entries are leaf files in mount-relative path space with no summary row, and the generic derives directory rows (#642).
  • Command handlers take (accessor, paths, texts, opts). Generics own operands and flag interpretation, builders become wiring (#770), and the dispatcher builds CommandOpts with typed adapter ops (#772). A handler never declares a flag as a parameter.
  • One mount-lookup contract: mountFor throws, tryMountFor returns null (#781).
  • CommandFacts is renamed ParsedCommand (#693), and value_kind and type merge onto one ValueType axis (#689).
  • One error vocabulary and one stat view per language (#764); absolute operands keep their typed spelling (#765).
  • PythonRuntime is dropped in favor of the evaluator capability (#657), and the default python engine is named explicitly (#769).
  • tar -cj is unsupported in TypeScript. Every JavaScript bzip2 compressor is GPL, so TS reads .tar.bz2 and refuses to write one; Python still does both (#741).
  • Notion speaks Notion-Version: 2025-09-03, where a database is a container plus data sources: the schema lives on the data source, the mount nests a level deeper, and /search no longer accepts filter.value = "database" (#740).
  • Unknown config keys are rejected rather than ignored, and the index closes and evicts synchronously (#751).
  • find classifies walked entries through stat, never by name; the per-backend is_dir_name hints are gone (#719).

Features

  • cli: install registry, dispatch by name, YAML clis: (#691); CLI tree walk with git-pinned diagnostics (#685); author in code, by pointer, or as a script (#712); install from a file reference (#798); himalaya + gws (#699); slack, discord, ntn, linear (#703); git over any mount (#710); gh (#768); man/type/which discovery (#707).
  • policy: policy package with pre_command (#690); pre_ops/post_ops (#692); ParsedCommand and the cli fact (#693); Limit (#694); deny verdict (#659).
  • workspace: mount structure in the door's readdir and stat (#739); one door for VFS/FUSE ops (#753); state doors and per-plane views (#771); shared FileHandle/FileTable (#760); SessionProfile hidden paths and vars (#778); Workspace orchestration split into a package (#681).
  • shell: job console for streaming background output (#611); Redis console store (#795); $'...' quoting, git log/show formats, byte-exact MIME parity (#723); sh FILE / bash FILE as a script (#752); export/readonly -p (#661).
  • runtime: sandbox runtimes with FUSE-mounted workspaces (#590); uniform interface and one integ suite (#655); tiered taxonomy and TS package layout (#726); one mount op vocabulary, Python (#730) and TypeScript (#732); resolver protocol (#749); guest op parity and the Ops facade (#767); mount-access conformance suite (#727).
  • dsh: fs and shell providers over a workspace (#774); session binding (#784); dsh bundle with declarative mounts (#787); streaming, sandbox facts, spill (#796).
  • fuse: fskit mount backend and a MountCore/adapter split (#648).
  • notion: fake writes, data sources, ntn gated against the real CLI (#740); delete verb and trash bit (#747); comments and object versioning (#756).
  • google: Shared Drives in the g* mounts and a configurable Graph service root (#695); folder-scoped creates and Google's own errors (#715); calendar and forms passthrough (#754).
  • spec: argparse mirroring with aliases, long-option abbreviation and typed ints (#687); declarative count/multiple/choices/required/default (#679); specs compiled once with short and long flags on one dest (#676); typed spec-validated FlagView in TypeScript (#674); capability and CommandIO gating (#742).
  • cd: a logical cwd, so pwd -L/-P mean something (#766).
  • du: -S/--separate-dirs (#722).
  • jq: the rest of jq's flag surface (#713).
  • python3: CPython's option table, sys.path seeded on pyodide (#743).
  • integ: jaeger backend and real-server observability (#643); semantic DB virtualization with a JSON harness for every DB backend (#644); standalone suites cons...
Read more

Mirage 0.0.4

Choose a tag to compare

@zechengz zechengz released this 23 Jul 07:05
b6e4317

We are excited to announce the release of Mirage 0.0.4 🎉🎉🎉

Mirage 0.0.4 is an architecture and depth release. Path addressing becomes a real namespace layer with first-class symlinks and attribute overlays that survive restarts; the control plane moves onto pluggable state stores (RAM, disk, Redis, S3) with CAS-guarded writes; the shell grows GNU-grade bash semantics (arithmetic, control flow, brace expansion, printf, getopts, parameter expansion); commands can be run by pluggable runtimes that read and write workspace mounts; and eight new or rebuilt backends land. Python is mypy-clean and TypeScript is tsc-clean, both enforced as CI gates. Python and TypeScript are kept mirrored throughout.

pip install mirage-ai==0.0.4 · npm install @struktoai/mirage-core@0.0.4 (and -node, -browser, -server, -cli, -agents)

Highlights

  • The namespace is a real addressing layer. A Namespace facade consolidates mount resolution, symlink following, and attribute overlays behind one surface, and the Workspace routes dispatch, apply_io, and post-write invalidation through it instead of holding a dispatcher directly (#420, #424, #426). Symlinks are first-class namespace ops in both languages: ln -s creates a real link (not a copy), cat/ls/glob follow on read, rm/mv act on the link entry, cd honors -L/-P with ELOOP on cycles, and the link table is captured into snapshots (#421). FUSE and disk attributes route through the same layer, so a real inode base carries a residual overlay (#505, #509).
  • A persistent, CAS-guarded control plane. Namespace, observer, and session state unify under one WorkspaceStateStore (#523) with backends for disk (lockfile CAS), Redis, and S3 (#535, #544). Sessions survive restarts and are shared across processes (#521), with dirty-tracked flushes and generation CAS on both the session and workspace meta records (#530, #533). MIRAGE_HOME becomes the single root for the whole tree (#551), and state can be diffed and surgically restored per category (#552).
  • GNU-grade shell semantics. Bash arithmetic ((( )) and $(( ))), control flow, set options, and test/[[ semantics (#369, #477, #577); brace expansion (#563); full GNU printf with Python/TypeScript float parity (#580); getopts (#612); the command builtin (#595); sort -k KEYDEF grammar (#607); and three waves of agent-facing coreutils coverage — checksums, rmdir, unlink, :, type, chgrp, realpath -e, ln -r, rm safety flags, env, tr -C/-t, tee --output-error (#603, #613, #617, #618).
  • Pluggable runtimes that reach the filesystem. A WASI runtime runs CPython on wasmtime (#498), a node/js family runs on QuickJS in both languages (#504), and Python defaults to the monty sandbox with pyodide on TypeScript (#487). Sandboxed code reads and writes workspace mounts through interception (#508, #514), and a per-line routing ladder picks the runtime from the argument, route, entry script, or VFS (#547, #559).
  • Cross-mount commands get real strategies. STREAM, FANOUT, and RELAY run per-mount native commands and reassemble the result (#453), with a shared parse so cross-mount lines are parsed against the mount spec like single-mount ones (#474), GNU failure semantics and glob relay (#582), and du/md5/file fan-out where cp populates the read cache (#441).
  • Eight new and rebuilt backends. Google Drive read/write with a gws CLI and fake Workspace server (#549), Box (#562, #579), Dropbox subfolder mounts with a Python port (#558, #568), MongoDB GridFS with native revisions and server-side find (#566), Mem0 (#341), a Prisma-backed fake Slack Web API (#578), nested Trello and Linear CLI families with Linear documents (#581), and a Dify TypeScript backend (#601). OneDrive and SharePoint now share one Microsoft Graph drive core (#532, #534).
  • Resource change watching. A mount-scoped watch API lets an external agent service react to changes, with a Nextcloud source, attach/detach at runtime, per-root overflow collapse, and nested-mount coverage (#594, #598).
  • Provision you can trust. Field-wise combinators and default estimators by command family (#428), one NodeKind classification shared by the executor and planner so planner drift is structural rather than accidental (#431), exact glob and recursive-walk estimates with zero-cost stdin stages (#440), and cross-mount plans that sum per-mount estimates (#441).
  • One declarative integration harness. Python and TypeScript run the same shared harness against every backend (#520), with targets added for s3, onedrive, ssh, nextcloud, sharepoint, hf buckets, gapps, gmail, email, slack, gridfs, box, dropbox, databricks, and dify; the legacy per-backend scripts are retired (#539).
  • Types are a gate, not an aspiration. Python mypy went from a 441-module baseline to zero and is enforced (#500 through #522), TypeScript is tsc --noEmit clean with noImplicitOverride, noFallthroughCasesInSwitch, and knip dead-code checks in pre-commit (#463, #465).

Breaking Changes

  • PathSpec is pure-virtual. The prefix field and the strip_prefix/key properties are gone; a required resource_path is stamped by the mount at dispatch, with strip_mount/mount_key/rekey/mount_prefix_of in utils/key_prefix (#424). Core is PathSpec-only and the str coercion shims are removed (#496).
  • Per-backend op manifests are renamed to io.py/io.ts exporting IO, and the VFS/FUSE op layer is generated from each backend's CommandIO table rather than hand-written (#542, #545, #553).
  • The Workspace no longer holds a dispatcher directly — resolution, dispatch, and invalidation go through Namespace (#420).
  • Session mount grants become a modes vocabulary (read/write/exec), with tuple mounts in TS core (#436, #499).
  • index is non-optional; a NULL_INDEX no-op replaces None (#501).
  • Python defaults to the monty sandbox, TypeScript to pyodide, for python3 execution (#487).
  • FUSE sizes changed shape. The 100 MiB sentinel is gone in favor of direct_io (#491), and FileStat.size is render-derived or None — never a storage-side or source-side number (#488, #489).
  • Workspace and session ids are UUIDv7, and the reserved defaults are dropped (#526).
  • MIRAGE_HOME is the single root and the TypeScript daemon defaults to the disk store (#551).
  • Per-backend glob boilerplate is deleted in favor of the shared resolve_glob_with walk and a custom-backend SDK (#478, #540).

Features

  • box: Python + TypeScript Box backend with full read/write and an integ target (#562); special files served raw plus grep/rg search push-down (#579).
  • coreutils: env builtin, tr -C/-t, tee --output-error (#618); Tier 2 chgrp, realpath -e, ln -r, rm safety flags (#617); Tier 1 flag support (#613); Wave 1 checksums, rmdir, unlink, :, type (#603).
  • daemon: config.toml path settings and a mirage config command (#473).
  • dropbox: subfolder mounts via rootPath, a Python port, and battery targets (#558); grep/rg search push-down via files/search_v2 (#568).
  • gdrive: read/write Drive backend, gws CLI, fake Workspace server, integ targets (#549).
  • google: optional api_base override for GoogleConfig (#596).
  • gridfs: MongoDB GridFS backend with native revisions and server-side find (#566).
  • mem0: read-only Mem0 Memory resource, Python (#341).
  • namespace: symlinks as first-class namespace ops (#421); orphaned overlays reconciled on remote delete (#515).
  • nextcloud: server-side find via the Files Search API, with partial predicates and fallback (#475).
  • printf: full GNU printf builtin with Python/TypeScript float parity (#580).
  • provision: field-wise combinators and default estimators by command family (#428).
  • runtime: WASI runtime (CPython on wasmtime) with python3 safeguards following the script path in TS (#498); node/js command family on QuickJS (#504); per-line routing ladder (#547); run_line for runtimes that run whole lines (#559).
  • session: SessionStore seam so sessions survive restarts and are shared across processes (#521); dirty-tracked flush with generation CAS (#530).
  • shell: builtin specs — xargs batching, timeout enforcement, GNU echo/read/shift/return (#468); brace expansion in both hosts (#563); GNU control-flow, set-option, builtin, and test/[[ semantics with 147 integ cases (#577); command builtin (#595); getopts (#612).
  • slack: Prisma-backed fake Slack Web API and integ battery target (#578).
  • sort: full GNU -k KEYDEF grammar (#607).
  • store: generation CAS on the workspace meta record (#533); S3 backend for the sessions+meta group (#535); disk backend with lockfile CAS (#544).
  • trello, linear: nested CLI command families, Linear documents, integ coverage (#581).
  • ts: JS sandbox reads and writes workspace mounts (#514).
  • version: content-pure commit trees that strip cache and sessions (#536); whole-world commits via the .mirage/ control-plane subtree (#537).
  • watch: resource change watching with a Nextcloud source (#594); attach/detach runtime surface, per-root overflow collapse, nested-mount coverage (#598).
  • Dify TypeScript backend, Databricks JSON harness migration, and a systemic mkdir -p cache fix (#601).
  • Codex and Grok Build integrations (#575), a native OpenCode plugin with stale-write protection (#576), and scoped filesystem integration coverage (#587).

Bugfixes

  • cache: backend fingerprints thread into apply_io so ALWAYS mode stops evicting non-MD5 backends (#434); streamed reads background-drain into the Redis file cache (#439); the drain budget is clamped to the cache limit (#443).
  • crossmount: the GNU strerror suffix is appended on the not-found branch (#447); GNU failure semantics, relay glob, and dispatcher invalidation (#582).
  • **daemon:*...
Read more

Mirage 0.0.3

Choose a tag to compare

@zechengz zechengz released this 30 Jun 10:08

We are excited to announce the release of Mirage 0.0.3 🎉🎉🎉

Mirage 0.0.3 is a large parity and platform release. It lands a GNU-aligned shell environment (history, cwd/env, subshell isolation), a unified command factory shared across every backend, cache read-through with warm serving, the Claude Agent SDK integration, and four new/upgraded backends (SharePoint, Qdrant, OneDrive parity, MongoDB on PyMongo Async). Python and TypeScript are kept mirrored throughout.

pip install mirage-ai==0.0.3 · npm install @struktoai/mirage-core@0.0.3 (and -node, -browser, -server, -cli, -agents)

Highlights

  • GNU history subsystem (Python + TypeScript). A hidden Observer records every top-level command as timestamp-ordered events; /.bash_history is a read-only view in GNU histfile format and the history shell builtin (-c -d -a -n -r -w -s -p + count) routes through the same mount, so the file and the builtin never disagree. History is captured into snapshots and restored on load. (#313)
  • Claude Agent SDK integration. MirageServer + build_options wire a Mirage workspace into the Claude Agent SDK as a tool surface, mirrored in both languages with Python and TypeScript all-tools examples. (#322, #216)
  • GNU-aligned cwd/env and subshell isolation. HOME/PWD/OLDPWD mirrors, cd/tilde/CDPATH GNU semantics, relative-path display, and subshell isolation. (#331)
  • Unified command factory. Backend shell commands are now generated from one shared factory instead of per-backend wrappers, across disk, redis, ram, s3, ssh, google/chat, the database and SaaS families, notion, dify, nextcloud, onedrive, hf, box, dropbox, and email. Flag interpretation lives in the generics; wrappers are wiring only.
  • Cache read-through and warm serving. Warm reads are served in place through shared read-through consumers, with invalidation done at the write site via CacheManager; the file cache is now a store rather than a mount. (#329)
  • New and upgraded backends: SharePoint multi-site discovery (#365), a Qdrant resource (#367), full OneDrive S3-parity, and MongoDB migrated to PyMongo Async with client metadata (#330).
  • Virtual root is now a real mount. /_default is replaced by a real / mount that callers can override with their own / mount.

Breaking Changes

  • /_default is removed. The default scratch space is now a real virtual root mounted at /, overridable by a user-provided / mount.
  • File cache is no longer a mount. It is exposed as a store; the cache-mount read redirect is removed and warm reads are served in place.
  • MongoDB driver migrated from Motor to PyMongo Async (#330).
  • Workspace config: the removed history field is dropped from configs; foreign history formats are tolerated on cross-language snapshot load.
  • Cache API: invalidate_index_dirs is deleted in favor of write-site invalidation (#329); the factory drops unsupported_commands and per-command requires tuples.

Features

  • sed: GNU-aligned engine: ^/$ anchors, s/// numeric count and p flag, y (transliterate) and c (change), BRE by default with ERE under -E/-r, multiple -e expressions, -f script files, and address negation (addr!cmd) (#340, #326).
  • diff: full GNU-style recursive diff -r (py + ts).
  • find: aligned with GNU coreutils across all backends: GNU start-path emission, -empty, -not, and unknown-predicate errors (#393, #312).
  • FUSE: per-mount Mount spec with FuseManager ownership across both languages, in-memory xattr support, and caller-owned mountpoint cleanup (#345).
  • github: grep/rg narrowing via code search on subdirs and regex, with a -l short-circuit (#406).
  • mongodb: tail -f follows the change stream and stops caching live reads.
  • Wasmer and Microsandbox examples running over a Mirage FUSE mount.

Bugfixes

  • Many Python/TypeScript divergence fixes: stat on slack/discord/gdrive, du walk fallback, and assorted GNU command semantics (#419).
  • csplit -f cwd resolution, ssh write recording, and disk mkdir invalidation ordering (#419).
  • sed: honor ^/$ line anchors in TS substitution and addresses; pattern space excludes the trailing newline (#326).
  • onedrive: ls trailing newline (#354), index-cache metadata (#361), and S3-parity command suite (#357).
  • databricks_volume: stat reads content_length/last_modified (#355); record mount-relative write keys in touch/mkdir (#356).
  • s3/nextcloud: populate ls -l / stat mtime across object-store and API backends (#362).
  • Cache invalidation completed at every mutation site for create/copy/rm/rmdir (#329).
  • Multi-pattern grep -e / rg -e routed through the generic on search-pushdown backends.
  • tar: load bzip2/xz codecs via createRequire for ESM compatibility; redis read enoent preserves the virtual path; fixed open()/os interception hijacking real paths under the virtual root.

Changes

  • Cross-mount commands (cp/mv/diff/cmp + read family) reuse the generics through a dispatch-backed adapter, split into per-command modules.
  • Shared epoch_to_iso/epochToIso util dedups mtime ISO formatting and enforces second precision; diff flags grouped into a frozen struct.
  • Dead-code and dead-test sweep (#359, #348).
  • Security: resolved CodeQL code-scanning alerts (path-injection, request-forgery, ReDoS), cleared Dependabot vulnerabilities, added server rate limiting, and confined snapshot/load paths (#323, #324, #325, #342, #358, #360).
  • Dependencies: bumped joserfc, pyjwt, nodemailer, undici, js-yaml, pypdf, fast-xml-parser, langchain, aiohttp (<3.14 cap lifted), and several GitHub Actions; added an informational uv audit CI job (#346, #352).
  • Expanded the cross-language integ harness (history/observer, cache coherence, cross-mount, sed/find/diff, notion database, onedrive).

Contributors

Thanks to everyone who contributed to this release: @zechengz, @sonhmai, @MarshuMax, @hieu650002, @alexbevi, @ki3nd, @anush008, @C1-BA-B1-F3, and @dependabot.

New Contributors

  • @MarshuMax made their first contribution: Notion database browsing support (#21)
  • @alexbevi made their first contribution: MongoDB PyMongo Async migration + client metadata (#330)
  • @hieu650002 made their first contribution: SharePoint multi-site discovery (#365) and OneDrive metadata (#361)
  • @anush008 made their first contribution: Qdrant resource (#367)
  • @C1-BA-B1-F3 made their first contribution: GNU find alignment (#393) and compact JSON rendering (#391)

Full Changelog: v0.0.2...v0.0.3

v0.0.2

Choose a tag to compare

@zechengz zechengz released this 15 Jun 11:33

Release v0.0.2.

TypeScript (npm, @struktoai/*) at 0.0.2:

  • mirage-core, mirage-node, mirage-browser, mirage-server, mirage-agents, mirage-cli

Python (PyPI, mirage-ai) at 0.0.3a0 (alpha).

Notable: the CLI now reports its real package version instead of a hardcoded 0.0.0.

v0.0.1 — first public release

Choose a tag to compare

@zechengz zechengz released this 06 May 18:44

The first public release of Mirage — a unified virtual filesystem for AI agents.

Mount S3, Google Drive, Slack, Gmail, GitHub, Linear, Notion, Postgres, MongoDB, SSH, and more behind one filesystem so agents read, write, and pipe across services with familiar shell commands.

What's included

  • Python SDKmirage-ai on PyPI
  • TypeScript SDKs@struktoai/mirage-{core,node,browser,agents,cli,server} (npm publish forthcoming)
  • CLI + daemonuvx mirage-ai or uv tool install mirage-ai
  • FUSE mounts — expose any workspace as a real filesystem (macOS / Linux)
  • Agent integrations — OpenAI Agents SDK, Vercel AI SDK, LangChain (deepagents), Pydantic AI, CAMEL, OpenHands, Mastra, Pi Coding Agent
  • CLI agent integrations — Claude Code and Codex via FUSE
  • Documentationhttps://docs.mirage.strukto.ai

Install

# Python (library + CLI)
uv add mirage-ai

# Or run the CLI directly
uvx mirage-ai

Quickstart

from mirage import MountMode, Workspace
from mirage.resource.ram import RAMResource

ws = Workspace({"/data": RAMResource()}, mode=MountMode.WRITE)
await ws.execute('echo "hello mirage" | tee /data/hello.txt')

See docs.mirage.strukto.ai for the full guide.

License

Apache 2.0. See LICENSE.

Notes

This is an early release. Expect bugs and breaking changes through the 0.0.x line. Report issues at github.com/strukto-ai/mirage/issues or report security concerns per SECURITY.md.