@piwebui/pi-web-bridge

pi-web bridge for terminal pi sessions: live streaming and browser prompts with zero configuration.

Packages

Package details

extension

Install @piwebui/pi-web-bridge from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:@piwebui/pi-web-bridge
Package
@piwebui/pi-web-bridge
Version
0.1.1
Published
Nov 8, 2026
Downloads
2,648/mo · 2,648/wk
Author
h8notme
License
MIT
Types
extension
Size
69.3 KB
Dependencies
0 dependencies · 1 peer
Pi manifest JSON
{
  "extensions": [
    "./extensions/pi-web-bridge.js"
  ],
  "changelogPath": "./CHANGELOG.md"
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

@piwebui/pi-web-bridge

Let a terminal pi session be seen and driven from pi-web — live, streaming, and with nothing to configure.

pi install npm:@piwebui/pi-web-bridge     # once, ever

That is the whole installation. Start pi-web in one terminal, pi in another, open the URL pi-web prints, and that terminal appears as Terminal (bridged) within a couple of seconds — thinking, tool calls, tool output and the answer stream into the browser token by token, and the browser can send prompts, steer a running turn, rename, switch model/thinking level and abort, while the terminal keeps working normally.

/new, /resume, /fork and /reload inside pi keep all of that working with no further action.

What it actually does

The extension runs inside your terminal pi process. It finds the running pi-web server through its descriptor (~/.pi-web/bridge.json by default), dials the server's Unix socket, streams this pi's live events out, and executes the commands that come back in.

pi (your terminal) ── pi events ──▶ bridge ── JSONL over a unix socket ──▶ pi-web ──▶ browser
                     ◀── prompt / abort / rename / setModel / setThinking ───

It uses only Pi's public extension API. It does not patch Pi, read another process's memory, attach a debugger, write session files, or talk to a provider. It has zero dependencies (Node builtins only), so it loads even when Pi is offline.

Nothing to configure — and what it reads if you do want to

Resolution order, first usable hit wins (every step is reported by /piweb):

Step Source
1 PIWEB_BRIDGE_DISABLE=1 — off, silently, no socket, no retry
2 PIWEB_BRIDGE_FILE=/path/bridge.json
3 PIWEB_BRIDGE_SOCKET + PIWEB_BRIDGE_TOKEN (inline; containers, tests)
4 $PIWEB_DATA_DIR/bridge.json
5 $PI_CODING_AGENT_DIR/../pi-web/bridge.json
6 ~/.pi-web/bridge.json — the normal case
7 ~/.pi-web/servers/*.json — pointers to other servers (multi-server fan-out)
8 legacy PIWEB_BRIDGE_DIR + PIWEB_BRIDGE_TOKEN (pre-1.0 registry mode, one release)

Other knobs, all optional:

Variable Default Meaning
PIWEB_BRIDGE_MODES tui which run modes get bridged; pi -p, JSON/RPC and pi-web's own managed host stay unbridged
PIWEB_BRIDGE_MAX_SERVERS 4 how many pi-web servers one pi will serve at once
PIWEB_BRIDGE_DISABLE – 1 turns the bridge off for this process
PIWEB_BRIDGE_DEBUG – 1/stderr or a file path: log what the bridge decided
--no-pi-web-bridge – per-invocation opt-out flag

Inside pi:

  • the footer shows ● pi-web · 1 viewer · <serverId>;
  • /piweb prints the session, the viewers, dropped-frame counts, or why it is not connected with the command that fixes it.

What the browser can not do from a terminal session (honest limits)

Limit Why
Answer a terminal extension dialog from the browser Pi's public API exposes no response handle for another extension's dialog (ui_prompt_start/end carry kind/title only), so it is shown as observed with "answer in the terminal" — never auto-approved
List or clear the message queue not exposed by Pi; only a "pending" flag
Expand slash commands / @paths in browser text opt-in only (expandCommands), because expanding dispatches extension commands from browser input
Show the exact provider request Pi hooks/routing are below the extension API; what you see is labelled a runtime preview

Security model, in one paragraph

The bridge listens on no network port: one Unix socket owned by the pi-web server, 0600 in a 0700 directory, authenticated by a token that only ever lives in that 0600 descriptor. Same uid is the trust boundary: anything running as you that can read ~/.pi-web/bridge.json can register a runtime and push prompts into a pi it can name. Beyond that floor, the server attests every bridge — the claimed pid must be a live process that looks like the Pi CLI and that started when it claims it did — and keeps a runtime list you can revoke (pi-web revoke-runtime <id>). Node exposes no SO_PEERCRED accessor, so peer credentials are not part of this design; process attestation plus file modes are. Set PIWEB_BRIDGE_DISABLE=1 if you do not want any terminal bridged.

Uninstall

pi remove npm:@piwebui/pi-web-bridge     # or: rm ~/.pi/agent/extensions/pi-web-bridge.js

Nothing else is left behind: the bridge writes no files, no sockets and no pid files of its own.