
Plugins
- 12 installs
- 610 repo stars
- Updated June 26, 2026
- alsk1992/cloddsbot
Plugins (in cloddsbot) is a skill that installs, manages, and authors plugins that extend a bot with new commands, tools, and event handlers.
About
This skill manages the plugin system that extends a bot's functionality. A developer uses it to install plugins from a registry, URL, or local path, enable/disable and update them, and edit their settings. It also defines how to author custom plugins that register commands, tools, and event handlers under scoped permissions.
- Installs, manages, and configures plugins to extend a bot's functionality
- Plugin lifecycle: install, enable/disable, update, configure, uninstall
- Custom plugins register commands, tools, and event handlers with scoped permissions
Plugins by the numbers
- 12 all-time installs (skills.sh)
- Ranked #502 of 782 Skill Development skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
plugins capabilities & compatibility
- Capabilities
- agent tooling
- Use cases
- orchestration
- Pricing
- Free
What plugins says it does
Install, manage, and configure plugins to extend Clodds functionality.
Plugin management, installation, and lifecycle control
npx skills add https://github.com/alsk1992/cloddsbot --skill pluginsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 12 |
|---|---|
| repo stars | ★ 610 |
| Last updated | June 26, 2026 |
| Repository | alsk1992/cloddsbot ↗ |
What it does
Install, configure, and author plugins that extend a bot's commands and tools.
When should I use this skill?
You want to install or build plugins that add commands or tools to the bot.
What you get
Installed, configured plugins that register new commands and tools for the agent.
By the numbers
- 5 plugin permissions
- 3 install sources (registry, URL, local path)
Files
Plugins - Complete API Reference
Install, manage, and configure plugins to extend Clodds functionality.
---
Chat Commands
List Plugins
/plugins List installed plugins
/plugins available Browse available plugins
/plugins search <query> Search plugin registryInstall/Remove
/plugins install <name> Install from registry
/plugins install <url> Install from URL
/plugins uninstall <id> Remove plugin
/plugins update <id> Update plugin
/plugins update-all Update all pluginsEnable/Disable
/plugins enable <id> Enable plugin
/plugins disable <id> Disable plugin
/plugins restart <id> Restart pluginConfiguration
/plugins config <id> View plugin settings
/plugins set <id> <key> <value> Update setting
/plugins reset <id> Reset to defaults---
TypeScript API Reference
Create Plugin Manager
import { createPluginManager } from 'clodds/plugins';
const plugins = createPluginManager({
// Plugin directory
pluginDir: './plugins',
// Registry URL
registry: 'https://plugins.clodds.ai',
// Auto-update
autoUpdate: true,
updateCheckIntervalMs: 86400000, // Daily
});List Plugins
// Get installed plugins
const installed = plugins.list();
for (const plugin of installed) {
console.log(`${plugin.id}: ${plugin.name} v${plugin.version}`);
console.log(` Status: ${plugin.status}`); // 'enabled' | 'disabled' | 'error'
console.log(` Description: ${plugin.description}`);
}Install Plugin
// Install from registry
await plugins.install('advanced-charts');
// Install from URL
await plugins.install('https://github.com/user/plugin/releases/latest/plugin.zip');
// Install from local path
await plugins.install('/path/to/plugin');Enable/Disable
// Enable plugin
await plugins.enable('advanced-charts');
// Disable plugin
await plugins.disable('advanced-charts');
// Check status
const status = plugins.getStatus('advanced-charts');
console.log(`Enabled: ${status.enabled}`);Configure Plugin
// Get plugin settings
const settings = plugins.getSettings('advanced-charts');
console.log(settings);
// Update settings
await plugins.setSettings('advanced-charts', {
theme: 'dark',
refreshInterval: 5000,
});
// Reset to defaults
await plugins.resetSettings('advanced-charts');Uninstall Plugin
await plugins.uninstall('advanced-charts');Create Custom Plugin
// plugins/my-plugin/index.ts
import { Plugin, PluginContext } from 'clodds/plugins';
export default class MyPlugin implements Plugin {
id = 'my-plugin';
name = 'My Custom Plugin';
version = '1.0.0';
description = 'Adds custom functionality';
// Default settings
defaultSettings = {
enabled: true,
threshold: 0.5,
};
async onLoad(ctx: PluginContext) {
console.log('Plugin loaded!');
// Register commands
ctx.registerCommand({
name: 'my-command',
description: 'Does something cool',
handler: async (args) => {
return `Result: ${args.join(' ')}`;
},
});
// Register tools
ctx.registerTool({
name: 'my-tool',
description: 'A custom tool',
execute: async (params) => {
return { result: 'success' };
},
});
// Subscribe to events
ctx.on('message', async (msg) => {
if (msg.content.includes('hello')) {
await ctx.reply('Hello back!');
}
});
}
async onUnload(ctx: PluginContext) {
console.log('Plugin unloaded!');
}
async onSettingsChange(settings: any, ctx: PluginContext) {
console.log('Settings updated:', settings);
}
}Plugin Lifecycle
// Events
plugins.on('installed', (plugin) => {
console.log(`Installed: ${plugin.name}`);
});
plugins.on('enabled', (plugin) => {
console.log(`Enabled: ${plugin.name}`);
});
plugins.on('disabled', (plugin) => {
console.log(`Disabled: ${plugin.name}`);
});
plugins.on('error', (plugin, error) => {
console.error(`Plugin error: ${plugin.name}`, error);
});---
Plugin Structure
my-plugin/
├── index.ts # Main plugin file
├── package.json # Plugin metadata
├── settings.json # Default settings
├── commands/ # Command handlers
├── tools/ # Tool definitions
└── assets/ # Static assetspackage.json
{
"name": "my-plugin",
"version": "1.0.0",
"description": "My custom plugin",
"main": "index.ts",
"clodds": {
"minVersion": "0.1.0",
"permissions": ["network", "storage"],
"commands": ["my-command"],
"tools": ["my-tool"]
}
}---
Plugin Permissions
| Permission | Access |
|---|---|
network | HTTP/WebSocket requests |
storage | Local file storage |
exec | Shell command execution |
trading | Trading APIs |
memory | User memory access |
---
Best Practices
1. Minimal permissions — Only request what you need 2. Handle errors — Don't crash on plugin errors 3. Clean unload — Release resources on unload 4. Version compatibility — Check minVersion 5. Document settings — Explain configuration options
/**
* Plugins CLI Skill
*
* Commands:
* /plugins list - List registered plugins and their state
* /plugins install <path> - Load plugins from a directory
* /plugins remove <id> - Unregister a plugin
* /plugins enable <id> - Enable a plugin
* /plugins disable <id> - Disable a plugin
* /plugins info <id> - Show plugin details
* /plugins commands - List all plugin commands
*/
async function execute(args: string): Promise<string> {
const parts = args.trim().split(/\s+/);
const cmd = parts[0]?.toLowerCase() || 'help';
try {
const mod = await import('../../../plugins/index');
const pluginService = mod.createPluginService();
switch (cmd) {
case 'list':
case 'ls': {
const all = pluginService.list();
if (all.length === 0) {
return '**Installed Plugins**\n\nNo plugins registered. Use `/plugins install <path>` to load from a directory.';
}
let output = `**Installed Plugins** (${all.length})\n\n`;
output += '| Name | Version | State | Commands |\n|------|---------|-------|----------|\n';
for (const reg of all) {
const { meta } = reg.plugin;
const cmdCount = reg.commands.size;
const stateLabel = reg.state === 'enabled' ? 'Enabled' :
reg.state === 'error' ? `Error: ${reg.error}` : reg.state;
output += `| ${meta.name} | ${meta.version} | ${stateLabel} | ${cmdCount} |\n`;
}
return output;
}
case 'install':
case 'load': {
const dir = parts[1];
if (!dir) return 'Usage: /plugins install <directory>\n\nLoads all .js/.mjs plugin files from the given directory.';
const count = await pluginService.loadFromDirectory(dir);
if (count === 0) {
return `No plugins found in \`${dir}\`. Plugins must export a \`meta\` object with at least an \`id\` field.`;
}
return `Loaded **${count}** plugin${count !== 1 ? 's' : ''} from \`${dir}\`.`;
}
case 'remove':
case 'uninstall': {
const pluginId = parts[1];
if (!pluginId) return 'Usage: /plugins remove <id>\n\nUse `/plugins list` to see plugin IDs.';
const existing = pluginService.get(pluginId);
if (!existing) {
return `Plugin \`${pluginId}\` not found.`;
}
pluginService.unregister(pluginId);
return `Unregistered plugin **${existing.plugin.meta.name}** (\`${pluginId}\`).`;
}
case 'enable': {
const pluginId = parts[1];
if (!pluginId) return 'Usage: /plugins enable <id>';
const existing = pluginService.get(pluginId);
if (!existing) {
return `Plugin \`${pluginId}\` not found.`;
}
if (existing.state === 'enabled') {
return `Plugin **${existing.plugin.meta.name}** is already enabled.`;
}
try {
await pluginService.enable(pluginId);
return `Enabled plugin **${existing.plugin.meta.name}**.`;
} catch (e) {
return `Failed to enable plugin \`${pluginId}\`: ${e instanceof Error ? e.message : String(e)}`;
}
}
case 'disable': {
const pluginId = parts[1];
if (!pluginId) return 'Usage: /plugins disable <id>';
const existing = pluginService.get(pluginId);
if (!existing) {
return `Plugin \`${pluginId}\` not found.`;
}
if (existing.state !== 'enabled') {
return `Plugin **${existing.plugin.meta.name}** is not currently enabled.`;
}
await pluginService.disable(pluginId);
return `Disabled plugin **${existing.plugin.meta.name}**.`;
}
case 'info': {
const pluginId = parts[1];
if (!pluginId) return 'Usage: /plugins info <id>';
const existing = pluginService.get(pluginId);
if (!existing) {
return `Plugin \`${pluginId}\` not found.`;
}
const { meta } = existing.plugin;
let output = `**Plugin: ${meta.name}**\n\n`;
output += `ID: \`${meta.id}\`\n`;
output += `Version: ${meta.version}\n`;
output += `State: ${existing.state}\n`;
if (meta.description) output += `Description: ${meta.description}\n`;
if (meta.author) output += `Author: ${meta.author}\n`;
if (meta.homepage) output += `Homepage: ${meta.homepage}\n`;
if (meta.dependencies && meta.dependencies.length > 0) {
output += `Dependencies: ${meta.dependencies.join(', ')}\n`;
}
output += `\nCommands: ${existing.commands.size}\n`;
output += `Tools: ${existing.tools.size}\n`;
output += `Message hooks: ${existing.hooks.message.length}\n`;
output += `Response hooks: ${existing.hooks.response.length}\n`;
if (existing.error) {
output += `\nError: ${existing.error}`;
}
return output;
}
case 'commands':
case 'cmds': {
const commands = pluginService.listCommands();
if (commands.length === 0) {
return '**Plugin Commands**\n\nNo commands registered. Enable a plugin with `/plugins enable <id>` first.';
}
let output = `**Plugin Commands** (${commands.length})\n\n`;
output += '| Command | Plugin | Description |\n|---------|--------|-------------|\n';
for (const cmd of commands) {
output += `| /${cmd.name} | ${cmd.pluginId} | ${cmd.description || '-'} |\n`;
}
return output;
}
case 'tools': {
const tools = pluginService.getTools();
if (tools.length === 0) {
return '**Plugin Tools**\n\nNo tools registered by plugins.';
}
let output = `**Plugin Tools** (${tools.length})\n\n`;
for (const tool of tools) {
output += `- **${tool.name}**: ${tool.description}\n`;
}
return output;
}
default:
return helpText();
}
} catch (error) {
return `Error: ${error instanceof Error ? error.message : String(error)}`;
}
}
function helpText(): string {
return `**Plugin Commands**
/plugins list - List installed plugins
/plugins install <directory> - Load plugins from directory
/plugins remove <id> - Unregister a plugin
/plugins enable <id> - Enable a plugin
/plugins disable <id> - Disable a plugin
/plugins info <id> - Show plugin details
/plugins commands - List plugin commands
/plugins tools - List plugin tools`;
}
export default {
name: 'plugins',
description: 'Plugin management, installation, and lifecycle control',
commands: ['/plugins', '/plugin'],
handle: execute,
};
Related skills
FAQ
Where can plugins be installed from?
From the registry, a URL, or a local path.
What can a custom plugin register?
Commands, tools, and event handlers, gated by permissions like network, storage, exec, trading, and memory.