main
Pi Web UI
A full-stack web interface for the Pi coding agent, providing browser access to a system-level Pi agent with bash, file read/write/edit, and extension tools.
Read the writeup on Sleeping Robots: Pi Web UI: A Browser Interface for the Pi Coding Agent.
Architecture
Browser (Lit + pi-web-ui components)
│ WebSocket (/api/ws)
▼
Node.js server (Express + ws)
│
▼
Session broker (runtime ownership and WebSocket attachments)
│ Pi SDK (createAgentSession)
▼
System tools (bash, files, skills, extensions)
- Server (
server/index.ts): Owns broker runtimes that contain Pi SDKAgentSessioninstances with full system access. WebSocket clients attach to and detach from runtimes. A disconnect does not stop active work. Loads auth and model config from~/.pi/agentthroughModelRuntime. Model discovery can use LiteLLM. - Client (
client/main.ts): Lit-based UI using@earendil-works/pi-web-uicomponents (MessageList,MessageEditor,StreamingMessageContainer). Communicates only through WebSocket. - Protocol (
shared/protocol.ts): Typed JSON message definitions for the WebSocket wire format.
Setup
npm install
npm run build
Environment variables
| Variable | Default | Description |
|---|---|---|
PORT |
3001 |
Server listen port |
HOST |
127.0.0.1 |
Server listen address. Use 0.0.0.0 only on a trusted network and with PI_WEBUI_TOKEN set. |
PI_WEBUI_TOKEN |
(unset) | Required by default shared secret for /api/ws and the skills editor API. If set, open /?token=<token> once on first load; the client stores it in localStorage and removes the query parameter from the URL. |
PI_WEBUI_ALLOW_ANONYMOUS |
false |
Local development escape hatch only: tokenless mode requires this flag and a loopback HOST. Non-loopback/public binding always requires PI_WEBUI_TOKEN. |
PI_WEBUI_ALLOWED_ORIGINS |
same host as request | Additional comma-separated WebSocket Origin allowlist values. |
PI_WEBUI_TITLE |
Pi Web UI |
Browser title and visible application name. |
PI_CODING_AGENT_DIR |
~/.pi/agent |
Pi agent config directory for auth, models, settings, sessions, and shared skills. |
PI_WEBUI_SKILL_MAX_FILES |
220 |
Max SKILL parse candidates per skill directory scan. |
PI_WEBUI_SKILL_PARSE_BYTE_BUDGET |
3000000 |
Max total bytes read while scanning skills for a list call. |
PI_WEBUI_SKILL_FILE_MAX_BYTES |
240000 |
Max bytes per individual skill file. |
PI_WEBUI_SKILL_MAX_DEPTH |
8 |
Max recursive directory depth while scanning skill directories. |
PI_WEBUI_SKILL_DIRECTORY_ENTRY_LIMIT |
1000 |
Max entries inspected in any one visited skill directory. |
PI_WEBUI_SESSION_DIRECTORY_SCAN_LIMIT |
800 |
Max directory entries considered for a session listing scan before sorting and pagination. |
PI_WEBUI_SESSION_MAX_FILES |
240 |
Max session files parsed per listing request. |
PI_WEBUI_SESSION_PARSE_BYTE_BUDGET |
6000000 |
Max total bytes read for session list parsing per request. |
PI_WEBUI_SESSION_FILE_MAX_BYTES |
220000 |
Max leading bytes read from each session for bounded listing/search; large sessions remain listable but searches do not inspect content beyond this prefix. |
PI_WEBUI_USER_SKILLS_DIR |
~/.pi/skills |
Private skills edited from /skills. With the default working directory this is loaded by Pi as a project-local skills directory. |
PI_WEBUI_SHARED_SKILLS_DIR |
$PI_CODING_AGENT_DIR/skills |
Shared read-only skills listed in /skills and available to all agents using this agent dir. |
PI_WEBUI_RESTRICT_MODELS_TO_SCOPED |
(unset) | If true/yes/on/1, only models from PI_WEBUI_MODEL, PI_MODEL, settings.defaultProvider/defaultModel, or settings.enabledModels are listed/selectable. |
PI_WEBUI_FORCE_MODEL_ALIAS_LABELS |
(unset) | If true/yes/on/1, show configured model aliases (name) instead of raw provider/model ids in the UI and response metadata. |
SESSION_LIST_LIMIT |
30 |
Default sessions fetched per sidebar page. |
SESSION_LIST_MAX_LIMIT |
100 |
Maximum sessions accepted per sidebar page request. |
MESSAGE_PAGE_LIMIT |
60 |
Default newest messages sent for an opened conversation. |
MESSAGE_PAGE_MAX_LIMIT |
200 |
Maximum messages accepted per conversation page request. |
SESSION_LIST_CACHE_MS |
10000 |
Sessions sidebar cache TTL. |
LITELLM_URL |
(empty) | Optional LiteLLM API base URL for extra model listing. |
LITELLM_KEY |
(from ~/.pi/agent) | LiteLLM API key (auto-detected from Pi config if unset) |
Development
npm run dev
Starts the server (tsx watch) on port 3001 and Vite dev server on port 5173 with WebSocket proxy.
Production
npm run build
HOST=127.0.0.1 PORT=8085 PI_WEBUI_TOKEN=change-me npm start
Features
- Full Pi agent with system access (bash, read, edit, write, extensions)
- Broker-owned sessions with persistence, history, reconnect support, and multi-tab observation
- Session search, rename, deletion, stable session links, and paged loading
- Model switching with scoped/default models first and an optional full model list
- Optional scoped-only model selection and alias-only model labels
- Configurable thinking level with saved session settings restored on resume
- Startup resource summary for the model, session, tools, and advertised skills
- Activity and compaction status during long turns
- Prompt history through the Up and Down keys
- Structured tool-result summaries and one-toggle Input and Result details
- Authenticated previews and downloads for files in the agent home directory
- Built-in skills manager at
/skillsfor private and shared skills - Expanded-by-default responsive session sidebar and mobile top-bar controls
- Dark/light theme toggle with green accent
Project structure
├── client/
│ ├── index.html Entry point
│ ├── main.ts Client application (state, WebSocket, rendering)
│ └── app.css Theme overrides and sidebar styles
├── server/
│ ├── index.ts Express + WebSocket server and Pi SDK adapter
│ └── session-broker.ts Runtime ownership, attachments, commands, and cleanup
├── shared/
│ └── protocol.ts WebSocket message type definitions
├── vite.config.ts Vite config (build, dev proxy)
├── tsconfig.json TypeScript config
└── package.json Dependencies and scripts
Description
Fork of https://github.com/Zetaphor/pi-webui for local evaluation
1.2 MiB
0 Stars
1 Watchers
0 Forks
Languages
TypeScript
90.5%
CSS
9.4%
HTML
0.1%