carapace-plugin-sdk
v1.0.3
Published
π¦π SDK for building OpenClaw plugins β types, helpers, CLI generation
Downloads
668
Maintainers
Readme
π¦π carapace-plugin-sdk
SDK for building OpenClaw plugins.
Define your tools and config. The SDK generates a fully typed OpenClaw plugin, a standalone CLI, and a plugin manifest β automatically.
Install
npm install carapace-plugin-sdkQuick start
New plugin? Use carapace-plugin-template β it scaffolds the full project structure, CI, and tests in one click.
Here's what you write in src/plugin.ts:
import { definePlugin } from "carapace-plugin-sdk";
import { Type } from "@sinclair/typebox";
// The export must be named `createEntry` β the SDK's build tools look for it by name.
export const createEntry = definePlugin({
id: "my-plugin",
name: "My Plugin",
description: "Does something useful.",
configSchema: Type.Object({
apiKey: Type.Optional(Type.String({ description: "API key for the service." })),
}),
tools: (tool) => [
tool({
name: "do_thing",
description: "Does the thing.",
parameters: Type.Object({
input: Type.String({ description: "Input value." }),
}),
execute: async ({ input }, config) => {
// input: string β config.apiKey: string | undefined β
return { result: input, usingKey: !!config.apiKey };
},
}),
],
});Run npm run build and you get:
| Generated file | What it is |
|----------------|-----------|
| dist/adapter.js | OpenClaw plugin adapter |
| dist/bin/my-plugin.js | Standalone CLI β each tool is a subcommand |
| openclaw.plugin.json | Plugin manifest read by OpenClaw at install time |
Nothing else to write. No registration boilerplate, no result wrapping, no manifest to maintain.
What the SDK handles for you
| You write | SDK handles |
|-----------|-------------|
| execute() returning a plain object | Wrapping in the OpenClaw result format |
| configSchema TypeBox schema | JSON Schema for the manifest + OpenClaw settings UI (defaults to an empty object schema if omitted) |
| Tool names | contracts.tools list in the manifest β auto-discovered even for raw register() plugins |
| src/plugin.ts | dist/adapter.js, dist/bin/*.js, openclaw.plugin.json |
Build setup
Add to package.json:
{
"bin": { "my-plugin": "./dist/bin/my-plugin.js" },
"scripts": {
"build": "tsup && carapace-generate-cli --entry ./dist/plugin.js --out ./dist/bin"
}
}The SDK ships shared configs so your project files stay minimal:
tsconfig.json β one line:
{ "extends": "carapace-plugin-sdk/tsconfig.base.json" }tsup.config.ts β three lines:
import { defineConfig } from "tsup";
import { definePluginConfig } from "carapace-plugin-sdk/tsup";
export default defineConfig(definePluginConfig());vitest.config.ts β not needed. Vitest finds tests/**/*.test.ts without configuration.
CLI β for free
Every plugin is automatically a standalone CLI. After npm run build:
my-plugin --help
my-plugin do-thing "hello"
my-plugin do-thing "hello" --json
MY_PLUGIN_API_KEY=sk-... my-plugin do-thing "hello"Config fields map to environment variables:
<PLUGIN_ID_SCREAMING_SNAKE>_<FIELD_SCREAMING_SNAKE>
Reusable CI/CD workflows
Call the shared GitHub Actions workflows from your plugin repo β no workflow logic to copy:
# .github/workflows/ci.yml
jobs:
ci:
uses: JeffSteinbok/carapace-plugin-sdk/.github/workflows/plugin-ci.yml@main# .github/workflows/release.yml
on:
workflow_dispatch:
inputs:
version-bump:
type: choice
options: [patch, minor, major]
prerelease:
type: choice
options: ['', alpha, beta, rc]
jobs:
release:
uses: JeffSteinbok/carapace-plugin-sdk/.github/workflows/plugin-release.yml@main
with:
version-bump: ${{ inputs.version-bump }}
prerelease: ${{ inputs.prerelease }}
secrets:
npm-token: ${{ secrets.NPM_TOKEN }}Examples
- carapace-plugin-template β starter template with CI, tests, and build pre-configured
- carapace-stock-quotes β real plugin with multiple data sources (Yahoo Finance + Finnhub)
Internals
See ARCHITECTURE.md for how the SDK works under the hood β the type machinery behind definePlugin, how carapace-generate-cli generates artifacts, the CLI runtime, and the adapter pattern.
License
MIT
