npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@nopeek/agent-bridge

v0.3.0

Published

Run your own agents as E2EE NoPeek bots. Pairs with a one-time code, runs every bot you own, and pipes messages to any command or webhook.

Downloads

213

Readme

@nopeek/agent-bridge

Run your own AI agents as end-to-end-encrypted NoPeek bots — from your Mac, a Linux box, or a Raspberry Pi.

The bridge is a small always-on process that:

  1. Pairs with your NoPeek account — one tap in the NoPeek app ("Connect this computer"), or a one-time pairing code (npr_…) if you prefer the terminal.
  2. Runs every bot you own — each bot connects as a real NoPeek user with its own server device, publishes MLS key packages, and decrypts messages locally like any other client. The server never sees plaintext.
  3. Pipes each incoming message to your "brain" — any shell command (message on stdin, reply on stdout) or any HTTP webhook — and sends the reply back into the encrypted channel.

When you create a new bot in the NoPeek app, the bridge adopts it live over its control connection. No restart, no redeploy.

Quick start — one command, then the app

npm install -g @nopeek/agent-bridge && nopeek-agent-bridge install

That installs the bridge as a background service (launchd on macOS, systemd --user on Linux) that starts at login and waits, unpaired. Then, in the NoPeek app on the same computer:

  1. Contacts → My Bots → Connect this computer — one tap. The app mints the pairing secret and hands it straight to the local bridge; you never see or paste it.
  2. Create bots; each one starts on your computer within seconds.
  3. Per bot: ⋯ → Choose brain… — pick a detected agent (Hermes, Claude Code, llm, Ollama), a custom command, a webhook, or echo. Changes apply to the next message, no restart.

Every bot you own answers in every chat it's a member of. Add a bot to a group in the NoPeek app and it just starts working.

Quick start — terminal-only (no app steps)

# Zero config: bots run in echo mode ("You said: …") — a smoke test
npx @nopeek/agent-bridge --pair npr_XXXXXXXX --app-id app_XXXXXXXX

# Plug in a real agent runtime (Hermes example):
npx @nopeek/agent-bridge \
  --pair npr_XXXXXXXX \
  --app-id app_XXXXXXXX \
  --brain-cmd 'HERMES_HOME=/Volumes/x10drive/hermes hermes --profile nopeek chat -Q -q "$(cat)"'

The npr_… code comes from Settings → Connect your computer (bots) in the app. install also accepts --pair/--app-id to pre-pair the service from the terminal.

Local control API

The bridge serves a loopback-only HTTP API on 127.0.0.1:8790 — this is what the NoPeek app uses; you can script it too.

| Endpoint | Auth | Purpose | | --- | --- | --- | | GET / | none | Minimal status: {ok, service, version, paired, machine, uptime} | | POST /pair | the npr_… secret itself; only accepted while unpaired | {pairingSecret, appId, apiUrl?} — validate, persist, start bots | | GET /status | x-nopeek-runtime: rt_… | Full status: bots, brains, runtime id | | GET /detect | x-nopeek-runtime | Agent runtimes found on PATH (hermes, claude, llm, ollama) with suggested commands | | PUT /brains | x-nopeek-runtime | {brainCmd?, brainUrl?, map?: {"<handle>": {cmd|url|echo}|null}} — applies live, persists | | DELETE /pair | x-nopeek-runtime | Unpair: stop bots, forget the secret (device keys kept) |

The x-nopeek-runtime header is the runtime id — a capability only the owner's logged-in app can fetch from the NoPeek server, so a random webpage poking 127.0.0.1 can't read your bot list or change brain commands. Everything the app configures persists to ~/.nopeek-bridge/settings.json (mode 600).

How the brain works

The bridge is runtime-agnostic on purpose. A "brain" turns a message into a reply, and there are three flavors:

1. Command brain (--brain-cmd / BRAIN_CMD)

The bridge spawns bash -c "<your command>", writes the user's message text to stdin, and takes trimmed stdout as the reply. ANSI escape codes are stripped automatically (agent CLIs like Hermes colorize their output).

Context is passed as environment variables:

| Variable | Meaning | | --- | --- | | NOPEEK_BOT_HANDLE | handle of the bot answering | | NOPEEK_BOT_USER_ID | user id of the bot | | NOPEEK_CHANNEL_ID | channel the message arrived in | | NOPEEK_SENDER_USER_ID | who sent the message |

Examples:

# Hermes
--brain-cmd 'HERMES_HOME=/Volumes/x10drive/hermes hermes --profile nopeek chat -Q -q "$(cat)"'

# OpenClaw, Claude Code, llm, anything that reads a prompt and prints an answer
--brain-cmd 'openclaw ask --stdin'
--brain-cmd 'llm -m gpt-4o "$(cat)"'

# Route per channel inside your own script
--brain-cmd '/home/me/route.sh'   # read stdin, inspect $NOPEEK_CHANNEL_ID, print reply

On non-zero exit, timeout, or empty output the bridge logs the error and sends a short friendly fallback so the chat never goes silent.

2. Webhook brain (--brain-url / BRAIN_URL)

The bridge POSTs JSON to your endpoint and expects { "text": "…" } (or { "reply": "…" }) back:

POST <your url>
Content-Type: application/json

{
  "text": "what's the weather?",
  "botHandle": "weatherbot",
  "botUserId": "usr_…",
  "channelId": "ch_…",
  "senderUserId": "usr_…"
}

Minimal server:

// node server.mjs
import { createServer } from "node:http";
createServer((req, res) => {
  let body = "";
  req.on("data", (d) => (body += d));
  req.on("end", async () => {
    const { text } = JSON.parse(body);
    res.setHeader("content-type", "application/json");
    res.end(JSON.stringify({ text: `You asked: ${text}` }));
  });
}).listen(9000);
npx @nopeek/agent-bridge --pair npr_… --app-id app_… --brain-url http://localhost:9000

3. Echo (default)

With no brain configured, every bot replies You said: <text>. Use it to verify pairing and E2EE end to end before wiring a real agent.

Per-bot brains (BRAIN_MAP)

Different bots, different brains. BRAIN_MAP is a JSON object keyed by bot handle; each entry is {"cmd": "…"} or {"url": "…"}:

BRAIN_MAP='{
  "hermesbot": {"cmd": "HERMES_HOME=/Volumes/x10drive/hermes hermes --profile nopeek chat -Q -q \"$(cat)\""},
  "weatherbot": {"url": "http://localhost:9000/weather"}
}' npx @nopeek/agent-bridge --pair npr_… --app-id app_…

Resolution order per bot: BRAIN_MAP[handle] → global BRAIN_CMD → global BRAIN_URL → echo.

Configuration

Everything can be set three ways, highest precedence first: CLI flag → environment variable → nopeek-bridge.config.json (same key names as the env vars, in the working directory or via --config <path>).

| Flag | Env var | Default | Meaning | | --- | --- | --- | --- | | --pair | NOPEEK_PAIRING_CODE | — | Pairing code (npr_…); optional — pairing from the app is easier | | --app-id | NOPEEK_APP_ID | — | Your NoPeek app id (set automatically when pairing from the app) | | --api-url | NOPEEK_API_URL | https://d3qweh72vesa98.cloudfront.net | NoPeek API base | | --brain-cmd | BRAIN_CMD | — | Global command brain | | --brain-url | BRAIN_URL | — | Global webhook brain | | --brain-map | BRAIN_MAP | {} | Per-handle overrides (JSON) | | --brain-timeout-ms | BRAIN_TIMEOUT_MS | 180000 | Brain timeout (generous: agent runtimes think slowly) | | --port | NOPEEK_BRIDGE_PORT | 8790 | Local control API port (loopback only) | | --data-dir | NOPEEK_BRIDGE_DATA_DIR | <home>/data (legacy ./data honored) | Per-bot device-key store directory | | --home | NOPEEK_BRIDGE_HOME | ~/.nopeek-bridge | Settings, default data dir, service logs | | --config | — | ./nopeek-bridge.config.json | Config file path |

Precedence: CLI flag → env var → nopeek-bridge.config.json<home>/settings.json (written when you pair or set brains from the app).

Example config file:

{
  "NOPEEK_PAIRING_CODE": "npr_XXXXXXXX",
  "NOPEEK_APP_ID": "app_XXXXXXXX",
  "BRAIN_CMD": "HERMES_HOME=/Volumes/x10drive/hermes hermes --profile nopeek chat -Q -q \"$(cat)\""
}

Health endpoint

GET http://localhost:8790/

{
  "ok": true,
  "runtime": "rt_…",
  "bots": [
    { "handle": "hermesbot", "userId": "usr_…", "connected": true, "handled": 12 }
  ],
  "uptime": 3600
}

ok reflects the control connection; each bot reports its own connection and how many messages it has answered.

Behavior & reliability

  • Live adoption — create a bot in the app and the bridge starts running it within seconds (control WebSocket push), plus a full re-sync on every reconnect so nothing is missed.
  • Isolation — each bot runs independently with its own retry/backoff loop; one misbehaving bot never affects the others.
  • Reconnects — the control socket and every bot connection reconnect forever with capped exponential backoff. Runtime sessions are refreshed before they expire.
  • Dedupe — redelivered messages are never answered twice.
  • Crash guards — unhandled rejections/exceptions are logged and survived; the process only exits on config errors (clearly, at startup) or a signal.
  • Typing indicator — shown while the brain is thinking.

Security notes

  • Messages are E2EE (MLS): decryption happens on your machine, inside this process. The NoPeek server only ever relays ciphertext.
  • Your API keys, agent credentials, and brain commands are yours — the bridge never sends them anywhere. Brains run locally (or on the webhook host you choose).
  • The only state written to disk is ./data/<botUserId>.json: each bot's device identity and channel keys, needed so restarts keep the same device. Treat that directory like a private key (it is one) — it's .gitignored, and you can move it with --data-dir.
  • The pairing code is a bearer credential for running your bots, nothing more. Revoke it from the NoPeek app at any time; the bridge simply stops authenticating.

Running it long-term

nopeek-agent-bridge install does this for you (launchd LaunchAgent on macOS, systemd user unit on Linux; uninstall removes it, status queries the running bridge). If you'd rather manage the process yourself, anything that keeps it alive works. For example, on Linux:

# /etc/systemd/system/nopeek-bridge.service
[Service]
Environment=NOPEEK_PAIRING_CODE=npr_…
Environment=NOPEEK_APP_ID=app_…
Environment=BRAIN_CMD=…
WorkingDirectory=/home/me/nopeek-bridge
ExecStart=/usr/bin/npx @nopeek/agent-bridge
Restart=always

On macOS, a launchd plist or just tmux works fine.

Requirements

  • Node.js 22+ (global fetch, WebSocket, WebCrypto — no polyfills needed).
  • bash on PATH if you use a command brain.