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 # These are scanned directly:~/.pizzapi/plugins/my-plugin/~/.agents/plugins/my-plugin/# Claude Code marketplace plugins are loaded via installed_plugins.json — see below. -
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/
- .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)
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", "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.
Commands
Section titled “Commands”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 → /reviewcommands/deploy.md → /deploycommands/a/b/c/deep.md → /a/b/c/deepCommands 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.
Command 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 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" } ] } ] }}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 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.
Marketplaces
Section titled “Marketplaces”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.
From a session
Section titled “From a session”/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.
From the CLI
Section titled “From the CLI”pizza plugins marketplace add anthropics/claude-plugins-officialpizza plugins marketplace listpizza plugins marketplace show claude-plugins-officialpizza plugins install my-plugin@claude-plugins-officialpizza plugins installedpizza plugins disable my-plugin@claude-plugins-officialpizza plugins uninstall my-plugin@claude-plugins-officialpizza plugins marketplace remove claude-plugins-officialSources
Section titled “Sources”| 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.
Where state lives
Section titled “Where state lives”| 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 |
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 & 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.
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 |
|---|---|---|
| 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.
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, 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
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
# Copy individual plugins you want (symlinked plugin roots are ignored)cp -r /tmp/claude-plugins/plugins/code-review ~/.pizzapi/plugins/code-reviewcp -r /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