8.8 KiB
What it is
PiAgentUI is a chat UI and workspace for the Pi coding agent. It runs as a web app served by a Pi extension or as a Tauri 2 desktop app, and shows in one window what a bare terminal hides: the session list, tool calls, MCP servers, skills and context usage.
- Streams real Pi sessions over SSE (
/global/event) and renders Markdown, code (Shiki) and math (KaTeX). - Shows tool calls as cards and the context usage of the active session.
- Switches models using the capabilities the runtime reports.
- Lists configured MCP servers (transport, command, URL, source) and effective skills grouped by source.
- Exposes built-in and dynamic slash commands, plus Git controls in the composer.
- Embeds a terminal (xterm.js) and a file explorer next to the chat.
- Accepts voice input through an OpenAI-compatible STT endpoint set in settings.
- UI locales:
en,pt-BR,es,zh-CN,hi,bn,ar(src/locales/).
Why use it
PiAgentUI does not keep its own agent state. Sessions, models, tools, skills and commands come from the Pi runtime through the extension, so what you see is what Pi is running.
Do not use it if you do not run Pi: without the extension the UI only shows the server connection dialog. It also handles one runtime per window and has no hosted demo or published npm package.
How it works
extensions/piagentui-server.tsis the Pi extension. It serves the built UI fromdist/over Nodehttp+wsand injectswindow.PI_BOOT_DATA(base URL and token).- On start it listens on port
58785(or the next free one) and writes the port and a random token to~/.pi/agent/piagentui-port.json. GET /global/healthis open; other/api/*routes requireAuthorization: Bearer <token>. The socket binds0.0.0.0, but each request is checked against loopback unless the LAN toggle at/api/network/accessis on (off by default).- The Tauri app reads the same discovery file through
get_pi_agent_connection, so the desktop build connects to the local runtime without manual setup. - In containers, the Rust router (
src-router/, axum) sits behind Caddy as the gateway in front of the frontend and backend services.
Quickstart
| Tool | Version | Needed for |
|---|---|---|
| Node.js | >=22 (.tool-versions: 22.22.0) |
everything |
| npm | bundled with Node | everything (package-lock.json) |
| Rust | 1.85.0 (.tool-versions) |
desktop app and gateway router |
| Docker Compose | any recent | container stack only |
| Pi Agent | installed locally | real sessions and models |
git clone https://git.evandro.dev.br/evandro/PiAgentUI.git
cd PiAgentUI
npm ci # postinstall runs scripts/copy-material-icons.mjs
npm run build # tsc -b && vite build -> dist/
npm run dev # Vite dev server on http://localhost:5173
npm run dev is front end only: it proxies /api to 127.0.0.1:4096 with the prefix stripped. For the Pi flow, build first and let the extension serve dist/ (Pi loads this repository as a package through the pi.extensions field of package.json):
npm run build
cat ~/.pi/agent/piagentui-port.json # {"port": 58785, "token": "..."}
# open http://127.0.0.1:58785
Desktop and Android:
npm run tauri dev # desktop window on the Vite dev server
npm run tauri build # bundles: nsis, dmg, deb (src-tauri/tauri.conf.json)
npm run tauri android dev # see scripts/dev-android.sh
Before a PR, npm run validate runs typecheck, extension typecheck, lint, build and tests; it is the gate CI runs in build.yml.
Configuration
The container stack is inherited from the OpenCodeUI deployment. Copy .env.example to .env first.
| File | Command | What it does |
|---|---|---|
docker-compose.yml |
docker compose up -d |
Full stack: gateway (Caddy + Rust router, 127.0.0.1:6658 and 6659), frontend, backend (opencode serve, 4096, 4G memory limit). |
docker-compose.standalone.yml |
docker compose -f docker-compose.standalone.yml up -d |
Front end only, for an existing opencode serve. Uses BACKEND_URL (default host.docker.internal:4096) and PORT (default 3000). |
docker-compose.host.yml |
docker compose -f docker-compose.yml -f docker-compose.host.yml up -d |
Optional override: backend runs privileged with the Docker socket and host / mounted at /host. |
docker-compose.build.yml |
docker compose -f docker-compose.yml -f docker-compose.build.yml up -d --build |
Optional override: builds gateway, frontend and backend locally from docker/. |
Environment variables (container stack only)
| Variable | Required | Description |
|---|---|---|
ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, DEEPSEEK_API_KEY, GROQ_API_KEY, MISTRAL_API_KEY, XAI_API_KEY |
At least one | LLM provider keys passed to the backend container. |
GATEWAY_PORT |
No (6658) |
Host port of the unified entry point. |
PREVIEW_PORT |
No (6659) |
Host port of the preview entry point. |
PREVIEW_DOMAIN |
No | Separate domain for previews; the reverse proxy forwards it to PREVIEW_PORT. |
WORKSPACE |
No (./workspace) |
Host directory mounted at /workspace in the backend. |
OPENCODE_SERVER_PASSWORD |
Public deployments | Password for the backend and the router. |
OPENCODE_SERVER_USERNAME |
No (opencode) |
Username paired with the password above. |
PUBLIC_BASE_URL |
No | Public base URL used by the router built into the gateway. |
ROUTER_SCAN_INTERVAL |
No (5) |
Router scan interval. |
ROUTER_TOKEN_LENGTH |
No (12) |
Length of the generated route tokens. |
ROUTER_PORT_RANGE |
No (3000-9999) |
Port range the router handles. |
ROUTER_EXCLUDE_PORTS |
No (4096) |
Ports the router skips. |
DOCKER_API_VERSION |
No (1.40) |
Docker API version for the backend; set in docker-compose.yml, not in .env.example. |
USE_CHINA_MIRROR |
No (1) |
Backend image build option: use the mirror sources below. |
APT_MIRROR, APT_SECURITY_MIRROR, NPM_CONFIG_REGISTRY, NODEJS_ORG_MIRROR, PIP_INDEX_URL, PIP_TRUSTED_HOST |
No | Mirrors for the backend toolchain. |
MISE_INSTALL_URL, OPENCODE_INSTALL_URL |
No | Installer URLs used when building the backend image. |
Project status
Beta, pre-1.0 (0.6.10), maintained by one developer. Releases are built by release.yml on v* tags (Windows, macOS, Linux and Android artifacts); deploy.yml publishes the web build with VITE_BASE_PATH=/PiAgentUI/.
- OpenCodeUI naming is only partly cleaned: the Rust router crate is
opencodeui-router, images areopencodeui-*, Android APKs are namedOpenCodeUI-*,.env.examplecomments are in Chinese, and the Docker backend runsopencode serve, which belongs to the inherited deployment, not to the Pi extension flow. docker-compose.ymlanddocker-compose.standalone.ymlstill pull the upstreamghcr.io/lehhair/opencodeui-frontendimage.- Tests are component- and server-level (Vitest). There are no tests for the Tauri shell or the Rust router beyond compilation, no end-to-end browser test and no coverage threshold.
- Voice input needs an OpenAI-compatible STT endpoint and has no automated browser test.
Issues and pull requests go to the issue tracker; run npm run validate before a PR.
License
GPL-3.0-only, see LICENSE. PiAgentUI is a fork and rework of OpenCodeUI; the original author is credited in src-tauri/Cargo.toml.
