12 KiB
PiAgentUI
Desktop and web workspace for AI coding agents: streams real Pi Agent sessions with chat, tool cards, MCP and skills panels.
Quickstart · Architecture · Docs · Issues
English (US) | Português (BR) | Español | 日本語
📌 The problem
Pi Agent runs in a terminal. A bare terminal gives you no overview of sessions, no readable tool calls, and no place to inspect MCP servers, skills or context usage. PiAgentUI puts those in one window, as a web app or a Tauri desktop app, without inventing agent state: sessions, models, tools, skills and commands come from the Pi runtime whenever possible.
✨ What it does
- Streams real Pi Agent sessions into a chat view over SSE (
/global/event), with Markdown, code highlighting (Shiki) and math (KaTeX). - Renders tool calls as cards and shows context usage for the active session.
- Switches models, using the normalized capabilities returned by the runtime.
- 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 configured in settings.
- Ships as a web build or a Tauri 2 app, with UI locales
en,pt-BR,es,ja,zh-CN,hi,bnandar.
🚀 Quickstart
| Tool | Minimum version | Needed for |
|---|---|---|
| Node.js | >=22 (.tool-versions: 22.22.0) |
everything |
| npm | >=10 |
everything (package-lock.json is authoritative) |
| Rust | 1.85.0 (src-tauri/Cargo.toml) |
desktop app and gateway router only |
| Docker | Docker Compose | container stack only |
| Pi Agent | installed locally | real sessions and models |
Without Pi Agent the UI starts in standalone mode and only shows the server connection dialog.
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/:
npm run build
cat ~/.pi/agent/piagentui-port.json # {"port": 58785, "token": "..."}
# open http://127.0.0.1:58785 (Pi Agent running this repo as a Pi package, see package.json "pi")
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
Container stack
Copy .env.example to .env first. Four compose files exist:
| 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 (Caddy, 3000) and 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 the host / mounted at /host. Use only when really needed. |
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/. |
The backend and gateway images come from ghcr.io/evandrodevbr/opencodeui-{backend,gateway}. The frontend image still points at upstream ghcr.io/lehhair/opencodeui-frontend, because docker-frontend.yml has failed since 2026-06-01 and no ghcr.io/evandrodevbr/opencodeui-frontend was published.
Environment variables
All variables come from .env.example and apply to the container stack only (the Pi extension flow needs none).
| 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 dedicated preview entry point. |
PREVIEW_DOMAIN |
No | Separate domain for previews, to avoid front-end asset path problems; 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. Set it when exposing the stack. |
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. |
USE_CHINA_MIRROR |
No (1) |
Backend image build option: use the mirror sources below. |
APT_MIRROR, APT_SECURITY_MIRROR |
No | Debian mirrors for the backend image build. |
NPM_CONFIG_REGISTRY, NODEJS_ORG_MIRROR, PIP_INDEX_URL, PIP_TRUSTED_HOST |
No | npm, Node.js and pip sources for the backend toolchain. |
MISE_INSTALL_URL, OPENCODE_INSTALL_URL |
No | Installer URLs used when building the backend image. |
🧱 Architecture
flowchart LR
UI["React UI in browser or Tauri webview"] -->|"HTTP api, SSE, WebSocket"| SRV["Pi extension server"]
PI["Pi Agent runtime"] -->|"loads extension"| SRV
SRV -->|"writes port and token"| DISC["~/.pi/agent/piagentui-port.json"]
TAURI["Tauri shell"] -->|"get_pi_agent_connection"| DISC
TAURI --> UI
- The extension (
extensions/piagentui-server.ts, Nodehttp+ws) serves the built UI fromdist/and injectswindow.PI_BOOT_DATA {baseUrl, token}. - On session start it listens on port
58785(or the next free one) and publishes the port and a random token in the discovery file. GET /global/healthis open; other/api/*routes requireAuthorization: Bearer <token>. Access is loopback-only by default, with a LAN toggle at/api/network/access.- The extension bridges sessions, models, tools, MCP, skills and commands; the full route table lives in the server file.
- The Tauri app reads the same discovery file, 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.
🗂️ Structure
extensions/ Pi extension: HTTP/WebSocket server, settings, git and extension managers (Vitest)
src/ React 19 front end: api, components, features, hooks, locales, store
src-router/ Rust gateway router (axum) behind Caddy
src-tauri/ Tauri 2 desktop and mobile shell, Android project in gen/
docker/ Dockerfiles, Caddyfiles, entrypoints
scripts/ icon copy, version bump, release preparation, Android dev helper
docs/ design specs and plans (docs/superpowers/)
assets/ app icon sources
.github/ 6 workflows: build, deploy, release, docker-backend/frontend/gateway
🧪 Scripts
| Command | What it does |
|---|---|
npm run dev |
Vite dev server (front end only). |
npm run build |
tsc -b && vite build, output in dist/. |
npm run preview |
Serves dist/ locally for a final check. |
npm run typecheck |
tsc -b (app and extension projects). |
npm run type-check |
Alias of typecheck. |
npm run typecheck:extensions |
tsc -p tsconfig.extension.json --noEmit. |
npm run lint |
eslint . |
npm run format |
prettier . --write |
npm run format:check |
prettier . --check |
npm run test |
vitest in watch mode. |
npm run test:run |
vitest run (needs dist/, so build first). |
npm run validate |
typecheck, extension typecheck, lint, build, tests. The gate CI runs in build.yml. |
npm run check |
format check, lint, build, tests. |
npm run tauri |
Tauri CLI (dev, build, android dev). |
npm run icons:tauri |
Regenerates src-tauri/icons from src-tauri/app-icon.manifest.json. |
npm run release:prepare |
Runs scripts/prepare-release.mjs. |
npm run postinstall |
Runs scripts/copy-material-icons.mjs (automatic after npm ci). |
Deploy notes: dist/ is a plain SPA; under a subpath build with VITE_BASE_PATH=/subpath/ npm run build. deploy.yml publishes to GitHub Pages with VITE_BASE_PATH=/PiAgentUI/ on pushes to main, and release.yml attaches Windows, macOS, Linux and Android artifacts on v* tags.
📚 Documentation
| Document | Content |
|---|---|
docs/superpowers/specs/ |
Design specs: Pi extension migration, sessions, STT and Git controls. |
docs/superpowers/plans/ |
Implementation plans and the context, skills and MCP roadmap. |
CHANGELOG.md |
Release history used by the release workflow. |
docker/ |
Dockerfiles, Caddy configs and entrypoints. |
🛣️ Limitations and next steps
- Active single-developer project, pre-1.0 (
0.6.10); some areas are still moving. - OpenCodeUI naming is only partly cleaned: the Rust crate is
opencodeui-router, images areopencodeui-*,.env.examplecomments are in Chinese, and the Docker backend runsopencode serve, which belongs to the inherited deployment, not the Pi extension flow. docker-frontend.ymlmust be fixed beforeghcr.io/evandrodevbr/opencodeui-frontendexists; compose files pull that image from upstream until then.- No tests for the Tauri shell or the Rust gateway beyond compilation; desktop and Android bundles are only built by the release workflow.
- Tests are component- and server-level: no end-to-end browser test and no coverage threshold.
npm run format:checkreported unformatted files at the last audit, sonpm run checkcan fail on that step whilenpm run validatepasses. @mariozechner/pi-coding-agentis a devDependency for types only, and npm marks that package line as deprecated in favour of@earendil-works/pi-coding-agent.- One runtime per window (discovery file or manually configured server); no multi-runtime aggregation.
- Voice input needs an OpenAI-compatible STT endpoint and has no automated browser test.
- No published npm package and no hosted web demo.
🤝 Contributing
Open an issue or a PR on the issue tracker. Before a PR, this must pass:
npm run validate
📄 License
GPL-3.0-only, see LICENSE. PiAgentUI is a fork and rework of OpenCodeUI; the original authors are credited in src-tauri/Cargo.toml.