pios-webui
Web chat interface for the pi coding agent, powered by the pi SDK (@earendil-works/pi-coding-agent) — one-command run, systemd/launchd deployable
Package details
Install pios-webui from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pios-webui- Package
pios-webui- Version
0.37.0- Published
- Aug 30, 2026
- Downloads
- 304/mo · 304/wk
- Author
- mrytsr
- License
- MIT
- Types
- extension
- Size
- 3.5 MB
- Dependencies
- 20 dependencies · 0 peers
Pi manifest JSON
{
"extensions": [
"./extensions"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pios
Local-first AI coding workspace for pi
面向 pi coding agent 的本地优先 AI 编程工作台
English / 中文 · 简体中文文档
Turn pi into a complete browser-based coding cockpit.
让 pi 不只是聊天机器人,而是一个可观察、可操作、可持续运行的编程工作台。
pios is a full-featured web interface for the pi coding agent. It runs the pi SDK in the server process and connects your browser directly to the agent's live work: streaming answers, thinking blocks, tool calls, files, images, terminal sessions and Git changes.
它把 AI 编程中最重要的工作流放在同一个界面里:对话、文件、终端、Git、模型配置和任务复核。数据默认保留在本机,服务默认只监听 loopback,适合个人开发、远程工作站和长期运行的项目会话。
Requires Node.js ≥ 22.19 and a configured pi environment.
Why pios?
普通 AI chat UI 只能看到答案;pios 让你看到并控制完整的 coding loop:
- Observe / 可观察 — Streaming responses, thinking blocks, tool calls and bash output with live status.
- Act / 可操作 — Attach a file or selected lines, steer a running turn, use the terminal, and work with Git without leaving the browser.
- Keep context / 保持上下文 — Multiple conversations can run per project; switch away and come back without losing the running task.
- Verify / 可复核 — Set a goal and let an independent review session check the final response and
git diff, then feed back actionable corrections. - Own your setup / 掌控环境 — Configure models, system prompts, skills, extensions and reusable presets from the UI; provider credentials stay on the server.
- Run anywhere / 随处运行 — One command locally, or install as a macOS launchd agent, Linux systemd unit or Windows scheduled task.
Core workflow
- Open a project / 打开项目 — Start
piosin any workspace and use the browser as your coding cockpit. - Ask and inspect / 对话并检查 — Follow the agent's reasoning, tool calls and file changes as they happen.
- Operate / 直接操作 — Preview files, select exact lines, attach images, run commands in the built-in terminal, and review Git status or diff.
- Guide / 持续引导 — Send a steer while a turn is running, edit and re-ask an earlier question, or keep several project conversations running in parallel.
- Review / 自动复核 — Lock a goal, review the result with a separate model, and iterate until the work passes or reaches the configured limit.
Features
Chat
- Streaming agent chat over WebSocket — the pi SDK runs in-process; events are pushed as snapshots (60 ms throttled) and the browser renders them.
- Thinking blocks, tool-call cards and bash outputs with live status (running → finished · waiting for the model · duration).
- 补充 (steer) — send a follow-up while the agent is replying; it is queued and injected as soon as the current turn's tool calls settle (the "Interrupt" equivalent of the pi CLI).
- Slash commands —
/opens a command picker (built-in / extension / template / skill); built-ins include/new /model /compact /cwd /thinking /resume, plus/help(command list) and/copy(copy last reply). - Multiple conversations per project — each conversation gets its own agent runtime and keeps running in the background after you switch away; the "Running conversations" list shows stream progress and lets you switch back.
- Edit & re-ask — fork any past question into a new branch and re-prompt; the original conversation stays untouched.
- Long threads auto-collapse messages older than 30 into lazy summary rows (click to expand).
- Question navigation — a floating rail plus per-question tags to jump between questions.
Files, images & attachments
- Three attachment modes:
inline(≤12 KB),reference(path only),lines(selected ranges) — over-limit ones degrade automatically. - Paste / drag-drop / upload images — resized client-side and sent as image content when the model supports vision (warning otherwise).
- Vision bridge — when the current model is text-only, images are transcribed into text evidence by an auto-discovered vision model (cached per batch; model & on/off configurable in Settings).
- Attach arbitrary files without a workspace path — stored in a global uploads dir, inlined when small, referenced by absolute path otherwise.
- File preview — line numbers, click/drag/Shift selection (add to chat as
lines), GBK fallback decoding, binary hex view, media preview over HTTP with Range support, and a download button. - Live file tree — the server watches the listed directory (fs.watch) and re-lists on change; oversized directories show a truncation warning.
Terminal & Git
- Built-in terminal (xterm.js + node-pty) with per-client PTY management; Windows auto-selects Git Bash (busybox fallback).
- Source control (Git) panel — status / branch / diff / untracked files via a hidden query terminal; commit, switch branch, push and pull run in the visible terminal and auto-switch to the terminal view.
Models & settings
- Theme switching — pick a theme in the top bar; each theme is a full standalone stylesheet (default white + a bundled dark). See Themes for how to add your own or contribute one.
- Model management — edit
models.jsonin the UI and set per-provider API keys (keys/headers never leave the server). - Thinking level per model (only the levels the model actually supports are shown).
- First-run setup wizard.
- Settings panel — system prompt (append or replace), toggle skills/extensions on/off with immediate effect, save/apply/delete settings presets, and vision-bridge model & switch.
Goal mode
- Goal bar — set a target with a review model, max rounds and a lock switch.
- Goal wizard ("AI 提炼") — turns a raw request into a concrete goal through a guided questionnaire.
- Automatic review loop — after each turn an independent review session checks the goal against the final text and
git diff HEAD; on fail the feedback is injected as steer until it passes (or the round cap is hit).
Background tasks
- Background-task panel — servers launched by the agent are detected via port snapshots and listed (port/pid/name); stop one or kill all.
- Tool watchdog — a tool call running over 20 minutes is aborted automatically.
- Stop bash command only — abort a running bash tool without killing the conversation.
Safety & operations
- Loopback-only by default; set
PI_WEB_HOST=0.0.0.0for LAN / containers. - WebSocket Origin/Host same-authority check — cross-origin pages are rejected (403);
PI_WEB_ALLOW_ORIGINSwhitelist for reverse proxies. - Quiesce drain mode via a local control socket (
server status|quiesce|unquiesce). - Credentials stay server-side — provider headers are never sent to the browser.
- Sound alerts, Chinese/English UI, and a recent-projects list (click to switch workspace).
Deploy & update
- Foreground, global npm install, macOS launchd, Linux systemd, Windows Task Scheduler, and a desktop shortcut (
server shortcut). - In-app self-update — checks the npm registry, installs and auto-restarts the service.
Screenshots




Install / 安装
Requires Node.js 22.19+.
npm install -g pios # recommended / 推荐:全局安装
pios # start the workspace / 启动工作台
Prefer a one-off run? Use npx pios — suitable for trying the latest release without a global install.
npm ≥ 12: npm 12+ may block dependency install scripts by default. node-pty is a native module, so allow its script during installation:
npm install -g --allow-scripts=node-pty,@google/genai,protobufjs pios@latest
Start / 启动
pios # foreground, http://localhost:8787
PORT=9000 PI_WEB_CWD=/path/to/project pios # custom port / workspace
pios --no-browser # headless server / 无需自动打开浏览器
On first launch, open the setup wizard to configure your pi environment and models.
首次启动后,根据引导配置 pi 环境和模型即可开始使用。
Stop
- Foreground: press
Ctrl+Cin the terminal running it. - As a service:
pios server stop(stops the instance; auto-start stays untilserver uninstall).
Update
npm i -g pios@latest # upgrade to the latest published version
pios server restart # restart the service to apply it (foreground: restart manually)
Uninstall
npm uninstall -g pios
Uninstalling does not delete your chats — session data lives in
<cwd>/.pi-web (or PI_WEB_DATA_DIR) and survives uninstall/upgrade.
Run as a system service (auto-start on boot)
pios server install --port 9000 --cwd /path/to/project # install + start
pios server status # running? auto-start?
pios server restart # restart (applies config/version changes)
pios server stop # stop (auto-start stays)
pios server start # start again
pios server uninstall # remove the service entirely
pios server shortcut # desktop one-click launch icon
pios server quiesce # drain: refuse NEW chats/messages, let running ones finish
pios server unquiesce # reopen admission
server status also shows live stats via a local control socket (version,
PID, quiesce state, connected browsers, running conversations) — the same
socket drives quiesce/unquiesce.
- macOS → launchd agent (no sudo), logs to
/tmp/pios.log/.err - Linux → systemd unit (
systemctl enable --now), logs viajournalctl -u pios -f - Windows → Task Scheduler logon task (hidden PowerShell window, no black console)
Options: --port (default 8787), --cwd (workspace), --data-dir (sessions),
--name (custom service name). Rerunning server install with new options
regenerates the config and restarts the service — that's how you change its
port/cwd.
Themes
Each theme is a complete standalone stylesheet — a self-contained CSS file (no CSS-variable extraction, no base file to include). Picking a theme swaps the whole file, so any theme works with every build.
Built-in themes ship in the npm package (themes/); the only bundled theme is the light white.css. The theme picker lives in the settings panel (⚙ → 外观 → 主题); the current choice is stored per browser in localStorage.
Using a theme
Just pick it in the top bar — built-in and user themes are merged in the same menu. User themes win over built-ins on the same id.
Providing a theme locally (no GitHub needed)
Any CSS file dropped into your data-dir themes folder shows up in the theme menu automatically — no restart, no rebuild:
- Find your data dir (default
~/.pi-web, override withPI_WEB_DATA_DIR). - Create
<dataDir>/themes/and drop your stylesheet in: e.g.~/.pi-web/themes/my-theme.css. - Reload the page and pick it in the top bar. The file name (without
.css) is the theme id shown in the menu.
~/.pi-web/
└── themes/
└── my-theme.css # appears in the menu as "my-theme"
Easiest way to write one: copy themes/white.css and change the :root colors plus any hardcoded values — the file must be self-contained. Notes:
- The terminal follows the theme — set the
--term-*variables (terminal ANSI palette +--term-bg) in your:rootand both the xterm canvas and its padded container adapt automatically (see the defaults inthemes/white.css). - Syntax-highlight colors (
highlight.js'sgithub-dark.cssis bundled) must be overridden in your theme file or code will be unreadable — see the.hljsoverrides at the bottom ofthemes/white.cssfor the pattern. - Theme ids must match
^[A-Za-z0-9_-]+$(no dots/slashes — path-traversal guard on the server).
Contributing a theme to the repository (GitHub)
Want your theme shipped to everyone? Open a pull request at github.com/xing-shuyin/pios:
- Fork the repo and clone it.
- Create your theme as
themes/<id>.css— a self-contained stylesheet. Copythemes/white.cssas the starting template. - Verify locally: run
npm run dev, then use the settings panel theme picker — your theme must be listed and render correctly (chat cards, code blocks, tool-call cards, git/terminal panels). - Commit (
git add themes/<id>.css) and open the PR. Thethemes/folder is already in the npm packagefileswhitelist, so once merged and released,npm i -g pioswill ship your theme to everyone.
Rules for merged themes: the file must be a single self-contained CSS file, be a full standalone theme (no base file to import), set the --term-* variables for a readable terminal, and override .hljs syntax colors for readable code.
Security
- Loopback-only by default — the server binds
127.0.0.1and is not reachable from the network unless you explicitly setPI_WEB_HOST=0.0.0.0(e.g. LAN access when explicitly configured). - WebSocket origin check — browser pages connecting to
/wsmust present anOriginwhose hostname and port match the requestHost; cross-origin pages are rejected with 403. Non-browser clients (noOrigin) are unaffected. AddPI_WEB_ALLOW_ORIGINS=http://your-host:portfor reverse-proxy setups. - Quiesce —
server quiescerefuses new prompts/forks/session resumes until youserver unquiesce; in-flight runs finish cleanly (useful before upgrades/backups). - Credentials stay server-side — provider
headers(which may carryAuthorization/ API keys) are never sent to the browser; the model management UI edits everything else and the server preserves the headers.
Reverse proxy (nginx)
Serve pios behind nginx on the same host (it binds loopback only, so a
same-machine reverse proxy is the supported remote-access path — no
PI_WEB_HOST=0.0.0.0 needed):
# pios on 127.0.0.1:8787, exposed as https://your-host/pi/
server {
listen 443 ssl;
server_name your-host;
# ssl_certificate ... / ssl_certificate_key ...
# App entry at a sub-path (strips the /pi/ prefix)
location /pi/ {
proxy_pass http://127.0.0.1:8787/;
proxy_http_version 1.1;
# $http_host keeps the port — the server's origin check compares the
# full authority (hostname AND port). $host would drop it and get 403.
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# WebSocket — MUST forward Host identically or the upgrade is 403'd
# (page loads, but chat/terminal keep reconnecting)
location /ws {
proxy_pass http://127.0.0.1:8787;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
# Absolute-path assets/API the built frontend requests (root, not /pi/)
location /assets/ { proxy_pass http://127.0.0.1:8787; }
location = /favicon.svg { proxy_pass http://127.0.0.1:8787; }
location = /favicon-streaming.svg { proxy_pass http://127.0.0.1:8787; }
location = /api/file { proxy_pass http://127.0.0.1:8787; }
location = /api/health { proxy_pass http://127.0.0.1:8787; }
}
Key points:
Hostmust be$http_host(keeps the port) on both/pi/and/ws— the origin check compares hostname and port.proxy_set_header Host $hostor leaving it unset (defaults to the upstream127.0.0.1:8787) both fail with 403.- Same-origin works automatically: as long as the browser's
Originequals the forwardedHost(it does through a plain proxy), noPI_WEB_ALLOW_ORIGINSis needed. Only set it when the browser origin differs from the Host the server sees (e.g. a TLS-terminating proxy that changes the port). - No
proxy_protocolunless you really need real client IPs: it makes nginx reject every connection that does not send a PROXY header, which breaks direct LAN access and any non-frp clients. With frp, droptransport.proxyProtocolVersionfrom the proxy config unless nginx listens withproxy_protocoltoo. - LAN access without a proxy: just set
PI_WEB_HOST=0.0.0.0(and a firewall rule) — or put the whole server block above on port 80/443.
Full working example (with an frp tunnel): deploy/nginx-pios.conf.
License
MIT