Tools
Carapace Plugin Sdk
SDK for building OpenClaw plugins โ types, helpers, CLI generation
Install
npm install carapace-plugin-sdk
Configuration Example
{
"bin": {
"my-plugin": "./dist/bin/my-plugin.js"
},
"scripts": {
"build": "tsup && carapace-generate-cli --entry ./dist/index.js --out ./dist/bin"
}
}
README
# ๐ฆ carapace-plugin-sdk
SDK for building [OpenClaw](https://github.com/JeffSteinbok/octo-docs) plugins โ types, helpers, and automatic CLI generation.
Write your plugin logic once. Get an OpenClaw plugin **and** a standalone CLI tool โ for free.
## Install
```bash
npm install carapace-plugin-sdk
```
## What's included
| Export | What it does |
|--------|-------------|
| `PluginApi` | Type for the OpenClaw plugin registration API |
| `PluginEntry` | Type for `createEntry()` return shape |
| `PluginTool` | Type for a registered tool |
| `formatResult()` | Wraps data in the standard OpenClaw result format |
| `createAdapter()` | Creates the SDK adapter (handles optional `openclaw` peer dep) |
| `run()` | CLI runtime โ turns any plugin into a CLI tool |
| `carapace-generate-cli` | Build-time CLI entry point generator |
## Plugin structure
Every plugin built with Carapace follows this structure:
```
my-plugin/
โโโ src/
โ โโโ handlers.ts โ Pure business logic (your code)
โ โโโ index.ts โ createEntry() โ registers tools
โ โโโ adapter.ts โ One-liner SDK adapter
โโโ tests/
โ โโโ index.test.ts
โโโ openclaw.plugin.json
โโโ package.json
โโโ tsconfig.json
โโโ tsup.config.ts
โโโ vitest.config.ts
```
## Quick start
### `src/handlers.ts` โ Your logic
```ts
export interface MyConfig {
apiKey?: string;
}
export async function greet(name: string): Promise<string> {
return `Hello, ${name}! ๐ฆ`;
}
```
### `src/index.ts` โ Plugin registration
```ts
import { Type } from "@sinclair/typebox";
import { type PluginApi, formatResult } from "carapace-plugin-sdk";
import { greet } from "./handlers.js";
export function createEntry() {
return {
id: "my-plugin",
name: "My Plugin",
description: "Does something cool",
configSchema: { type: "object" as const, additionalProperties: false, properties: {} },
register(api: PluginApi) {
api.registerTool({
name: "greet",
label: "Greet",
description: "Say hello",
parameters: Type.Object({
name: Type.String({ description: "Name to greet" }),
}),
async execute(_id: string, params: Record<string, unknown>) {
return formatResult(await greet(params.name as string));
},
});
},
};
}
```
### `src/adapter.ts` โ SDK bridge
```ts
import { createAdapter } from "carapace-plugin-sdk";
import { createEntry } from "./index.js";
export default createAdapter(createEntry(), import.meta.url);
```
## CLI generation
Every plugin can also run as a standalone CLI โ without writing any CLI-specific code.
### Setup
Add to your `package.json`:
```json
{
"bin": {
"my-plugin": "./dist/bin/my-plugin.js"
},
"scripts": {
"build": "tsup && carapace-generate-cli --entry ./dist/index.js --out ./dist/bin"
}
}
```
### Usage
```bash
npm run build
node dist/bin/my-plugin.js --help
node dist/bin/my-plugin.js greet World
node dist/bin/my-plugin.js greet World --json
```
### How it works
1. **Build time**: `carapace-generate-cli` imports your `createEntry()`, captures tool definitions, and emits a CLI entry point
2. **Run time**: Each registered tool becomes a subcommand with automatic arg parsing, `--help`, `--json` output, and env var config mapping
### Config via environment variables
When running as a CLI, config comes from env vars:
```
<PLUGIN_PREFIX>_<FIELD_NAME_IN_SCREAMING_SNAKE>
```
For example, plugin `stock-quotes` with `configSchema.properties.finnhubApiKey`:
- Env var: `STOCK_QUOTES_FINNHUB_API_KEY`
## Template
Use [carapace-plugin-template](https://github.com/JeffSteinbok/carapace-plugin-template) to scaffold a new plugin with all the boilerplate pre-configured.
## License
MIT
tools
Comments
Sign in to leave a comment