Installation guide

# Get PI WEB running where your agents work.

The recommended setup runs PI WEB as per-user services. PI WEB chooses the native user-service backend for your operating system.

## Requirements

- Node.js 22.19.0 or newer and npm.
- Pi Coding Agent `>=0.80.8 <0.81` installed/configured so the `pi` command works for your user.
- A shell login environment that exposes Node, npm, Pi, git, and any tools your agents need.
- For the automatic installer: a supported per-user service manager.

Important PATH detail: PI WEB services run through a non-interactive login shell with `-lc`. Setup that only lives in interactive shell files or prompt hooks may not be visible to the systemd or launchd manager. The installer probes the safely verifiable requirements of the exact candidate plan in that manager context before changing config or replacing services. Arbitrary configured command overrides are preserved but not executed by preflight; run `pi-web doctor` later to repeat plan-specific diagnostics.

## Recommended: run PI WEB as user services

This creates two per-user services: one long-lived session daemon and one web/API service. The CLI chooses the native user-service backend automatically. It is the easiest way to keep sessions available after SSH disconnects, browser restarts, or web/API restarts.

User service install

    $ npm install -g @jmfederico/pi-web --allow-scripts=node-pty
    $ pi-web install
    $ pi-web doctor

The scoped `--allow-scripts=node-pty` flag lets npm 12 run the native-module installation required by PI WEB terminals without enabling install scripts for other dependencies.

Then open http://127.0.0.1:8504.

If preflight fails, no config or existing services are changed. Follow the detected shell guidance: zsh services read `~/.zprofile`, not interactive-only `~/.zshrc`; bash uses `~/.bash_profile` or `~/.profile`.

On Linux servers, also consider `sudo loginctl enable-linger "$USER"` so user services survive logout/reboot.

## One-line install

If you prefer a curl pipe for the native user-service install, use the repository installer. This path still requires Node.js, npm, and Pi Coding Agent on the host.

One-liner

    $ curl -fsSL https://raw.githubusercontent.com/jmfederico/pi-web/main/install.sh | sh

## Install through Pi

PI WEB is also published as a Pi package. This exposes a `/pi-web` command inside Pi.

When installed this way, `/pi-web install` can use PI WEB's package-local service entrypoints, so `pi-web-server` and `pi-web-sessiond` do not need to be on your shell `PATH`.

Pi package path

    $ pi install npm:@jmfederico/pi-web

    # Then inside Pi:
    /pi-web install
    /pi-web status
    /pi-web logs
    /pi-web doctor
    /pi-web version

## WSL / manual run

On WSL without systemd, containers without a user service manager, or other unsupported environments, install the package and run the daemon and web server yourself.

Manual processes

    $ npm install -g @jmfederico/pi-web --allow-scripts=node-pty

    # Terminal 1
    $ pi-web-sessiond

    # Terminal 2
    $ PI_WEB_PORT=8504 pi-web-server

On modern WSL distributions with systemd enabled, the installer can work. Without systemd, use the manual run approach above.

From a PI WEB checkout, `pi-web install --dev` installs the split development services on supported user-service platforms. `pi-web uninstall` removes both production and development service files; no uninstall flags are needed.

## Remote access

PI WEB binds to `127.0.0.1:8504` by default. For a remote server, the safest option is an SSH tunnel:

SSH tunnel

    $ ssh -L 8504:127.0.0.1:8504 user@your-server
    # Open http://127.0.0.1:8504 on your local machine

PI WEB is designed for trusted users and trusted server paths. Do not expose it directly to the public internet. If you use a VPN or private network, bind PI WEB to the server's VPN/private IP, such as a NetBird/Tailscale/WireGuard/LAN address, and make sure that network policy limits access. Avoid `0.0.0.0` unless a firewall, VPN, or authenticated reverse proxy strictly controls the port.

## Reverse proxy root and path-prefix deployments

The published PI WEB client is deployment-independent. The same package works at the origin root (`/`) or at canonical nested prefixes such as `/ai/` and `/test/ai/`; no prefix-specific rebuild or PI WEB configuration is needed.

For a root deployment, proxy `/` directly to `http://127.0.0.1:8504` without rewriting the path. For a nested deployment:

1. Redirect the slashless prefix, such as `/ai`, to `/ai/`. The browser uses the trailing-slash document URL as the application base.
2. Strip the prefix before forwarding. PI WEB continues to serve root paths on its localhost listener.
3. Apply authentication to the whole served `/ai/` application and preserve required authentication headers and cookies.
4. Forward WebSocket upgrades through the same location as HTTP, API, image, PWA, and plugin traffic.

Nginx path-prefix proxy

    # http context
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }

    server {
        listen 443 ssl;
        server_name pi.example.com;

        ssl_certificate     /etc/letsencrypt/live/pi.example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/pi.example.com/privkey.pem;

        auth_basic "PI WEB";
        auth_basic_user_file /etc/nginx/pi-web.htpasswd;

        location = /ai {
            return 308 /ai/$is_args$args;
        }

        location ^~ /ai/ {
            # The trailing slash strips /ai/ before forwarding.
            proxy_pass http://127.0.0.1:8504/;
            proxy_http_version 1.1;

            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Authorization $http_authorization;
            proxy_set_header Cookie $http_cookie;

            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
            proxy_read_timeout 1h;
        }
    }

Use the same pattern for `/test/ai/` by changing both Nginx locations. If your proxy uses bearer tokens, SSO, or another authentication mechanism, keep that policy on the prefixed application location and continue forwarding the headers or cookies it requires; the slashless redirect serves no PI WEB content. Do not create unprotected exceptions for `/api/` or `/pi-web-plugins/`.

Once the proxy follows this contract, relative client assets, images, PWA assets, API calls, local and federated plugins, and WebSocket URLs stay inside the prefix. Installed PWA `start_url` and scope stay inside it as well.

## Federated machines

To use one PI WEB instance as a gateway to others, install and run PI WEB on each target machine first. Make each target reachable from the gateway through a trusted path, then open the gateway and use Actions → Add Machine with the target PI WEB base URL.

The remote URL can be reachable through NetBird, Tailscale, WireGuard, LAN, an SSH tunnel, or an authenticated reverse proxy. The browser keeps using the gateway origin while projects, sessions, files, and terminals run on the selected remote runtime.

Read the fleet guide

## Manage services

`pi-web version` compares the installed package version with the versions reported by the running Web/UI and session daemon services.

Useful commands

    $ pi-web status
    $ pi-web logs
    $ pi-web restart
    $ pi-web doctor
    $ pi-web version

    # From a checkout, install the split development services:
    $ pi-web install --dev

## Configure

The installer writes a config file to `~/.config/pi-web/config.json`, or to `$XDG_CONFIG_HOME/pi-web/config.json` when `XDG_CONFIG_HOME` is set. You can choose a different config file during install with `pi-web install --config /path/to/config.json`, or at runtime with `PI_WEB_CONFIG=/path/to/config.json`.

Common config

    {
      "host": "127.0.0.1",
      "port": 8504,
      "pathAccess": {
        "allowedPaths": ["~/SDKs", "/opt/reference"]
      },
      "spawnSessions": true,
      "subsessions": false
    }

Use Settings → General for host, port, and external filesystem roots; Settings → Session daemon for agent-spawn tools; Settings → Pi packages for Pi package install/remove/update; Settings → PI WEB plugins for browser plugin enablement; and Settings → Keyboard for shortcut overrides.

Need the full schema, restart rules, project-local `.pi-web/config.json`, path access details, and environment variable reference? Read the configuration reference.

The web server defaults to `127.0.0.1:8504`, and PI WEB-managed state defaults to `~/.pi-web`. External filesystem paths are denied by default unless listed in `pathAccess.allowedPaths`.

## Uninstall

`pi-web uninstall` stops, disables, and removes PI WEB's production and development service files. It does not remove the npm package, config file, or data directory.

Uninstall services and package

    $ pi-web uninstall
    $ npm uninstall -g @jmfederico/pi-web

Optional cleanup, if you also want to delete PI WEB config and state:

Delete config and data

    $ CONFIG_FILE="${PI_WEB_CONFIG:-${XDG_CONFIG_HOME:-$HOME/.config}/pi-web/config.json}"
    $ DATA_DIR="${PI_WEB_DATA_DIR:-$HOME/.pi-web}"
    $ rm -f "$CONFIG_FILE"
    $ rmdir "$(dirname "$CONFIG_FILE")" 2>/dev/null || true
    $ rm -rf "$DATA_DIR"

    # If you configured a socket outside PI_WEB_DATA_DIR, remove it too:
    $ [ -z "${PI_WEB_SESSIOND_SOCKET:-}" ] || rm -f "$PI_WEB_SESSIOND_SOCKET"

If you installed with `pi-web install --config /custom/path.json`, delete that custom file instead of the default config path.