Robutler

Plugin Skill

Claude Code compatible plugin system with marketplace discovery, fuzzy search, and dynamic tool registration.

TypeScript: the plugin runtime is implemented in TypeScript (PluginSkill), but the marketplace client and CLI flows remain Python-only. The plugin manifest format and SKILL.md spec are language-agnostic — plugins authored against the Python toolchain run unchanged on the TS plugin loader. Track parity in the parity matrix.

Overview

The Plugin skill enables agents to discover, install, and manage plugins from the Claude Marketplaces ecosystem. It provides:

  • Marketplace Discovery - Search and browse plugins from claudemarketplaces.com
  • Fuzzy Search - Find plugins by name, description, or keywords with typo tolerance
  • GitHub Star Ranking - Results ranked by popularity and relevance
  • Claude Code Compatibility - Works with existing Claude Code plugins
  • Dynamic Tool Registration - Plugin tools automatically registered with agent

Quick Start

Enable Plugin Skill

import { BaseAgent } from 'webagents';
import { PluginSkill } from 'webagents/skills/plugin';

const agent = new BaseAgent({
  name: 'my-agent',
  skills: [new PluginSkill()],
});

Basic Commands

# Search for plugins
/plugin/search code review

# Install a plugin
/plugin/install code-review

# List installed plugins
/plugin/list

# Get plugin info
/plugin/info code-review

Commands

CommandDescriptionScope
/pluginShow help and subcommandsall
/plugin/listList installed pluginsall
/plugin/search <query>Search marketplaceall
/plugin/install <name>Install plugin from marketplace or URLowner
/plugin/uninstall <name>Remove installed pluginowner
/plugin/enable <name>Enable disabled pluginowner
/plugin/disable <name>Disable enabled pluginowner
/plugin/info <name>Show plugin detailsall
/plugin/refreshRefresh marketplace indexall

Examples

# Search with fuzzy matching
/plugin/search summarize text
# Finds: text-summarizer, summary-tool, summarization, etc.

# Install by name
/plugin/install text-summarizer

# Install from GitHub URL
/plugin/install https://github.com/user/my-plugin

# View installed plugin details
/plugin/info text-summarizer

Plugin Format

Plugins use the Claude Code plugin.json format:

{
  "name": "my-plugin",
  "version": "1.0.0",
  "description": "My awesome plugin",
  "author": "Your Name",
  "license": "MIT",
  "commands": "./commands/",
  "skills": "./skills/",
  "agents": "./agents/",
  "hooks": "./hooks/hooks.json",
  "mcpServers": "./.mcp.json",
  "dependencies": ["requests>=2.28"],
  "keywords": ["utility", "automation"],
  "repository": "https://github.com/user/my-plugin"
}

Manifest Fields

FieldTypeRequiredDescription
namestringYesPlugin identifier (alphanumeric, hyphens, underscores)
versionstringNoSemantic version (e.g., "1.0.0")
descriptionstringNoHuman-readable description
authorstringNoPlugin author
licensestringNoLicense identifier (MIT, Apache-2.0, etc.)
commandsstringNoPath to commands directory (default: ./commands/)
skillsstringNoPath to skills directory (default: ./skills/)
agentsstringNoPath to agents directory (default: ./agents/)
hooksstringNoPath to hooks configuration file
mcpServersstringNoPath to MCP servers config
dependenciesarrayNoPython package dependencies
keywordsarrayNoSearchable keywords
repositorystringNoGit repository URL
homepagestringNoPlugin homepage URL

Directory Structure

my-plugin/
├── plugin.json          # Plugin manifest (required)
├── commands/            # Python command scripts
│   ├── analyze.py
│   └── report.py
├── skills/              # SKILL.md files
│   └── review.md
├── hooks/               # Hook configurations
│   ├── hooks.json
│   └── on_message.py
└── .mcp.json           # MCP server configs (optional)

SKILL.md Format

Skills use Markdown with YAML frontmatter:

---
name: code-review
description: Review code for issues and improvements
disable-model-invocation: false
allowed-tools: [read_file, write_file]
context: inline
---

# Code Review Skill

Review the file at `$ARGUMENTS.file_path` for:

1. Code quality issues
2. Security vulnerabilities  
3. Performance improvements

Focus on: $ARGUMENTS.focus_areas

Frontmatter Options

OptionTypeDefaultDescription
namestringfilenameSkill identifier
descriptionstring""Human-readable description
disable-model-invocationboolfalseRun without LLM
allowed-toolslistnullTool whitelist for forked execution
contextstring"inline"Execution mode: "inline" or "fork"

Argument Substitution

Use $ARGUMENTS.key or $ARGUMENTS['key'] for dynamic values:

Review the repository at $ARGUMENTS.repo_path

Options:
- Include tests: $ARGUMENTS['include_tests']
- Max depth: $ARGUMENTS.depth

Commands (Python)

Plugin commands are Python scripts in the commands/ directory:

# commands/analyze.py
"""Analyze code for issues."""

import json
import os

def run(arguments):
    """Main entry point. Receives arguments dict."""
    file_path = arguments.get("file_path")
    
    # Do analysis...
    results = analyze_file(file_path)
    
    # Return dict for structured output
    return {
        "issues": results,
        "file": file_path
    }

if __name__ == "__main__":
    # For subprocess execution
    args = json.loads(os.environ.get("PLUGIN_ARGUMENTS", "{}"))
    result = run(args)
    print(json.dumps(result))

Hooks

Hooks allow plugins to respond to agent lifecycle events:

{
  "hooks": [
    {
      "event": "on_message",
      "handler": "./on_message.py",
      "priority": 50,
      "enabled": true
    },
    {
      "event": "on_tool_call",
      "handler": "./on_tool_call.py",
      "priority": 100
    }
  ]
}

Hook handler example:

# hooks/on_message.py
async def run(event_data):
    """Handle message event."""
    message = event_data.get("message")
    
    # Process message...
    
    return {
        "processed": True,
        "modified_message": message
    }

Supported Events

EventTriggerData
on_messageNew user message{message, context}
on_tool_callTool invocation{tool_name, arguments}
on_responseAgent response{response, context}
on_errorError occurred{error, context}

MCP Servers

Plugins can include MCP server configurations:

{
  "mcpServers": {
    "my-server": {
      "command": "python",
      "args": ["-m", "my_mcp_server"],
      "env": {
        "API_KEY": "${MY_API_KEY}"
      }
    }
  }
}

Marketplace

The skill fetches plugins from https://claudemarketplaces.com/api/marketplaces.

Search Algorithm

  1. Fuzzy Match - Uses rapidfuzz WRatio for typo tolerance
  2. Star Boost - GitHub stars provide log-scale ranking boost
  3. Combined Score - rank = match_score + log10(stars + 1) * 10

Caching

  • Index cached to ~/.webagents/plugin_cache/marketplace_index.json
  • Refreshes every 6 hours in background
  • Manual refresh with /plugin/refresh

Configuration

new PluginSkill({
  // GitHub token for higher API rate limits
  githubToken: 'ghp_...',
  // Custom plugins directory
  pluginsDir: '/path/to/plugins',
  // Disable background refresh
  autoRefresh: false,
});

Environment Variables

VariableDescription
GITHUB_TOKENGitHub API token for higher rate limits

API Reference

PluginLoader

import { PluginLoader } from 'webagents/skills/plugin';

const loader = new PluginLoader();

// Load from local path
const plugin = await loader.loadLocal('./my-plugin');

// Install from Git
const installed = await loader.installFromRepo('https://github.com/user/plugin');

// List installed
const plugins = loader.listInstalled();

// Uninstall
loader.uninstall('plugin-name');

MarketplaceClient

// MarketplaceClient is currently Python-only. Until the TypeScript port lands,
// drive marketplace operations from the Python CLI (`webagents plugin search ...`)
// or invoke the marketplace HTTP API directly:
const res = await fetch(
  `https://claudemarketplaces.com/api/marketplaces?q=${encodeURIComponent('code review')}`,
);
const results = await res.json();

Creating a Plugin

mkdir my-plugin && cd my-plugin

# Create manifest
cat > plugin.json << 'EOF'
{
  "name": "my-plugin",
  "version": "1.0.0",
  "description": "My first plugin",
  "commands": "./commands/",
  "skills": "./skills/"
}
EOF

# Create a command
mkdir commands
cat > commands/hello.py << 'EOF'
"""Say hello."""
def run(args):
    name = args.get("name", "World")
    return {"message": f"Hello, {name}!"}
EOF

# Create a skill
mkdir skills
cat > skills/greet.md << 'EOF'
---
name: greet
description: Greet the user
---
Please greet $ARGUMENTS.name warmly.
EOF

Dependencies

rapidfuzz>=3.0     # Fuzzy search
pyyaml>=6.0        # YAML frontmatter parsing
gitpython>=3.1     # Git repository installation
httpx>=0.25        # HTTP client for marketplace API

See Also

On this page