Files
claudecodeui/examples/plugins/hello-world/server.js
simosmik 2588851746 feat(plugins): add backend subprocess support via RPC bridge
Extend the plugin system so plugins can optionally declare a
entry in their manifest. The host spawns a Node.js subprocess for that
script, assigns it a random local port, and exposes an RPC proxy route
() that the sandboxed iframe can call via
postMessage — avoiding the need for the iframe to hold auth tokens.

Changes:
- Add plugin process manager to spawn/stop server subprocesses
- Wire subprocess lifecycle into enable/disable and uninstall routes
- Add RPC proxy route on the host server
- Extend PluginsContext and PluginTabContent to handle ccui:rpc and
  ccui:rpc-response postMessage events
- Add hello-world server.js as a reference subprocess implementation
- Update manifest.json and README with server field documentation
2026-03-05 11:58:04 +00:00

43 lines
1.1 KiB
JavaScript

const http = require('http');
let requestCount = 0;
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'application/json');
// Secrets are injected by the host as X-Plugin-Secret-* headers
const apiKey = req.headers['x-plugin-secret-apikey'];
if (req.method === 'GET' && req.url === '/hello') {
requestCount++;
res.end(JSON.stringify({
message: 'Hello from the plugin server!',
requestCount,
hasApiKey: Boolean(apiKey),
timestamp: new Date().toISOString(),
}));
return;
}
if (req.method === 'POST' && req.url === '/echo') {
let body = '';
req.on('data', (chunk) => { body += chunk; });
req.on('end', () => {
let parsed;
try { parsed = JSON.parse(body); } catch { parsed = body; }
res.end(JSON.stringify({ echo: parsed }));
});
return;
}
res.writeHead(404);
res.end(JSON.stringify({ error: 'Not found' }));
});
// Listen on a random available port
server.listen(0, '127.0.0.1', () => {
const { port } = server.address();
// Signal readiness to the host — this JSON line is required
console.log(JSON.stringify({ ready: true, port }));
});