Building
Build output is what HarborClient loads at runtime. Your plugin source can live in TypeScript, JSX, or plain JavaScript, but the plugin folder must contain a manifest.json at the root and bundled files under paths referenced by that manifest, usually dist/renderer.js and optionally dist/main.js.
HarborClient does not ship a plugin SDK runtime or build step. Use your plugin project's own package.json scripts to install tools, bundle source files, and create the .hcp archive when you are ready to distribute.
Recommended project setup
Create a plugin project folder, then put manifest.json and package.json next to each other at the folder root. The manifest tells HarborClient which built files to load. The package.json is only for your development toolchain: dependencies, pnpm scripts, and packaging commands.
For example, a renderer plugin can start with this layout:
request-logger/
├── manifest.json
├── package.json
├── README.md
├── src/
│ └── renderer.tsx
└── dist/Reference the built renderer file from manifest.json:
{
"id": "com.example.request-logger",
"name": "Request Logger",
"version": "1.0.0",
"renderer": "dist/renderer.js",
"permissions": ["ui", "storage"]
}Then add build scripts to the root package.json:
{
"name": "request-logger",
"private": true,
"type": "module",
"devDependencies": {
"@harborclient/sdk": "^0.2.0",
"@types/react": "^19.0.0",
"esbuild": "^0.25.0",
"typescript": "^5.0.0"
},
"scripts": {
"build": "pnpm build:renderer",
"build:renderer": "esbuild src/renderer.tsx --bundle --outfile=dist/renderer.js --format=esm --jsx=automatic --jsx-import-source=@harborclient/sdk --external:react --external:react-dom",
"dev": "pnpm build:renderer --watch",
"pack:hcp": "pnpm build && zip -r ../request-logger.hcp manifest.json README.md dist"
}
}For renderer plugins, mark react and react-dom as external and set --jsx=automatic --jsx-import-source=@harborclient/sdk. The host installs the shared React instance before activate(hc) runs. See React.
Build with pnpm
Install dependencies once from your plugin folder:
cd request-logger
pnpm installBuild the plugin code whenever src/ changes:
pnpm buildThat command writes the files HarborClient loads from dist/. A renderer-only plugin usually needs dist/renderer.js. A plugin with background logic also needs dist/main.js and a matching "main" field in manifest.json.
During development, run the watch script in your plugin checkout:
pnpm devWhen the plugin is loaded unpacked, HarborClient watches the built entry files referenced by the manifest. Rebuilding dist/renderer.js or dist/main.js triggers a plugin reload. See Dev workflow for the full hot-reload loop.
Main entry
Only add a main entry when the plugin needs HTTP hooks, custom IPC handlers, script orchestration, or other background work. Main entries run in the SES utilityProcess; keep React UI code in the renderer entry.
Add the built file to manifest.json:
{
"renderer": "dist/renderer.js",
"main": "dist/main.js",
"permissions": ["ui", "http", "ipc"]
}Then include build:main in the main build command:
{
"scripts": {
"build": "pnpm build:renderer && pnpm build:main",
"build:renderer": "esbuild src/renderer.tsx --bundle --outfile=dist/renderer.js --format=esm --jsx=automatic --jsx-import-source=@harborclient/sdk --external:react --external:react-dom",
"build:main": "esbuild src/main.ts --bundle --outfile=dist/main.js --format=esm --platform=neutral"
}
}Main and renderer entries both export activate(hc). Use renderer code for contributed panels, tabs, and other UI. Use main code for long-lived background registrations such as hc.http.onBeforeSend.
Serve or package the plugin
For local development, serve the plugin directly from its git checkout as an unpacked plugin. Build once so dist/ exists, then choose File → Plugins → Install → Load unpacked… and select the plugin project folder containing manifest.json. You can also register the path when launching HarborClient from the app checkout:
HARBOR_PLUGINS_DEV=~/projects/request-logger pnpm devFor distribution, create a ZIP archive and use the .hcp extension:
cd request-logger
pnpm pack:hcpThe pack:hcp script shown above runs pnpm build and writes ../request-logger.hcp with manifest.json, README.md, and dist/. You can also build request-logger.zip and rename it to request-logger.hcp; HarborClient treats both the same way at install time as long as the contents are a valid plugin layout.
Before sharing a packaged plugin, sign the built plugin directory with an Ed25519 key so users can verify file integrity. See Signing for key generation, CLI usage, and the signature.json format.
See Package layout for the expected directory structure and Dev workflow for iterative development with unpacked loading.
