Plugin System
Extend XibeCode with custom tools and domain-specific logic. Create JavaScript or TypeScript plugins with registerTools, initialize, and cleanup hooks.
XibeCode's plugin system lets you extend the AI with custom tools and domain-specific logic. Plugins are JavaScript/TypeScript modules that register new tool definitions.
Why Use Plugins?
- Custom Tools — Add tools specific to your workflow
- Domain Logic — Integrate with internal APIs and services
- Automation — Create deployment, testing, or CI/CD tools
- Data Access — Connect to databases, APIs, or file systems
Quick Start
# 1. Create a plugin file
touch my-plugin.js
# 2. Add to config (~/.xibecode/config.json)
# "plugins": ["/path/to/my-plugin.js"]
# 3. Reload XibeCode
xibecode chat
> /reloadCreating a Plugin
A plugin exports a default object with metadata and a registerTools() method:
export default {
name: "my-custom-plugin",
version: "1.0.0",
description: "Adds custom tools for my workflow",
registerTools() {
return [
{
schema: {
name: "deploy_to_staging",
description: "Deploy the app to staging environment",
input_schema: {
type: "object",
properties: {
branch: { type: "string", description: "Branch to deploy" },
force: { type: "boolean", description: "Force deploy" },
},
required: ["branch"],
},
},
async handler(input) {
console.log(`Deploying ${input.branch} to staging...`);
await new Promise((resolve) => setTimeout(resolve, 2000));
return { success: true, url: "https://staging.example.com" };
},
},
];
},
initialize() {
console.log("Plugin loaded!");
},
cleanup() {
console.log("Plugin unloaded!");
},
};Loading Plugins
Add plugin paths to your config:
{
"plugins": [
"/absolute/path/to/my-plugin.js",
"./relative/path/to/plugin.js",
"~/plugins/deploy-plugin.js"
]
}Plugin API
| Property | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Unique plugin identifier |
version | string | Yes | Semver version string |
description | string | Yes | What the plugin does |
registerTools() | Tool[] | Yes | Returns array of tool definitions |
initialize() | void | No | Setup hook |
cleanup() | void | No | Cleanup hook |
Tool Schema
Each tool follows the Anthropic tool use schema:
{
schema: {
name: 'tool_name',
description: 'What it does',
input_schema: {
type: 'object',
properties: {
param1: { type: 'string', description: 'Description' },
param2: { type: 'number', description: 'Description' },
param3: { type: 'boolean', description: 'Description' },
param4: { type: 'array', items: { type: 'string' }, description: 'List' }
},
required: ['param1']
}
},
handler: async (input) => {
return { result: '...' };
}
}Plugin Examples
Deployment Plugin
export default {
name: "deploy-plugin",
version: "1.0.0",
description: "Deployment tools for staging and production",
registerTools() {
return [
{
schema: {
name: "deploy_to_staging",
description: "Deploy the current branch to staging",
input_schema: {
type: "object",
properties: { branch: { type: "string" } },
required: ["branch"],
},
},
async handler(input) {
const { execSync } = await import("child_process");
execSync(`git push origin ${input.branch}:staging`);
return { success: true, environment: "staging" };
},
},
{
schema: {
name: "check_deployment_status",
description: "Check if deployment is complete",
input_schema: {
type: "object",
properties: {
environment: { type: "string", enum: ["staging", "production"] },
},
required: ["environment"],
},
},
async handler(input) {
return { status: "deployed", environment: input.environment };
},
},
];
},
};Database Migration Plugin
export default {
name: "migration-plugin",
version: "1.0.0",
description: "Database migration tools",
registerTools() {
return [
{
schema: {
name: "run_migration",
description: "Run database migration",
input_schema: {
type: "object",
properties: {
direction: { type: "string", enum: ["up", "down"] },
steps: { type: "number" },
},
required: ["direction"],
},
},
async handler(input) {
const { execSync } = await import("child_process");
const cmd =
input.direction === "up"
? "npx prisma migrate deploy"
: "npx prisma migrate reset --skip-seed";
execSync(cmd, { stdio: "inherit" });
return { success: true, direction: input.direction };
},
},
];
},
};Internal API Integration
export default {
name: "internal-api-plugin",
version: "1.0.0",
description: "Connect to internal company APIs",
initialize() {
this.apiBase = process.env.INTERNAL_API_URL;
this.apiKey = process.env.INTERNAL_API_KEY;
},
registerTools() {
const apiBase = this.apiBase;
const apiKey = this.apiKey;
return [
{
schema: {
name: "query_internal_api",
description: "Query internal company API",
input_schema: {
type: "object",
properties: {
endpoint: { type: "string" },
method: {
type: "string",
enum: ["GET", "POST", "PUT", "DELETE"],
},
body: { type: "object" },
},
required: ["endpoint"],
},
},
async handler(input) {
const res = await fetch(`${apiBase}${input.endpoint}`, {
method: input.method || "GET",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: input.body ? JSON.stringify(input.body) : undefined,
});
return await res.json();
},
},
];
},
};Notification Plugin
export default {
name: "notification-plugin",
version: "1.0.0",
description: "Send notifications via Slack",
registerTools() {
return [
{
schema: {
name: "send_slack_message",
description: "Send a message to Slack",
input_schema: {
type: "object",
properties: {
channel: { type: "string" },
message: { type: "string" },
},
required: ["channel", "message"],
},
},
async handler(input) {
const webhookUrl = process.env.SLACK_WEBHOOK_URL;
await fetch(webhookUrl, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
channel: input.channel,
text: input.message,
}),
});
return { success: true, channel: input.channel };
},
},
];
},
};Error Handling
async handler(input) {
try {
const result = await someOperation(input);
return { success: true, data: result };
} catch (error) {
return {
success: false,
error: error.message,
suggestion: 'Try checking if the service is running'
};
}
}Best Practices
- Clear descriptions — The AI reads tool descriptions to decide when to use them
- Handle errors gracefully — Return useful error messages
- Keep plugins focused — One concern per plugin
- Use
initialize()for setup — Database connections, API clients - Use
cleanup()for teardown — Close connections, clean resources - Validate inputs — Check required inputs before proceeding
- Return structured data — Objects with clear success/failure status
Debugging Plugins
xibecode chat
> /plugins # Check if plugin is loaded
> /tools # View available tools from plugins
> Use the deploy_to_staging tool with branch "main"Next Steps
- MCP Integration — Connect to external servers
- Tools Reference — Built-in tools
- Examples — Real-world workflows
MCP Integration
Connect to external servers via the Model Context Protocol for databases, APIs, file systems, and more. Configure GitHub, PostgreSQL, Slack, filesystem, and custom MCP servers.
Examples & Workflows
Real-world examples showing how to use XibeCode for common development tasks. Build features, fix bugs, refactor, test, review, and automate with 20+ examples.