Run AI-generated backend code without giving it your process, filesystem, or network. Capsid is an embeddable JavaScript data plane for untrusted Web-standard Fetch handlers. Your Host keeps control of listeners, TLS, routing, worker pools, and policy; each worker receives one self-contained ESM bundle and only the capabilities the Host approves.
Status:
0.2.0-beta, ABI v7. The first-partycapsid-hostis a development/benchmark entry point, not a production deployment interface; production isolation is only promised by the Linux strict sandbox.
Capsid is aimed at AI app builders, multi-tenant automation, and plugin systems that need to execute generated code as a service—not as trusted code inside the main application process.
| Concern | Host-controlled boundary | What untrusted code receives |
|---|---|---|
| HTTP | Listener, TLS, routing, admission, and pool lifecycle | A standard fetch(request) call |
| Authority | Module and resource policy, Linux sandbox, limits, and audit | Deny-by-default capsid:* facades |
| Databases and services | Trusted Binding implementation, credentials, and maximum permissions | A narrow asynchronous capsid:binding/<id> API |
| Failure | Process lifetime, timeout, cancellation, crash budget, and replacement | No process-control API |
This is not a general-purpose Node.js replacement. Capsid intentionally omits runtime package installation, server adapters and listeners, FFI, raw sockets, and ambient process APIs. In return, the Host gets a non-blocking C ABI/C++11 data plane with streaming, credit backpressure, explicit lifecycle control, and a capability boundary designed for hostile code.
The implementation is small and measurable: the published 4-core baseline reaches about 6,800 QPS, starts small bundles in 8–10 ms, and uses about 12.3 MB idle PSS for the Host plus two workers. Claims are backed by pinned WPT, framework differentials, sanitizers, fuzzing, privileged sandbox probes, and identity-linked performance evidence.
export default {
async fetch(request) {
return Response.json({
message: "hello from Capsid",
path: new URL(request.url).pathname,
});
},
};Linux / macOS:
git submodule update --init --recursive
npm ci --ignore-scripts --prefix vendor/txiki.js
cmake -S . -B build-release -DCMAKE_BUILD_TYPE=Release \
-DBUILD_TESTING=OFF -DCAPSID_BUILD_HOST=ON
cmake --build build-release --parallelWindows (PowerShell + MSVC + vcpkg):
vcpkg install openssl boost-system boost-asio boost-beast --triplet x64-windows-static
cmake -S . -B build-release -G Ninja `
-DCMAKE_C_COMPILER=cl -DCMAKE_CXX_COMPILER=cl `
-DCMAKE_BUILD_TYPE=Release -DCAPSID_BUILD_HOST=ON `
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" `
-DVCPKG_TARGET_TRIPLET=x64-windows-static
cmake --build build-release --parallelFor a single-machine run, explicitly using a least-privilege capsid.json is
recommended: when the file is absent, the baseline is deny-all, and you add
allows item by item when capsid:* modules or egress fetch are needed.
// capsid.json
{
"apiVersion": "capsid/app-v1",
"permissions": {
"modules": [],
"fetch": { "allow": [] }
},
"pool": { "minReady": 1, "maxWorkers": 1 }
}npx esbuild app.js --bundle --format=esm \
--platform=neutral --target=esnext --outfile=app.bundle.js
./build-release/capsid-host --mode single-worker \
--worker ./build-release/capsid-worker \
--source-bundle app.bundle.js \
--source-name "file://$PWD/app.bundle.js" \
--application orders --listen 127.0.0.1:8080 \
--routing path --public-scheme http \
--capsid-json ./capsid.jsoncurl http://127.0.0.1:8080/@capsid/orders/
# {"message":"hello from Capsid","path":"/"}capsid-host supports single-worker, static-pool, and managed;
step-by-step permission field configuration is in the
capsid.json tutorial.
Application permissions are written in capsid.json; managed mode adds a
Host-authoritative host.json.
// capsid.json — what capabilities the application requests
{
"apiVersion": "capsid/app-v1",
"permissions": {
"modules": ["capsid:env"],
"fetch": { "allow": ["api.example.com"] }
},
"pool": { "minReady": 1, "maxWorkers": 1 }
}// host.json — managed mode: what the Host allows, where data lives
{
"apiVersion": "capsid/host-v1",
"applicationsRoot": "/srv/capsid/applications",
"stateRoot": "/srv/capsid/state",
"secretRootTemplate": "/srv/capsid/secrets/{application}",
"admin": { "unix": "/run/capsid/admin.sock", "mode": "0600" }
}See docs/capsid-json.md for the capsid.json
tutorial, and docs/host-config.md for host.json
fields.
The host links libcapsid_runtime and manages the listener, TLS, routing,
and pool lifecycle itself:
#include <capsid/runtime.h>
capsid_worker_config config;
capsid_worker_config_init(&config);
config.worker_path = "/opt/capsid/bin/capsid-worker";
config.request_timeout_ms = 5000;
capsid_worker *worker = NULL;
capsid_result result = capsid_worker_spawn(&config, &worker);Install the header <capsid/runtime.h> and the C++11 wrapper
<capsid/runtime.hpp>:
cmake --install build-release --prefix "$PWD/dist"Or embed Capsid into the host build:
add_subdirectory(path/to/capsid EXCLUDE_FROM_ALL)
target_link_libraries(my_gateway PRIVATE capsid::runtime)The full READY/credit/streaming/cancel contract is described in the host embedding specification.
Least privilege by default: without a capability policy, capsid:* modules cannot be imported. When egress_policy == NULL, all egress Fetch requests are denied. strict_sandbox is off by default, and the default configuration is only suitable for trusted code.
Authorization goes through three gates: build-time capabilities → module whitelist → resource allow/deny rules; Host limits and application requests are intersected.
Current public modules (each requires explicit authorization):
- Policy-constrained:
capsid:env,capsid:fs,capsid:stdio,capsid:storage,capsid:system - Permission query:
capsid:permissions - Pure utilities:
capsid:assert,capsid:getopts,capsid:hashing,capsid:ipaddr,capsid:utils,capsid:uuid
tjs:* modules cannot be enabled through configuration. Linux production environments must explicitly enable the strict sandbox and verify that CAPSID_EVENT_READY.flags contains the sandbox features required by the deployment. See Linux strict sandbox, capability policy, and security policy.
Bindings let the Host install trusted integrations such as MongoDB, MySQL, or Redis clients and expose only a small asynchronous method surface:
import mongo from "capsid:binding/mongo";
const rows = await mongo.find({ collection: "orders", filter: { open: true } });Each package is a Host-managed directory containing manifest.json and
index.js. Its manifest fixes the maximum modules, network targets,
filesystem paths, and Linux sandbox profiles; the App can only narrow those
resources. When an App declares a Binding, Capsid creates a separate Binding
Runtime in the same worker process and crosses the runtime boundary through
bounded asynchronous queues and structured-cloned values. If no Binding is
declared, Capsid keeps the original single-runtime path and pays no Binding
runtime or sandbox cost.
Application code receives the generated capsid:binding/<id> facade, never
the Binding's TJS modules, sockets, native handles, or credentials. See the
technical design and the exact
module and permission reference.
Capsid targets ECMA-429 Minimum Common Web API — the WinterTC (ECMA TC55)
specification, first edition, December 2025 — through the profile
CAPSID-MIN-2025-subset-v0. Conformance evidence is a pinned Web Platform Tests
revision plus process-level regressions; Capsid does not claim full ECMA-429
coverage beyond this profile. See
standards and conformance.
Frameworks that compile to a single self-contained ESM exporting a standard
fetch(request) handler are the supported integration path, provided they avoid
Node/server adapters, listeners, and filesystem static serving. External
services can be exposed through Host-authored Capsid Bindings. The compatibility
suite pins and continuously verifies Hono 4.12.32,
itty-router 5.0.24, and H3 v2 2.0.1-rc.26; other Web-standard frameworks
can be evaluated against the same rules, but only pinned versions carry evidence.
See framework compatibility.
4-core benchmark (Ryzen 3300X, Alpine v3.24/WSL2):
| Dimension | Capsid | Comparison |
|---|---|---|
| JSON 1 KiB throughput | 6,820 QPS | Flask 4,625 · Slim 1,826 |
| Small bundle cold start | 8–10 ms | Node 110 ms · Deno 39 ms |
| 1 MB trusted bytecode cold start | 42 ms | Node 149 ms · Deno 53 ms |
| Host + 2 workers idle PSS | 12.3 MB | Python 3 stack 62.6 MB |
Full methodology, 12 workloads, and evidence rules are in performance-benchmarks.md.
- Linux: full support.
single-worker/static-pool(multi-shard) /managedare available; strict sandbox andcapsid:fsare complete. For production, run untrusted code only on Linux. - macOS: development only. Runtime, worker, bytecode compiler, and the
single/static-pool Host are available;
capsid:fsis degraded (symlinks are rejected); strict sandbox andmanagedare unavailable, and--mode managedprints a notice and exits at runtime. - Windows: development only (MSVC, since v0.1.2). Runtime, worker,
bytecode compiler, and the single/static-pool Host are available;
multi-shard static-pool is distributed by a pool-level acceptor;
capsid:fsis degraded (C:/...paths only, reparse points are rejected); local Binding development (--bindings-root) is supported with reparse-point/hard-link/ACL checks, while strict sandbox profiles andmanagedremain Linux-only and--mode managedprints a notice and exits at runtime.
The full matrix and build requirements are in docs/platform-support.md.
| Topic | Entry |
|---|---|
| Architecture & boundaries | architecture.md |
| Platform differences | platform-support.md · windows.md |
| Host embedding | host-integration.md |
| Configuration & permissions | host-config.md · capsid-json.md |
| Host Bindings | binding-technical-design.md · binding-modules.md |
| Security & sandbox | capability-policy.md · linux-sandbox.md |
| Compatibility | conformance.md · framework-compatibility/ |
| Quality & performance | testing.md · performance-benchmarks.md |
The full task index is in docs/README.md.
for d in examples/hono-reference examples/itty-router-reference examples/h3-v2-reference; do
npm ci --ignore-scripts --prefix "$d"
done
cmake -S . -B build-release -DCMAKE_BUILD_TYPE=Release \
-DBUILD_TESTING=ON -DCAPSID_BUILD_HOST=ON
cmake --build build-release --parallel
ctest --test-dir build-release --output-on-failure \
-E '^wpt_conformance_not_configured$'The full CI matrix is in testing.md; contribution guidelines are in CONTRIBUTING.md.
Apache-2.0 © Capsid contributors
