feat: stabilize Pi Web plugin API

This commit is contained in:
Federico Jaramillo Martinez
2026-05-17 22:46:44 +02:00
parent c77c47c1d5
commit 30995797ea
24 changed files with 764 additions and 496 deletions
+241
View File
@@ -0,0 +1,241 @@
<!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 and develop trusted local Pi Web UI plugins." />
<meta property="og:title" content="Pi Web plugins" />
<meta property="og:image" content="assets/pi-web-banner.png" />
<link rel="icon" href="data:," />
<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 local 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="#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 Pi Web HTTP/WebSocket APIs.</li>
</ul>
<p>
Plugins cannot extend the session daemon or add server-side hooks. They run in the browser UI only.
</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 the reference example because it uses all
current contribution types: one action, one workspace label, and one workspace panel.
</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.js</code> shows the browser module shape.</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>
</section>
<section id="production">
<h2>Production usage</h2>
<p>
Local plugins work with the production npm/systemd 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>