Context Course documentation

Plugin Anatomy

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Plugin Anatomy

What’s inside a plugin depends on whether the platform is manifest-first or code-first. Claude Code and Codex use manifests plus root-level plugin components. OpenCode plugins are JavaScript/TypeScript modules loaded from local files or npm. Pi’s closest equivalent is a package declared in package.json that can bundle skills, extensions, prompts, and themes.

Plugin Structure

There isn’t one universal plugin shape:

  1. Manifest-first plugins use a plugin.json manifest plus root-level directories and config files such as skills/, .mcp.json, or .app.json.
  2. Code-first plugins are JS/TS modules that export hooks or custom tools. Skills and MCP configuration stay as separate surfaces.
  3. Package-based bundles use package.json plus conventional directories such as skills/ and extensions/.

Let’s see how each platform implements that idea.

Plugin Structure by Platform

Claude Code
Codex
OpenCode
Pi

Claude Code Plugin Structure

Claude Code plugins are self-contained directories. The manifest lives in .claude-plugin/plugin.json, and the plugin’s skills, hooks, MCP config, and other components stay at the plugin root.

my-plugin/
├── .claude-plugin/
│   └── plugin.json             # Plugin manifest
├── skills/                     # Collection of skills
│   ├── analyze-text/
│   │   └── SKILL.md            # Skill definition
│   ├── extract-keywords/
│   │   └── SKILL.md
│   └── check-reading-level/
│       └── SKILL.md
├── agents/                     # Custom agents (optional)
├── .mcp.json                   # MCP server configuration
├── hooks/                      # Hook configuration (optional)
│   └── hooks.json
├── .lsp.json                   # LSP server configuration (optional)
├── settings.json               # Plugin defaults (optional)
└── README.md                   # Documentation

plugin.json (in .claude-plugin/ directory) declares the plugin:

{
  "name": "text-processor-plugin",
  "version": "1.0.0",
  "description": "Text analysis skills powered by the text-processor MCP server",
  "author": {
    "name": "Your Name"
  }
}

Key Properties:

  • name — Unique plugin identifier
  • version — Semantic version (1.0.0, 1.1.0, etc.)
  • description — What the plugin does
  • author — Creator information

Only plugin.json goes inside .claude-plugin/. Skills, agents, hooks, MCP config, and LSP config stay at the plugin root. Skills are namespaced when invoked:

/text-processor-plugin:analyze-text

MCP servers are configured in .mcp.json at the plugin root, using the same format as project-scoped MCP config from Unit 2. The server can be local or remote:

{
  "mcpServers": {
    "text-processor": {
      "url": "https://YOUR-USERNAME-text-processor-mcp.hf.space/gradio_api/mcp/"
    }
  }
}

Key Takeaways

Claude Code and Codex use manifest-first plugin bundles: a plugin.json manifest alongside root-level components like skills/, .mcp.json, and integration files. OpenCode uses a code-first model: plugins are JS/TS modules loaded from .opencode/plugins/ or npm, with skills and MCP configuration handled separately. Pi packages use package.json plus conventional directories such as skills/ and extensions/.

Next we’ll build a plugin from scratch.

Update on GitHub