Creating or opening a session could stall for reasons the daemon knew
about and never shared. The browser invented the whole message it showed
while waiting -- "Creating session: Waiting for the backend session to be
ready" -- which says that we are waiting but never what for. A shared
ModelRuntime read during startup can be handed a network refresh that is
already in flight, and extensions may do their own network I/O while
loading, so the wait is real and previously unattributable.
The pre-session gap turned out to be a missing shared key rather than a
missing channel: publishActivity needs the PiAgentSession being built, but
the session id and cwd are both known before the first await. So create()
now publishes a new global session.startup event carrying an ordinary
SessionActivity, routed by cwd -- the one identity a browser row waiting
for a session id can match, since the client-invented pending id is
unknown to the daemon and the daemon's id is unknown to the browser.
Two phases are reported, each published before the await it describes so
the label changes during the wait rather than after it: "Starting the Pi
session" and "Loading session extensions". Both are facts, because the
service awaits exactly one call for each. A concurrent background catalog
refresh is appended as a note ("provider model lists are refreshing"),
never as the cause: the refresher can prove a refresh is running but not
that this startup joined it. ModelCatalogRefresher gains only a read-only
isRefreshInFlight() getter; cadence, timeout, and coalescing are untouched.
Reporting is event-only and synchronous. It writes no activities entry, no
workspace activity, and no unread state, so a failed creation leaves
nothing stranded, no await is added, and creation ordering and semantics
are unchanged. The window-ending idle report is skipped when a real
activity was published during startup, so an extension error survives.
The browser applies startup progress only when it can prove the target:
one non-discarded pending start in that cwd on the selected machine, or a
session whose id it already knows. A foreign workspace, another machine,
or two concurrent starts in one workspace keep today's generic wording
rather than showing one row the phase of another. An idle report restores
that generic wording, including the queued-messages variant.
docs/config.md said nothing a request triggers waits on a catalog fetch.
That is not strictly true for a refresh already in flight, so both it and
the generated docs/config.html now state the exception and say PI WEB
reports it while it happens.
PI WEB
PI WEB is a web UI for Pi Coding Agent that keeps agent sessions running in real workspaces on your machine or server.
Run agents where your code, tools, credentials, and build caches live. Supervise them from any browser.
Website and docs: https://pi-web.dev/
Why PI WEB?
Agentic development works better when the work environment is persistent.
PI WEB lets you:
- keep Pi Coding Agent sessions alive after browser disconnects;
- run agents inside real repositories and git worktrees;
- supervise multiple sessions in parallel;
- switch between laptop, phone, tablet, and desktop;
- use a server, workstation, or remote dev box as your agent runtime;
- manage projects, workspaces, files, terminals, sessions, and remote machines from one web UI.
Your browser is the control surface. The work stays where it can keep running.
Quick start
Requirements:
- Node.js 22.19.0 or newer
- npm
- Pi Coding Agent
>=0.82.1 <0.83, configured for your user - git and the development tools your agents need
Install and start PI WEB as per-user services:
npm install -g @jmfederico/pi-web --allow-scripts=node-pty
pi-web install
pi-web doctor
On npm 12, the scoped flag lets node-pty prepare its required native module without enabling install scripts for other dependencies.
Then open:
http://127.0.0.1:8504
Useful commands:
pi-web status
pi-web logs
pi-web restart
pi-web doctor
pi-web version
pi-web uninstall
For more install options, including one-line install, Pi package install, WSL/manual usage, and remote access, see the installation guide.
Core model
PI WEB organizes work like this:
Machine a local or remote PI WEB runtime endpoint
Project a folder on that machine
Workspace a git worktree, or the project folder for non-git projects
Session a Pi Coding Agent chat running inside a workspace
A typical flow:
- Add a project.
- Choose a workspace or git worktree.
- Start a session.
- Let the agent work.
- Come back later from any browser.
Remote-first development
PI WEB is designed for remote AI-driven development.
Instead of tying agent work to your laptop session, run PI WEB on a machine that stays available: a server, desktop, cloud VM, home lab machine, or remote dev box.
Use a private network, SSH tunnel, trusted reverse proxy, or federated PI WEB machine setup when accessing it remotely.
Read more: Remote-first development
Machines and fleets
PI WEB can register other PI WEB runtimes as remote machines. One browser-facing PI WEB instance can proxy projects, files, git state, sessions, terminals, activity, Pi package management, and selected-machine settings from trusted remote machines.
When a remote machine is selected, Settings tabs label their target. Pi packages, PI WEB plugin enablement, session daemon toggles, external file access, and upload defaults target the selected machine. Gateway/server settings such as host, port, allowed hosts, registered machines/tokens, and keyboard shortcuts stay local to the gateway/browser.
Read more: Fleet and machines guide
PI WEB plugins
PI WEB supports trusted browser-side plugins that can add actions, workspace panels, and workspace metadata. Use Settings → PI WEB plugins to enable or disable them on the selected machine.
Pi packages are a separate Pi package-manager concept. A Pi package may include a PI WEB browser plugin, but installing a package and enabling its browser plugin are different operations.
Read more: PI WEB plugin guide and API
Configuration
Global config lives at:
$PI_WEB_CONFIG
~/.config/pi-web/config.json
Project-local PI WEB config lives at:
<project>/.pi-web/config.json
Common configuration includes host/port, path access, uploads, PI WEB plugin enablement, shortcuts, and session daemon options. In Settings, machine-affecting config targets the selected machine; gateway host/port/allowed-hosts, remote machine registration, tokens, and keyboard shortcuts stay local.
Read more: Configuration reference
Development
Clone the repository and run:
npm install
npm run dev
Open the Vite URL, usually:
http://localhost:8505
For the split development setup:
npm run dev:sessiond
npm run dev:web
npm run dev:client
Validate changes with:
npm run verify
Security model
PI WEB assumes trusted users, trusted repositories, and trusted server paths.
It is not a sandbox, permission system, or multi-tenant platform. Do not expose it directly to the public internet without a trusted network, firewall, VPN, SSH tunnel, or authenticated reverse proxy.
Documentation
License
MIT © 2026 Federico Jaramillo Martinez. See LICENSE.

