Plugin development

Customize PI WEB with UI plugins.

Plugins are trusted browser-side ES modules. They can add actions, workspace panels, and compact workspace labels to the PI WEB UI.

What can be extended

Plugins can add small, focused UI extensions to PI WEB:

  • Action palette commands for custom workflows.
  • Workspace tools and panels next to Files, Git, and Terminal.
  • Workspace labels in the workspace list, header, and status bar.
  • Static assets served from the plugin folder.
  • Browser-side integrations using documented PI WEB plugin context helpers.

Plugins cannot extend the session daemon or add server-side hooks. They run in the browser UI only. Use documented context helpers for the stable API surface. Daring plugins can reach into PI WEB internals, but those private surfaces are experimental: they may graduate into stable helpers, change shape, or disappear.

The plugin API is intentionally limited and actively developed. Feedback is appreciated: if an extension point is missing, unclear, or awkward, please open a GitHub issue.

Pi packages vs PI WEB plugins

Pi packages are packages managed by Pi (pi install, pi remove, pi update). A Pi package can provide extensions, skills, prompt templates, themes, context/system prompt files, and/or PI WEB browser plugins. Many Pi packages do not include a PI WEB plugin.

PI WEB plugins are browser-side UI modules discovered from bundled, local, dev, and installed Pi-package sources. Enabling or disabling a PI WEB plugin is a PI WEB config task; installing, removing, or updating a Pi package is a Pi package-manager task.

Use Settings → Pi packages to view configured Pi packages or install/remove/update a package. Enter only the package source, such as npm:@scope/package, a git/URL source, or a local path. PI WEB uses Pi's default package location, equivalent to pi install <source>, and does not ask for an install location.

When machine federation is enabled, Settings → Pi packages targets the currently selected machine. The panel labels whether changes will run on the local/gateway machine or on a selected remote PI WEB machine. If an older or unavailable remote PI WEB server does not expose package-management routes, PI WEB reports the package management operation as unsupported or unavailable instead of silently falling back to the gateway.

Use Settings → PI WEB plugins to enable or disable discovered PI WEB browser plugins before the browser imports them. In a federated setup, this plugin enablement surface targets the currently selected machine and labels where changes are saved. If an older or unavailable remote PI WEB server does not advertise selected-machine settings support, PI WEB reports the plugin settings as unsupported or unavailable instead of silently falling back to the gateway. After installing, removing, or updating a Pi package, type /reload in each idle PI WEB session on the target machine to refresh Pi runtime resources such as extensions, skills, prompt templates, themes, and context/system prompt files as supported by Pi. Reload the browser page separately for newly discovered or changed PI WEB browser plugins. A routine session daemon restart is not required.

What to ask AI to build

You do not need to hand-code plugins. Give an AI agent a clear goal, the workspace/project facts it should use, and the PI WEB plugin rules.

  • Show a workspace badge from a repo file, environment file, branch name, container, or dev URL.
  • Add a workspace panel that summarizes project-specific health, commands, links, or runbooks.
  • Add action-palette commands for common project workflows or prompts.
  • Add links to local services, preview deployments, dashboards, CI, logs, or docs.
Prompt: create a plugin
Build a PI WEB plugin for this project.
Goal: <describe the UI behavior>.
Before coding, read the PI WEB plugin docs:
https://pi-web.dev/plugins
Full API reference:
https://pi-web.dev/plugins.md
Create it as a local plugin under ~/.pi-web/plugins/<plugin-id>.
Use the appropriate extension points from the docs.
Validate by checking /pi-web-plugins/manifest.json and explain how to reload/debug it.
Do not modify PI WEB itself.
Prompt: improve a plugin
Improve the PI WEB plugin at <path>.
Before coding, read the PI WEB plugin docs:
https://pi-web.dev/plugins
Full API reference:
https://pi-web.dev/plugins.md
Keep the plugin compatible with the documented v1 API.
After editing, check the manifest endpoint and browser-console failure cases.

Canonical example

PI WEB ships a real bundled Info plugin. It is intentionally small while still using all core contribution types: one action, one workspace label, and one workspace panel.

Bundled PI WEB plugins are developed as TypeScript in the repository, while their package metadata points at the built JavaScript ES modules that the browser loads. npm run dev:web watches and rebuilds bundled plugin TS into dist/pi-web-plugins/ during development, and npm run build emits JS before release packaging.

  • pi-web-plugins/info/package.json shows the required metadata shape.
  • pi-web-plugins/info/pi-web-plugin.ts shows the TypeScript source shape.
  • dist/pi-web-plugins/info/pi-web-plugin.js is the built browser module in a checkout.

Read it on GitHub: pi-web-plugins/info. If you copy it, choose a new plugin id so it does not conflict with the bundled info plugin.

The bundled updates plugin demonstrates dynamic visible and badge callbacks for tabs that only appear when the host has status messages or needs extra install visibility.

Built-in plugins

PI WEB ships core, discoverable plugins in the main @jmfederico/pi-web npm package. No separate pi install step is required: update PI WEB, reload the browser tab, and the bundled plugins appear in /pi-web-plugins/manifest.json.

Built-in plugins can be managed from Settings → PI WEB plugins or with the top-level plugins config key.

Updates

Updates adds a conditional Updates workspace tab with PI WEB update, restart, and installed-service guidance. It is built into PI WEB, enabled by default, and uses the selected machine's plugin copy when machine federation is active.

  • Plugin id: updates
Disable Updates
{
  "plugins": {
    "updates": { "enabled": false }
  }
}

Workspace Tasks

Workspace Tasks adds a Tasks workspace tab for running configured shell commands in dedicated PI WEB terminals. It is built into PI WEB and enabled by default.

  • Plugin id: workspace-tasks
  • Config file: .pi-web/tasks.json
Disable Workspace Tasks
{
  "plugins": {
    "workspace-tasks": { "enabled": false }
  }
}
Example .pi-web/tasks.json
{
  "version": 1,
  "tasks": [
    {
      "id": "app.start",
      "title": "Start app",
      "group": "Development",
      "description": "Start the local development server.",
      "command": "npm run dev"
    },
    {
      "id": "db.reset",
      "title": "Reset DB",
      "group": "Database",
      "command": "go -C klingit-go run ./cli db reset",
      "confirm": true
    }
  ]
}

Open a workspace, choose the Tasks tab, and click Run next to a task. Commands run in the workspace root because PI WEB creates the terminal for that workspace.

Review task configs before running them, especially in shared projects. Workspace Tasks runs trusted shell commands from your repositories.

Manage PI WEB plugins

Open Settings → PI WEB plugins to review discovered bundled, local, dev, and Pi package plugins for the selected PI WEB machine. When the local machine is selected, this is the gateway plugin list; when a remote machine is selected, the list comes from that remote PI WEB server and includes disabled discovered plugins it exposes. PI WEB can disable any discovered selected-machine plugin before the browser imports it. Core app contributions such as the command palette, base workspace tools, and themes are not managed through this plugin list.

This surface is only for PI WEB plugin enablement. To install, remove, or update Pi packages that may provide plugins or other Pi resources, use Settings → Pi packages. In a federated setup, both the Pi packages panel and the PI WEB plugins panel target the selected machine; plugin enablement still writes the PI WEB plugins config key rather than changing Pi package-manager settings.

Plugin config shape
{
  "plugins": {
    "workspace-tasks": {
      "enabled": true,
      "settings": {}
    },
    "info": {
      "enabled": false
    }
  }
}

Plugins are enabled by default. Set enabled to false to remove a plugin from /pi-web-plugins/manifest.json so it is not imported or activated on the next page load. The optional settings object is reserved for plugin-specific settings.

After changing plugin enablement, reload the PI WEB browser tab. Already-loaded plugin JavaScript is not unloaded from the current page.

Remote machine plugins

With machine federation, PI WEB also loads discovered plugins from the selected remote machine. Remote plugins are trusted browser-side code like local plugins, but their actions, workspace panels, and workspace labels only appear while that machine is selected.

  • File and terminal helpers run against the selected remote machine.
  • Remote plugin code is loaded best-effort through the current gateway and cached for the page lifetime.
  • If the gateway and remote machine both have an enabled plugin with the same original id, machineSpecific metadata decides whether the gateway copy is reused or only the selected-machine copy can appear.
  • Remote theme contributions are ignored for now because themes are app-wide.
  • Mixed PI WEB versions across federated machines are best-effort and not guaranteed compatible.

Remote plugin enablement is controlled by the remote machine's PI WEB plugin config. To edit or disable one, select that machine and use Settings → PI WEB plugins when the remote server exposes selected-machine settings, or open that machine directly/update its config file.

Plugin package metadata can set machineSpecific: true. Use it for plugins like Updates whose UI should come from the selected PI WEB instance; on remote machines, the gateway copy is hidden unless the remote machine exposes its own copy.

For portable plugin assets, prefer URLs relative to the plugin module, such as new URL("./asset.json", import.meta.url). If a remote plugin constructs absolute asset URLs, it should use the pluginId from activate(); hard-coded /pi-web-plugins/<original-id>/... URLs may point at the gateway instead of the remote machine.

Production usage

Local plugins work with the production native-service install. Put each plugin under ~/.pi-web/plugins/<plugin-id>/, or symlink it there while developing. No PI WEB rebuild or session-daemon restart is required.

If PI_WEB_DATA_DIR is set, use $PI_WEB_DATA_DIR/plugins instead of ~/.pi-web/plugins.
Install a local plugin folder

AI-friendly docs

The full plugin reference is available as Markdown for AI agents to read, fetch, and follow: plugins.md.

If you want to understand the API yourself, ask an agent to read that file and explain the relevant public extension points for the plugin you want. Private PI WEB internals exist for the daring; treat them as experimental surfaces that may graduate into stable helpers, change shape, or disappear.

Develop and debug

  • Keep the source folder outside ~/.pi-web/plugins and symlink it in.
  • After edits, reload or hard-reload the browser tab.
  • Check discovery with the manifest endpoint.
  • Check the browser console if a plugin fails to import or activate.
Check discovered plugins
$ curl http://127.0.0.1:8504/pi-web-plugins/manifest.json

For all contribution types and package metadata, read the Plugin API reference.

Trust model

Plugins are not sandboxed. They run as JavaScript in the browser, can use browser APIs, call documented PI WEB helpers, and render arbitrary UI. If a plugin reaches beyond those helpers into private PI WEB internals, treat that dependency as experimental: it may become stable, change shape, or disappear. Install only plugins you trust.

Plugins do not run inside the session daemon and do not provide server-side hooks.