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
CLISpecbuilt onCommandSpecgives a program a typed verb tree (#682), installed host-side into a registry and dispatched by name rather than by operand path, with aclis:section in YAML (#691) and file-reference installs (#798). Builtin families land in waves:himalayaandgws(#699),slack,discord,ntnandlinear(#703),gitover any mount (#710), andghwith 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 throughman,typeandwhich(#707) because help renders from the spec. - A CLI that mimics a real program is gated against that program.
ntnruns 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), andhimalayawas realigned to the upstream pimalaya grammar the same way (#709, #723, #761). - A policy layer with hooks at every door.
routebecomespolicyand gains a deny verdict (#659), then a real package withpre_commandabsorbing the old command guards (#690),pre_ops/post_opsat the op doors (#692),ParsedCommandplus a cli fact and registry snapshot (#693), and output safeguards folded in asLimit(#694). Session writes join it: every expansion-time writer (${X:=d},$((X=5)),printf -v,for ((...))) now passes throughSessionView.setinstead of around it (#791). - One door per state plane. Mount structure merges into the door's
readdirandstat(#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 sharedFileHandle/FileTablebehind the buffered handle tables (#760) and per-session hidden paths and vars viaSessionProfile(#778). - Runtimes consolidate onto one vocabulary. A uniform runtime interface and one integ suite for all runtimes (#655), evaluator as a capability with
PythonRuntimedropped (#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 oneOpsfacade (#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);python3parses CPython's real option table (#743). - Background commands stream. A
JobConsolerecords 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-dshpackage providesctx.fsandctx.shellover 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.
tarandzipplan 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);taraccepts GNU's old option style (#734),unzipselects members and exits 11 on unmatched filespecs (#725), and the GPL bzip2 dependency is gone in favor ofmodern-tarplus MITseek-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
CommandIOslots 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/pdfextras and thehyparquet/apache-arrow/h5wasmdependencies are removed; a file with an unregistered extension reads as raw bytes. Registration on a mount survives as the extension point (#651). duhas one backend contract.du_sizeanddu_entriesreplace the flat-listdu_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 buildsCommandOptswith typed adapter ops (#772). A handler never declares a flag as a parameter. - One mount-lookup contract:
mountForthrows,tryMountForreturns null (#781). CommandFactsis renamedParsedCommand(#693), andvalue_kindandtypemerge onto oneValueTypeaxis (#689).- One error vocabulary and one stat view per language (#764); absolute operands keep their typed spelling (#765).
PythonRuntimeis dropped in favor of the evaluator capability (#657), and the default python engine is named explicitly (#769).tar -cjis unsupported in TypeScript. Every JavaScript bzip2 compressor is GPL, so TS reads.tar.bz2and 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/searchno longer acceptsfilter.value = "database"(#740). - Unknown config keys are rejected rather than ignored, and the index closes and evicts synchronously (#751).
findclassifies walked entries throughstat, never by name; the per-backendis_dir_namehints 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);gitover any mount (#710);gh(#768);man/type/whichdiscovery (#707). - policy: policy package with
pre_command(#690);pre_ops/post_ops(#692);ParsedCommandand 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);SessionProfilehidden 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/showformats, byte-exact MIME parity (#723);sh FILE/bash FILEas 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
Opsfacade (#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
FlagViewin TypeScript (#674); capability andCommandIOgating (#742). - cd: a logical cwd, so
pwd -L/-Pmean something (#766). - du:
-S/--separate-dirs(#722). - jq: the rest of jq's flag surface (#713).
- python3: CPython's option table,
sys.pathseeded 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 consolidated into the shared battery (#625).
Bugfixes
- find: start point classified once, above every backend (#696); an empty directory start point,
-typeno longer collapsed in TS (#701); walked entries classified throughstat(#719);!is negation, not a start point (#780). - glob: nested mount roots and symlinks are visible to expansion (#775); quoted glob characters never trigger pathname expansion (#783); a match named like the glob word is not the nullglob literal (#790).
- links: an operand's link prefix resolves, and a trailing slash is honored (#782); the symlink arrow renders for
stat %N(#779). - shell: ambient session for nested evals and whole-body command substitution (#788); an already-expanded word is not unescaped again in classification (#785); raw embedded-python literals and a quoted
"$@"spliced into its word (#750). - traversal: nested mounts crossed correctly in
du,find,ls -Randtree(#755);wc --totalhonored anddu -hno longer rounds twice across mounts (#702); a namespace-only directory is not absent (#776). - errors: a read-family operand is shell-quoted the way GNU does (#789);
teewrites every operand and uses the append slot (#745). - flat-store: implicit dirs, ancestor cache invalidation, exact-only negated
-name, ssh revalidation (#793). - email: messages bucketed by IMAP
INTERNALDATEwhenDate:is missing (#729); the sender's own copy of a sent message is filed (#761). - parity: truncate/split data-loss flag values, od radix, registry membership (#706); find multi-root walk, honest error classes, one filetype table (#731); GNU byte pins across
tail,split,numfmt,sed,cp,find(#758);trescapes,wccolumn geometry, code-point sort order (#759). - security: aiohttp 3.14.3 for GHSA-mq44-7p77-q5h7 (#697), cryptography 50.0.0 for GHSA-g6cj-pr64-35w5 (#698), and a CodeQL and dependency alert sweep (#786).
Changes
- flags: dead short-flag params deleted and the bag's type named (#733); spec-bound
FlagViewacross every command wrapper, plus the three Python bugs it surfaced (#735). - ts: config types derived from their zod schemas (#773); four shared factories mirroring the Python originals (#792); builtin command specs split by family (#672).
- executor:
command.py/command.tssplit into a command package (#686). - runtime: a root mount reported in prefixes, runtime names inlined, monty tests split (#736).
- test: the Python test tree moved onto the source layout and gated (#763); the integ runner fails on zero work (#737).
Contributors
@zechengz, @bytecii, @ThomasHartDev
New Contributors
- @ThomasHartDev made their first contribution in #623
Full Changelog: v0.0.4...v0.0.5