Skip to content

Open-VCS/OpenVCS-SDK

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

154 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@openvcs/sdk

Nightly Dev Stable

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.

Install

npm install --save-dev @openvcs/sdk

This package installs a local CLI command named openvcs.

One-off usage without adding to a project:

npx --package @openvcs/sdk openvcs --help

SDK development

This repository is authored in TypeScript under src/ and compiles runtime files to bin/ and lib/.

Build the SDK:

npm run build

Run tests (builds first):

npm test

Run the local CLI through npm scripts:

npm run openvcs -- --help
npm run openvcs -- build --help
npm run openvcs -- init --help
npm run openvcs -- dist --help

Scaffold a plugin

Interactive module plugin scaffold:

openvcs init my-plugin

The 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.

Compile-time override safety

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-theme

Build plugin assets

In a generated code plugin folder:

npm run build

This 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.

Build a .ovcsp bundle

In a generated plugin folder:

npm run dist

This 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 with module.exec)
  • entry directory (required for UI plugins with top-level entry field; 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.json exists.
  • If package-lock.json is 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.

CLI usage

Package a plugin manually:

npx openvcs build --plugin-dir /path/to/plugin
npx openvcs dist --plugin-dir /path/to/plugin --out /path/to/dist

Show command help:

npx openvcs --help
npx openvcs build --help
npx openvcs dist --help
npx openvcs init --help

Releases

Stable releases are published from .github/workflows/release.yml.

  • npm publishes use npm Trusted Publishing (OIDC), so no NPM_TOKEN is required.
  • npm prepack compiles TypeScript so published packages include bin/ and lib/ JS outputs.

License

Copyright © 2025-2026 OpenVCS Contributors. SPDX-License-Identifier: GPL-3.0-or-later

About

Plugin development toolkit for OpenVCS. Provides build, validation, and packaging support for plugins. Experimental and may change.

Topics

Resources

License

Stars

Watchers

Forks

Contributors