199 lines
12 KiB
Markdown
199 lines
12 KiB
Markdown
<div align="center">
|
|
|
|
<img src="./assets/app-icons/app-icon.svg" width="96" alt="PiAgentUI logo" />
|
|
|
|
<h1>PiAgentUI</h1>
|
|
|
|
<p><strong>Desktop and web workspace for AI coding agents: streams real Pi Agent sessions with chat, tool cards, MCP and skills panels.</strong></p>
|
|
|
|
<a href="#-quickstart">Quickstart</a> ·
|
|
<a href="#-architecture">Architecture</a> ·
|
|
<a href="#-documentation">Docs</a> ·
|
|
<a href="https://git.evandro.dev.br/evandro/PiAgentUI/issues">Issues</a>
|
|
|
|

|
|

|
|

|
|
|
|
**English (US)** | [Português (BR)](./README.pt-BR.md) | [Español](./README.es.md) | [日本語](./README.ja.md)
|
|
|
|
</div>
|
|
|
|
<hr />
|
|
|
|
## 📌 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`, `bn` and `ar`.
|
|
|
|
## 🚀 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.
|
|
|
|
```bash
|
|
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/`:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
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
|
|
|
|
```mermaid
|
|
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`, Node `http` + `ws`) serves the built UI from `dist/` and injects `window.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/health` is open; other `/api/*` routes require `Authorization: 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
|
|
|
|
```text
|
|
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/`](docs/superpowers/specs/) | Design specs: Pi extension migration, sessions, STT and Git controls. |
|
|
| [`docs/superpowers/plans/`](docs/superpowers/plans/) | Implementation plans and the context, skills and MCP roadmap. |
|
|
| [`CHANGELOG.md`](CHANGELOG.md) | Release history used by the release workflow. |
|
|
| [`docker/`](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 are `opencodeui-*`, `.env.example` comments are in Chinese, and the Docker backend runs `opencode serve`, which belongs to the inherited deployment, not the Pi extension flow.
|
|
- `docker-frontend.yml` must be fixed before `ghcr.io/evandrodevbr/opencodeui-frontend` exists; 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:check` reported unformatted files at the last audit, so `npm run check` can fail on that step while `npm run validate` passes.
|
|
- `@mariozechner/pi-coding-agent` is 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](https://git.evandro.dev.br/evandro/PiAgentUI/issues). Before a PR, this must pass:
|
|
|
|
```bash
|
|
npm run validate
|
|
```
|
|
|
|
## 📄 License
|
|
|
|
GPL-3.0-only, see [`LICENSE`](LICENSE). PiAgentUI is a fork and rework of OpenCodeUI; the original authors are credited in `src-tauri/Cargo.toml`.
|