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
    # Any of these work:
    ~/.pizzapi/plugins/my-plugin/
    ~/.agents/plugins/my-plugin/
    ~/.claude/plugins/my-plugin/
  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/
    • plugin.json (optional — name, description, version)
    • 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"
}

If plugin.json is missing, the plugin name is inferred from the directory name.


Command files are Markdown files in the commands/ directory. Each file becomes a pi slash command namespaced to the plugin:

commands/review.md → /my-plugin:review
commands/deploy.md → /my-plugin:deploy

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`
VariableDescription
$ARGUMENTSReplaced 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 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 EventPi EventBehavior
PreToolUsetool_callCan block tool execution (exit code 2 or {"decision":"block"})
PostToolUsetool_resultObserves tool results
PostToolUseFailuretool_result (error only)Fires only on tool errors
UserPromptSubmitinputCan transform or block user input
Stopagent_endCan inject a follow-up message to continue
SessionStartsession_startRuns on session initialization
SessionEndsession_shutdownRuns on session teardown
PreCompactsession_before_compactCan cancel compaction (exit code 2)

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

Exit CodeMeaning
0Allow — continue normally
2Block — 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:

PatternMatches
EditOnly the Edit tool
Edit|WriteEdit or Write
.* or omittedAll 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:

RulesSkills
LoadedAlways — injected into every session automaticallyOn-demand — agent activates when relevant
FormatPlain markdown (no frontmatter needed)SKILL.md with structured frontmatter
PurposeConstraints, conventions, guidelinesCapabilities, how-to knowledge
Analogy.claude/CLAUDE.mdTool 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:

DirectorySource
~/.pizzapi/plugins/PizzaPi’s own plugin directory
~/.agents/plugins/Agent Skills standard directory
~/.claude/plugins/Claude Code’s plugin directory
DirectorySource
<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 / 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:

FeatureStatusNotes
MCP servers (mcp.json)⚠️ Shown as warningUse pi’s own MCP integration instead
Agents (agents/)⚠️ InformationalClaude Code–specific agent definitions
LSP (lsp/)⚠️ InformationalLanguage Server Protocol — Claude-specific
Prompt hooks ("type": "prompt")SkippedClaude-specific hook type
Agent hooks ("type": "agent")SkippedClaude-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, 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
# Symlink individual plugins you want
ln -s /tmp/claude-plugins/plugins/code-review ~/.pizzapi/plugins/code-review
ln -s /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