# pi-remote-web-ui A minimal, secure web GUI for the [pi coding agent](https://github.com/badlogic/pi-mono). image ## Security model The server **only binds to `127.0.0.1`** – it is never reachable from the internet. You access it by forwarding a port through your existing SSH connection: ``` ssh -L 8080:localhost:8080 root@your-vps ``` Then open **http://localhost:8080** in your browser. Authentication is provided entirely by your SSH key – no passwords, tokens, or TLS certificates required. Add this to `~/.ssh/config` on your local machine so the tunnel opens automatically every time you SSH in: ``` Host your-vps HostName User root IdentityFile ~/.ssh/your_key LocalForward 8080 127.0.0.1:8080 ``` ## Architecture ``` Browser tabs (localhost:8080) │ │ SSH tunnel │ └─► pi-remote-web-ui server (127.0.0.1:8080) ← binds here only │ ├─► AgentSession (in-process, shared across all tabs) │ Uses pi SDK directly — no subprocess spawning │ tools: bash, read, edit, write … │ └─► static files (dist/) ``` A single `AgentSession` instance runs inside the server process. All browser tabs share the same conversation — events are broadcast to every connected client in real time. When a new tab connects, it receives the full conversation history via a `state_sync` message. This follows the [pi SDK recommendation](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/docs/sdk.md) for Node.js applications to use `AgentSession` directly rather than spawning `pi --mode rpc` subprocesses. ## Setup ### 1. Install dependencies & build ```bash cd ~/dev/pi-remote-web-ui npm install npm run build # builds frontend → dist/ npm run build:server # compiles server → dist-server/ ``` ### 2. Run manually (for testing) ```bash # Option A – run compiled server node dist-server/index.js # Option B – dev mode (Vite HMR + tsx watch) npm run dev ``` Then SSH in with port forwarding and open http://localhost:8080. ### 3. Install as a systemd service (runs on boot, auto-restarts) ```bash sudo cp pi-remote-web-ui.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable --now pi-remote-web-ui sudo systemctl status pi-remote-web-ui ``` View logs: ```bash journalctl -u pi-remote-web-ui -f ``` ## Usage | Action | How | |--------|-----| | Send message | Type and press **Enter** | | New line in message | **Shift+Enter** | | Abort generation | Click **Stop** button | | New session | Click **+ New** in the header (resets for all tabs) | | Expand tool output | Click any tool card | | Expand thinking | Click the 💭 Thinking block | **Note:** All connected tabs share the same session. Starting a new session or sending a prompt from any tab affects every tab. ## Project structure ``` pi-remote-web-ui/ ├── index.html Frontend entry point ├── src/ │ ├── main.ts Frontend app (TypeScript) │ └── style.css Dark theme ├── server/ │ └── index.ts WebSocket + HTTP server (AgentSession in-process) ├── dist/ Built frontend (git-ignored) ├── dist-server/ Built server (git-ignored) ├── pi-remote-web-ui.service systemd unit file ├── vite.config.ts Frontend build config ├── tsconfig.json Frontend TypeScript config └── tsconfig.server.json Server TypeScript config ```