peekpoint
v0.3.0
Published
Live runtime inspector for Node — see real variable values at any line without redeploying
Downloads
429
Maintainers
Readme
PeekPoint
Live runtime inspector for Node — see the real value of any variable, at any line, inside a running server, on demand. No redeploy. No pause. No hosted backend.
Quick start
npm install peekpointAdd PeekPoint to your server (pick one):
Recommended for ESM (runs before your app loads):
node --import peekpoint/register ./server.jsOr add to your server entrypoint:
import { init } from "peekpoint";
init({ token: process.env.PEEKPOINT_TOKEN, port: 9999 });For ESM apps,
importstatements are hoisted aboveinit(), so breakpoints bind best with--import peekpoint/register.
Start the local bridge and dashboard:
npx peekpointOpen the printed URL (e.g. http://127.0.0.1:9999/?t=<token>), set a logpoint on a file + line with variable names, then hit your endpoint — captures appear within ~1s.
Auto-capture every request (Express / MERN)
Add the middleware once and every request/response/error is recorded automatically — no manual logpoints:
import { init, expressMiddleware, expressErrorMiddleware } from "peekpoint";
app.use(express.json());
app.use(expressMiddleware()); // after body parser, before routes
// ...your routes...
app.use(expressErrorMiddleware()); // last, to capture thrown errorsEach request becomes a capture with method, url, route, statusCode, durationMs, and a tree of query, params, body, headers, responseBody, and error — serialized and redacted in-process. In the dashboard's Inspect tab, filter by HTTP to see them. Captures persist in the browser (IndexedDB) across refreshes; use Clear to wipe them.
Capture browser state per request (cookies, localStorage, sessionStorage, IndexedDB)
Install once in your frontend (React, Vue, plain HTML — any browser app) to attach the page's state to every backend HTTP capture:
import { initPeekpointClient } from "peekpoint/client";
initPeekpointClient({
token: import.meta.env.VITE_PEEKPOINT_TOKEN, // same token as the bridge
// host: "127.0.0.1", // default
// port: 9999, // default
// captureIndexedDB: true,
});The SDK wraps fetch and XMLHttpRequest, stamps each request with an X-Peekpoint-Trace-Id header, snapshots cookies/localStorage/sessionStorage (+ IndexedDB DB & store names), and ships it to the bridge over WebSocket. The bridge correlates by trace id and shows the Browser state panel inside the matching backend HTTP card. Sensitive keys (password, token, authorization, …) are redacted client-side before leaving the browser.
Watch hits inside requests
When a watch (logpoint) fires during an HTTP request (same process, within the request's lifecycle), it is automatically attached to the request card as a Watch hit — you don't have to look in two places. Requests with watch hits also appear in the Watch filter.
Optional project config:
npx peekpoint init # writes peekpoint.config.js onlyHow it works
flowchart LR
Browser -->|WS token| Bridge
AppAgent -->|WS outbound| Bridge
Bridge -->|relay commands| AppAgent
AppAgent -->|V8 logpoint condition| Capture
Capture -->|serialize + redact| Bridge
Bridge -->|captures| Browserinit()attaches an in-processnode:inspectorsession (no--inspect, no open debug port).- Logpoints use
Debugger.setBreakpointByUrlwith a condition that captures data and returnsfalse— V8 never pauses. npx peekpointstarts a localhost-only bridge that serves the bundled dashboard and relays WebSocket messages.
Security model
| Property | Behavior |
|----------|----------|
| Network | Bridge binds 127.0.0.1 only — never 0.0.0.0 |
| Auth | Shared secret token in URL + WS handshake |
| Debugger | In-process inspector on current process only |
| Data | Redaction runs in the agent before values leave the process |
| Install | No postinstall file writes; dashboard ships inside the package |
| AI | Optional Gemini key stored in ~/.peekpoint/config.json (chmod 600), used by bridge only |
Remote servers (SSH tunnel)
Run on the server:
npx peekpointOn your laptop:
ssh -L 9999:localhost:9999 your-serverOpen http://127.0.0.1:9999/?t=<token> locally. Agent and bridge always talk over localhost on the machine where the app runs.
Demo apps
# Terminal 1 — bridge (note the token)
npx peekpoint --token devtoken --no-open
# Terminal 2 — demo Express app
cd examples/demo-express
npm install
set PEEKPOINT_TOKEN=devtoken # Windows
# export PEEKPOINT_TOKEN=devtoken # macOS/Linux
npm start # uses node --import peekpoint/register
# Terminal 3 — trigger capture
curl "http://localhost:3000/checkout?code=SAVE10"In the dashboard Inspect tab, watch server.js line 37 with vars discount, code, cart.total (use the absolute path printed by the demo).
TypeScript + source maps demo:
cd examples/demo-ts && npm install && npm run build && npm startWatch src/server.ts line 35 with vars subtotal, multiplier, total.
API
init({
token?: string; // default: PEEKPOINT_TOKEN env
port?: number; // default: 9999
serve?: boolean; // embedded bridge (single-process local use)
release?: string; // e.g. GIT_SHA — for source map matching
redact?: string[]; // extra redaction keys
enabled?: boolean; // default: NODE_ENV !== "test"
});Known limits (v1)
- Long-running Node processes only — not serverless (Vercel/Lambda).
- Default capture path never pauses; optional pause-and-read mode is off by default.
- Source maps require
.mapfiles on disk near the running app.
Development
npm install
npm run build
npm testLicense
MIT
