Skip to main content

Building a Custom Plugin

End-to-end.

1. Scaffold

Create an npm package:

mkdir vibe-plugin-hello
cd vibe-plugin-hello
bun init -y
bun add @vibecontrols/plugin-sdk
bun add -d typescript @types/node

2. Write the plugin

// src/index.ts
import type {
HostServices,
ProfileContext,
VibePlugin,
VibePluginFactory,
} from "@vibecontrols/plugin-sdk/contract";
import {createLifecycleHooks} from "@vibecontrols/plugin-sdk/lifecycle";

const PLUGIN_NAME = "hello";
const PLUGIN_VERSION = "0.1.0";

export const createPlugin: VibePluginFactory = (ctx: ProfileContext): VibePlugin => {
const plugin: VibePlugin = {
name: PLUGIN_NAME,
version: PLUGIN_VERSION,
description: "Says hello",
tags: ["backend"],
capabilities: {
storage: "rw",
subprocess: false,
telemetry: true,
},
};

createLifecycleHooks({
name: PLUGIN_NAME,
onInit: async (hostServices: HostServices) => {
const log = hostServices.logger.bind({plugin: PLUGIN_NAME});
log.info("hello plugin loaded for profile " + ctx.name);
},
});

return plugin;
};

3. Add a package.json entry

{
"name": "vibe-plugin-hello",
"version": "0.1.0",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc"
},
"peerDependencies": {
"@vibecontrols/plugin-sdk": "*"
}
}

4. Build

bun run build

5. Install into the agent

# Locally (development)
cd ~/path/to/vibecontrols-agent
npm install /path/to/vibe-plugin-hello

# Or globally
npm install -g /path/to/vibe-plugin-hello

Register the plugin in your agent's config:

// ~/.boff/vibecontrols/agents/<id>/config.json
{
"plugins": {
"hello": {
"enabled": true
}
}
}

Restart the agent:

vibe restart
vibe status

The plugin's onInit runs and you'll see "hello plugin loaded" in the agent logs.

6. Publish

npm publish --access public

Others can then install via npm install -g vibe-plugin-hello.

7. Provide a real capability

If your plugin should provide sessions, tunnels, or AI:

import type {SessionProvider} from "@vibecontrols/plugin-sdk/providers";

class HelloSessionProvider implements SessionProvider {
readonly name = "hello";
async create(config) { /*...*/ }
async terminate(id) { /*...*/ }
// ... 21 more methods
async healthCheck() { /*...*/ }
}

createLifecycleHooks({
name: PLUGIN_NAME,
onInit: async (hostServices) => {
hostServices.providers.register("session", new HelloSessionProvider(hostServices));
},
});

Next steps