docs: add PI WEB configuration reference

This commit is contained in:
Federico Jaramillo Martinez
2026-06-23 19:58:36 +02:00
parent 6933d3aa88
commit c2e2a29847
16 changed files with 769 additions and 25 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@jmfederico/pi-web": patch
---
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.
+21 -7
View File
@@ -259,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 `<project>/.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:
@@ -270,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.
+2
View File
@@ -40,6 +40,7 @@
<a href="/remote-first">Remote-first</a>
<a href="/machines">Fleet</a>
<a href="/install">Install</a>
<a href="/config">Config</a>
<a href="/plugins">Plugins</a>
<a href="/faq">FAQ</a>
</div>
@@ -90,6 +91,7 @@
<div class="footer-links">
<a href="/machines">Fleet</a>
<a href="/install">Install</a>
<a href="/config">Config</a>
<a href="/plugins">Plugins</a>
<a href="/faq">FAQ</a>
<a href="https://www.npmjs.com/package/@jmfederico/pi-web">npm</a>
+481
View File
@@ -0,0 +1,481 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Configure PI WEB — config files, paths, and session tools</title>
<meta
name="description"
content="Configure PI WEB config files, external path access, session daemon tools, plugins, shortcuts, uploads, and runtime environment variables."
/>
<link rel="canonical" href="https://pi-web.dev/config" />
<meta property="og:type" content="website" />
<meta property="og:site_name" content="PI WEB" />
<meta property="og:title" content="Configure PI WEB" />
<meta
property="og:description"
content="Reference for PI WEB config files, path access allowlists, session daemon options, plugins, shortcuts, uploads, and environment variables."
/>
<meta property="og:url" content="https://pi-web.dev/config" />
<meta property="og:image" content="https://pi-web.dev/assets/pi-web-banner.png" />
<meta property="og:image:alt" content="PI WEB browser UI for persistent Pi Coding Agent sessions" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Configure PI WEB" />
<meta
name="twitter:description"
content="Reference for PI WEB config files, path access allowlists, session daemon options, plugins, shortcuts, uploads, and environment variables."
/>
<meta name="twitter:image" content="https://pi-web.dev/assets/pi-web-banner.png" />
<link rel="icon" type="image/svg+xml" href="assets/favicon.svg" />
<script>
(() => {
const theme = window.localStorage.getItem("pi-web-theme");
if (theme === "light" || theme === "dark") document.documentElement.dataset.theme = theme;
})();
</script>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600;700&family=IBM+Plex+Sans:wght@400;500;600;700;800&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<header class="site-header">
<nav class="container nav" aria-label="Main navigation">
<a class="brand" href="./" aria-label="PI WEB home">PI WEB</a>
<div class="nav-links">
<div class="nav-pages">
<a href="remote-first">Remote-first</a>
<a href="machines">Fleet</a>
<a href="install">Install</a>
<a href="config" aria-current="page">Config</a>
<a href="plugins">Plugins</a>
<a href="faq">FAQ</a>
</div>
<div class="nav-actions">
<a class="github-link" href="https://github.com/jmfederico/pi-web" aria-label="PI WEB on GitHub">
<svg class="github-icon" viewBox="0 0 16 16" aria-hidden="true">
<path
fill="currentColor"
d="M8 0C3.58 0 0 3.67 0 8.2c0 3.63 2.29 6.7 5.47 7.79.4.08.55-.18.55-.4 0-.2-.01-.85-.01-1.55-2.01.38-2.53-.5-2.69-.96-.09-.24-.48-.96-.82-1.16-.28-.16-.68-.56-.01-.57.63-.01 1.08.59 1.23.84.72 1.24 1.87.89 2.33.68.07-.53.28-.89.51-1.09-1.78-.21-3.64-.91-3.64-4.04 0-.89.31-1.62.82-2.2-.08-.2-.36-1.03.08-2.16 0 0 .67-.22 2.2.84A7.4 7.4 0 0 1 8 3.94c.68 0 1.36.09 2 .28 1.53-1.06 2.2-.84 2.2-.84.44 1.13.16 1.96.08 2.16.51.58.82 1.31.82 2.2 0 3.14-1.87 3.83-3.65 4.04.29.26.54.76.54 1.53 0 1.1-.01 1.99-.01 2.27 0 .22.15.49.55.4A8.12 8.12 0 0 0 16 8.2C16 3.67 12.42 0 8 0Z"
/>
</svg>
<span>GitHub</span>
</a>
<button class="theme-toggle" type="button" data-theme-toggle aria-label="Toggle light and dark theme">
<span data-theme-icon aria-hidden="true"></span>
<span data-theme-label>Theme</span>
</button>
</div>
</div>
</nav>
</header>
<main>
<section class="page-hero">
<div class="container">
<p class="eyebrow"><span class="pulse"></span> Configuration reference</p>
<h1>Configure PI WEB where your agents work.</h1>
<p>
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.
</p>
</div>
</section>
<section class="section compact">
<div class="container doc-layout">
<aside class="toc" aria-label="Config page contents">
<strong>On this page</strong>
<a href="#files">Config files</a>
<a href="#precedence">Precedence and reloads</a>
<a href="#global-config">Global config</a>
<a href="#project-config">Project config</a>
<a href="#keys">Config matrix</a>
<a href="#path-access">External path access</a>
<a href="#session-tools">Session tools</a>
<a href="#completion-tools">Completion tools</a>
</aside>
<div class="doc-content">
<section id="files">
<h2>Config files</h2>
<p>PI WEB uses a global config file for machine-local settings and a project-local file for repository settings.</p>
<ul>
<li><strong>Global config:</strong> <code>$PI_WEB_CONFIG</code>, or <code>$XDG_CONFIG_HOME/pi-web/config.json</code>, or <code>~/.config/pi-web/config.json</code>.</li>
<li><strong>Project config:</strong> <code>&lt;project&gt;/.pi-web/config.json</code> for commit-able project settings.</li>
</ul>
<p>
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.
</p>
<p>
If you installed services with a custom config path, rerun
<code>pi-web install --config /path/to/config.json</code> 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 <code>PI_WEB_CONFIG</code>.
</p>
</section>
<section id="precedence">
<h2>Precedence and reloads</h2>
<p>Runtime values are resolved in this order:</p>
<div class="code-card">
<pre><code>defaults → config file → environment overrides</code></pre>
</div>
<p>
Environment overrides include <code>PI_WEB_HOST</code>, <code>PI_WEB_PORT</code> / <code>PORT</code>,
<code>PI_WEB_ALLOWED_HOSTS</code>, <code>PI_WEB_MAX_UPLOAD_BYTES</code>, <code>PI_WEB_SPAWN_SESSIONS</code>,
and <code>PI_WEB_SUBSESSIONS</code>.
</p>
<ul>
<li><code>host</code> / <code>port</code>: restart the web/API service or process.</li>
<li><code>maxUploadBytes</code>: restart both the web/API process and the session daemon.</li>
<li><code>spawnSessions</code> / <code>subsessions</code>: restart the session daemon.</li>
<li><code>pathAccess</code>: applies on the next request; existing file views may need a browser refresh.</li>
<li><code>plugins</code>: reload the browser tab after changing plugin enablement.</li>
<li><code>shortcuts</code>: saved settings apply in the browser after config refresh/save.</li>
</ul>
</section>
<section id="global-config">
<h2>Global config example</h2>
<p>
<code>pi-web install</code> creates the initial file. You can also save settings from
<strong>Settings → General</strong>, <strong>Settings → Plugins</strong>, <strong>Settings → Keyboard</strong>,
and <strong>Settings → Session daemon</strong>.
</p>
<div class="code-card">
<div class="copy-row">
<strong>Example config.json</strong>
<button class="copy-button" data-copy="#global-config-example">Copy</button>
</div>
<pre id="global-config-example"><code>{
"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
}
}</code></pre>
</div>
</section>
<section id="project-config">
<h2>Project-local config</h2>
<p>
Project-local config lives at <code>&lt;project&gt;/.pi-web/config.json</code>. Use it for settings that should
follow a repository. When a project config defines <code>pathAccess</code>, PI WEB merges it after the
global path list.
</p>
<div class="code-card">
<div class="copy-row">
<strong>.pi-web/config.json</strong>
<button class="copy-button" data-copy="#project-config-example">Copy</button>
</div>
<pre id="project-config-example"><code>{
"version": 1,
"pathAccess": {
"allowedPaths": ["~/SDKs", "/opt/reference"]
}
}</code></pre>
</div>
<p>
Project-local <code>pathAccess.allowedPaths</code> entries must still be host-absolute or
<code>~</code>-prefixed; relative roots are not supported. Plugins may own separate project files, such as
<code>.pi-web/tasks.json</code> for the built-in Workspace Tasks plugin.
</p>
</section>
<section id="keys">
<h2>Config matrix</h2>
<p>
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
<code></code> are runtime-only environment variables, not config-file keys.
</p>
<div class="table-scroll" role="region" aria-label="PI WEB configuration matrix" tabindex="0">
<table class="config-matrix">
<thead>
<tr>
<th scope="col">Config</th>
<th scope="col">JSON key</th>
<th scope="col">Env var</th>
<th scope="col">Scope</th>
<th scope="col">Project-local behavior</th>
<th scope="col">Applies / restart</th>
</tr>
</thead>
<tbody>
<tr class="table-section"><th scope="rowgroup" colspan="6">Config-file keys</th></tr>
<tr>
<td>Web/API bind host</td>
<td><code>host</code></td>
<td><code>PI_WEB_HOST</code></td>
<td>Global</td>
<td>Not supported locally</td>
<td>Restart web/API</td>
</tr>
<tr>
<td>Web/API port</td>
<td><code>port</code></td>
<td><code>PI_WEB_PORT</code>, <code>PORT</code></td>
<td>Global</td>
<td>Not supported locally</td>
<td>Restart web/API</td>
</tr>
<tr>
<td>Dev-server allowed hosts</td>
<td><code>allowedHosts</code></td>
<td><code>PI_WEB_ALLOWED_HOSTS</code></td>
<td>Global</td>
<td>Not supported locally</td>
<td>Restart dev web/UI</td>
</tr>
<tr>
<td>External filesystem roots</td>
<td><code>pathAccess.allowedPaths</code></td>
<td></td>
<td>Global + project</td>
<td><strong>Merges:</strong> global roots first, then project roots; duplicates removed</td>
<td>Next file request; refresh existing views if needed</td>
</tr>
<tr>
<td>Upload/body limit</td>
<td><code>maxUploadBytes</code></td>
<td><code>PI_WEB_MAX_UPLOAD_BYTES</code></td>
<td>Global</td>
<td>Not supported locally</td>
<td>Restart web/API and session daemon</td>
</tr>
<tr>
<td>Agent can spawn sessions</td>
<td><code>spawnSessions</code></td>
<td><code>PI_WEB_SPAWN_SESSIONS</code></td>
<td>Global/session daemon</td>
<td>Not supported locally</td>
<td>Restart session daemon</td>
</tr>
<tr>
<td>Tracked subsessions (beta)</td>
<td><code>subsessions</code></td>
<td><code>PI_WEB_SUBSESSIONS</code></td>
<td>Global/session daemon</td>
<td>Not supported locally; also requires <code>spawnSessions</code></td>
<td>Restart session daemon</td>
</tr>
<tr>
<td>Plugin enablement/settings</td>
<td><code>plugins.&lt;id&gt;.enabled</code>, <code>plugins.&lt;id&gt;.settings</code></td>
<td></td>
<td>Global</td>
<td>Not core local config; plugins may read their own project files</td>
<td>Reload browser tab</td>
</tr>
<tr>
<td>Keyboard shortcuts</td>
<td><code>shortcuts.&lt;actionId&gt;</code></td>
<td></td>
<td>Global</td>
<td>Not supported locally</td>
<td>Applies after settings save/config refresh</td>
</tr>
<tr>
<td>Project config version</td>
<td><code>version</code></td>
<td></td>
<td>Project</td>
<td>Project-local only; must be <code>1</code> when present</td>
<td>Next project-config read</td>
</tr>
<tr class="table-section"><th scope="rowgroup" colspan="6">Runtime-only environment variables</th></tr>
<tr>
<td>Global config file path</td>
<td></td>
<td><code>PI_WEB_CONFIG</code> (<code>XDG_CONFIG_HOME</code> affects the default path)</td>
<td>Process/env</td>
<td>Selects the global config file; not a project config</td>
<td>Restart services/processes after changing env</td>
</tr>
<tr>
<td>Managed data directory</td>
<td></td>
<td><code>PI_WEB_DATA_DIR</code></td>
<td>Process/env</td>
<td>Not supported locally</td>
<td>Restart services before changing; moves managed state location</td>
</tr>
<tr>
<td>Session daemon socket</td>
<td></td>
<td><code>PI_WEB_SESSIOND_SOCKET</code></td>
<td>Web/API + session daemon env</td>
<td>Not supported locally</td>
<td>Restart daemon and web/API; both must match</td>
</tr>
<tr>
<td>Session daemon TCP port</td>
<td></td>
<td><code>PI_WEB_SESSIOND_PORT</code></td>
<td>Session daemon env</td>
<td>Not supported locally</td>
<td>Restart session daemon; set <code>PI_WEB_SESSIOND_URL</code> for web/API too</td>
</tr>
<tr>
<td>Session daemon TCP host</td>
<td></td>
<td><code>PI_WEB_SESSIOND_HOST</code></td>
<td>Session daemon env</td>
<td>Not supported locally</td>
<td>Restart session daemon</td>
</tr>
<tr>
<td>Web-to-daemon URL</td>
<td></td>
<td><code>PI_WEB_SESSIOND_URL</code></td>
<td>Web/API env</td>
<td>Not supported locally</td>
<td>Restart web/API</td>
</tr>
<tr>
<td>Projects storage file</td>
<td></td>
<td><code>PI_WEB_PROJECTS_FILE</code></td>
<td>Web/API + session daemon env</td>
<td>Not supported locally</td>
<td>Restart services; advanced state override</td>
</tr>
<tr>
<td>Remote machines storage file</td>
<td></td>
<td><code>PI_WEB_MACHINES_FILE</code></td>
<td>Web/API env</td>
<td>Not supported locally</td>
<td>Restart web/API; advanced state override</td>
</tr>
<tr>
<td>Pi session storage directory</td>
<td></td>
<td><code>PI_CODING_AGENT_SESSION_DIR</code></td>
<td>Pi/session daemon env</td>
<td>Not supported locally</td>
<td>Restart session daemon; follows Pi session priority</td>
</tr>
<tr>
<td>Pi agent config directory</td>
<td></td>
<td><code>PI_CODING_AGENT_DIR</code></td>
<td>Pi/Web/API/session daemon env</td>
<td>Not supported locally</td>
<td>Restart services</td>
</tr>
<tr>
<td>Skip update checks</td>
<td></td>
<td><code>PI_WEB_SKIP_VERSION_CHECK</code>, <code>PI_WEB_OFFLINE</code>, <code>PI_SKIP_VERSION_CHECK</code>, <code>PI_OFFLINE</code></td>
<td>Web/API env</td>
<td>Not supported locally</td>
<td>Restart web/API after env changes</td>
</tr>
</tbody>
</table>
</div>
</section>
<section id="path-access">
<h2>External path access</h2>
<p>
<code>pathAccess.allowedPaths</code> grants PI WEB's file explorer and absolute <code>@</code> 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.
</p>
<p>Accepted root forms:</p>
<ul>
<li>Unix absolute paths, for example <code>/opt/reference</code>.</li>
<li>Home-relative paths, for example <code>~/SDKs</code>.</li>
<li>Windows absolute paths on Windows hosts, for example <code>C:\Users\dev\SDKs</code>.</li>
</ul>
<p>
When an absolute request is served, PI WEB expands <code>~</code>, canonicalizes configured roots with
<code>realpath</code>, requires roots to be existing directories, and rejects symlink escapes outside the
allowed roots.
</p>
<div class="callout warning">
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.
</div>
</section>
<section id="session-tools">
<h2>Session daemon tools</h2>
<h3><code>spawnSessions</code></h3>
<p>
Boolean. Controls whether agents receive the <code>spawn_session</code> tool. Defaults to
<code>true</code>. Set it to <code>false</code> if you do not want an agent to start independent PI WEB sessions.
</p>
<p>Environment override: <code>PI_WEB_SPAWN_SESSIONS=0|1|true|false</code>.</p>
<h3><code>subsessions</code></h3>
<p>
Boolean. Beta. Controls whether agents receive the tracked-subsession tools:
<code>spawn_subsession</code>, <code>list_subsessions</code>, <code>check_subsession</code>, and
<code>read_subsession</code>. Defaults to <code>false</code> and also requires <code>spawnSessions</code>
to be enabled.
</p>
<p>
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.
</p>
<p>Environment override: <code>PI_WEB_SUBSESSIONS=0|1|true|false</code>.</p>
</section>
<section id="completion-tools">
<h2>Optional completion tools</h2>
<p>
File and path <code>@</code> completions work without extra tools. If <code>fzf</code> is available on the
PI WEB server's <code>PATH</code>, PI WEB uses it to improve completion filtering and ranking; otherwise it
falls back to built-in ranking.
</p>
<div class="doc-actions">
<a class="button primary" href="install">Install guide</a>
<a class="button" href="config.md">Markdown reference</a>
</div>
</section>
</div>
</div>
</section>
</main>
<footer class="site-footer">
<div class="container footer-inner">
<span>PI WEB docs</span>
<div class="footer-links">
<a href="./">Home</a>
<a href="remote-first">Remote-first</a>
<a href="machines">Fleet</a>
<a href="install">Install</a>
<a href="config">Config</a>
<a href="plugins">Plugins</a>
<a href="faq">FAQ</a>
<a href="https://github.com/jmfederico/pi-web">GitHub</a>
</div>
</div>
</footer>
<script src="site.js"></script>
</body>
</html>
+166
View File
@@ -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 <https://pi-web.dev/config>.
## 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:** `<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 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 `<project>/.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.<id>.enabled`, `plugins.<id>.settings` | — | Global | Not core local config; plugins may read their own project files | Reload browser tab |
| Keyboard shortcuts | `shortcuts.<actionId>` | — | 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.<id>.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.
+2
View File
@@ -50,6 +50,7 @@
<a href="remote-first">Remote-first</a>
<a href="machines">Fleet</a>
<a href="install">Install</a>
<a href="config">Config</a>
<a href="plugins">Plugins</a>
<a href="faq" aria-current="page">FAQ</a>
</div>
@@ -305,6 +306,7 @@
<a href="remote-first">Remote-first</a>
<a href="machines">Fleet</a>
<a href="install">Install</a>
<a href="config">Config</a>
<a href="plugins">Plugins</a>
<a href="https://github.com/jmfederico/pi-web/issues">Issues</a>
</div>
+2
View File
@@ -66,6 +66,7 @@
<a href="remote-first">Remote-first</a>
<a href="machines">Fleet</a>
<a href="install">Install</a>
<a href="config">Config</a>
<a href="plugins">Plugins</a>
<a href="faq">FAQ</a>
</div>
@@ -349,6 +350,7 @@
<a href="remote-first">Remote-first</a>
<a href="machines">Fleet</a>
<a href="install">Install</a>
<a href="config">Config</a>
<a href="plugins">Plugins</a>
<a href="faq">FAQ</a>
<a href="https://www.npmjs.com/package/@jmfederico/pi-web">npm</a>
+20 -12
View File
@@ -50,6 +50,7 @@
<a href="remote-first">Remote-first</a>
<a href="machines">Fleet</a>
<a href="install" aria-current="page">Install</a>
<a href="config">Config</a>
<a href="plugins">Plugins</a>
<a href="faq">FAQ</a>
</div>
@@ -265,27 +266,33 @@
</p>
<div class="code-card">
<div class="copy-row">
<strong>Default config</strong>
<strong>Common config</strong>
<button class="copy-button" data-copy="#config-example">Copy</button>
</div>
<pre id="config-example"><code>{
"host": "127.0.0.1",
"port": 8504,
"allowedHosts": []
"pathAccess": {
"allowedPaths": ["~/SDKs", "/opt/reference"]
},
"spawnSessions": true,
"subsessions": false
}</code></pre>
</div>
<p>
The web server defaults to <code>127.0.0.1:8504</code> and stores PI WEB state in <code>~/.pi-web</code>.
Use <strong>Settings → General</strong> for host, port, and external filesystem roots; <strong>Settings → Session daemon</strong>
for agent-spawn tools; <strong>Settings → Plugins</strong> for plugin enablement; and <strong>Settings → Keyboard</strong>
for shortcut overrides.
</p>
<div class="callout">
Need the full schema, restart rules, project-local <code>.pi-web/config.json</code>, path access details, and
environment variable reference? Read the <a href="config">configuration reference</a>.
</div>
<p>
The web server defaults to <code>127.0.0.1:8504</code>, and PI WEB-managed state defaults to
<code>~/.pi-web</code>. External filesystem paths are denied by default unless listed in
<code>pathAccess.allowedPaths</code>.
</p>
<ul>
<li><code>PI_WEB_CONFIG</code>: path to a config JSON file. Defaults to <code>~/.config/pi-web/config.json</code>.</li>
<li><code>PI_WEB_PORT</code> or <code>PORT</code>: web server port. Overrides the config file.</li>
<li><code>PI_WEB_HOST</code>: web server bind host. Overrides the config file. Use <code>127.0.0.1</code> for local/tunnel-only access, or a specific VPN/private-network IP for trusted remote access.</li>
<li><code>PI_WEB_DATA_DIR</code>: data directory, default <code>~/.pi-web</code>.</li>
<li><code>PI_WEB_SESSIOND_SOCKET</code>: Unix socket path for daemon communication.</li>
<li><code>PI_CODING_AGENT_SESSION_DIR</code>: Pi session storage directory. PI WEB follows Pi's priority for sessions: this environment variable, then <code>sessionDir</code> in Pi settings for the selected workspace, then Pi's default session directory.</li>
<li><code>PI_CODING_AGENT_DIR</code>: Pi agent config directory for auth, settings, resources, and default session storage.</li>
</ul>
</section>
<section id="uninstall">
@@ -334,6 +341,7 @@
<a href="./">Home</a>
<a href="remote-first">Remote-first</a>
<a href="machines">Fleet</a>
<a href="config">Config</a>
<a href="plugins">Plugins</a>
<a href="faq">FAQ</a>
<a href="https://github.com/jmfederico/pi-web">GitHub</a>
+2
View File
@@ -50,6 +50,7 @@
<a href="remote-first">Remote-first</a>
<a href="machines" aria-current="page">Fleet</a>
<a href="install">Install</a>
<a href="config">Config</a>
<a href="plugins">Plugins</a>
<a href="faq">FAQ</a>
</div>
@@ -289,6 +290,7 @@ PI WEB gateway you opened
<a href="./">Home</a>
<a href="remote-first">Remote-first</a>
<a href="install">Install</a>
<a href="config">Config</a>
<a href="plugins">Plugins</a>
<a href="faq">FAQ</a>
<a href="https://github.com/jmfederico/pi-web">GitHub</a>
+2
View File
@@ -50,6 +50,7 @@
<a href="remote-first">Remote-first</a>
<a href="machines">Fleet</a>
<a href="install">Install</a>
<a href="config">Config</a>
<a href="plugins" aria-current="page">Plugins</a>
<a href="faq">FAQ</a>
</div>
@@ -430,6 +431,7 @@ After editing, check the manifest endpoint and browser-console failure cases.</c
<a href="remote-first">Remote-first</a>
<a href="machines">Fleet</a>
<a href="install">Install</a>
<a href="config">Config</a>
<a href="faq">FAQ</a>
<a href="https://github.com/jmfederico/pi-web">GitHub</a>
</div>
+2
View File
@@ -50,6 +50,7 @@
<a href="remote-first" aria-current="page">Remote-first</a>
<a href="machines">Fleet</a>
<a href="install">Install</a>
<a href="config">Config</a>
<a href="plugins">Plugins</a>
<a href="faq">FAQ</a>
</div>
@@ -206,6 +207,7 @@
<a href="./">Home</a>
<a href="machines">Fleet</a>
<a href="install">Install</a>
<a href="config">Config</a>
<a href="plugins">Plugins</a>
<a href="faq">FAQ</a>
<a href="https://github.com/jmfederico/pi-web">GitHub</a>
+1
View File
@@ -4,6 +4,7 @@
<url><loc>https://pi-web.dev/remote-first</loc></url>
<url><loc>https://pi-web.dev/machines</loc></url>
<url><loc>https://pi-web.dev/install</loc></url>
<url><loc>https://pi-web.dev/config</loc></url>
<url><loc>https://pi-web.dev/plugins</loc></url>
<url><loc>https://pi-web.dev/faq</loc></url>
</urlset>
+54
View File
@@ -847,6 +847,60 @@ code .comment,
font-size: 1.25rem;
}
.table-scroll {
overflow-x: auto;
margin: 16px 0;
border: 1px solid var(--line);
background: var(--panel);
}
.doc-content table {
width: 100%;
min-width: 860px;
border-collapse: collapse;
}
.doc-content th,
.doc-content td {
padding: 12px 14px;
border-bottom: 1px solid var(--line);
text-align: left;
vertical-align: top;
}
.doc-content th {
background: var(--panel-strong);
color: var(--text);
font-size: 0.78rem;
letter-spacing: 0.05em;
text-transform: uppercase;
}
.doc-content .table-section th {
border-top: 2px solid var(--line-bright);
border-bottom-color: var(--line-bright);
background: var(--panel-strong);
color: var(--text);
letter-spacing: 0.08em;
}
.doc-content td {
color: var(--muted);
}
.doc-content td:first-child {
color: var(--text);
font-weight: 700;
}
.doc-content tr:last-child td {
border-bottom: 0;
}
.doc-content table code {
white-space: nowrap;
}
.code-card {
overflow: hidden;
margin: 16px 0;
+1
View File
@@ -17,6 +17,7 @@
"LICENSE",
"extensions",
"docs/plugins.md",
"docs/config.md",
"docs/assets",
"plugin-api.d.ts",
"plugin-api/unstable.d.ts"
+6 -4
View File
@@ -386,20 +386,21 @@ function restartOrder(refs: ServiceRef[]): ServiceRef[] {
}
function productionServiceDefinitions(options: InstallOptions, configPath: string, executables: ServiceExecutables): ServiceDefinition[] {
const environment = configEnvironment(options, configPath);
return [
{
...serviceRefs.sessiond,
description: "PI WEB session daemon",
shellCommand: `exec ${executables.sessiond.command}`,
restart: "on-failure",
environment: {},
environment,
},
{
...serviceRefs.web,
description: "PI WEB server",
shellCommand: `exec ${executables.web.command}`,
restart: "on-failure",
environment: configEnvironment(options, configPath),
environment,
after: ["sessiond"],
wants: ["sessiond"],
},
@@ -429,13 +430,14 @@ function validateDevCheckout(root: string): void {
}
function devServiceDefinitions(options: InstallOptions, configPath: string, root: string): ServiceDefinition[] {
const environment = configEnvironment(options, configPath);
return [
{
...serviceRefs.sessiond,
description: "PI WEB session daemon (dev)",
shellCommand: "exec npm run start:sessiond",
restart: "never",
environment: {},
environment,
workingDirectory: root,
},
{
@@ -443,7 +445,7 @@ function devServiceDefinitions(options: InstallOptions, configPath: string, root
description: "PI WEB UI dev server",
shellCommand: `exec /usr/bin/env bash -c ${serviceShellQuote('trap "kill 0" EXIT; npm run dev:web & npm run dev:client & wait')}`,
restart: "never",
environment: configEnvironment(options, configPath),
environment,
after: ["sessiond"],
wants: ["sessiond"],
workingDirectory: root,
+2 -2
View File
@@ -21,13 +21,13 @@ import { getPiWebRuntimeComponent } from "./piWebStatus.js";
import { SESSIOND_RUNTIME_CAPABILITIES } from "../shared/capabilities.js";
import { effectivePiWebConfig, maxUploadBytes, spawnSessionsEnabled, subsessionsEnabled } from "../config.js";
const app = Fastify({ logger: true, bodyLimit: maxUploadBytes() });
const { config } = effectivePiWebConfig();
const app = Fastify({ logger: true, bodyLimit: maxUploadBytes(process.env, config) });
await app.register(fastifyWebsocket);
const eventHub = new SessionEventHub();
const workspaceActivity = new WorkspaceActivityService(eventHub);
const auth = new AuthService();
const { config } = effectivePiWebConfig();
const spawnTargets = spawnSessionsEnabled(process.env, config)
? new ProjectScopedSpawnTargetResolver({ projects: new ProjectService(new ProjectStore()), workspaces: new WorkspaceService() })
: undefined;