Quick start
Install @harborclient/sdk first — see Install.
Renderer entry
import type { PluginContext } from '@harborclient/sdk';
export function activate(hc: PluginContext): void {
hc.subscriptions.push(
hc.http.onAfterSend(async (request, response) => {
// react to completed requests without a main entry
})
);
}Do not bundle react / react-dom in your plugin bundle. For JSX setup, esbuild flags, and hook imports, see React and JSX.
Main entry
Main entries run in the SES utilityProcess for HTTP hooks and custom IPC — not for React UI. Import MainPluginContext from @harborclient/sdk/main:
import type { MainPluginContext } from '@harborclient/sdk/main';
export function activate(hc: MainPluginContext): void {
hc.subscriptions.push(
hc.http.onBeforeSend((request) => {
request.headers['X-Trace'] = '1';
})
);
}See Main API for HTTP hooks and IPC, and Building to package your plugin as .hcp.
Utility imports
Shared helpers ship as subpath exports (requires @harborclient/sdk 0.3.1+):
import { copyToClipboard } from '@harborclient/sdk/clipboard';
import { resolveRequest } from '@harborclient/sdk/http';
import { randomId, truncateBody } from '@harborclient/sdk/runtime-utils';
import {
asRecord,
bool,
createCappedList,
mergeById,
num,
oneOf,
recordOf,
str
} from '@harborclient/sdk/storage';
import { createExternalStore } from '@harborclient/sdk/store';
import { formatRelativeTime, methodColorClass } from '@harborclient/sdk/ui';Plugin build and tooling baseline
Requires @harborclient/sdk 0.7.0+. Shared config reduces drift across plugins.
Renderer build (@harborclient/sdk/build)
Add scripts/build.mjs:
import { buildRenderer } from '@harborclient/sdk/build';
await buildRenderer({
jsxRuntime: 'runtime', // 'host' | 'runtime' | 'automatic' | 'none'
watch: process.argv.includes('--watch')
});Point package.json at node scripts/build.mjs (and node scripts/build.mjs --watch for dev).
Use jsxRuntime: 'host' when bundling third-party React libraries (CodeMirror, Font Awesome). Use nodeBuiltinStubsPlugin(['path', 'fs']) from the same export when a dependency imports unused Node built-ins (see the dotenv plugin).
TypeScript (@harborclient/sdk/tsconfig.base.json)
{
"extends": "@harborclient/sdk/tsconfig.base.json",
"include": ["src"]
}ESLint (@harborclient/sdk/eslint)
eslint.config.mjs:
export { default } from '@harborclient/sdk/eslint';Your plugin still needs eslint as a devDependency; the preset pulls shared rules from the SDK.