ws.execute('python3 ...') can open(), os.listdir(), pathlib.Path() etc. against any registered Mirage mount. Mirage mounts a filesystem of its own inside the interpreter, below the syscall boundary, so those calls reach Mirage’s mount layer (RAM, S3, Linear, GDocs, Slack, anything you’ve registered).
What works
- Read a file
- Write a file
- List a directory
- pathlib & glob
- Native libs
- Cross-mount
What doesn’t work
How it works (one paragraph)
Mirage registers its own Emscripten filesystem at each mount prefix, so every spelling of an operation (open, os.open, pathlib, a C extension’s fopen, shutil’s fd-relative walk) arrives as the same callback. Emscripten’s callbacks are synchronous, so nothing reaches the mount inline: before each run Mirage collects every mounted prefix into the filesystem’s node table, and reads are served from there. Writes are recorded on a journal in the order the guest performed them, and replayed against the mounts after the script returns, where awaiting is free. A handle that only extended a file replays as an append, so an append loop ships its tail rather than the whole file each time. A failed replay lands on stderr with a nonzero exit, and stops the rest of the journal rather than applying entries whose prerequisite never landed.
Quick start (TypeScript)
examples/typescript/pyodide/vfs.ts.
Python packages (PIL, numpy, pandas, …)
Pyodide ships CPython, but third-party packages aren’t loaded until you import them. Mirage scans the code you run forimport statements and auto-fetches matching packages on demand, so from PIL import Image, import numpy as np, import pandas as pd all just work the first time. Subsequent calls hit Pyodide’s package cache.
If you need to opt out (e.g., to keep workspace startup lean):
Resource compatibility
Runtime requirements
None. Reads, mounts added between runs, and writes all work on any engine, with no V8 flag and no JSPI. That is the point of collecting the tree before the run and replaying writes after it: a filesystem callback never has to suspend, so nothing depends on stack switching, which no shipping Node enables by default and Safari does not implement. To run the example:Errors you might see
See also
python: broaderpython3builtin behavior (env, argv, stdin, exit codes)examples/typescript/pyodide/vfs.ts: runnable demo across RAM, S3, GDocs, Linear