This repository has been archived on 2026-08-23. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
pi-web/docs/plugins.html
T

378 lines
18 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>PI WEB plugins</title>
<meta name="description" content="Use built-in PI WEB plugins and develop trusted local UI plugins." />
<meta property="og:title" content="PI WEB plugins" />
<meta property="og:image" content="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">
<a href="remote-first.html">Remote-first</a>
<a href="install.html">Install</a>
<a href="plugins.html" aria-current="page">Plugins</a>
<a href="faq.html">FAQ</a>
<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>
</nav>
</header>
<main>
<section class="page-hero">
<div class="container">
<p class="eyebrow"><span class="pulse"></span> Plugin development</p>
<h1>Customize PI WEB with UI plugins.</h1>
<p>
Plugins are trusted browser-side ES modules. They can add actions, workspace panels, and compact workspace
labels to the PI WEB UI.
</p>
</div>
</section>
<section class="section compact">
<div class="container doc-layout">
<aside class="toc" aria-label="Plugin page contents">
<strong>On this page</strong>
<a href="#extend">What can be extended</a>
<a href="#ask-ai">What to ask AI to build</a>
<a href="#example">Canonical example</a>
<a href="#built-in-plugins">Built-in plugins</a>
<a href="#manage-plugins">Manage plugins</a>
<a href="#production">Production usage</a>
<a href="#agent-docs">AI-friendly docs</a>
<a href="#develop">Develop and debug</a>
<a href="#trust">Trust model</a>
</aside>
<div class="doc-content">
<section id="extend">
<h2>What can be extended</h2>
<p>Plugins can add small, focused UI extensions to PI WEB:</p>
<ul>
<li><strong>Action palette commands</strong> for custom workflows.</li>
<li><strong>Workspace tools and panels</strong> next to Files, Git, and Terminal.</li>
<li><strong>Workspace labels</strong> in the workspace list, header, and status bar.</li>
<li><strong>Static assets</strong> served from the plugin folder.</li>
<li><strong>Browser-side integrations</strong> using documented PI WEB plugin context helpers.</li>
</ul>
<p>
Plugins cannot extend the session daemon or add server-side hooks. They run in the browser UI only.
PI WEB's internal API routes are not plugin API; use documented context helpers instead.
</p>
<div class="callout">
The plugin API is intentionally limited and actively developed. Feedback is appreciated: if an extension
point is missing, unclear, or awkward, please
<a href="https://github.com/jmfederico/pi-web/issues">open a GitHub issue</a>.
</div>
</section>
<section id="ask-ai">
<h2>What to ask AI to build</h2>
<p>
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.
</p>
<ul>
<li>Show a workspace badge from a repo file, environment file, branch name, container, or dev URL.</li>
<li>Add a workspace panel that summarizes project-specific health, commands, links, or runbooks.</li>
<li>Add action-palette commands for common project workflows or prompts.</li>
<li>Add links to local services, preview deployments, dashboards, CI, logs, or docs.</li>
</ul>
<div class="code-card">
<div class="copy-row">
<strong>Prompt: create a plugin</strong>
<button class="copy-button" data-copy="#plugin-create-prompt">Copy</button>
</div>
<pre id="plugin-create-prompt"><code>Build a PI WEB plugin for this project.
Goal: &lt;describe the UI behavior&gt;.
Before coding, read the PI WEB plugin docs:
https://pi-web.dev/plugins.html
Full API reference:
https://pi-web.dev/plugins.md
Create it as a local plugin under ~/.pi-web/plugins/&lt;plugin-id&gt;.
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.</code></pre>
</div>
<div class="code-card">
<div class="copy-row">
<strong>Prompt: improve a plugin</strong>
<button class="copy-button" data-copy="#plugin-improve-prompt">Copy</button>
</div>
<pre id="plugin-improve-prompt"><code>Improve the PI WEB plugin at &lt;path&gt;.
Before coding, read the PI WEB plugin docs:
https://pi-web.dev/plugins.html
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.</code></pre>
</div>
</section>
<section id="example">
<h2>Canonical example</h2>
<p>
PI WEB ships a real bundled <strong>Info</strong> plugin. It is intentionally small while still using all
core contribution types: one action, one workspace label, and one workspace panel.
</p>
<p>
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. <code>npm run dev:web</code> watches and
rebuilds bundled plugin TS into <code>dist/pi-web-plugins/</code> during development, and <code>npm run build</code>
emits JS before release packaging.
</p>
<ul>
<li><code>pi-web-plugins/info/package.json</code> shows the required metadata shape.</li>
<li><code>pi-web-plugins/info/pi-web-plugin.ts</code> shows the TypeScript source shape.</li>
<li><code>dist/pi-web-plugins/info/pi-web-plugin.js</code> is the built browser module in a checkout.</li>
</ul>
<p>
Read it on GitHub:
<a href="https://github.com/jmfederico/pi-web/tree/main/pi-web-plugins/info">pi-web-plugins/info</a>.
If you copy it, choose a new plugin id so it does not conflict with the bundled <code>info</code> plugin.
</p>
<p>
The bundled <code>updates</code> plugin demonstrates dynamic <code>visible</code> and <code>badge</code>
callbacks for tabs that only appear when the host has status messages or needs extra install visibility.
</p>
</section>
<section id="built-in-plugins">
<h2>Built-in plugins</h2>
<p>
PI WEB ships core, discoverable plugins in the main <code>@jmfederico/pi-web</code> npm package. No
separate <code>pi install</code> step is required: update PI WEB, reload the browser tab, and the bundled
plugins appear in <code>/pi-web-plugins/manifest.json</code>.
</p>
<p>
Built-in plugins can be managed from <strong>Settings → Plugins</strong> or with the top-level
<code>plugins</code> config key.
</p>
<h3>Updates</h3>
<p>
<strong>Updates</strong> adds a conditional <strong>Updates</strong> workspace tab with PI WEB update,
restart, and installed-service guidance. It is built into PI WEB and enabled by default.
</p>
<ul>
<li>Plugin id: <code>updates</code></li>
</ul>
<div class="code-card">
<div class="copy-row">
<strong>Disable Updates</strong>
<button class="copy-button" data-copy="#updates-disable">Copy</button>
</div>
<pre id="updates-disable"><code>{
"plugins": {
"updates": { "enabled": false }
}
}</code></pre>
</div>
<h3>Workspace Tasks</h3>
<p>
<strong>Workspace Tasks</strong> adds a <strong>Tasks</strong> workspace tab for running configured shell
commands in dedicated PI WEB terminals. It is built into PI WEB and enabled by default.
</p>
<ul>
<li>Plugin id: <code>workspace-tasks</code></li>
<li>Config file: <code>.pi-web/tasks.json</code></li>
</ul>
<div class="code-card">
<div class="copy-row">
<strong>Disable Workspace Tasks</strong>
<button class="copy-button" data-copy="#workspace-tasks-disable">Copy</button>
</div>
<pre id="workspace-tasks-disable"><code>{
"plugins": {
"workspace-tasks": { "enabled": false }
}
}</code></pre>
</div>
<div class="code-card">
<div class="copy-row">
<strong>Example .pi-web/tasks.json</strong>
<button class="copy-button" data-copy="#workspace-tasks-config">Copy</button>
</div>
<pre id="workspace-tasks-config"><code>{
"version": 1,
"tasks": [
{
"id": "docker.start",
"title": "Start Docker",
"group": "Docker",
"description": "Start the local Docker Compose environment.",
"command": "./docker/scripts/docker-compose-dev up -d"
},
{
"id": "db.reset",
"title": "Reset DB",
"group": "Database",
"command": "go -C klingit-go run ./cli db reset",
"confirm": true
}
]
}</code></pre>
</div>
<p>
Open a workspace, choose the <strong>Tasks</strong> tab, and click <strong>Run</strong> next to a task.
Commands run in the workspace root because PI WEB creates the terminal for that workspace.
</p>
<p>
Review task configs before running them, especially in shared projects. Workspace Tasks runs trusted
shell commands from your repositories.
</p>
</section>
<section id="manage-plugins">
<h2>Manage plugins</h2>
<p>
Open <strong>Settings → Plugins</strong> to review discovered bundled, local, dev, and Pi package plugins.
PI WEB can disable any discovered 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.
</p>
<div class="code-card">
<div class="copy-row">
<strong>Plugin config shape</strong>
<button class="copy-button" data-copy="#plugin-config-shape">Copy</button>
</div>
<pre id="plugin-config-shape"><code>{
"plugins": {
"workspace-tasks": {
"enabled": true,
"settings": {}
},
"info": {
"enabled": false
}
}
}</code></pre>
</div>
<p>
Plugins are enabled by default. Set <code>enabled</code> to <code>false</code> to remove a plugin from
<code>/pi-web-plugins/manifest.json</code> so it is not imported or activated on the next page load.
The optional <code>settings</code> object is reserved for plugin-specific settings.
</p>
<p>
After changing plugin enablement, reload the PI WEB browser tab. Already-loaded plugin JavaScript is not
unloaded from the current page.
</p>
</section>
<section id="production">
<h2>Production usage</h2>
<p>
Local plugins work with the production native-service install. Put each plugin under
<code>~/.pi-web/plugins/&lt;plugin-id&gt;/</code>, or symlink it there while developing. No PI WEB rebuild or
session-daemon restart is required.
</p>
<div class="callout warning">
If <code>PI_WEB_DATA_DIR</code> is set, use <code>$PI_WEB_DATA_DIR/plugins</code> instead of
<code>~/.pi-web/plugins</code>.
</div>
<div class="code-card">
<div class="copy-row">
<strong>Install a local plugin folder</strong>
<button class="copy-button" data-copy="#plugin-symlink">Copy</button>
</div>
<pre id="plugin-symlink"><code><span class="prompt">$</span> mkdir -p ~/.pi-web/plugins
<span class="prompt">$</span> ln -s /path/to/plugin-folder ~/.pi-web/plugins/plugin-id</code></pre>
</div>
</section>
<section id="agent-docs">
<h2>AI-friendly docs</h2>
<p>
The full plugin reference is available as Markdown for AI agents to read, fetch, and follow:
<a href="plugins.md">plugins.md</a>.
</p>
<p>
If you want to understand the API yourself, ask an agent to read that file and explain the relevant
extension points for the plugin you want. The Markdown reference also marks which context fields are
stable and which PI WEB internals should be avoided unless necessary.
</p>
</section>
<section id="develop">
<h2>Develop and debug</h2>
<ul>
<li>Keep the source folder outside <code>~/.pi-web/plugins</code> and symlink it in.</li>
<li>After edits, reload or hard-reload the browser tab.</li>
<li>Check discovery with the manifest endpoint.</li>
<li>Check the browser console if a plugin fails to import or activate.</li>
</ul>
<div class="code-card">
<div class="copy-row">
<strong>Check discovered plugins</strong>
<button class="copy-button" data-copy="#plugin-manifest">Copy</button>
</div>
<pre id="plugin-manifest"><code><span class="prompt">$</span> curl http://127.0.0.1:8504/pi-web-plugins/manifest.json</code></pre>
</div>
<p>
For all contribution types and package metadata, read the
<a href="plugins.md">Plugin API reference</a>.
</p>
</section>
<section id="trust">
<h2>Trust model</h2>
<p>
Plugins are not sandboxed. They run as JavaScript in the browser, can call PI WEB APIs available to the
current session, and can render arbitrary UI. Install only plugins you trust.
</p>
<p>
Plugins do not run inside the session daemon and do not provide server-side hooks.
</p>
</section>
</div>
</div>
</section>
</main>
<footer class="site-footer">
<div class="container footer-inner">
<span>PI WEB plugin docs</span>
<div class="footer-links">
<a href="./">Home</a>
<a href="remote-first.html">Remote-first</a>
<a href="install.html">Install</a>
<a href="faq.html">FAQ</a>
<a href="https://github.com/jmfederico/pi-web">GitHub</a>
</div>
</div>
</footer>
<script src="site.js"></script>
</body>
</html>