CloudCLI Cloud · Discord · Bug Reports · Plugin Docs
This plugin scans the currently selected project and shows file counts, lines of code, a file-type breakdown chart, largest files, and recently modified files.
It demonstrates the full plugin API — frontend rendering with live context updates and a Node.js backend server with RPC communication. Fork this repo to build your own plugin.
For a complete guide to the plugin system, see the Plugin Overview.
From git (recommended): Open Settings > Plugins in CloudCLI UI, paste this repository's URL, and click Install. The repo is cloned, dependencies are installed, TypeScript is compiled, and the plugin is ready to enable.
Manual: Clone or copy this repository into your plugins directory:
git clone https://github.com/cloudcli-ai/cloudcli-plugin-starter.git ~/.claude-code-ui/plugins/project-stats
cd ~/.claude-code-ui/plugins/project-stats
npm install
npm run buildThen open Settings > Plugins — "Project Stats" should appear. Enable it to add the tab.
project-stats/
manifest.json # Required — plugin metadata
package.json # Dependencies and build script
tsconfig.json # TypeScript configuration
src/
types.ts # Plugin API type definitions
index.ts # Frontend entry point (ES module)
server.ts # Backend entry point (Node.js subprocess)
dist/ # Compiled output (auto-generated, not committed)
index.js # Compiled frontend — referenced by manifest "entry"
server.js # Compiled backend — referenced by manifest "server"
icon.svg # Custom SVG icon for the tab
Plugins are TypeScript modules compiled to ES modules. The host calls your exported mount(container, api) function when the plugin tab is activated and unmount(container) when it is torn down.
Plugins that need server-side logic can declare a "server" entry in their manifest. The host spawns it as a child process and proxies requests to it via api.rpc().
┌─────────────────────────────────────────────────────┐
│ CloudCLI UI Host │
│ │
│ Plugin subprocess (dist/server.js): │
│ Runs as a child process with restricted env │
│ Listens on random local port │
│ Receives secrets via X-Plugin-Secret-* headers │
└───────────┬─────────────────────────┬───────────────┘
│ serves static files │ proxies RPC
┌───────────▼─────────────────────────▼───────────────┐
│ Frontend (browser) │
│ │
│ Plugin module (dist/index.js) │
│ import(url) → mount(container, api) │
│ api.context — theme / project / session │
│ api.onContextChange — subscribe to changes │
│ api.rpc(method, path, body) → Promise │
└─────────────────────────────────────────────────────┘
This plugin is written in TypeScript. The src/types.ts file contains full type definitions for the plugin API (PluginAPI, PluginContext, PluginModule). Copy this file into your own plugin for type-safe development.
Build: npm run build compiles src/ → dist/ via tsc.
Watch: npm run dev recompiles on file changes.
When installing via Settings > Plugins, the host automatically runs npm install and npm run build — no manual build step needed.
The host dynamically imports your compiled entry file and calls mount(container, api). Render any UI inside the container — plain HTML, styled components, charts, dashboards, anything you can build with vanilla JavaScript and the DOM.
import type { PluginAPI, PluginContext } from './types.js';
export function mount(container: HTMLElement, api: PluginAPI): void {
const ctx: PluginContext = api.context;
container.innerHTML = `<p>Hello! Theme: ${ctx.theme}</p>`;
const unsub = api.onContextChange((ctx) => {
container.style.background = ctx.theme === 'dark' ? '#111' : '#fff';
});
(container as any)._cleanup = unsub;
}
export function unmount(container: HTMLElement): void {
(container as any)._cleanup?.();
container.innerHTML = '';
}interface PluginContext {
theme: 'dark' | 'light';
project: { name: string; path: string } | null;
session: { id: string; title: string } | null;
}const data = await api.rpc('GET', '/stats?path=/my/project');
const result = await api.rpc('POST', '/echo', { greeting: 'hi' });Plugins that need filesystem access, external APIs, npm packages, or persistent state can declare a "server" entry in their manifest. The host manages the lifecycle:
- When the plugin is enabled, the host spawns
node dist/server.js - The subprocess must print a JSON line to stdout:
{"ready": true, "port": 12345} - The host proxies requests from
api.rpc()to that port - When the plugin is disabled or uninstalled, the host sends SIGTERM
Per-plugin secrets are configured in Settings > Plugins and injected as HTTP headers on every proxied request (x-plugin-secret-<name>). They are never stored in the subprocess environment.
The subprocess runs with a minimal env — only PATH, HOME, NODE_ENV, and PLUGIN_NAME. It does not inherit the host's API keys or other secrets.
Plugins cannot:
- Modify built-in tabs or appear outside the tab area
- Interact with Claude's chat system
- Communicate with other plugins
- Access authentication tokens or intercept requests
Plugins run at your own risk. A plugin's frontend code executes in the same JavaScript context as the host application — there is no runtime sandbox. Only install plugins whose source code you have reviewed or that come from authors you trust.
CloudCLI follows a trust-through-transparency model: plugins are installed from git repositories with visible source, not from an anonymous marketplace. You are responsible for reviewing plugin code before installing.
Frontend — Plugin modules run in the same JS context as the host and only receive the api object. All server communication goes through api.rpc(). However, because there is no runtime sandbox, a malicious plugin could in principle reach beyond the provided API.
Backend — The subprocess runs as a separate OS process with restricted env, per-call secret injection via headers, and process-level isolation. Auth headers are stripped before proxying.
Install-time — npm postinstall scripts are blocked (--ignore-scripts). Ship pre-built or use packages that work without postinstall hooks. The npm run build step is run automatically after install.
If you've built a plugin and would like it added to the official CloudCLI UI plugin repository, open an issue with a link to your plugin's repository. The team will review it for inclusion.
MIT

{ "name": "project-stats", // Unique id — alphanumeric, hyphens, underscores "displayName": "Project Stats", // Shown in the UI "version": "1.0.0", "description": "Short description shown in settings.", "author": "Your Name", "icon": "icon.svg", // Custom SVG icon "type": "module", // Must be "module" "slot": "tab", // Where the plugin appears — only "tab" today "entry": "dist/index.js", // Compiled frontend entry file "server": "dist/server.js", // Optional — compiled backend entry file "permissions": [] // Reserved for future use }