plugin-builder
# ClaudeWave: Plugin Builder Plugin Builder guides users through building and shipping Vellum plugins end-to-end, from scaffolding the directory structure and wiring imports against the plugin API to packaging manifests and publishing to the marketplace. Use this skill when a user wants to bundle hooks, tools, and skills into an installable plugin package, publish existing capabilities to the marketplace, or deploy updates to a plugin's GitHub repository.
git clone --depth 1 https://github.com/vellum-ai/vellum-assistant /tmp/plugin-builder && cp -r /tmp/plugin-builder/skills/plugin-builder ~/.claude/skills/plugin-builderSKILL.md
# Plugin Builder
You guide the user through building a Vellum plugin end to end: deciding what surfaces they need, scaffolding the directory, wiring imports against `@vellumai/plugin-api`, packaging the manifest, and shipping the plugin through the marketplace catalog.
Plugins are in beta. The peer-dep range you declare is what gets you load. Treat everything you write in this skill as something that can break between Vellum releases until 1.0 ships, and pin a real range.
## When to use this skill
USE THIS SKILL WHEN:
- The user wants to build a plugin for their assistant, even if they have not said "plugin" by name. Any "extend my assistant so it can do X automatically" request that implies shipping a capability is in scope.
- The user has existing skills, hooks, or tools scattered in their workspace and wants to bundle them.
- The user wants to publish a GitHub repo into the Vellum plugin marketplace.
- The user is exploring the surfaces (hooks, tools, skills) for the first time and needs a guided scaffold.
DO NOT use this skill when:
- The user only wants to install a plugin (`assistant plugins install <name>` is a 30-second CLI call, no skill needed).
- The user only wants a single SKILL.md authored (skill-management is the right skill).
- The user wants to add a webhook or user route (`assistant routes` is the right skill).
- The user wants to write a one-off TypeScript file the assistant should execute inline (no packaging needed).
## Before you write a single file
Ask before building. Five questions, in this order. Stop if the user is unclear on any of them.
1. **What job does the plugin do?** One sentence, plain language. If you cannot write this, the plugin should not be built yet.
2. **Which surfaces does it ship?** Tools (model calls), hooks (lifecycle transforms), and skills (on-demand instructions) are the three. Most plugins ship one or two, not all three.
3. **Does it need credentials?** An API key, OAuth token, or webhook secret is not a value that belongs in a `.ts` file. Anything sensitive gets declared in the manifest and resolved at `init` time.
4. **Where will the source live?** A GitHub repo, ideally under the user's own namespace. The marketplace entry pins to a full commit SHA.
5. **Is the user writing TypeScript or compiling ahead?** In-repo Bun/Node compile on daemon start is the default. If they want a different build, ask now.
You have an alignment problem if the user cannot answer questions 1 and 2. Push back and clarify before scaffolding. The most expensive waste of plugin-authoring time is building a plugin whose job is fuzzy.
✓ Checkpoint: alignment on job and surfaces locked before continuing.
## Mental model
A plugin is a directory with a manifest and zero or more surface subdirectories. The host walks the directory on load and discovers what the plugin contributes. Missing directories are silently skipped, so a plugin contributes only what it ships. A broken surface file fails only itself; sibling plugins keep loading.
| Surface | Lives in | When it fires |
| ------- | ----------------- | ------------------------------------------------------------------------------------------------------------- |
| Tools | `tools/<name>.ts` | When the model decides to call the tool. |
| Hooks | `hooks/<name>.ts` | At fixed lifecycle events (init, user-prompt-submit, pre/post-model-call, post-tool-use, post-compact, stop). |
| Skills | `skills/<name>/` | When the conversation matches the skill's `description` and activation hints. |
Everything else inside the plugin directory (`src/`, `utils/`, `schemas/`) is yours and is not walked by the loader. Put shared helpers there.
A broken plugin never blocks the rest of the workspace. Loading is per-plugin, per-surface, and time-boxed to 10 seconds.
## Scaffold the directory
The loader expects exactly this shape:
```
my-plugin/
├── package.json # Manifest, required
├── README.md # Optional docs
├── hooks/ # One file per hook
├── tools/ # One file per tool
├── skills/ # One directory per skill
│ └── <skill-name>/
│ └── SKILL.md
└── src/ # Yours, not walked by the loader
```
Choose a kebab-case directory name. It becomes the install name. `@scope/<name>` is allowed; the loader strips the scope for the runtime plugin name. Duplicate names fail registration.
The manifest is a normal `package.json` with three watched fields:
```json
{
"name": "@you/my-plugin",
"version": "0.1.0",
"peerDependencies": {
"@vellumai/plugin-api": "^0.8.0"
},
"vellum": {}
}
```
- `name`: required. The scope is stripped for the runtime plugin name.
- `version`: informational. Defaults to `0.0.0` if absent.
- `peerDependencies["@vellumai/plugin-api"]`: required while the API is in beta. Pin a real range. Mismatches are logged but do not yet block load; they will harden into a hard reject before 1.0.
- `vellum`: reserved.
To exercise the plugin locally before pushing to the catalog, drop the directory into the path the loader scans. The host walks `<workspaceDir>/plugins/<name>/` on each daemon start:
```
cp -R my-plugin "$(assistant daemon workspace)/plugins/my-plugin"
```
(or copy into the path your runtime resolves for `<workspaceDir>`, then restart the daemon). Install by name is reserved for catalog-published plugins shipped through `marketplace.json`.
✓ Checkpoint: directory tree and manifest written. Plugin directory copied into the workspace's `plugins/<name>/`, daemon restarted, `assistant plugins list` shows your plugin with status `ok`.
## Recipe 1: a tool the model can call
A tool is a default-exported object from `tools/<name>.ts`. The file basename becomes the tool name unless you override `name`. Every fie>
>
>
>
Check Vellum Assistant architecture and package boundaries. Use when editing imports, moving code, adding endpoints, touching assistant/gateway/client/skill boundaries, or reviewing architecture-sensitive changes.
Review Vellum Assistant code changes for correctness, repo-specific quality rules, security risks, and missing validation. Use when reviewing diffs, preparing a PR, finishing implementation work, or when the user asks for a code review, quality pass, or pre-merge check in this repository.
Guide Vellum Assistant feature flag changes and rollout hygiene. Use when adding, editing, reviewing, or documenting assistant feature flags, rollout-gated behavior, or platform flag follow-up work.
Validate Vellum Assistant database and workspace migrations. Use when adding, editing, reviewing, or testing migrations, release-note migrations, persisted schemas, workspace file formats, or data backfills.