Skip to content

Claude Code Plugins

PizzaPi includes a Claude Code plugin adapter that discovers plugins designed for Claude Code and loads them into the pi coding agent runtime. Plugin commands become slash commands, hooks map to pi lifecycle events, and skills are shared via the Agent Skills standard.


  1. Place a plugin in one of the global plugin directories:

    Terminal window
    # These are scanned directly:
    ~/.pizzapi/plugins/my-plugin/
    ~/.agents/plugins/my-plugin/
    # Claude Code marketplace plugins are loaded via installed_plugins.json — see below.
  2. Check that it’s detected:

    Terminal window
    pizza plugins
  3. Start a session — plugin commands and hooks are active immediately:

    Terminal window
    pizza

A Claude Code plugin is a directory with any combination of commands, hooks, skills, rules, and metadata:

  • Directorymy-plugin/
    • .claude-plugin/plugin.json (Claude Code standard location; takes precedence over root plugin.json)
    • plugin.json (optional — name, description, version, author, homepage, repository, license, keywords)
    • Directorycommands/
      • review.md
      • deploy.md
    • Directoryhooks/
      • hooks.json
    • Directoryskills/
      • Directorymy-skill/
        • SKILL.md
    • Directoryrules/
      • no-console-log.md
      • prefer-const.md
    • .mcp.json (not adapted — shown as warning)
{
"name": "my-plugin",
"description": "A helpful plugin for code reviews",
"version": "1.0.0",
"author": "Your Name",
"homepage": "https://example.com",
"repository": "https://github.com/example/my-plugin",
"license": "MIT",
"keywords": ["review", "lint"]
}

If plugin.json is missing, the plugin name is inferred from the directory name. PizzaPi also checks .claude-plugin/plugin.json first (the Claude Code standard location); if that file exists it takes precedence over a root plugin.json.


Command files are Markdown files in the commands/ directory. Each file becomes a pi slash command with a flat name derived from its relative path:

commands/review.md → /review
commands/deploy.md → /deploy
commands/a/b/c/deep.md → /a/b/c/deep

Commands are registered by their file-derived name, not namespaced to the plugin. Two plugins that both ship commands/review.md will collide; the last-loaded plugin wins.

Commands support YAML frontmatter and several template variables:

---
description: Run a code review on the current changes
---
Review the following changes and provide feedback:
$ARGUMENTS
Focus on:
- Security issues
- Performance problems
- Code style
Current branch: !`git branch --show-current`
Variable Description
$ARGUMENTS Replaced with whatever the user types after the command
$ARGUMENTS[0], $ARGUMENTS[1], … Individual space-separated arguments
!`command` Inline shell execution — replaced with stdout at invocation time
${CLAUDE_PLUGIN_ROOT} Absolute path to the plugin directory

Hooks are shell commands that run at specific lifecycle events. They’re defined in one or more *.json files inside the plugin’s hooks/ directory (commonly hooks/hooks.json):

{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/check-lint.sh",
"timeout": 10
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/on-stop.sh"
}
]
}
]
}
}

Claude Code hook events are mapped to pi lifecycle events:

Claude Event Pi Event Behavior
PreToolUse tool_call Can block tool execution (exit code 2 or {"decision":"block"})
PostToolUse tool_result Observes tool results
PostToolUseFailure tool_result (error only) Fires only on tool errors
UserPromptSubmit input Can transform or block user input
Stop agent_end Can inject a follow-up message to continue
SessionStart session_start Runs on session initialization
SessionEnd session_shutdown Runs on session teardown
PreCompact session_before_compact Can cancel compaction (exit code 2)

Hook commands receive JSON on stdin and communicate via exit codes and stdout:

Exit Code Meaning
0 Allow — continue normally
2 Block — reject the tool call or cancel the action

Stdout JSON can include:

{
"decision": "block",
"reason": "This file is read-only",
"transformedPrompt": "Modified input text",
"hookSpecificOutput": {
"additionalContext": "Extra context for the agent"
}
}

Matchers filter which tools a hook applies to:

Pattern Matches
Edit Only the Edit tool
Edit|Write Edit or Write
.* or omitted All tools

Plugin skills follow the Agent Skills standard — the same SKILL.md format used by both Claude Code and pi. They’re automatically discovered and loaded alongside PizzaPi’s own skills.

  • Directorymy-plugin/
    • Directoryskills/
      • Directorycode-review/
        • SKILL.md
      • Directorytesting/
        • SKILL.md

Plugin rules are static markdown files that are injected into the system prompt as always-on context. They’re the plugin equivalent of project-level .claude/CLAUDE.md rules — guidelines, conventions, and constraints that the agent follows for every message.

  • Directorymy-plugin/
    • Directoryrules/
      • no-console-log.md
      • prefer-const.md
      • error-handling.md

Every .md file in the rules/ directory is loaded and injected under a # Plugin Rules (plugin-name) heading in the system prompt. There’s no frontmatter, no registration step — just write markdown.

rules/no-console-log.md
## No console.log in production code
Never use `console.log()` for logging in source files under `src/`.
Use the structured logger (`import { log } from '@lib/logger'`) instead.
`console.log` is acceptable only in:
- Test files (`*.test.ts`)
- Build scripts (`scripts/`)

Rules and skills serve different purposes:

Rules Skills
Loaded Always — injected into every session automatically On-demand — agent activates when relevant
Format Plain markdown (no frontmatter needed) SKILL.md with structured frontmatter
Purpose Constraints, conventions, guidelines Capabilities, how-to knowledge
Analogy .claude/CLAUDE.md Tool documentation

Use rules for things the agent should always know (“never commit to main”, “use bun not npm”). Use skills for things the agent should know when relevant (“how to deploy to staging”).

The plugin detail view in the web UI shows a rules badge with the count of loaded rule files, alongside the existing badges for commands, hooks, and skills.


PizzaPi searches for plugins in these directories:

Directory Source
~/.pizzapi/plugins/ PizzaPi’s own plugin directory
~/.agents/plugins/ Agent Skills standard directory
~/.claude/plugins/ Claude Code marketplace cache — discovered via installed_plugins.json + enabledPlugins from Claude Code settings

A plugin folder placed directly in ~/.claude/plugins/ without a matching installed_plugins.json entry will not be discovered.

enabledPlugins is read from ~/.claude/settings.json, then <cwd>/.claude/settings.json, then <cwd>/.claude/settings.local.json. Project files may disable a plugin, but they cannot re-enable a plugin that ~/.claude/settings.json sets to false. Repository-controlled settings must not turn your globally disabled plugin’s hooks or MCP servers back on. To use the plugin again, enable it in user-level settings with pizza plugins enable.


PizzaPi can add marketplaces and install plugins itself, writing to the same files Claude Code uses — so an install made from either tool is visible to both.

/plugin List marketplaces and installed plugins
/plugin marketplace add <source> Add a marketplace
/plugin marketplace list
/plugin marketplace show <name> List a marketplace's plugins
/plugin marketplace remove <name>
/plugin install <name[@marketplace]>
/plugin uninstall <name[@marketplace]>
/plugin enable|disable <name[@marketplace]>

Mutating subcommands reload session resources afterwards, so a newly installed plugin’s commands, skills, and rules are usable immediately — no restart.

In the web UI, /plugin and /plugins reply with an interactive card instead of text. It shows loaded plugins (expand one to see its commands, skills, agents, hooks, and install path), disabled plugins, registered marketplaces, and configured pi packages. Use its buttons to enable, disable, or uninstall a plugin, browse a marketplace’s catalog and install from it, and add, update, or remove a marketplace. Each button runs the matching /plugin subcommand in the session, so changes reload the session the same way they do when you type the command.

The runner panel’s Plugins tab has the same controls at runner level, split into Claude Plugins and Pi Packages sub-tabs. Changes made there apply to new sessions; click Apply to live sessions to reload the runner’s running sessions. The tab calls POST /api/runners/{runnerId}/plugins/command with { "args": ["install", "my-plugin@market"] } (the /plugin arguments as an array), which returns the same structured overview.

Terminal window
pizza plugins marketplace add anthropics/claude-plugins-official
pizza plugins marketplace list
pizza plugins marketplace show claude-plugins-official
pizza plugins install my-plugin@claude-plugins-official
pizza plugins installed
pizza plugins disable my-plugin@claude-plugins-official
pizza plugins uninstall my-plugin@claude-plugins-official
pizza plugins marketplace remove claude-plugins-official
Spec Interpreted as
owner/repo GitHub repository (shallow clone)
https://…/x.git, git@host:x.git Git URL (shallow clone)
./path, /abs/path, ~/path Local directory (copied)

A marketplace source must contain .claude-plugin/marketplace.json. The marketplace is named after that manifest’s name field.

The @marketplace suffix can be omitted when the plugin name is unambiguous.

Path Contents
~/.claude/plugins/known_marketplaces.json Registered marketplaces and their sources
~/.claude/plugins/marketplaces/<name>/ Cloned marketplace repository
~/.claude/plugins/cache/<marketplace>/<plugin>/ Installed plugin payload
~/.claude/plugins/installed_plugins.json Install registry (plugin@marketplace → installations)
~/.claude/settings.json → enabledPlugins Enabled/disabled state
Directory Source
<cwd>/.pizzapi/plugins/ Project-level PizzaPi plugins
<cwd>/.agents/plugins/ Project-level Agent Skills plugins
<cwd>/.claude/plugins/ Project-level Claude Code plugins

Plugins can execute arbitrary shell commands via hooks, so project-local plugins require explicit trust.

Plugins in global directories (~/.pizzapi/plugins/ etc.) load automatically without any prompt. They have the same trust level as global extensions or skills.

Plugins under the project directory (.pizzapi/plugins/ etc.) need explicit approval. There are three ways to grant it:

  1. CLI — pre-approve before starting a session:

    Terminal window
    # Trust all untrusted local plugins in the current project
    pizza plugins trust
    # Trust a specific plugin
    pizza plugins trust .pizzapi/plugins/my-linter
  2. TUI — interactive confirmation dialog at session start (when running pizza directly)

  3. Web UI — amber trust banner with Trust & Load / Skip buttons (when running via the runner daemon)

Once approved by any method, trust is persisted to ~/.pizzapi/config.json (the trustedPlugins array). Future sessions auto-load without re-prompting.

Terminal window
# Show trusted plugin paths
pizza plugins trusted
# Remove a specific plugin from the trust list
pizza plugins untrust /path/to/plugin
# Clear the entire trust list
pizza plugins untrust

Some Claude Code plugin features don’t have direct pi equivalents:

Feature Status Notes
Commands ✅ Adapted Become pi slash commands
Hooks ✅ Adapted Merged into pi lifecycle events
Skills ✅ Adapted Loaded via the Agent Skills standard
Rules ✅ Adapted Injected into the system prompt
Agents ✅ Adapted Loaded as subagent definitions
MCP servers (.mcp.json) ⚠️ Shown as warning Use pi’s own MCP integration instead
LSP (.lsp.json) ⚠️ Shown as warning Language Server Protocol — Claude-specific
Prompt hooks ("type": "prompt") Skipped Claude-specific hook type
Agent hooks ("type": "agent") Skipped Claude-specific hook type

These are surfaced in the web UI’s plugin detail view so you know they exist but aren’t active.


The PizzaPi web UI includes a Plugins panel in the runner manager that shows all discovered plugins:

  • Plugin names with capability badges (commands, hooks, skills, rules, MCP)
  • Click to expand and see full details
  • Rescan button to re-discover after adding new plugins
  • Empty state with instructions when no plugins are found

Anthropic publishes a collection of reference plugins at anthropics/claude-plugins-official. To use them:

Terminal window
# Clone to a global plugin directory
git clone https://github.com/anthropics/claude-plugins-official.git /tmp/claude-plugins
# Copy individual plugins you want (symlinked plugin roots are ignored)
cp -r /tmp/claude-plugins/plugins/code-review ~/.pizzapi/plugins/code-review
cp -r /tmp/claude-plugins/plugins/testing ~/.pizzapi/plugins/testing
# Verify they're discovered
pizza plugins

Or symlink the entire plugins/ directory contents:

Terminal window
for plugin in /tmp/claude-plugins/plugins/*/; do
ln -s "$plugin" ~/.pizzapi/plugins/
done