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

Packages

Package details

extension

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 / 中文 · 简体中文文档

npm version Node.js License

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

  1. Open a project / 打开项目 — Start pios in any workspace and use the browser as your coding cockpit.
  2. Ask and inspect / 对话并检查 — Follow the agent's reasoning, tool calls and file changes as they happen.
  3. Operate / 直接操作 — Preview files, select exact lines, attach images, run commands in the built-in terminal, and review Git status or diff.
  4. Guide / 持续引导 — Send a steer while a turn is running, edit and re-ask an earlier question, or keep several project conversations running in parallel.
  5. 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.json in 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.0 for LAN / containers.
  • WebSocket Origin/Host same-authority check — cross-origin pages are rejected (403); PI_WEB_ALLOW_ORIGINS whitelist 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

Settings panel

Built-in terminal

Chat interface

Git source control panel

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+C in the terminal running it.
  • As a service: pios server stop (stops the instance; auto-start stays until server 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 via journalctl -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:

  1. Find your data dir (default ~/.pi-web, override with PI_WEB_DATA_DIR).
  2. Create <dataDir>/themes/ and drop your stylesheet in: e.g. ~/.pi-web/themes/my-theme.css.
  3. 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 :root and both the xterm canvas and its padded container adapt automatically (see the defaults in themes/white.css).
  • Syntax-highlight colors (highlight.js's github-dark.css is bundled) must be overridden in your theme file or code will be unreadable — see the .hljs overrides at the bottom of themes/white.css for 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:

  1. Fork the repo and clone it.
  2. Create your theme as themes/<id>.css — a self-contained stylesheet. Copy themes/white.css as the starting template.
  3. 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).
  4. Commit (git add themes/<id>.css) and open the PR. The themes/ folder is already in the npm package files whitelist, so once merged and released, npm i -g pios will 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.1 and is not reachable from the network unless you explicitly set PI_WEB_HOST=0.0.0.0 (e.g. LAN access when explicitly configured).
  • WebSocket origin check — browser pages connecting to /ws must present an Origin whose hostname and port match the request Host; cross-origin pages are rejected with 403. Non-browser clients (no Origin) are unaffected. Add PI_WEB_ALLOW_ORIGINS=http://your-host:port for reverse-proxy setups.
  • Quiesceserver quiesce refuses new prompts/forks/session resumes until you server unquiesce; in-flight runs finish cleanly (useful before upgrades/backups).
  • Credentials stay server-side — provider headers (which may carry Authorization / 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:

  • Host must be $http_host (keeps the port) on both /pi/ and /ws — the origin check compares hostname and port. proxy_set_header Host $host or leaving it unset (defaults to the upstream 127.0.0.1:8787) both fail with 403.
  • Same-origin works automatically: as long as the browser's Origin equals the forwarded Host (it does through a plain proxy), no PI_WEB_ALLOW_ORIGINS is 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_protocol unless 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, drop transport.proxyProtocolVersion from the proxy config unless nginx listens with proxy_protocol too.
  • 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