OpenVCS SDK for npm-based plugin development.
Install this package in plugin projects, scaffold a starter plugin, and package
plugins into .ovcsp bundles. The SDK also exports a Node-only JSON-RPC runtime
layer and shared protocol/types so plugins do not have to hand-roll stdio
framing or method dispatch.
npm install --save-dev @openvcs/sdkThis package installs a local CLI command named openvcs.
One-off usage without adding to a project:
npx --package @openvcs/sdk openvcs --helpThis repository is authored in TypeScript under src/ and compiles runtime files
to bin/ and lib/.
Build the SDK:
npm run buildRun tests (builds first):
npm testRun the local CLI through npm scripts:
npm run openvcs -- --help
npm run openvcs -- build --help
npm run openvcs -- init --help
npm run openvcs -- dist --helpInteractive module plugin scaffold:
openvcs init my-pluginThe generated module template includes TypeScript and Node typings (@types/node).
Plugin IDs entered during scaffold must not be ./.. and must not contain path
separators (/ or \\).
Generated module plugins now export a declarative PluginDefinition plus an
OnPluginStart() hook that the SDK-owned bootstrap calls for them:
import type { PluginModuleDefinition } from '@openvcs/sdk/runtime';
export const PluginDefinition: PluginModuleDefinition = {
plugin: {
async 'plugin.init'(_params, context) {
context.host.info('OpenVCS plugin started');
return null;
},
},
};
export function OnPluginStart(): void {}VCS backends can also derive from VcsDelegateBase and attach exact vcs.*
delegates during startup:
import {
VcsDelegateBase,
type PluginRuntimeContext,
type PluginModuleDefinition,
} from '@openvcs/sdk/runtime';
import type { RequestParams, VcsCapabilities } from '@openvcs/sdk/types';
class ExampleVcsDelegates extends VcsDelegateBase<{ cwd: string }> {
override getCaps(
_params: RequestParams,
_context: PluginRuntimeContext,
): VcsCapabilities {
return {
commits: true,
branches: true,
tags: false,
staging: true,
push_pull: true,
fast_forward: true,
};
}
}
export const PluginDefinition: PluginModuleDefinition = {};
export function OnPluginStart(): void {
const vcs = new ExampleVcsDelegates({ cwd: process.cwd() });
PluginDefinition.vcs = vcs.toDelegates();
}Define ordinary prototype methods such as getCaps() and commitIndex() on the
subclass. toDelegates() maps those camelCase methods to the exact host method
names like vcs.get_caps and vcs.commit_index, and only registers methods
that differ from the SDK base class. Use override with the full params/context
signature so TypeScript checks your subclass against the SDK contract. Base
stubs throw through an internal never-returning helper, which is why concrete
plugins should always implement the methods they intend to expose.
The SDK enforces correct method signatures at compile time. Subclasses that
override with the wrong return type or parameter shape produce a TypeScript error.
The SDK test suite includes test/vcs-delegate-base.types.ts which explicitly
verifies that incompatible overrides (e.g. returning string instead of
VcsCapabilities) fail the compiler under @ts-expect-error. Runtime tests
in test/vcs-delegate-base.test.js cover behavior — not signatures.
Runtime and protocol imports are exposed as npm subpaths:
import { VcsDelegateBase, pluginError } from '@openvcs/sdk/runtime';
import type { PluginDelegates, VcsDelegates } from '@openvcs/sdk/types';The runtime handles stdio framing, JSON-RPC request dispatch, host notifications,
default plugin.* handlers, exact-method delegate registration for vcs.*, and
the generated bin/<module.exec> bootstrap created by openvcs build.
Interactive theme plugin scaffold:
openvcs init --theme my-themeIn a generated code plugin folder:
npm run buildThis runs openvcs build, which executes scripts["build:plugin"], expects your
compiled plugin author module at bin/plugin.js, and then generates the SDK-owned
bin/<module.exec> bootstrap that imports ./plugin.js, applies PluginDefinition,
invokes OnPluginStart(), and starts the runtime.
Theme-only plugins can also run npm run build; the command exits successfully
without producing bin/ output.
In a generated plugin folder:
npm run distThis produces dist/<plugin-id>.ovcsp.
openvcs dist runs openvcs build first unless --no-build is provided.
Use --no-build when packaging prebuilt plugin assets.
Generated code plugin scripts use this split by default:
{
"scripts": {
"build:plugin": "tsc -p tsconfig.json",
"build": "openvcs build",
"dist": "openvcs dist --plugin-dir . --out dist"
}
}For code plugins, reserve bin/plugin.js for the compiled author module and point
module.exec at a different bootstrap filename such as openvcs-plugin.js.
.ovcsp is a gzip-compressed tar archive (tar.gz) that contains a top-level
<plugin-id>/ directory with openvcs.plugin.json and plugin runtime assets.
Bundle contents:
openvcs.plugin.json(required)icon.*(optional, first found by extension priority)bin/(required for code plugins withmodule.exec)entrydirectory (required for UI plugins with top-levelentryfield; the entire directory containing the entry file is bundled)themes/(required for theme plugins)node_modules/(if npm dependencies are bundled)
Dependency behavior while packaging:
- npm dependency bundling is enabled by default when
package.jsonexists. - If
package-lock.jsonis missing, SDK generates it in the staging area (not the plugin worktree). - Dependencies are installed into the bundle staging dir with:
npm ci --omit=dev --ignore-scripts --no-bin-links --no-audit --no-fund
- Disable npm dependency processing with
--no-npm-deps. - Native Node addons (
*.node) are rejected for portable bundles.
Package a plugin manually:
npx openvcs build --plugin-dir /path/to/plugin
npx openvcs dist --plugin-dir /path/to/plugin --out /path/to/distShow command help:
npx openvcs --help
npx openvcs build --help
npx openvcs dist --help
npx openvcs init --helpStable releases are published from .github/workflows/release.yml.
- npm publishes use npm Trusted Publishing (OIDC), so no
NPM_TOKENis required. npm prepackcompiles TypeScript so published packages includebin/andlib/JS outputs.
Copyright © 2025-2026 OpenVCS Contributors. SPDX-License-Identifier: GPL-3.0-or-later