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

anyagent-bridge

v0.9.3

Published

Control your local terminal and any CLI AI coding agent from a browser, anywhere.

Readme

anyagent-bridge

Control your local computer's terminal — and any CLI AI coding agent you've registered (Claude Code, Codex, aider, …) — from a browser on your phone or another PC, anywhere.

🤖 Are you an AI agent someone handed this repo to? If a person just asked you to "install this" / "set it up" / "run it," follow AGENTS.md top to bottom — the full clone → install → test → launch → verify playbook, with the few steps only a human can do (a browser login, an approval, a phone QR) clearly marked. The person does not need to tell you which files to read or what commands to run; it's all in there.

anyagent-bridge — a live terminal in the browser

Quick start

First install Node.js 18+ (the LTS build from https://nodejs.org) — npx needs it. Then:

# New here? A guided, first-timer setup (checks prerequisites, helps you go mobile):
npx anyagent-bridge setup

# Or run it directly (Node 18+):
npx anyagent-bridge

# Or self-host with Docker:
docker compose up -d --build && docker compose logs bridge

Open the printed URL, paste the access token from the banner, and you're in. To open it on a phone or another PC, click "📱 Connect a device" in the top bar and scan the QR. New to all this? Start with docs/GETTING-STARTED.md. Full install paths (npx · from source · Docker) and per-OS notes are in docs/INSTALL.md; read docs/SECURITY.md before exposing the bridge beyond localhost, and docs/WALKTHROUGH.md for a guided tour.

Let an AI agent set it up for you

Don't want to touch a terminal? If you already have a command-capable AI agent (Claude Code or Codex) installed and logged in, just give it this repo's URL and ask it to install — that's all. You don't need to know or mention any filenames. Paste something like this:

Install and run this on my computer for me: https://github.com/elon-choo/anyagent-bridge Do everything you can yourself, and only ask me for the things you genuinely can't do.

The agent finds the install playbook in the repo on its own — it's in AGENTS.md (which Codex reads automatically) and CLAUDE.md (which Claude Code reads) — then clones, installs, tests, launches, and verifies the bridge, pausing only for the handful of things it can't do for you (a browser login, an approval, a phone QR). Handing it just the URL is enough.

Brand-new and have no agent installed yet? Run the wizard yourself instead: npx anyagent-bridge setup — it checks prerequisites and helps you install one.

Goals

  • Open — fully open source, no lock-in, bring whatever agent you like.
  • Cross-platform — runs on macOS, Windows, and Linux.
  • Free & secure — no accounts, no cloud middleman; localhost-only by default with a single-token gate.

Features

  • Drive a real terminal (PTY) from the browser, with full scrollback (10,000 lines).
  • Register any command as an "agent" and launch it with one click — not hardcoded to one tool.
  • Multiple browser viewers can watch/control the same session at once (live broadcast).
  • Persistent sessions that survive reconnects, with automatic PTY respawn and backoff.
  • Heartbeat + dead-connection detection so stale viewers get cleaned up.
  • File management API: browse, read, write, rename, move, delete, upload, download — all behind a path whitelist.
  • Add projects by browsing folders in the UI (the 📁 Projects button) — no typing full paths.
  • Save API keys / tokens into a project's .env.local from the UI (the 🔑 Secrets button) — never paste them into the chat or hand-edit files.
  • Crash guards (uncaught exceptions, signals) so the server stays up.
  • Constant-time token comparison and basic rate limiting.
  • Optional login: Google/GitHub OAuth, TOTP 2FA, and signed expiring sessions on top of the token (Stage 3).
  • Boot-time update check (anonymous, rate-limited to once/24h, opt-out via BRIDGE_UPDATE_CHECK=off) plus a one-line GitHub-star nudge — it only notifies, never auto-updates.

Requirements

  • Node.js 18+
  • Your own AI CLI, already installed and logged in. anyagent-bridge never injects or stores any credentials — it just runs the command you registered (e.g. claude, codex), and that CLI uses its own existing authentication.

Install

npm install

node-pty is a native module, so npm install compiles it on first run. If the build fails you likely need standard build tools:

  • macOS — Xcode Command Line Tools: xcode-select --install
  • Linuxbuild-essential (or your distro's gcc/g++/make) and Python 3
  • Windows — the Visual Studio Build Tools (C++ workload)

For one-command npx and Docker / docker-compose installs, plus updating, uninstalling, and per-OS troubleshooting, see docs/INSTALL.md.

Configure

Copy the example config and edit it:

cp config.example.json config.json
{
  "host": "127.0.0.1",
  "port": 3001,
  "shell": null,
  "auth": { "token": null },
  "agents": [
    { "id": "claude", "name": "Claude Code", "command": "claude" },
    { "id": "codex", "name": "Codex", "command": "codex" }
  ],
  "projects": [],
  "allowedPaths": [],
  "sessionTimeoutDays": 7
}
  • host127.0.0.1 (default) keeps the bridge on localhost only. Set 0.0.0.0 to expose it on your network (opt-in; you'll see a warning at boot).
  • port — the port to listen on.
  • shellnull auto-picks per OS ($SHELL or /bin/bash; on Windows %COMSPEC% or powershell.exe). Set a path to override.
  • auth.tokennull generates a random token on first boot and saves it to .data/auth.json. There is no default password or default token.
  • agents — register any command. Each entry is { "id", "name", "command" }; command can be literally any executable on your PATH. Add your own (aider, custom scripts, etc.) by adding more entries.
  • projects — optional [{ "name", "path" }] shortcuts for quick directory switching.
  • allowedPaths — file-API whitelist. [] defaults to your home directory.
  • sessionTimeoutDays — how long idle sessions persist.

Run

npm start

Connect

On first boot the server prints your access token and the local URL in a banner like this:

===============================================================
  AnyAgent Bridge — server running
===============================================================
  URL:       http://127.0.0.1:3001?token=9f3c...
  Host:      127.0.0.1
  Shell:     /bin/zsh
  Agents:    claude, codex
  ...
  Access token (generated): 9f3c...
===============================================================

The URL already includes the token, so opening it logs you in; otherwise visit the address and paste the token when prompted. The token is saved to .data/auth.json and reused on the next boot.

Remote access (Stage 2)

To reach the bridge from your phone or another machine, enable a tunnel. The first four providers wrap external CLIs you install yourself; the fifth is a built-in endpoint for a relay you self-host. There are no new npm dependencies. Tunnels are off by default; when disabled, missing, or misconfigured the server runs exactly as before (localhost-only) and never crashes.

| Provider (provider id) | CLI | Account? | URL | One-time setup | |---|---|---|---|---| | Microsoft Dev Tunnels (devtunnel, default) | devtunnel | yes | rotates per run (stable with a pre-created tunnelId) | devtunnel user login | | Cloudflare Quick (cloudflare-quick) | cloudflared | no | ephemeral *.trycloudflare.com | none — testing-grade (≈200 req cap, no SSE) | | Tailscale Funnel (tailscale) | tailscale | yes | stable *.ts.net | tailscale up + enable Funnel in the tailnet ACL | | cloudflared named (cloudflared-named) | cloudflared | yes | stable custom hostname | cloudflared tunnel logintunnel createtunnel route dns | | E2EE self-hosted relay (e2ee-relay) | built in + your relay | no | operator-configured | Run the opaque relay + configure endpoint keys; protocol and limitations |

Enable it in config.json:

{
  "tunnel": {
    "enabled": true,
    "provider": "devtunnel",
    "cloudflared-named": { "tunnelName": "my-tunnel", "hostname": "bridge.example.com" },
    "e2ee-relay": { "relayUrl": null, "publicUrl": null, "channelId": null, "pairingSecret": null }
  }
}

Or via environment variables (override config.json):

  • BRIDGE_TUNNEL_ENABLEDtrue/1 to enable.
  • BRIDGE_TUNNEL_PROVIDER — one of the ids above.
  • BRIDGE_TUNNEL_HOSTNAME — public hostname for the cloudflared-named provider.
  • BRIDGE_RELAY_URL, BRIDGE_RELAY_PUBLIC_URL, BRIDGE_RELAY_CHANNEL, BRIDGE_RELAY_SECRET — self-hosted E2EE relay endpoint settings. Keep the pairing secret out of URLs; see docs/RELAY.md.

Inspect and control the tunnel at runtime (all require the access token):

  • GET /api/tunnel/status — current state, provider, and public URL.
  • POST /api/tunnel/start · POST /api/tunnel/stop · POST /api/tunnel/restart.

The boot banner prints the public URL once the tunnel is ready. With the four transparent tunnel providers, your access token may be the only thing between the internet and your terminal — keep it secret, or add a login (next section). The E2EE relay adds a separate endpoint pairing secret but does not replace bridge authentication.

The E2EE relay is different from a transparent HTTP tunnel: conforming endpoint traffic is X25519/HKDF/AES-256-GCM protected and the relay forwards ciphertext only. The current same-origin browser UI is not automatically remapped into that byte transport; use the trusted client endpoint described in docs/RELAY.md. The repository provisions no hosted relay.

Login & accounts (Stage 3)

On top of the static token you can require a real login. Everything here is opt-in: with OAuth off, no 2FA enrolled, and requireLogin false, the bridge behaves exactly as before (the token works directly). No new npm dependencies.

The one rule: the static token is a direct credential unless you set requireLogin or enroll 2FA — then it becomes login-only (you exchange it, with your 2FA code, for a session). That is what makes 2FA actually protective. Logins mint a signed, expiring session delivered as an httpOnly cookie.

Two-factor (TOTP). Once authenticated, enroll from the API: POST /api/auth/totp/setup returns an otpauth:// URI to scan with Google Authenticator / 1Password / Authy, then POST /api/auth/totp/confirm with a code activates it and returns one-time recovery codes (store them). Enrolling 2FA flips the token to login-only.

OAuth (Google / GitHub). Register an OAuth app with each provider, then set the client id/secret (in env, not committed config) and enable it:

{
  "auth": {
    "requireLogin": false,
    "oauth": {
      "enabled": true,
      "callbackBaseUrl": "https://your-tunnel.example",
      "claimFirstUser": true,
      "google": { "clientId": "…", "clientSecret": "…", "allowedEmails": ["[email protected]"] },
      "github": { "clientId": "…", "clientSecret": "…", "allowedLogins": ["yourlogin"] }
    }
  }
}

Set each provider's callback to <callbackBaseUrl>/api/auth/oauth/<provider>/callback. The allowlist (allowedEmails / allowedLogins) is fail-closed — an empty allowlist admits no one, unless claimFirstUser is on, in which case the first successful login claims the bridge and everyone else is denied (so don't expose a fresh, unclaimed bridge publicly). Always set callbackBaseUrl when OAuth is reachable, so the redirect URI is not derived from request headers.

Login endpoints (all under /api/auth): POST /login · POST /logout · GET /config · GET /me · GET /sessions · DELETE /sessions/:id · GET /oauth/:provider/{start,callback} · POST /totp/{setup,confirm,disable}. Configure it all via the auth block in config.json or BRIDGE_* env vars (see .env.example).

Sandboxing & safety (Stage 4)

Four opt-in safety layers, all off by default. With safety.enabled false the server is byte-identical to Stage 3. No new npm dependencies — the Docker layer spawns the docker CLI; everything else is Node core. Configure via the safety block in config.json or BRIDGE_* env vars (see .env.example).

{
  "safety": {
    "enabled": true,
    "trustProxy": false,
    "sandbox": { "enabled": true, "image": "your-image-with-claude:latest", "network": "bridge", "onDockerMissing": "host" },
    "killSwitch": { "enabled": true },
    "audit": { "enabled": true },
    "redaction": { "liveStream": false }
  }
}
  • Docker sandbox — runs each session's shell (and therefore its agent) inside a container instead of on the host. Only sessions with a real project folder are sandboxed (it never bind-mounts your whole home directory); the project is mounted at /workspace. You supply an image that already contains your agent CLI (we can't ship one). network defaults to bridge so the agent can reach its API; set none for offline file-only work. Resource limits (memory/cpus/pidsLimit) and no-new-privileges are applied by default; readOnlyRootfs / dropAllCaps / runAsHostUser are opt-in hardening. Secrets reach the container via an envPassthrough allowlist as -e NAME (values never appear in the process table; BRIDGE_*/token are always denied). If docker is missing, onDockerMissing decides: host (fall back to a host shell, the default) or refuse (don't start).
  • Kill-switchPOST /api/safety/kill/:sessionId hard-kills one session (SIGKILL + container removal); POST /api/safety/panic kills all sessions, sweeps stray containers, optionally stops the tunnel, and locks the bridge so no new agents launch until POST /api/safety/unlock. The lock never strands your shell (only agent launches are refused) and survives a restart. All operator-only; also reachable over WebSocket ({type:"panic"} / {type:"kill"}).
  • Audit log — append-only JSONL under .data/audit/ of REST mutations and the semantic agent commands (agent.start / agent.send); raw keystrokes are not logged (they can't be reconstructed into commands). Date + size rotation with retention pruning. Every field is redacted before write.
  • Secret redaction — the audit log is always scrubbed (AWS / OpenAI / GitHub / Slack / Google keys, JWTs, PEM private keys, plus the bridge's own token). Live PTY-stream redaction is opt-in (redaction.liveStream) and best-effort — it holds back partial tokens across chunk boundaries but is kept off by default so the terminal stream stays byte-identical.

Proxy trust (trustProxy). Closes a Stage-3 residual: by default the client IP for rate limiting and the audit log now comes from the direct socket peer, ignoring a spoofable X-Forwarded-For. Behind a tunnel or reverse proxy, set trustProxy to true (trust the nearest hop) or a number N (trust N hops) so per-client IPs are correct. It only takes effect once you opt into the safety subsystem, so an upgraded install with no safety config is unchanged.

Status at GET /api/safety/status (and folded into GET /api/system/status).

Note: the Docker sandbox is implemented and unit-tested for argv/secret correctness and graceful degradation, but live container spawning was not exercised on the build machine (no daemon). Test your image end-to-end before relying on it.

Security notes

  • Localhost by default. Out of the box the server binds 127.0.0.1, so only your own machine can reach it.
  • The token is the gate. There is no default password and no default token — one is generated on first boot and persisted to .data/auth.json. Keep it secret. If you set host to 0.0.0.0, the token is the only thing standing between the internet (or your LAN) and your terminal — the server warns you about this at boot.
  • No credential injection. The bridge runs your registered command and nothing more; your AI CLI's own login is used as-is.
  • One optional outbound call. The bridge doesn't phone home. The only exception is the update check: at most once per 24h the boot banner makes one anonymous GET to the public npm registry for a newer release (nothing sent but the package name, cached in .data/update-check.json, fail-open and non-blocking). It prints a one-line notice and never updates anything. Turn it off with BRIDGE_UPDATE_CHECK=off (or NO_UPDATE_CHECK=1).
  • Add a login before exposing it. Free tunnels (Stage 2), OAuth + 2FA login (Stage 3), and the Docker sandbox / kill-switch / audit / redaction (Stage 4, see Sandboxing & safety) are all shipped. If you expose the bridge, require a login, set callbackBaseUrl, and set trustProxy for your proxy; prefer localhost or a trusted network otherwise. The full security model and disclaimers are in docs/SECURITY.md.

Roadmap

  • Stage 1 (this release) — portable, cross-platform core: terminal + any-agent control over WebSocket, file API, persistent sessions, token auth.
  • Stage 2 (this release) — free tunnel adapters (Dev Tunnels, Cloudflare, Tailscale, cloudflared) for zero-config remote access. See Remote access.
  • Stage 3 (this release) — OAuth (Google/GitHub) + 2FA + real session management. See Login & accounts.
  • Stage 4 (this release) — Docker sandboxing, kill-switch, audit logging, secret redaction. See Sandboxing & safety.
  • Stage 5 (this release) — packaging: a bin launcher for npx, a Dockerfile + docker-compose, cross-platform install docs (INSTALL), a security guide (SECURITY), and a walkthrough.

Full detail in docs/ROADMAP.md.

License

MIT — see LICENSE.