@aletheia-works/formicarium

中文文档
0.12.0发布于 2026/11/05Apache-2.0TypeScriptES Module零依赖构建来源已验证近 30 天下载 6172

Run unmodified x86-64 Linux CLI programs in the browser and Node.js on the paludarium WebAssembly emulator

原始使用文档
文档目录9 节
  1. Status
  2. Install
  3. Quick start (Node.js)
  4. In the browser
  5. What the API does
  6. Limits
  7. How it works
  8. Contributing
  9. License

formicarium

Run unmodified x86-64 Linux command-line programs in the browser and in Node.js, without booting a kernel. formicarium wraps paludarium, a user-mode x86-64 Linux emulator compiled to WebAssembly (a Rust counterpart of jart/blink), and gives it a small JavaScript API: give it a static Linux executable and some files, run it, and get back the exit code, the output and the files it wrote. The goal is to let a CLI bug reproduction run as-is in a web page.

  • Try it: the showcase site has terminals that install and run aube, pitchfork, Biome, nano, jj and git in your browser.
  • Package: @aletheia-works/formicarium on npm.
  • Documentation: the site has guides (including the install and command APIs) and a Development section (runtime architecture, design decisions), in English and Japanese.

Status

formicarium is young (0.x) and its API may still change. What is checked on every change:

  • A Rust probe (threads, timers, UnixStream::pair, rayon, Mutex/Condvar, hard links, symlinks, flock) passes on Node.js, Chromium, Firefox and WebKit.
  • Multi-step sessions of aube and pitchfork produce the same output as on native x86-64 Linux.
  • Line coverage of the distributed JavaScript stays at 80% or more.

It runs an interpreter (no JIT yet), so heavy programs are much slower than native. CI runs the browser probe, the install and command checks, the showcase acceptance and the showcase site's acceptance in real Safari on macOS; the other browser suites use Playwright's WebKit in its place. The browser probe and the install and command checks also run in Safari on iOS in an iOS 26 Simulator (not yet iOS 27, which safaridriver cannot drive); a real iPhone is not tested.

Install

npm install @aletheia-works/formicarium

Node.js 24 or later is required.

Quick start (Node.js)

import { createSession } from '@aletheia-works/formicarium/node';
import { decodeUtf8 } from '@aletheia-works/formicarium';

// guestBytes: a static ELF64 little-endian x86-64 Linux executable (Uint8Array).
const session = await createSession({ cwd: '/work', home: '/home/guest' });
try {
  const result = await session.run({ guest: guestBytes, args: ['--version'] });
  console.log(result.exitCode, decodeUtf8(result.stdout));
} finally {
  await session.dispose();
}

Guests are not included. Build them as static musl executables, or install them from a catalog with the install API (below).

In the browser

Import createSession from @aletheia-works/formicarium/browser. The page must be able to use SharedArrayBuffer:

  • Serve the page with Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp (or use a service worker such as coi-serviceworker on static hosting).
  • Serve the package Worker (runtime/web/package-worker.bundle.js) and the core under assets/paludarium/ from your page's origin.
  • Allow same-origin scripts and Workers and WebAssembly compilation in the Content Security Policy, for example script-src 'self' 'wasm-unsafe-eval'; worker-src 'self'; connect-src 'self'. blob: is not needed.

The embedding guide has a complete example.

What the API does

  • Sessions. A Session holds a virtual filesystem between runs. Only the working directory and the home directory persist; files sharing an inodeId stay hard links, symlinks stay links, and modes are kept. Between runs use listEntries, readFile, remove, setCwd and reset; dispose closes the session for good.
  • Runs. Each run starts a fresh Worker and a fresh core. A session runs one thing at a time (BUSY otherwise). A nonzero guest exit resolves normally with the exit code and the raw stdout/stderr bytes; onOutput streams them in order. Host, core, timeout (600000 ms by default, timeoutMs to change) and cancellation (AbortSignal) failures reject with an ExecutionError carrying a stable code (all codes are listed in ERROR_CODES and on the error codes page) and the partial output. When the run failed inside the Worker, its cause chain names the original errors; it keeps the messages that the JavaScript engine, WebAssembly or the core wrote, and only the names of other errors, so caller data such as env values stays out. A failed or cancelled run leaves the filesystem as it was. For an interactive guest, stdin streams its standard input and terminal: { columns, rows } makes its standard streams a terminal; a run with stdin has no default timeout. In a browser, the runs of all sessions on one page start their cores one at a time (each waits until the run before it has started its guest, ended, or held the start for 10 s), and the wait counts toward timeoutMs; the guests still run side by side.
  • Network. A guest has no network unless a run passes network: { allow: ['github.com:443'] }. It can then open TCP connections to the listed destinations only, and resolve only the listed names; anything else fails with ENETUNREACH (a loopback address with no guest listener with ECONNREFUSED); a guest may serve on its own loopback. TLS runs inside the guest, so give it CA certificates. A browser has no TCP sockets, so a browser run also needs network.relay: { url, protocols? }, a WebSocket relay such as @aletheia-works/paludarium-wasm/relay serves; without one it fails with UNSUPPORTED_ENV. Node.js uses the relay when given.
  • Core assets. Before the core starts, the pinned paludarium version and the SHA-256 of every core file are checked against assets/paludarium/build-info.json (ASSET_LOAD if missing or changed, CORE_INIT if the core fails to start). Node.js loads the checked bytes from a private directory. Browsers load the core from its URLs after the check, so serve the assets from an origin you trust.
  • Guests and catalogs. validateGuest checks a guest's bytes and build information, createInstaller installs tools from a fixed catalog of checksummed ELF or tar.gz downloads, registerValidatedGuest registers a checked guest you already hold (runValidatedGuest runs it once instead), fixtureToFsEntries checks the files a session starts with, and createCommandSession runs one command line (ls, cat, cd, rm -rf, cp, mv, install <tool>, or an installed tool, optionally after NAME=value environment assignments) without a shell. A registered tool runs by name in a command session, and every guest run finds it as /usr/bin/<tool>. Installing with createInstaller writes no output, so a page can have tools ready before the user types anything. See the install API and command API.

Limits

  • Guests must be static x86-64 Linux ELF executables. validateGuest and installs also refuse a guest over 128 MiB.
  • Guests reach the network only as TCP clients of the allowed destinations, through a relay in the browser. A guest may also serve TCP and exchange UDP on its own loopback; other UDP reaches only name lookups.
  • The core's memory is capped at 1 GB.
  • Each run starts from a fresh filesystem; only the working directory and the home directory carry over.

How it works

The runtime splits into the public API, a per-run Worker, guest input/output and one module, runtime/core.ts, that knows the emulator core. The core itself is the @aletheia-works/paludarium-wasm npm package, pinned to an exact version and shipped in assets/paludarium/. See the runtime architecture and the architecture decisions.

Contributing

See CONTRIBUTING.md for setup, builds, tests and pull requests, and follow the Code of Conduct. Report vulnerabilities privately as described in the security policy.

License

Apache License 2.0. The bundled paludarium core is also Apache-2.0; see THIRD_PARTY_NOTICES.md and the core license.

版本与发布记录

@aletheia-works/formicarium 共发布 15 个版本,首次发布于 2026/10/10;过去 12 个月发布了 15 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.12.0latest2026/11/051 天前
0.11.02026/11/014 天前
0.10.02026/10/315 天前
0.9.02026/10/307 天前
0.8.02026/10/289 天前
0.7.12026/10/2710 天前

关于 @aletheia-works/formicarium 的常见问题

@aletheia-works/formicarium 是什么?

Run unmodified x86-64 Linux CLI programs in the browser and Node.js on the paludarium WebAssembly emulator

如何安装 @aletheia-works/formicarium?

在项目目录运行 npm install @aletheia-works/formicarium,或使用 pnpm add / yarn add / bun add。

@aletheia-works/formicarium 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@aletheia-works/formicarium 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@aletheia-works/formicarium 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=24。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@aletheia-works/formicarium 可以商用吗?

@aletheia-works/formicarium 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@aletheia-works/formicarium 的下载量有多少?

根据 npm 官方下载统计,@aletheia-works/formicarium 在 2026/10/06 – 2026/11/04 这 30 天内被下载 6,172 次,日均约 206 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@aletheia-works/formicarium 还在维护吗?

最新版本 0.12.0 发布于 2026/11/05(1 天前);至今共发布 15 个版本,其中过去 12 个月发布了 15 个;首次发布于 2026/10/10。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。