Tools
Carapace Plugin Template
Starter template for OpenClaw plugins built with carapace-plugin-sdk
Install
npm install
npm
README
# ๐ฆ carapace-plugin-template
A template for building [OpenClaw](https://github.com/JeffSteinbok/octo-docs) plugins using the [Carapace SDK](https://github.com/JeffSteinbok/carapace-plugin-sdk).
Click **"Use this template"** on GitHub to create your own plugin repo.
## Getting started
1. Click **"Use this template"** โ **"Create a new repository"**
2. Clone your new repo
3. Find and replace `my-plugin` / `My Plugin` with your plugin's name
4. Update `openclaw.plugin.json` with your plugin's metadata
5. Write your logic in `src/handlers.ts`
6. Register your tools in `src/index.ts`
```bash
npm install
npm run build
npm test
```
## Project structure
```
my-plugin/
โโโ src/
โ โโโ handlers.ts โ Pure business logic (your code lives here)
โ โโโ index.ts โ createEntry() โ registers tools with OpenClaw
โ โโโ adapter.ts โ SDK adapter (you rarely touch this)
โโโ tests/
โ โโโ index.test.ts โ Tests (vitest)
โโโ openclaw.plugin.json โ Plugin metadata for OpenClaw
โโโ package.json
โโโ tsconfig.json
โโโ tsup.config.ts
โโโ vitest.config.ts
```
### How the layers work
| Layer | File | What goes here |
|-------|------|----------------|
| **Logic** | `handlers.ts` | Pure functions. No framework deps. Easily testable. |
| **Plugin** | `index.ts` | `createEntry()` โ wires handlers into OpenClaw's `registerTool()` API |
| **Adapter** | `adapter.ts` | One-liner that wraps with optional OpenClaw SDK. Don't edit. |
The key idea: **handlers.ts knows nothing about OpenClaw**. It's just TypeScript functions that take input and return output. The plugin shim in `index.ts` handles all the OpenClaw wiring.
## Writing your plugin
### 1. Define your handlers
In `src/handlers.ts`, write pure functions for your business logic:
```ts
export interface MyConfig {
apiKey: string;
}
export async function fetchData(config: MyConfig, query: string): Promise<DataResult> {
// Your logic here โ API calls, data processing, etc.
}
```
### 2. Register tools
In `src/index.ts`, register each handler as an OpenClaw tool:
```ts
import { Type } from "@sinclair/typebox";
import { type PluginApi, formatResult } from "carapace-plugin-sdk";
import { fetchData } from "./handlers.js";
export function createEntry() {
return {
id: "my-plugin",
name: "My Plugin",
description: "Does something useful",
configSchema: { /* ... */ },
register(api: PluginApi) {
api.registerTool({
name: "fetch_data",
label: "Fetch Data",
description: "Fetches data from the service.",
parameters: Type.Object({
query: Type.String({ description: "Search query" }),
}),
async execute(_id: string, params: Record<string, unknown>) {
return formatResult(await fetchData(config, params.query as string));
},
});
},
};
}
```
### 3. Write tests
Tests follow a simple pattern โ create a mock API, register tools, and call `execute()`:
```ts
const { createEntry } = await import("../src/index.js");
const entry = createEntry();
const tools = {};
entry.register({
registerTool: (t) => { tools[t.name] = t; },
pluginConfig: {},
});
const result = await tools["fetch_data"].execute("id", { query: "test" });
```
## CLI support
Your plugin is automatically a standalone CLI tool โ no extra code needed.
After building, run:
```bash
node dist/bin/my-plugin.js --help
node dist/bin/my-plugin.js greet World
node dist/bin/my-plugin.js greet World --json
```
### Config via environment variables
When running as a CLI, config comes from env vars instead of OpenClaw config:
```
<PLUGIN_PREFIX>_<FIELD_NAME_IN_SCREAMING_SNAKE>
```
For example, if your plugin id is `my-plugin` and you have a config field `apiKey`:
- Env var: `MY_PLUGIN_API_KEY`
## Checklist
- [ ] Replace `my-plugin` / `My Plugin` everywhere
- [ ] Update `openclaw.plugin.json` with real metadata
- [ ] Write handlers in `src/handlers.ts`
- [ ] Register tools in `src/index.ts`
- [ ] Update `configSchema` if your plugin needs config
- [ ] Write tests
- [ ] `npm run build` succeeds
- [ ] `npm test` passes
- [ ] `node dist/bin/<name>.js --help` works
## License
MIT
tools
Comments
Sign in to leave a comment