Command line for NodeUI: attach the console to any Node app without changing its code, watch several services from one page, and expose the data to AI agents over MCP.
npx @singhak/nodeui-cli attach -- node server.js
npx @singhak/nodeui-cli attach -- npm run dev
npx @singhak/nodeui-cli dashboard api=http://127.0.0.1:3000 worker=http://127.0.0.1:3001
npx @singhak/nodeui-cli check --run latest --max-p99 300 http://127.0.0.1:3000Runs your command with a small preload (NODE_OPTIONS=--require …) that wraps http.Server / https.Server. The console is served on your app's own port under /nodeui, and the terminal prints the URL once the app is listening:
[nodeui] console: http://127.0.0.1:3000/nodeui/
| Option | Effect |
|---|---|
--path <prefix> |
console path (default /nodeui) |
--token <secret> |
require an access token |
--persist <file> |
journal that survives restarts |
--otlp <url> |
export spans to an OTLP/HTTP collector |
--bodies |
capture request/response bodies (masked, capped) |
--force |
attach even when NODE_ENV=production |
What you get: requests, outgoing calls, logs, errors, health, memory/CPU/event loop, and queries from pg/mysql2. What you do not: route patterns and the route table for frameworks that expose them only through an adapter (Express still gets req.route patterns; Fastify, Koa, Hapi and Hono need their adapter), and Prisma (server.trackPrisma) or other manual hooks.
Notes and limits:
- It does not attach to an already running process; start the app through the CLI. Node cannot inject code into a process that is already running.
- Do not combine it with a NodeUI adapter in the same app: requests would be recorded twice.
- Production stays fail-closed: with
NODE_ENV=productionnothing is attached unless you pass--force. The usual loopback, Host and Origin checks apply. - Child processes inherit
NODE_OPTIONS, so tools that fork workers (e.g.npm run dev) attach in each Node process that creates an HTTP server.
Fails (exit 1) when a running console's recent traffic or a saved load-test run breaks a budget, for CI or a pre-push script:
npx @singhak/nodeui-cli check --window 300 --max-p99 300 --max-error-rate 1 http://127.0.0.1:3000
npx @singhak/nodeui-cli check --run latest --max-regression 10 http://127.0.0.1:3000| Option | Meaning |
|---|---|
--window <sec> |
check the last N seconds (default 300) |
--run <name|latest> |
check a saved run instead |
--max-p50/--max-p95/--max-p99 |
latency budgets in ms |
--max-error-rate <pct> |
percentage of 5xx responses |
--min-rps <n> |
throughput floor |
--max-loop-p99 <ms> |
event-loop delay budget |
--max-rss-mb <n> |
memory budget |
--max-regression <pct> |
with --run: p99 may rise and throughput may fall at most this much against the pinned baseline |
Exit codes: 0 all budgets held, 1 a budget failed, 2 nothing to check (no traffic, unknown run, console unreachable, or no limits given).
One loopback page that lists several running consoles with health, request count, error rate, p95 and error groups, and opens any of them through a proxy at /s/<name>/:
nodeui dashboard --port 4000 api=http://127.0.0.1:3000 billing=http://127.0.0.1:3100/nodeui?token=secret- A service entry is
name=urlor justurl; the console path defaults to/nodeui;?token=is the service's access token and is sent as a bearer header by the proxy (never put into the page). - The dashboard is loopback-only, rejects foreign
HostandOriginheaders, and strips cookies/origin when proxying so each service's own checks still apply. - Each service keeps its own data; the dashboard stores nothing.
A Model Context Protocol server over stdio, so an agent (Claude Code, Cursor, …) can read what your app is doing instead of you pasting logs:
{
"mcpServers": {
"nodeui": { "command": "npx", "args": ["@singhak/nodeui-cli", "mcp", "http://127.0.0.1:3000"] }
}
}Give it one console URL, or several as name=url (tools then take a service argument). Tools, all read-only:
| Tool | Returns |
|---|---|
nodeui_overview |
start here: prioritised digest of health, traffic, grouped errors, failing/slow requests, slow and N+1 queries, failing outgoing calls |
nodeui_errors |
grouped errors with stacks and the last linked request |
nodeui_requests |
recent requests; filter by minStatus / minDurationMs |
nodeui_request |
one request joined with its outgoing calls, queries and log lines |
nodeui_queries, nodeui_outgoing, nodeui_logs, nodeui_routes |
the matching panels, trimmed |
It reads the console's REST API, so everything is already masked, and it never calls heap snapshots or any confirmation-gated action. An agent sees only what the console would show you, and only on your machine unless you point it elsewhere.
import { startDashboard, parseTarget } from '@singhak/nodeui-cli';
const dashboard = await startDashboard({ services: [parseTarget('api=http://127.0.0.1:3000')] });