← Back to Plugins
Tools

Carapace Plugin Template

JeffSteinbok By JeffSteinbok 👁 52 views ▲ 0 votes

Starter template for OpenClaw plugins built with carapace-plugin-sdk

GitHub

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

Loading comments...