diff --git a/.agents/skills/changeset-changelog/SKILL.md b/.agents/skills/changeset-changelog/SKILL.md index 529e7e7..3e3cc3a 100644 --- a/.agents/skills/changeset-changelog/SKILL.md +++ b/.agents/skills/changeset-changelog/SKILL.md @@ -25,7 +25,11 @@ Create a changeset for changes that affect users, operators, package consumers, - Dependency/runtime requirement changes - Release-process changes that future maintainers need to see -A changeset is usually not needed for purely internal refactors, tests, lint-only changes, build cleanup, or agent-only project skills unless the user wants them recorded. When in doubt, ask briefly or create a patch changeset with a clear note. +A changeset is usually not needed for purely internal refactors, tests, lint-only changes, or build cleanup unless the user wants them recorded. + +A changeset is also not needed for changes that are not part of what a pi-web release ships to users. The release is the published npm package, and its contents are an allowlist defined by the `files` field in `package.json` (plus `package.json` itself). Anything outside that allowlist never reaches package consumers, so it cannot be a user-visible release change. This includes repo-only material such as agent skills under `.agents/` and `skills/`, internal docs, CI config, and developer tooling. If you are unsure whether a path ships, check it against `package.json` `files` (or run `npm pack --dry-run`); when a change lives entirely outside the published files, skip the changeset unless the user explicitly wants it recorded. + +When in doubt, ask briefly or create a patch changeset with a clear note. ## How to create a changeset diff --git a/.agents/skills/npm-release-via-github-actions/SKILL.md b/.agents/skills/npm-release-via-github-actions/SKILL.md index d174817..5b3b3cf 100644 --- a/.agents/skills/npm-release-via-github-actions/SKILL.md +++ b/.agents/skills/npm-release-via-github-actions/SKILL.md @@ -97,6 +97,15 @@ If there is no GitHub Actions publish workflow, stop and explain that one must b - Update the newly generated `CHANGELOG.md` heading to match the computed CalVer version if Changesets used a different heading. This manual changelog heading edit is acceptable during release prep; normal development should still use changeset fragments instead. - Review the generated `CHANGELOG.md` section. It should be suitable for GitHub Release notes. - Do not use plain `npm version ` because it creates a local git tag as a side effect; releases should be controlled via GitHub. + - **Sync the lockfile to the final version.** `npm run release:version` (Changesets) updates `package.json` but does not reliably rewrite `package-lock.json`, and the CalVer-enforcing `npm version --no-git-tag-version` only touches the lock when it actually runs. Either path can leave the committed `package-lock.json` behind at the previous version, which then resurfaces as an unexpected diff after the next `npm install`. After the version is finalized, always resync the lockfile without touching `node_modules`: + ```bash + npm install --package-lock-only + ``` + - Confirm the lockfile now matches `package.json` before continuing: + ```bash + node -e "const v=require('./package.json').version, l=require('./package-lock.json'); if (l.version!==v || l.packages[''].version!==v) { console.error('lockfile version mismatch:', l.version, l.packages[''].version, 'expected', v); process.exit(1); } console.log('lockfile in sync at', v);" + ``` + - If the lockfile mismatch persists, stop and resolve it before committing; do not ship a release whose `package-lock.json` version disagrees with `package.json`. 5. **Run checks before creating the release** - Run the repository's normal verification commands, for example: @@ -113,6 +122,7 @@ If there is no GitHub Actions publish workflow, stop and explain that one must b - `package-lock.json` - `CHANGELOG.md` - consumed/deleted `.changeset/*.md` fragments + - Before staging, confirm `package-lock.json` is actually in the diff and carries the new version. If `git status --short` does not show `package-lock.json` as modified while `package.json` changed version, the lockfile sync in step 4 was missed — go back and run `npm install --package-lock-only`. Never commit a release where `package.json` advanced but `package-lock.json` did not. - Use: ```bash git add package.json package-lock.json CHANGELOG.md .changeset diff --git a/.changeset/attachment-sending-indicator.md b/.changeset/attachment-sending-indicator.md deleted file mode 100644 index 4bd56b7..0000000 --- a/.changeset/attachment-sending-indicator.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@jmfederico/pi-web": patch ---- - -Show a per-session sending indicator while messages with image attachments are uploading. Previously the composer cleared instantly while the upload, server-side image resizing, and first-session open happened in the background, so it looked like nothing was happening. The chat activity dock now shows "Sending your message…" for the originating session (including the folder-mode upload step), and that session shows the activity dot in the session list so progress is visible even after switching away. The indicator is scoped per session, so it no longer leaks onto other sessions or machines, and the upload itself continues in the background regardless of navigation. diff --git a/.changeset/dark-theme-message-distinction.md b/.changeset/dark-theme-message-distinction.md deleted file mode 100644 index 6f85567..0000000 --- a/.changeset/dark-theme-message-distinction.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@jmfederico/pi-web": patch ---- - -Improve user/assistant message distinction in the dark theme. Previously the user and assistant message backgrounds were nearly identical (contrast ratio ~1.06), making it hard to tell speakers apart. Each message now has a colored left accent stripe by role (brand accent for user, neutral for assistant) with matching header labels, applied across all themes. The dark theme's user-message background was also lightened and decoupled from the generic hover color, and the user border brightened, so user turns stand out clearly. diff --git a/.changeset/prompt-composer-icon-actions.md b/.changeset/prompt-composer-icon-actions.md deleted file mode 100644 index 323c6c8..0000000 --- a/.changeset/prompt-composer-icon-actions.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@jmfederico/pi-web": patch ---- - -Declutter the chat composer bar with icon-based actions. The Send, Queue, Steer, and Stop buttons are now compact icons, the Attach button moved into the message box, and the thinking level is shown as a small gauge whose bars reflect the levels available for the current model. This leaves more room on narrow/mobile layouts while keeping the model selector readable. All controls retain accessible labels and tooltips. Thinking levels are now sourced from pi directly, so an unfamiliar level from a newer pi version is still selectable and displayed gracefully instead of causing an error. diff --git a/.changeset/prompt-image-attachments.md b/.changeset/prompt-image-attachments.md deleted file mode 100644 index 14010f0..0000000 --- a/.changeset/prompt-image-attachments.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@jmfederico/pi-web": minor ---- - -Add image attachments to the chat composer. You can now paste (Ctrl/Cmd+V), drag-and-drop, or use the new Attach button to add PNG, JPEG, GIF, and WebP images to a message, with thumbnail previews and multi-image support. Attachments are delivered to the session using pi's native image format (images are auto-resized to pi's inline limits for full compatibility), and image content now renders inline in the transcript. A per-message delivery toggle also lets you instead save attachments into the workspace `.pi-web/paste` folder and reference them so the agent reads them with its own tools. The accepted HTTP upload size is now configurable via `PI_WEB_MAX_UPLOAD_BYTES` or the `maxUploadBytes` config value. diff --git a/.changeset/restart-via-systemd-run.md b/.changeset/restart-via-systemd-run.md deleted file mode 100644 index 310def2..0000000 --- a/.changeset/restart-via-systemd-run.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@jmfederico/pi-web": patch ---- - -Run the suggested Linux restart commands inside a detached transient systemd user service (`systemd-run --user`) instead of directly. The restart now completes even when the launching PI WEB terminal is killed by restarting the session daemon, and its output can be inspected with `journalctl --user -u pi-web-restart`. diff --git a/.changeset/session-reload-from-disk.md b/.changeset/session-reload-from-disk.md deleted file mode 100644 index e0e57ac..0000000 --- a/.changeset/session-reload-from-disk.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"@jmfederico/pi-web": minor ---- - -Add a **Reload** action to the session three-dot menu that re-reads the session from disk. The session daemon keeps an in-memory `SessionManager` per session and never re-reads the session file, so when the same session is also driven by another process (for example the `pi` CLI), new on-disk entries were invisible to the web UI and the tail of the conversation appeared truncated. Reloading closes the active session, re-opens it from disk, discards the cached transcript, and re-fetches the history. - -Reload is also available from the command palette as **Reload Session**, so it can be triggered from the keyboard and assigned a custom shortcut. Reload refuses to run while the session has work in progress and on archived (read-only) sessions, and is gated behind a new `sessions.reload` runtime capability so it only appears for machines whose Pi-Web runtime supports it (both the menu item and the palette action are disabled otherwise). - -Note: this changes a session daemon code path, so `pi-web-sessiond.service` must be restarted manually for the server side of this change to take effect. diff --git a/.changeset/updates-panel-run-commands.md b/.changeset/updates-panel-run-commands.md deleted file mode 100644 index 21ad939..0000000 --- a/.changeset/updates-panel-run-commands.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@jmfederico/pi-web": patch ---- - -Make the Updates panel actionable: every suggested command now has both a Copy and a Run button (Run executes it in a workspace terminal), a single recommended all-in-one command is shown at the top so users do not have to choose, and the remaining commands are grouped as clearly optional additional commands. diff --git a/AGENTS.md b/AGENTS.md index ad93e79..c503ccf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,3 +10,11 @@ When working on this project, assume the session runtime owner is long-lived and If you make changes that affect `src/server/sessiond.ts`, session runtime ownership, the session daemon protocol, or any code path only loaded by the session daemon, inform the user that a manual restart of the session daemon is needed. Changes to the web/API/UI side generally only require the `pi-web-ui-dev.service` autoreload/restart path. + +## Configuration conventions + +- `$PI_WEB_DATA_DIR` (`~/.pi-web` by default) contains PI WEB-managed state such as `projects.json` and `machines.json`; do not treat it as the user-editable config API. +- Global user/machine config lives at `$PI_WEB_CONFIG` or `~/.config/pi-web/config.json`. +- Project-local PI WEB core config should use one commit-able file: `/.pi-web/config.json`. +- Core features should add keys to these config files, not create one project file per feature. +- Plugins may own separate project config files, such as `.pi-web/tasks.json`. diff --git a/CHANGELOG.md b/CHANGELOG.md index 17fa499..568c1bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,47 @@ # @jmfederico/pi-web +## 1.202606.5 + +### Patch Changes + +- c2e2a29: Add a dedicated PI WEB configuration reference covering config-file precedence, project-local config, external path access allowlists, session daemon tools, plugins, shortcuts, upload limits, and environment variables. Custom `pi-web install --config` paths are now passed to the session daemon service as well as the web service, and the session daemon now honors config-file `maxUploadBytes` values. +- 4f4c6fa: Fix remote session reloads so they proxy through the web/API instead of returning the app shell as JSON. +- 62c2234: Prevent live skill-loading cards from duplicating when the finalized transcript groups multiple skill reads. +- 27bc924: Persist the Settings → Session daemon tracked subsessions toggle so it remains enabled after restart. +- d931101: Fix dead-key/IME input in the terminal (e.g. typing `~` on a Swedish keyboard). The character previously stuck in the top-left corner and was never sent to the shell. The terminal panel now includes the xterm composition-view styles and no longer forces the helper textarea's position with `!important`, so dead-key composition is placed at the cursor and committed correctly. +- 6933d3a: Keep mobile navigation on the selected session when remote workspace loading finishes out of order. +- 2bb6e48: Normalize allowed external path suggestions on Windows so configured absolute paths use platform separators consistently. +- 9cc20d6: Allow configured external filesystem roots to be listed, read, configured from the global settings UI, and completed from absolute `@` path suggestions while keeping absolute paths denied by default, advertise workspace-scoped file suggestion support as a remote-machine capability, and use `fzf` when available to improve file/path completion filtering. +- 355ebe8: Add tracked subsessions (beta, off by default): agents can spawn child sessions they stay attached to. The new `spawn_subsession` tool starts a child session linked to its parent (recorded in the session tree), notifies the parent when the child stops working, and lets the parent inspect children via `list_subsessions`, `check_subsession` (a quick glance at a child's status and latest output), and `read_subsession` (read through a child's transcript with role/content filters, full-content substring search, optional per-value `maxChars` truncation that flags clipped parts, and pagination). The completion notice is delivered as a system-authored message (not attributed to the human), and still wakes an idle parent while queueing behind any in-flight work. Unlike the fire-and-forget `spawn_session`, subsessions are observable by their spawner. + + The capability is gated behind a beta flag so it can ship without being exposed in releases: enable it with the `PI_WEB_SUBSESSIONS` env var, the `subsessions` config key, or the "Allow agents to start tracked subsessions" toggle in Settings → Session daemon. It also requires `spawnSessions` to be enabled. Requires a manual session daemon restart to take effect. + +## 1.202606.4 + +### Patch Changes + +- 53b00c4: Show a per-session sending indicator while messages with image attachments are uploading. Previously the composer cleared instantly while the upload, server-side image resizing, and first-session open happened in the background, so it looked like nothing was happening. The chat activity dock now shows "Sending your message…" for the originating session (including the folder-mode upload step), and that session shows the activity dot in the session list so progress is visible even after switching away. The indicator is scoped per session, so it no longer leaks onto other sessions or machines, and the upload itself continues in the background regardless of navigation. +- cfb7493: Improve user/assistant message distinction in the dark theme. Previously the user and assistant message backgrounds were nearly identical (contrast ratio ~1.06), making it hard to tell speakers apart. The dark theme's user-message background was lightened and decoupled from the generic hover color, and the user border brightened, so user turns stand out clearly. +- dd23b3e: Fix a duplicate session appearing in the list when starting a new session. The `session.created` broadcast (added with the spawn_session tool) could race ahead of the start request's HTTP response in the same tab, leaving two badges with the same id — one with archive/reload actions and one with delete. The optimistic insert now replaces any entry the broadcast added, so the locally cached session (with its delete action and draft support) always wins. +- 3930505: Fix the "Catching up…" badge sometimes staying visible after a session goes idle. The stream catch-up mode was tracked by two fields that could drift — a private guard and the public badge flag — and the socket reconnect path updated one without the other, so the terminating idle status no longer cleared the badge. Both facets now route through a single source of truth, and any idle status for the selected session reliably dismisses the badge. +- 411e61a: Declutter the chat composer bar with icon-based actions. The Send, Queue, Steer, and Stop buttons are now compact icons, the Attach button moved into the message box, and the thinking level is shown as a small gauge whose bars reflect the levels available for the current model. This leaves more room on narrow/mobile layouts while keeping the model selector readable. All controls retain accessible labels and tooltips. Thinking levels are now sourced from pi directly, so an unfamiliar level from a newer pi version is still selectable and displayed gracefully instead of causing an error. +- d17050e: Add image attachments to the chat composer. You can now paste (Ctrl/Cmd+V), drag-and-drop, or use the new Attach button to add PNG, JPEG, GIF, and WebP images to a message, with thumbnail previews and multi-image support. Attachments are delivered to the session using pi's native image format (images are auto-resized to pi's inline limits for full compatibility), and image content now renders inline in the transcript. A per-message delivery toggle also lets you instead save attachments into the workspace `.pi-web/attachments` folder and reference them so the agent reads them with its own tools. The accepted HTTP upload size is now configurable via `PI_WEB_MAX_UPLOAD_BYTES` or the `maxUploadBytes` config value. +- 3c6b4a4: Run the suggested Linux restart commands inside a detached transient systemd user service (`systemd-run --user`) instead of directly. The restart now completes even when the launching PI WEB terminal is killed by restarting the session daemon, and its output can be inspected with `journalctl --user -u pi-web-restart`. +- 61f0b79: Move reload to the end of the session action menu. +- 82db15f: Add a **Reload** action to the session three-dot menu that re-reads the session from disk. The session daemon keeps an in-memory `SessionManager` per session and never re-reads the session file, so when the same session is also driven by another process (for example the `pi` CLI), new on-disk entries were invisible to the web UI and the tail of the conversation appeared truncated. Reloading closes the active session, re-opens it from disk, discards the cached transcript, and re-fetches the history. + + Reload is also available from the command palette as **Reload Session**, so it can be triggered from the keyboard and assigned a custom shortcut. Reload refuses to run while the session has work in progress and on archived (read-only) sessions, and is gated behind a new `sessions.reload` runtime capability so it only appears for machines whose Pi-Web runtime supports it (both the menu item and the palette action are disabled otherwise). + + Note: this changes a session daemon code path, so `pi-web-sessiond.service` must be restarted manually for the server side of this change to take effect. + +- 95c1512: Let agents start new sessions with a `spawn_session` tool. An agent can dispatch a fresh, independent session with an initial prompt — useful for ralph-style loops (an agent kicks off the next iteration when done) and for chaining long plans across sessions. Spawned sessions are normal sessions a human can open and interact with, and they now appear in the session list the moment they are created (in the matching workspace) without a manual reload. + + To keep every spawned session visible and controllable, an agent may only spawn into a workspace — any worktree, including one it just created — of the same registered project as the spawning session. The capability is on by default and can be toggled under Settings → Session daemon (or via the `spawnSessions` config key / `PI_WEB_SPAWN_SESSIONS` environment variable); changes take effect after the session daemon restarts. + + Note: this adds a session daemon code path, so `pi-web-sessiond.service` must be restarted manually for the server side of this change to take effect. + +- 3c6b4a4: Make the Updates panel actionable: every suggested command now has both a Copy and a Run button (Run executes it in a workspace terminal), a single recommended all-in-one command is shown at the top so users do not have to choose, and the remaining commands are grouped as clearly optional additional commands. + ## 1.202606.3 ### Patch Changes diff --git a/README.md b/README.md index d1d4e32..801f4b5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# PI WEB +# PI WEB — web UI for Pi Coding Agent [![CI](https://github.com/jmfederico/pi-web/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/jmfederico/pi-web/actions/workflows/ci.yml) [![npm version](https://img.shields.io/npm/v/@jmfederico/pi-web)](https://www.npmjs.com/package/@jmfederico/pi-web) @@ -10,11 +10,16 @@ Website: ![PI WEB](docs/assets/pi-web-banner.png) -**Run AI coding agents on your own machine or server, keep them alive in real workspaces, and control everything from a browser.** +**Run Pi Coding Agent from a web UI, keep sessions alive in real workspaces, and supervise them from any device.** -PI WEB is a web control plane for [Pi Coding Agent](https://github.com/earendil-works/pi/tree/main/packages/coding-agent). Add your repositories once, open project workspaces and git worktrees, start agent sessions inside them, and come back later without losing the work. Your browser becomes the cockpit; your server becomes the persistent development environment. Start on your laptop, check in from your phone, and continue from an iPad or another machine whenever that is the device you have at hand. +PI WEB is a web UI for [Pi Coding Agent](https://github.com/earendil-works/pi/tree/main/packages/coding-agent) that keeps agent sessions running on your own machine or server. Add your repositories once, open project workspaces and git worktrees, start sessions inside them, and come back later without losing the work. Your browser becomes the cockpit; your server becomes the persistent development environment. Start on your laptop, check in from your phone, and continue from an iPad or another machine whenever that is the device you have at hand. -![PI WEB demo](docs/assets/pi-web-demo.gif) +![PI WEB desktop screenshot showing an agent-created pi-web.dev screenshot selected in the file preview](docs/assets/pi-web-desktop.png) + +

+ PI WEB tablet screenshot + PI WEB mobile chat screenshot +

With PI WEB you can: @@ -32,6 +37,10 @@ Agentic development works best when agents are not trapped inside a single local PI WEB connects those two worlds. The work stays in the server-side environment while you move between devices: laptop for deep focus, phone for a quick check-in, tablet for review, desktop when you are back at a desk. It is not trying to recreate the old desktop IDE in a browser; it is a control surface for persistent, parallel, human-in-the-loop agent work. +### Is PI WEB a Pi web UI? + +Yes. PI WEB is a Pi web UI for running and supervising Pi Coding Agent sessions from a browser. Unlike simple session viewers, PI WEB is built around persistent server-side workspaces, long-running session daemons, git worktrees, remote machines, and multi-device supervision. + ## Core model PI WEB organizes work into four levels: @@ -69,7 +78,7 @@ This maps naturally to real development work: ## Architecture -PI WEB uses a split-process architecture so agent runtimes are not owned by the browser-facing dev server. +PI WEB uses a split-process architecture so agent runtimes are not owned by the browser-facing dev server. Under the hood, it acts as a browser-based control plane for sessions, workspaces, files, terminals, and trusted remote machines. ```text Browser UI @@ -104,7 +113,7 @@ PI WEB keeps its own state intentionally small: ## Machine federation -The Machines section lets one PI WEB instance act as a gateway to other PI WEB runtimes. Register a remote machine from **Actions → Add Machine** with the remote PI WEB base URL, for example a URL reachable over NetBird, Tailscale, WireGuard, an SSH tunnel, or a trusted reverse proxy. The browser continues talking to the local PI WEB origin; project, workspace, file, git, session, activity, and terminal HTTP/WebSocket traffic is proxied server-to-server. See the [Fleet guide](https://pi-web.dev/machines.html) for setup, trust model, and troubleshooting details. +The Machines section lets one PI WEB instance act as a gateway to other PI WEB runtimes. Register a remote machine from **Actions → Add Machine** with the remote PI WEB base URL, for example a URL reachable over NetBird, Tailscale, WireGuard, an SSH tunnel, or a trusted reverse proxy. The browser continues talking to the local PI WEB origin; project, workspace, file, git, session, activity, and terminal HTTP/WebSocket traffic is proxied server-to-server. See the [Fleet guide](https://pi-web.dev/machines) for setup, trust model, and troubleshooting details. Remote model-provider credentials and OAuth state stay on the target machine. API-key provider configuration can be proxied, but OAuth login should be completed by opening the remote PI WEB directly. Register remote machines only when you trust the endpoint and the network path: adding a machine gives this PI WEB server permission to contact that URL with the optional bearer token you configured. @@ -118,7 +127,7 @@ A useful prompt for AI agents: ```text Build a PI WEB plugin for this project. Goal: . -Before coding, read https://pi-web.dev/plugins.html and https://pi-web.dev/plugins.md. +Before coding, read https://pi-web.dev/plugins and https://pi-web.dev/plugins.md. Create it under ~/.pi-web/plugins/ using the documented PI WEB v1 plugin API. Validate with /pi-web-plugins/manifest.json and explain reload/debug steps. Do not modify PI WEB itself. @@ -250,10 +259,16 @@ npm publish --access public PI WEB uses a single-line CalVer-inspired npm version: `MAJOR.YYYYMM.SEQUENCE`, for example `1.202605.1`. The major number signals breaking-change eras; the middle number is the release month; the final number increments for additional releases in that month. Older major eras may be deprecated rather than maintained in parallel. -PI WEB declares `@earendil-works/pi-coding-agent` as a peer dependency (`>=0.74.0 <1`) and a development dependency for local builds. This keeps published installs flexible: npm 7+ installs the peer automatically, and users can upgrade the Pi package within the compatible range without PI WEB pinning a separate copy. +PI WEB declares `@earendil-works/pi-coding-agent` as a peer dependency (`>=0.78.0 <1`) and a development dependency for local builds. This keeps published installs flexible: npm 7+ installs the peer automatically, and users can upgrade the Pi package within the compatible range without PI WEB pinning a separate copy. -The web server defaults to `127.0.0.1:8504`. Set `PI_WEB_HOST=0.0.0.0` only when you intentionally want to bind directly on all interfaces. +## Configuration + +Global PI WEB config lives at `$PI_WEB_CONFIG`, or `$XDG_CONFIG_HOME/pi-web/config.json`, or `~/.config/pi-web/config.json`. Project-local core config lives at `/.pi-web/config.json`. + +See the full [Configuration reference](docs/config.md) for config-file precedence, project-local config, external path access, session daemon settings, plugins, shortcuts, upload limits, and environment variables. + +The web server defaults to `127.0.0.1:8504`. Set `PI_WEB_HOST=0.0.0.0` only when you intentionally want to bind directly on all interfaces behind a trusted network, firewall, or authenticated proxy. The session daemon defaults to a private Unix socket at: @@ -261,18 +276,26 @@ The session daemon defaults to a private Unix socket at: ~/.pi-web/sessiond.sock ``` -Environment variables: +Common config keys: -- `PI_WEB_PORT` / `PORT` — web server port. Defaults to `8504`. -- `PI_WEB_HOST` — web server bind host. Defaults to `127.0.0.1`. -- `PI_WEB_DATA_DIR` — PI WEB data directory. Defaults to `~/.pi-web`. +- `host` / `port` — web/API bind address. Environment overrides: `PI_WEB_HOST`, `PI_WEB_PORT` / `PORT`. +- `pathAccess.allowedPaths` — external filesystem roots that PI WEB may list/read through the file explorer and absolute `@` path completions. Absolute paths are denied by default. +- `maxUploadBytes` — maximum accepted request body size. Defaults to 64 MB. Environment override: `PI_WEB_MAX_UPLOAD_BYTES`. +- `spawnSessions` — enable the `spawn_session` tool. Defaults to `true`. Environment override: `PI_WEB_SPAWN_SESSIONS`. +- `subsessions` — beta tracked-subsession tools (`spawn_subsession`, `list_subsessions`, `check_subsession`, `read_subsession`). Defaults to `false`, requires `spawnSessions`, and requires a session daemon restart after changes. Environment override: `PI_WEB_SUBSESSIONS`. +- `plugins` — plugin enablement/settings. Reload the browser after changing plugin enablement. +- `shortcuts` — keyboard shortcut overrides; use `null` to disable an action shortcut. + +Operational environment variables: + +- `PI_WEB_CONFIG` — path to the global config JSON file. +- `PI_WEB_DATA_DIR` — PI WEB-managed data directory. Defaults to `~/.pi-web`. - `PI_WEB_SESSIOND_SOCKET` — Unix socket path used by both the daemon and web process when `PI_WEB_SESSIOND_URL` is not set. Defaults to `$PI_WEB_DATA_DIR/sessiond.sock`. - `PI_WEB_SESSIOND_PORT` — optional TCP port for the daemon. If unset, the daemon listens on the Unix socket instead. - `PI_WEB_SESSIOND_HOST` — daemon TCP bind host when `PI_WEB_SESSIOND_PORT` is set. Defaults to `127.0.0.1`. - `PI_WEB_SESSIOND_URL` — daemon URL used by the web process when connecting over TCP, for example `http://127.0.0.1:3001`. If you set `PI_WEB_SESSIOND_PORT`, set this for the web process too. - `PI_WEB_PROJECTS_FILE` — optional override for the projects storage JSON file. Defaults to `$PI_WEB_DATA_DIR/projects.json`. - `PI_WEB_MACHINES_FILE` — optional override for the remote machine registry JSON file. Defaults to `$PI_WEB_DATA_DIR/machines.json`. -- `PI_WEB_MAX_UPLOAD_BYTES` — maximum accepted HTTP request body size in bytes (covers pasted/attached images). Defaults to 64 MB. Also configurable as `maxUploadBytes` in `config.json`. - `PI_CODING_AGENT_SESSION_DIR` — Pi session storage directory. PI WEB follows the same session-location priority as Pi for web sessions: this environment variable, then `sessionDir` in Pi settings for the selected workspace, then Pi's default session directory. - `PI_CODING_AGENT_DIR` — Pi agent config directory. PI WEB uses this for Pi auth, settings, resources, and default session storage, matching Pi's own configuration layout. diff --git a/docs/404.html b/docs/404.html index 069a501..b80d812 100644 --- a/docs/404.html +++ b/docs/404.html @@ -6,8 +6,16 @@ Page not found — PI WEB + + - + + + + + + + + + + + + + + + +
+
+
+

Configuration reference

+

Configure PI WEB where your agents work.

+

+ PI WEB configuration covers the machine-local and project-local settings you usually need: bind address, + trusted development-host settings, UI preferences, plugin enablement, file-explorer path access, upload + limits, and session-daemon tools. +

+
+
+ +
+
+ + +
+
+

Config files

+

PI WEB uses a global config file for machine-local settings and a project-local file for repository settings.

+
    +
  • Global config: $PI_WEB_CONFIG, or $XDG_CONFIG_HOME/pi-web/config.json, or ~/.config/pi-web/config.json.
  • +
  • Project config: <project>/.pi-web/config.json for commit-able project settings.
  • +
+

+ Each PI WEB machine has its own config. When using Fleet/machine federation, edit a remote machine's + config by opening that machine directly or changing files on that machine. +

+

+ If you installed services with a custom config path, rerun + pi-web install --config /path/to/config.json after changing that path or after upgrading from + a version that only applied the custom path to the web service. This regenerates service files so the + web/API and session daemon use the same PI_WEB_CONFIG. +

+
+ +
+

Precedence and reloads

+

Runtime values are resolved in this order:

+
+
defaults → config file → environment overrides
+
+

+ Environment overrides include PI_WEB_HOST, PI_WEB_PORT / PORT, + PI_WEB_ALLOWED_HOSTS, PI_WEB_MAX_UPLOAD_BYTES, PI_WEB_SPAWN_SESSIONS, + and PI_WEB_SUBSESSIONS. +

+
    +
  • host / port: restart the web/API service or process.
  • +
  • maxUploadBytes: restart both the web/API process and the session daemon.
  • +
  • spawnSessions / subsessions: restart the session daemon.
  • +
  • pathAccess: applies on the next request; existing file views may need a browser refresh.
  • +
  • plugins: reload the browser tab after changing plugin enablement.
  • +
  • shortcuts: saved settings apply in the browser after config refresh/save.
  • +
+
+ +
+

Global config example

+

+ pi-web install creates the initial file. You can also save settings from + Settings → General, Settings → Plugins, Settings → Keyboard, + and Settings → Session daemon. +

+
+
+ Example config.json + +
+
{
+  "host": "127.0.0.1",
+  "port": 8504,
+  "pathAccess": {
+    "allowedPaths": ["~/SDKs", "/opt/reference"]
+  },
+  "maxUploadBytes": 67108864,
+  "spawnSessions": true,
+  "subsessions": false,
+  "plugins": {
+    "workspace-tasks": { "enabled": true },
+    "updates": { "enabled": true },
+    "info": { "enabled": false }
+  },
+  "shortcuts": {
+    "core:view.chat": "mod+1",
+    "core:session.stop": null
+  }
+}
+
+
+ +
+

Project-local config

+

+ Project-local config lives at <project>/.pi-web/config.json. Use it for settings that should + follow a repository. When a project config defines pathAccess, PI WEB merges it after the + global path list. +

+
+
+ .pi-web/config.json + +
+
{
+  "version": 1,
+  "pathAccess": {
+    "allowedPaths": ["~/SDKs", "/opt/reference"]
+  }
+}
+
+

+ Project-local pathAccess.allowedPaths entries must still be host-absolute or + ~-prefixed; relative roots are not supported. Plugins may own separate project files, such as + .pi-web/tasks.json for the built-in Workspace Tasks plugin. +

+
+ +
+

Config matrix

+

+ Use this table as the quick reference for where a setting can live, which environment variable overrides + it, and whether project-local config overrides or merges with global config. Rows with JSON key + are runtime-only environment variables, not config-file keys. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ConfigJSON keyEnv varScopeProject-local behaviorApplies / restart
Config-file keys
Web/API bind hosthostPI_WEB_HOSTGlobalNot supported locallyRestart web/API
Web/API portportPI_WEB_PORT, PORTGlobalNot supported locallyRestart web/API
Dev-server allowed hostsallowedHostsPI_WEB_ALLOWED_HOSTSGlobalNot supported locallyRestart dev web/UI
External filesystem rootspathAccess.allowedPathsGlobal + projectMerges: global roots first, then project roots; duplicates removedNext file request; refresh existing views if needed
Upload/body limitmaxUploadBytesPI_WEB_MAX_UPLOAD_BYTESGlobalNot supported locallyRestart web/API and session daemon
Agent can spawn sessionsspawnSessionsPI_WEB_SPAWN_SESSIONSGlobal/session daemonNot supported locallyRestart session daemon
Tracked subsessions (beta)subsessionsPI_WEB_SUBSESSIONSGlobal/session daemonNot supported locally; also requires spawnSessionsRestart session daemon
Plugin enablement/settingsplugins.<id>.enabled, plugins.<id>.settingsGlobalNot core local config; plugins may read their own project filesReload browser tab
Keyboard shortcutsshortcuts.<actionId>GlobalNot supported locallyApplies after settings save/config refresh
Project config versionversionProjectProject-local only; must be 1 when presentNext project-config read
Runtime-only environment variables
Global config file pathPI_WEB_CONFIG (XDG_CONFIG_HOME affects the default path)Process/envSelects the global config file; not a project configRestart services/processes after changing env
Managed data directoryPI_WEB_DATA_DIRProcess/envNot supported locallyRestart services before changing; moves managed state location
Session daemon socketPI_WEB_SESSIOND_SOCKETWeb/API + session daemon envNot supported locallyRestart daemon and web/API; both must match
Session daemon TCP portPI_WEB_SESSIOND_PORTSession daemon envNot supported locallyRestart session daemon; set PI_WEB_SESSIOND_URL for web/API too
Session daemon TCP hostPI_WEB_SESSIOND_HOSTSession daemon envNot supported locallyRestart session daemon
Web-to-daemon URLPI_WEB_SESSIOND_URLWeb/API envNot supported locallyRestart web/API
Projects storage filePI_WEB_PROJECTS_FILEWeb/API + session daemon envNot supported locallyRestart services; advanced state override
Remote machines storage filePI_WEB_MACHINES_FILEWeb/API envNot supported locallyRestart web/API; advanced state override
Pi session storage directoryPI_CODING_AGENT_SESSION_DIRPi/session daemon envNot supported locallyRestart session daemon; follows Pi session priority
Pi agent config directoryPI_CODING_AGENT_DIRPi/Web/API/session daemon envNot supported locallyRestart services
Skip update checksPI_WEB_SKIP_VERSION_CHECK, PI_WEB_OFFLINE, PI_SKIP_VERSION_CHECK, PI_OFFLINEWeb/API envNot supported locallyRestart web/API after env changes
+
+
+ +
+

External path access

+

+ pathAccess.allowedPaths grants PI WEB's file explorer and absolute @ path + completions access to specific filesystem roots outside the current workspace. By default, + workspace-relative file reads stay inside the workspace and absolute paths are denied. +

+

Accepted root forms:

+
    +
  • Unix absolute paths, for example /opt/reference.
  • +
  • Home-relative paths, for example ~/SDKs.
  • +
  • Windows absolute paths on Windows hosts, for example C:\Users\dev\SDKs.
  • +
+

+ When an absolute request is served, PI WEB expands ~, canonicalizes configured roots with + realpath, requires roots to be existing directories, and rejects symlink escapes outside the + allowed roots. +

+
+ This is not a sandbox for the underlying Pi Coding Agent or your OS user. It only controls PI WEB UI/API + file exposure outside a workspace. Add only roots you trust PI WEB to list and read through the browser UI. +
+
+ +
+

Session daemon tools

+

spawnSessions

+

+ Boolean. Controls whether agents receive the spawn_session tool. Defaults to + true. Set it to false if you do not want an agent to start independent PI WEB sessions. +

+

Environment override: PI_WEB_SPAWN_SESSIONS=0|1|true|false.

+ +

subsessions

+

+ Boolean. Beta. Controls whether agents receive the tracked-subsession tools: + spawn_subsession, list_subsessions, check_subsession, and + read_subsession. Defaults to false and also requires spawnSessions + to be enabled. +

+

+ Tracked subsessions let an agent delegate work to child sessions, get notified when children stop + working, and inspect their transcripts. Restart the session daemon after changing this setting. +

+

Environment override: PI_WEB_SUBSESSIONS=0|1|true|false.

+
+ + +
+

Optional completion tools

+

+ File and path @ completions work without extra tools. If fzf is available on the + PI WEB server's PATH, PI WEB uses it to improve completion filtering and ranking; otherwise it + falls back to built-in ranking. +

+ +
+
+
+
+
+ + + + + diff --git a/docs/config.md b/docs/config.md new file mode 100644 index 0000000..d437ca2 --- /dev/null +++ b/docs/config.md @@ -0,0 +1,166 @@ +# PI WEB configuration reference + +PI WEB configuration covers the machine-local and project-local settings you usually need: the web/API bind address, trusted development-host settings, UI preferences, plugin enablement, file-explorer path access, upload limits, and session-daemon tools. + +This file is the markdown reference for agents and package consumers. The website page is . + +## Config files + +PI WEB uses two config files: + +- **Global PI WEB config:** `$PI_WEB_CONFIG`, or `$XDG_CONFIG_HOME/pi-web/config.json`, or `~/.config/pi-web/config.json`. +- **Project-local PI WEB config:** `/.pi-web/config.json` for commit-able project settings. + +Each PI WEB machine has its own config. When using Fleet/machine federation, edit a remote machine's config by opening that machine directly or changing files on that machine. + +If you installed services with a custom config path, rerun `pi-web install --config /path/to/config.json` after changing that path or after upgrading from a version that only applied the custom path to the web service. This regenerates service files so the web/API and session daemon use the same `PI_WEB_CONFIG`. + +## Precedence and reloads + +Runtime values are resolved as: + +```text +defaults → config file → environment overrides +``` + +Environment overrides include `PI_WEB_HOST`, `PI_WEB_PORT` / `PORT`, `PI_WEB_ALLOWED_HOSTS`, `PI_WEB_MAX_UPLOAD_BYTES`, `PI_WEB_SPAWN_SESSIONS`, and `PI_WEB_SUBSESSIONS`. + +Process restarts depend on the key: + +- `host` / `port`: restart the web/API service or process. +- `maxUploadBytes`: restart both the web/API process and the session daemon. +- `spawnSessions` / `subsessions`: restart the session daemon. +- `pathAccess`: applies on the next request; existing file views may need a browser refresh. +- `plugins`: reload the browser tab after changing plugin enablement. +- `shortcuts`: saved settings apply in the browser after config refresh/save. + +## Global config example + +```json +{ + "host": "127.0.0.1", + "port": 8504, + "pathAccess": { + "allowedPaths": ["~/SDKs", "/opt/reference"] + }, + "maxUploadBytes": 67108864, + "spawnSessions": true, + "subsessions": false, + "plugins": { + "workspace-tasks": { "enabled": true }, + "updates": { "enabled": true }, + "info": { "enabled": false } + }, + "shortcuts": { + "core:view.chat": "mod+1", + "core:session.stop": null + } +} +``` + +## Project-local config + +Project-local config lives at `/.pi-web/config.json`. Use it for settings that should follow a repository. + +```json +{ + "version": 1, + "pathAccess": { + "allowedPaths": ["~/SDKs", "/opt/reference"] + } +} +``` + +Project-local `pathAccess.allowedPaths` entries are merged after the global list and deduplicated. Paths must still be host-absolute or `~`-prefixed; relative roots are not supported. + +Plugins may own separate project files, such as `.pi-web/tasks.json` for the built-in Workspace Tasks plugin. + +## Configuration matrix + +Rows with JSON key `—` are runtime-only environment variables, not config-file keys. + +| Config | JSON key | Env var | Scope | Project-local behavior | Applies / restart | +| --- | --- | --- | --- | --- | --- | +| **Config-file keys** | | | | | | +| Web/API bind host | `host` | `PI_WEB_HOST` | Global | Not supported locally | Restart web/API | +| Web/API port | `port` | `PI_WEB_PORT`, `PORT` | Global | Not supported locally | Restart web/API | +| Dev-server allowed hosts | `allowedHosts` | `PI_WEB_ALLOWED_HOSTS` | Global | Not supported locally | Restart dev web/UI | +| External filesystem roots | `pathAccess.allowedPaths` | — | Global + project | **Merges**: global roots first, then project roots; duplicates removed | Next file request; refresh existing views if needed | +| Upload/body limit | `maxUploadBytes` | `PI_WEB_MAX_UPLOAD_BYTES` | Global | Not supported locally | Restart web/API and session daemon | +| Agent can spawn sessions | `spawnSessions` | `PI_WEB_SPAWN_SESSIONS` | Global/session daemon | Not supported locally | Restart session daemon | +| Tracked subsessions (beta) | `subsessions` | `PI_WEB_SUBSESSIONS` | Global/session daemon | Not supported locally; also requires `spawnSessions` | Restart session daemon | +| Plugin enablement/settings | `plugins..enabled`, `plugins..settings` | — | Global | Not core local config; plugins may read their own project files | Reload browser tab | +| Keyboard shortcuts | `shortcuts.` | — | Global | Not supported locally | Applies after settings save/config refresh | +| Project config version | `version` | — | Project | Project-local only; must be `1` when present | Next project-config read | +| **Runtime-only environment variables** | | | | | | +| Global config file path | — | `PI_WEB_CONFIG` (`XDG_CONFIG_HOME` affects the default path) | Process/env | Selects the global config file; not a project config | Restart services/processes after changing env | +| Managed data directory | — | `PI_WEB_DATA_DIR` | Process/env | Not supported locally | Restart services before changing; moves managed state location | +| Session daemon socket | — | `PI_WEB_SESSIOND_SOCKET` | Web/API + session daemon env | Not supported locally | Restart daemon and web/API; both must match | +| Session daemon TCP port | — | `PI_WEB_SESSIOND_PORT` | Session daemon env | Not supported locally | Restart session daemon; set `PI_WEB_SESSIOND_URL` for web/API too | +| Session daemon TCP host | — | `PI_WEB_SESSIOND_HOST` | Session daemon env | Not supported locally | Restart session daemon | +| Web-to-daemon URL | — | `PI_WEB_SESSIOND_URL` | Web/API env | Not supported locally | Restart web/API | +| Projects storage file | — | `PI_WEB_PROJECTS_FILE` | Web/API + session daemon env | Not supported locally | Restart services; advanced state override | +| Remote machines storage file | — | `PI_WEB_MACHINES_FILE` | Web/API env | Not supported locally | Restart web/API; advanced state override | +| Pi session storage directory | — | `PI_CODING_AGENT_SESSION_DIR` | Pi/session daemon env | Not supported locally | Restart session daemon; follows Pi session priority | +| Pi agent config directory | — | `PI_CODING_AGENT_DIR` | Pi/Web/API/session daemon env | Not supported locally | Restart services | +| Skip update checks | — | `PI_WEB_SKIP_VERSION_CHECK`, `PI_WEB_OFFLINE`, `PI_SKIP_VERSION_CHECK`, `PI_OFFLINE` | Web/API env | Not supported locally | Restart web/API after env changes | + +## Key details + +### External path access + +`pathAccess.allowedPaths` grants PI WEB's file explorer and absolute `@` path completions access to specific filesystem roots outside the current workspace. + +By default, workspace-relative file reads stay inside the workspace and absolute paths are denied. Add only roots you trust PI WEB to list and read through the browser UI. + +Accepted root forms: + +- Unix absolute paths: `/opt/reference` +- Home-relative paths: `~/SDKs` +- Windows absolute paths on Windows hosts: `C:\Users\dev\SDKs` + +When an absolute request is served, PI WEB expands `~`, canonicalizes the configured roots with `realpath`, requires roots to be existing directories, and rejects symlink escapes outside the allowed roots. + +This is not a sandbox for the underlying Pi Coding Agent or your OS user. It only controls PI WEB UI/API file exposure outside a workspace. + +### Session daemon tools + +`spawnSessions` controls whether agents receive the `spawn_session` tool. It defaults to `true`; set it to `false` if you do not want an agent to start independent PI WEB sessions. + +`subsessions` is beta and controls whether agents receive the tracked-subsession tools: `spawn_subsession`, `list_subsessions`, `check_subsession`, and `read_subsession`. It defaults to `false` and also requires `spawnSessions` to be enabled. + +Tracked subsessions let an agent delegate work to child sessions, get notified when children stop working, and inspect their transcripts. + +### Plugin config + +Plugins are enabled by default. Set `plugins..enabled` to `false` to remove a plugin from `/pi-web-plugins/manifest.json` before the browser imports it. + +```json +{ + "plugins": { + "workspace-tasks": { "enabled": true, "settings": {} }, + "updates": { "enabled": false } + } +} +``` + +Reload the browser tab after changing plugin enablement. Already-loaded plugin JavaScript is not unloaded from the current page. + +### Shortcut config + +Shortcut values are keyed by action id. Values are shortcut strings such as `mod+k` or `mod+g p`; `null` disables that action's shortcut. + +```json +{ + "shortcuts": { + "core:view.chat": "mod+1", + "core:session.stop": null + } +} +``` + +Prefer Settings → Keyboard for editing shortcuts interactively. + +## Optional completion tools + +File and path `@` completions work without extra tools. If `fzf` is available on the PI WEB server's `PATH`, PI WEB uses it to improve completion filtering/ranking; otherwise it falls back to built-in ranking. diff --git a/docs/faq.html b/docs/faq.html index 6aa14e5..6e30e6d 100644 --- a/docs/faq.html +++ b/docs/faq.html @@ -3,10 +3,29 @@ - PI WEB FAQ - - - + PI WEB FAQ — Pi web UI troubleshooting + + + + + + + + + + + + +