nio-js v0.2.0
Release v0.2.0 Sub-millisecond Boot 68k+ req/sec Rust + QuickJS + PyO3

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 (rquickjs 0.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 .njs file 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 };
});
Registration Lifecycle: Routes must be registered during the evaluation of the entry file. Once the server binds to its port, registration closes permanently to prevent dynamic race conditions.

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)
  };
});
Benchmark Performance: Under a 100,000 iteration loop benchmark, 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)
Zero Python Startup Overhead: Python execution is completely modular and loaded on-demand. Standard TypeScript/JavaScript services, static routing, and native loops incur zero Python startup latency and zero Python memory footprint.

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:

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.