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.
Quick Start
Section titled “Quick Start”-
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/ -
Check that it’s detected:
Terminal window pizza plugins -
Start a session — plugin commands and hooks are active immediately:
Terminal window pizza
Plugin Structure
Section titled “Plugin Structure”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)
plugin.json (optional)
Section titled “plugin.json (optional)”{ "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.
Commands
Section titled “Commands”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:reviewcommands/deploy.md → /my-plugin:deployCommand file format
Section titled “Command file format”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 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" } ] } ] }}Hook event mapping
Section titled “Hook event mapping”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 I/O protocol
Section titled “Hook I/O protocol”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
Section titled “Matchers”Matchers filter which tools a hook applies to:
| Pattern | Matches |
|---|---|
Edit | Only the Edit tool |
Edit|Write | Edit or Write |
.* or omitted | All tools |
Skills
Section titled “Skills”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.
Example rule file
Section titled “Example rule file”## 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 vs. skills
Section titled “Rules vs. skills”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”).
Rules in the web UI
Section titled “Rules in the web UI”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.
Plugin Discovery
Section titled “Plugin Discovery”PizzaPi searches for plugins in these directories:
Global (auto-trusted)
Section titled “Global (auto-trusted)”| Directory | Source |
|---|---|
~/.pizzapi/plugins/ | PizzaPi’s own plugin directory |
~/.agents/plugins/ | Agent Skills standard directory |
~/.claude/plugins/ | Claude Code’s plugin directory |
Project-local (require trust)
Section titled “Project-local (require trust)”| 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 |
Trust Model
Section titled “Trust Model”Plugins can execute arbitrary shell commands via hooks, so project-local plugins require explicit trust.
Global plugins — always trusted
Section titled “Global plugins — always trusted”Plugins in global directories (~/.pizzapi/plugins/ etc.) load automatically without any prompt. They have the same trust level as global extensions or skills.
Project-local plugins — require trust
Section titled “Project-local plugins — require trust”Plugins under the project directory (.pizzapi/plugins/ etc.) need explicit approval. There are three ways to grant it:
-
CLI — pre-approve before starting a session:
Terminal window # Trust all untrusted local plugins in the current projectpizza plugins trust# Trust a specific pluginpizza plugins trust .pizzapi/plugins/my-linter -
TUI — interactive confirmation dialog at session start (when running
pizzadirectly) -
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.
Managing trust
Section titled “Managing trust”# Show trusted plugin pathspizza plugins trusted
# Remove a specific plugin from the trust listpizza plugins untrust /path/to/plugin
# Clear the entire trust listpizza plugins untrustWhat’s Not Adapted
Section titled “What’s Not Adapted”Some Claude Code plugin features don’t have direct pi equivalents:
| Feature | Status | Notes |
|---|---|---|
MCP servers (mcp.json) | ⚠️ Shown as warning | Use pi’s own MCP integration instead |
Agents (agents/) | ⚠️ Informational | Claude Code–specific agent definitions |
LSP (lsp/) | ⚠️ Informational | 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.
Web UI
Section titled “Web UI”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
Using Official Claude Plugins
Section titled “Using Official Claude Plugins”Anthropic publishes a collection of reference plugins at anthropics/claude-plugins-official. To use them:
# Clone to a global plugin directorygit clone https://github.com/anthropics/claude-plugins-official.git /tmp/claude-plugins
# Symlink individual plugins you wantln -s /tmp/claude-plugins/plugins/code-review ~/.pizzapi/plugins/code-reviewln -s /tmp/claude-plugins/plugins/testing ~/.pizzapi/plugins/testing
# Verify they're discoveredpizza pluginsOr symlink the entire plugins/ directory contents:
for plugin in /tmp/claude-plugins/plugins/*/; do ln -s "$plugin" ~/.pizzapi/plugins/done