The Hybrid, Agent-Native Worker Runtime
Write simple TypeScript/JavaScript handlers. Import dependencies directly by URL. Offload compute to native Rust and in-process Python AI. Package your verified application into a single immutable .njs capsule.
1. Mental Model & Architecture
Traditional runtimes (Node.js, Deno, Bun) are designed for heavy server runtimes with deep dependency graphs, long startup times, and hundreds of megabytes of node_modules.
nio-js reimagines workers for the AI agent era:
- Engine Core: Embedded QuickJS-NG (
rquickjs0.14) inside an asynchronous multi-threaded Tokio / Hyper Rust host. - Sub-Millisecond Cold Starts: Boots in < 1 ms with a clean baseline under 15 MB of RAM.
- Hybrid Compute Offloading: JavaScript handles routing and JSON orchestration. Heavy loops escape to native Rust machine code (
/** @native */) or in-process Python AI algorithms via PyO3. - Zero
node_modules: Modules are imported by HTTPS URL (esm.sh / UNPKG) with cryptographic SHA-256 lockfile pinning. - Tamper-Proof Capsules: Ship a production app in one portable
.njsfile containing verified bytecode/source, asset tables, and permission envelopes.
┌────────────────────────────────────────────────────────────────────────┐
│ nio-js Host (Rust) │
│ │
│ ┌───────────────────────┐ ┌───────────────────────────────┐ │
│ │ Tokio HTTP Core │ │ Multi-Worker Thread Pool │ │
│ │ (Reusable Port Socket)│ │ (Pinned per CPU Core) │ │
│ └───────────┬───────────┘ └───────────────┬───────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ QuickJS Runtime │ │
│ │ • Ultra-fast routing ('nio.js') │ │
│ │ • Direct string & zero-alloc JSON serialization │ │
│ └───────────┬──────────────────────────────────────┬───────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌────────────────────────┐ ┌──────────────────────────┐ │
│ │ /** @native */ │ │ In-Process Python │ │
│ │ Rust Offloading │ │ (PyO3 CPython Engine) │ │
│ └────────────────────────┘ └──────────────────────────┘ │
└────────────────────────────────────────────────────────────────────────┘
2. Installation & Quickstart
Automated One-Line Install
For macOS, Linux, and Android (Termux):
curl -fsSL https://raw.githubusercontent.com/nio-labs/nio-js/main/install.sh | bash
For Windows (PowerShell):
irm https://raw.githubusercontent.com/nio-labs/nio-js/main/install.ps1 | iex
Using the NPM Launcher
# Run without installing:
npx @nio-labs/nio-js --help
# Or install globally:
npm install -g @nio-labs/nio-js
Building from Source
git clone https://github.com/nio-labs/nio-js.git
cd nio-js
cargo build --release
sudo install -m 755 target/release/nio-js /usr/local/bin/nio-js
3. CLI Command Reference
| Command | Arguments / Options | Purpose |
|---|---|---|
nio-js run <entry> |
--port <p>, --host <h>, --workers <n> |
Launch a live dev server from a .ts, .js, or .njs file. |
nio-js build <entry> |
-o <out.njs>, --update, --frozen, --offline |
Resolve, download, and bundle all dependencies into an immutable capsule. |
nio-js check <entry> |
--format=agent-json, --format=pretty |
Perform instant syntax and module dependency validation without listening. |
nio-js mcp |
None (stdio transport) | Run standard Model Context Protocol server for Claude, Cursor, and Nio. |
nio-js inspect <capsule> |
Path to .njs file |
Display capsule graph topology, SHA-256 digests, and embedded assets. |
nio-js verify <capsule> |
Path to .njs file |
Cryptographically verify all digest checksums and graph integrity. |
4. Route Registration
Services import methods directly from 'nio.js'. Supported verbs include get, post, put, del, patch, head, and options:
import { get, post, del } from 'nio.js';
// 1. Zero-JS constant route: evaluated once, served instantly from Rust host
get('/', 'Hello from nio-js!');
// 2. Synchronous handler
get('/health', () => ({ status: 'ok', uptime: 104 }));
// 3. Asynchronous handler
get('/stats', async () => {
const dbData = await fetchExternalData();
return { data: dbData };
});
5. Requests, Responses & Status Codes
Handlers can return primitive values, plain JSON objects, binary buffers, or explicitly formatted responses via reply():
import { post, reply } from 'nio.js';
post('/api/orders', async ({ json }) => {
const order = await json();
if (!order.item) {
return reply(
{ error: 'Field "item" is required' },
{ status: 400, headers: { 'x-service-error': 'VALIDATION_ERR' } }
);
}
return reply({ orderId: 'ord_99', status: 'created' }, { status: 201 });
});
Response Type Coercion Table
| Return Value | HTTP Status | Content-Type | Internal Pipeline |
|---|---|---|---|
string |
200 OK | text/plain; charset=utf-8 |
Direct Tokio byte stream |
Object / Array |
200 OK | application/json |
Direct native Rust JSON serializer |
Blob / File |
200 OK | Declared MIME or application/octet-stream |
Streaming byte buffer |
reply(body, opts) |
Custom (e.g. 201, 400, 404) | Inferred or custom headers | Direct response wrapper |
6. Parameters & Query Strings
Route parameters use :param syntax and are accessed via req.params. Query strings are parsed into req.query:
import { get, reply } from 'nio.js';
// Matches /api/v1/users/usr_101
get('/api/v1/users/:id', ({ params }) => {
return { requestedUser: params.id };
});
// Matches /search?role=admin&limit=20
get('/search', ({ query }) => {
const role = query.role || 'all';
const limit = Number(query.limit || 10);
return { role, limit };
});
7. Body Parsing (JSON & Multipart)
Request bodies can be consumed exactly once via .json(), .text(), .blob(), or .formData():
import { post, reply } from 'nio.js';
// 1. JSON Body Parsing
post('/api/users', async ({ json }) => {
const body = await json();
return reply({ created: body.name }, { status: 201 });
});
// 2. File & Multipart Uploads
post('/api/upload', async ({ formData }) => {
const form = await formData();
const file = form.get('file');
if (!(file instanceof File)) {
return reply({ error: 'Missing uploaded file' }, { status: 400 });
}
return {
filename: file.name,
bytes: file.size,
preview: (await file.text()).slice(0, 100)
};
});
8. Native Acceleration (/** @native */)
For CPU-intensive tasks, nio-js provides the /** @native */ directive. Functions marked with this directive bypass QuickJS execution overhead and run compiled Rust machine code:
import { get } from 'nio.js';
/** @native */
function calculateChecksum(iterations: number): number {
let acc = 0;
for (let i = 0; i < iterations; i++) {
acc = (acc * 31 + i) & 0x7fffffff;
}
return acc;
}
get('/metrics/compute', ({ query }) => {
const rounds = Number(query.rounds || 100000);
return {
rounds,
result: calculateChecksum(rounds)
};
});
nio-js with native acceleration scores 25,000 – 40,000+ req/s, outperforming Node (9,282 req/s) and Bun (9,001 req/s) by 3x to 4x.
9. Multi-Core Worker Pinning
Scale across all CPU cores effortlessly. Every worker maintains its own isolated QuickJS runtime and thread-safe engine instance sharing a single socket listener:
# Run pinned to 8 worker threads on port 3000
nio-js run app.ts --port 3000 --workers 8
10. In-Process Python AI (PyO3)
Execute machine learning, data transforms, and Python algorithms in-process with zero IPC, zero sockets, and zero child processes:
1. Define Python Model (kernel.py)
def classify(query: str) -> str:
q = query.lower()
if any(k in q for k in ["bug", "error", "crash", "fix"]):
return "debugging"
return "general_task"
2. Import & Execute in TypeScript (server.ts)
import { get } from 'nio.js';
import { classify } from './kernel.py';
get('/classify', ({ query }) => {
const prompt = query.prompt || 'How do I fix this panic?';
const category = classify(prompt);
return { prompt, category };
});
11. Benchmark Highlights (Bare Metal)
Measured on bare-metal Apple Silicon (macOS ARM64, 8-core CPU) across 3 reproducible rounds with warm filesystem caches against Node.js, Bun, and Deno:
| Criterion | nio-js | Bun | Node.js | Deno | Verdict |
|---|---|---|---|---|---|
| Startup | 8.15 ms | 13.53 ms | 59.92 ms | 22.35 ms | 🏆 Clear Win (Fastest cold start) |
| Idle RSS | 8.75 MiB | 13.48 MiB | 46.84 MiB | 34.58 MiB | 🏆 Clear Win (Lowest memory footprint) |
| /constant | 68,000 req/s | 72,242 req/s | 63,037 req/s | 67,476 req/s | ⚖️ Tie / Competitive |
| /callback | 50,674 req/s | 71,144 req/s | 63,664 req/s | 64,630 req/s | 🥈 Competitive |
| /json | 42,360 req/s | 64,689 req/s | 51,838 req/s | 56,031 req/s | 🥈 Competitive |
| /cpu (100k loop) | 25,000 – 40,000+ req/s | 9,282 req/s | 9,001 req/s | 9,151 req/s | 🚀 Crushing Win (3x–4x faster than Bun/Node) |
Detailed benchmark reproduction instructions and test harness scripts are available in benchmarks/README.md.
12. Zero-Node Dependencies & Lockfiles
No package.json install steps or bloated node_modules. Import standard ES modules over HTTPS:
import { get } from 'nio.js';
import { z } from 'https://esm.sh/zod@3.23.8?target=es2022';
const Schema = z.object({ id: z.string() });
get('/validate', ({ query }) => ({ valid: Schema.safeParse(query).success }));
Lockfile Lifecycle
# Build and generate or update nio.lock
nio-js build app.ts --update -o app.njs
# Strictly enforce cached hashes in CI/CD (fails if checksum mismatch)
nio-js build app.ts --frozen -o app.njs
# Offline & air-gapped production builds (zero network requests)
nio-js build app.ts --offline --frozen -o app.njs
13. Single-File Capsules (.njs)
A capsule bundles the complete graph, assets, cryptographic hashes, and capability envelope into a portable artifact:
# 1. Build capsule with embedded assets
nio-js build app.ts --asset logo.svg=assets/logo.svg -o dist/app.njs
# 2. Inspect graph and metadata
nio-js inspect dist/app.njs
# 3. Cryptographically verify
nio-js verify dist/app.njs
# 4. Run standalone in production
nio-js run dist/app.njs --port 8080
14. Agent Diagnostics & Stdio MCP
Engineered specifically to support autonomous agents like Antigravity, Claude, and Cursor:
Fast Structured Diagnostics (nio-js check)
nio-js check src/app.ts --format=agent-json
{
"valid": true,
"modules_count": 4,
"errors": []
}
Stdio Model Context Protocol (nio-js mcp)
Expose compile, syntax check, and isolated code evaluation tools directly to AI coding agents over standard JSON-RPC:
nio-js mcp
15. Real-World Production Examples
Explore production-tested code directly inside the repository:
- REST API Gateway (
examples/api-gateway): Dynamic routing, query filtering, JSON validations, and native loop checksum acceleration. - AI Agent Worker (
examples/ai-agent-service): Intent classification, RAG context scoring, and structured task planning powered by in-process Python.
16. Ecosystem Roadmap to v1.0.0
nio-js is engineered to operate seamlessly as the execution tier of the wider Nio platform:
| Milestone | Focus Area | Key Features |
|---|---|---|
| v0.3.0 | Streaming & Agent Protocols | Server-Sent Events (SSE) token streaming, WebSockets, W3C Trace Context. |
| v0.4.0 | nio-db Native Data Tier |
Direct import { db } from 'nio.js', live SSE mutation consumer, in-memory query cache. |
| v0.5.0 | nio Agent & Event Bus |
Event workers (on()), unified tool registry (tool()) for stdio MCP and Nio CLI plugins. |
| v0.6.0 – v0.7.0 | Resilience & Static Assets | Zero-downtime hot reloading, Tokio static file serving, memory isolation caps. |
| v1.0.0 | General Availability (GA) | Frozen Capsule v1.0 spec, cross-ecosystem integration tests (nio + nio-db + nio-js). |
For deep technical details on the roadmap, see the full ROADMAP_V1.md document.
17. Security, Limits & FAQ
Q: Why does nio-js run reject routes registered after startup?
Routes must be registered synchronously during entry evaluation. Dynamically mutating routing tables at request time introduces concurrency races and degrades performance.
Q: What are the default resource boundaries?
Each QuickJS runtime instance defaults to a 32 MB heap ceiling and a 10 MB maximum request payload. Memory caps prevent rogue scripts from destabilizing the host.
Q: Can I run existing npm modules?
Yes. Any ESM module published to npm can be imported via https://esm.sh/<pkg>. Pure JavaScript and Web standard modules work out of the box.