CLI Reference
Synopsis
Section titled βSynopsisβpizzapi [command] [options]When called without a command, pizzapi starts an interactive coding session and streams it to the configured relay server.
Run pizzapi --help for a quick summary of all commands:
π PizzaPi v0.5.4
Commands: pizza Start an interactive agent session pizza local [flags] Start local relay + runner in one command pizza web [flags] Manage the PizzaPi web hub (Docker) pizza runner [args] Manage the background runner daemon pizza runner stop Stop the runner daemon pizza runner status [--json] Health check the runner daemon (exit 0 = healthy) pizza runner pair [--force] Pair (or re-pair) the runner with a fresh API key pizza setup Run first-time setup pizza usage [provider] Show API usage stats pizza models List available models pizza plugins [cmd] Manage Claude Code plugins (list/trust/marketplace/install) pizza install <source> Install a pi package (extensions, skills, prompts, themes) pizza remove <source> Remove an installed pi package pizza update [source|self] Update installed pi packages pizza list List installed pi packages pizza config Enable/disable package resources
Flags: --cwd <path> Set working directory --sandbox <mode> Set sandbox mode: enforce, audit, or off --safe-mode Skip MCP, plugins, hooks, and relay --no-mcp Skip MCP server connections --no-plugins Skip Claude Code plugin loading --no-hooks Skip hook execution --no-relay Skip relay server connection -v, --version Show version -h, --help Show this help
Run pizza <command> --help for command-specific help.Commands
Section titled βCommandsβpizzapi (default)
Section titled βpizzapi (default)βStart an interactive pi coding session and relay it to the web UI.
pizzapipizzapi --cwd /path/to/projectpizzapi --safe-mode # Skip MCP, plugins, hooks, relaypizzapi --no-mcp # Skip only MCP servers| Flag | Description |
|---|---|
--cwd <path> | Working directory for the session (default: current directory) |
--safe-mode | Skip all external dependencies (MCP, plugins, hooks, relay) for instant startup |
--no-mcp | Skip MCP server connections only |
--no-plugins | Skip Claude Code plugin discovery and loading |
--no-hooks | Skip all hook execution |
--no-relay | Skip relay server connection |
--sandbox <mode> | Set sandbox mode: enforce, audit, or off. See Agent Sandbox. |
Each --no-* flag also has a PIZZAPI_NO_*=1 environment-variable equivalent (PIZZAPI_NO_MCP, PIZZAPI_NO_PLUGINS, PIZZAPI_NO_HOOKS, PIZZAPI_NO_RELAY, and PIZZAPI_NO_SANDBOX for --sandbox=off).
The session ID is derived from the runner configuration and displayed on startup. Open the relay serverβs web UI to watch the session live.
If no API key is configured and the relay is not disabled, the CLI will automatically launch the setup wizard before starting the session.
Startup Performance
Section titled βStartup PerformanceβMCP servers are initialized in parallel with per-server timeouts (default: 30 seconds). If a server doesnβt respond in time, itβs skipped and an error is shown.
When startup takes longer than 5 seconds, a warning is displayed in both the TUI and web UI showing which servers were slow. You can disable this warning by setting "slowStartupWarning": false in your config.
pizzapi local
Section titled βpizzapi localβStart the local relay, web UI, and runner in one command. This is the fastest way to get a self-hosted PizzaPi running on your own machine.
pizzapi localpizzapi local --port 8080pizzapi local --no-browserWhat it does:
- Starts the local relay + web UI via
pizza web(Docker Compose) if it is not already healthy. - Runs the first-time setup wizard if no API key for the local relay is saved.
- Opens the browser to the local UI (unless
--no-browseris passed). - Starts the runner in the foreground.
Process ownership:
- The relay is managed by Docker /
pizza web. It keeps running after this command exits; stop it withpizza web stop. - The runner is owned by this command. Press
Ctrl+Cto stop the runner. No orphan daemon is left behind.
Re-running pizzapi local is safe and idempotent: an already-healthy relay is reused, an already-running runner is reported, and an existing local API key is preserved.
| Flag | Description |
|---|---|
--port <number> | Relay port (default: 7492) |
--no-browser | Print the UI URL instead of opening the browser |
-h, --help | Show help |
pizzapi setup
Section titled βpizzapi setupβRun (or re-run) the first-time setup wizard. Prompts for the relay server URL, your name (optional), email, and password, then saves the API key to ~/.pizzapi/config.json.
pizzapi setuppizzapi setup --scan
Section titled βpizzapi setup --scanβEnroll a new PC by QR code instead of typing credentials. The CLI prompts for the relay URL, prints a terminal QR code, and polls for approval. Scan the QR code from an authenticated PizzaPi web browser (or open the printed URL) and tap Allow Camera & Scan to approve the device.
pizzapi setup --scanThe claim expires after 10 minutes. Once approved, the CLI receives an API key and writes ~/.pizzapi/config.json automatically.
pizzapi runner
Section titled βpizzapi runnerβStart the headless runner daemon. The daemon registers with the relay server and waits for session-spawn requests from the web UI or from agents using the spawn_session tool.
# Start the runner (foreground)pizzapi runner
# Start the runner in the backgroundpizzapi runner &
# Stop a running daemonpizzapi runner stopSee the Runner Daemon guide for detailed usage.
pizzapi runner stop
Section titled βpizzapi runner stopβSend a stop signal to the currently running runner daemon.
pizzapi runner stoppizzapi runner status
Section titled βpizzapi runner statusβHealth check for the runner daemon β answers βis this runner alive and registered with the relay?β by combining a PID liveness check with the daemonβs last-known relay connection state. Fast and dependency-light: no relay round-trip, no config/model loading.
pizzapi runner status # human-readable summarypizzapi runner status --json # machine-readable, for scripting/monitoringExit code: 0 if healthy (process running and connected: true), 1 otherwise.
--json prints:
{ "healthy": true, "runnerId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "runnerName": "docker-runner", "relayUrl": "https://pizza.example.com", "connected": true, "pid": 12345, "startedAt": "2025-01-15T10:30:00.000Z", "cliVersion": "0.5.61"}| Field | Present when | Description |
|---|---|---|
healthy | always | true only if the process is alive and connected is true |
reason | unhealthy | "no runner state file found", "pairing pending β approve at <url>" (auto-pairing is waiting on approval), "process not running", "relay rejected credentials β check PIZZAPI_API_KEY / re-pair" (the relay rejected the key β distinct from an ordinary connectivity problem), or "not registered with relay" |
pairingUrl | pairing pending | The approval URL to open, when reason is a pending-pairing message |
runnerId, runnerName, relayUrl, cliVersion | state file exists | Copied from ~/.pizzapi/runner.json |
connected | always | Whether the daemonβs last-known state is registered with the relay |
pid | a pid was recorded | The daemon processβs own PID (not the supervisorβs) |
startedAt | state file exists | ISO timestamp of the daemonβs last start |
This is the command the runner container imageβs Docker HEALTHCHECK runs.
pizzapi runner pair
Section titled βpizzapi runner pairβMint a fresh headless-paired API key on demand β the same device-claim flow the daemon runs automatically on a credential-less boot (Runner Container β Credentials), but invokable any time. Useful after revoking a runnerβs key in the web UI, instead of hand-editing the data volume.
pizzapi runner pair # refuses if a credential already resolvespizzapi runner pair --force # pairs and overwrites any existing credentialPrints an approval URL + QR code (re-printed periodically while waiting), polls until approved or expired, then writes apiKey/relayUrl into config.json in the resolved agent dir, replacing only those two fields.
Exit code: 0 on a successful pair. Non-zero if refused, if the claim expires, or on any pairing failure.
Two guard rails, both bypassed only with --force:
- Refuses to clobber an existing credential. If an API key already resolves (env var or
config.json), it prints where it came from (never the key itself) and exits non-zero telling you to re-run with--force. - Refuses when an env var would shadow the result. The runtime resolution order is
PIZZAPI_RUNNER_API_KEYβPIZZAPI_API_KEYβPIZZAPI_API_TOKENβ configapiKey. If any of those three env vars is set, a freshly paired key written toconfig.jsonwould be silently ignored at runtime β pairing would βsucceedβ while nothing actually changes. This refuses outright by default (naming the offending variable and telling you to unset it) rather than just warning, because a warning line is easy to miss when the operator is scanning for a success message. Even with--force, the same warning still prints before proceeding, since forcing past the refusal doesnβt make the shadow go away.
If a runner daemon is already running when pairing succeeds, the daemon keeps using its old credential in memory β the command prints a reminder to restart it (pizzapi runner stop then start again, or docker restart <container>) rather than restarting anything itself.
If no relay URL is known (neither PIZZAPI_RELAY_URL nor a configured one), it fails immediately with an actionable message β it never prompts or guesses a default.
pizzapi web
Section titled βpizzapi webβStart the PizzaPi web hub (relay server + web UI) using Docker Compose. This is the easiest way to self-host the relay β no need to clone the repo or configure Docker manually.
Run pizzapi web --help for the full usage:
pizza web β Manage the PizzaPi web hub (server + UI via Docker Compose)
Commands: pizza web [flags] Start the web hub pizza web stop Stop the web hub pizza web logs Tail container logs pizza web status Show container status pizza web config Show current configuration pizza web config set <k> <v> Update a config value
Flags: --port <port> Set the host port (persisted to config.json) --origins <list> Set extra allowed CORS origins (comma-separated, persisted) --tag <tag> UI image tag from GHCR (default: CLI version, or latest) --build Build UI locally (fallback mode) --dev-ui Use the local dev UI (local repo only) -f, --foreground Run in the foreground (don't detach) --no-cache Rebuild Docker image without layer cache -h, --help Show this help
Configuration (~/.pizzapi/web/config.json): port Host port (default: 7492) vapidSubject VAPID subject for push notifications extraOrigins Extra CORS origins, comma-separated
Examples: pizza web Start on default port 7492 pizza web --tag main Pull ghcr.io/pizzaface/pizzapi-ui:main pizza web --build Build UI locally (fallback mode) pizza web --dev-ui Use local dev UI (local repo only) pizza web --port 8080 Start on port 8080 (remembered for next time) pizza web config set port 9000 Change port without starting pizza web config set extraOrigins "https://example.com"--dev-ui runs the local dev UI stack from a repo checkout (the server plus dev:ui on port 5173). --build uses the local-build fallback mode. PREBUILT_UI is a Docker build arg that pizza web sets automatically based on the host prebuild state.
# Start on the default port (7492)pizzapi web
# Start on a custom port (persisted for future runs)pizzapi web --port 8080
# Set extra CORS origins (persisted)pizzapi web --origins "https://example.com,https://other.com"
# Pull a specific GHCR UI tagpizzapi web --tag main
# Build the UI locally (fallback mode)pizzapi web --build
# Run the local dev UI stack (repo checkout only)pizzapi web --dev-ui
# Run in the foreground (don't detach)pizzapi web --foreground
# Managementpizzapi web stoppizzapi web logspizzapi web status| Subcommand | Description |
|---|---|
| (none) | Build and start the relay server + web UI |
stop | Stop the running web hub |
logs | Tail the container logs |
status | Show running container status |
config | Show current configuration from config.json |
config set <key> <value> | Update a config value (see below) |
| Flag | Description |
|---|---|
--port <number> | HTTP port to expose (default: 7492). Persisted to config.json. |
--origins <list> | Extra CORS origins, comma-separated. Persisted to config.json. |
--tag <tag> | UI image tag to pull from ghcr.io/pizzaface/pizzapi-ui (default: CLI version, or latest). |
--build | Build UI locally instead of pulling GHCR image (fallback mode). |
--dev-ui | Run the local dev UI stack from a repo checkout. |
--foreground, -f | Run in the foreground instead of detaching |
--no-cache | Rebuild Docker image without layer cache |
--help, -h | Show help |
pizzapi web config
Section titled βpizzapi web configβView the current web hub configuration:
pizzapi web configpizzapi web config set
Section titled βpizzapi web config setβUpdate a configuration value. Changes are saved to ~/.pizzapi/web/config.json and take effect on the next pizza web start.
pizzapi web config set port 9000pizzapi web config set extraOrigins "https://example.com"pizzapi web config set vapidSubject "mailto:ops@example.com"| Key | Default | Description |
|---|---|---|
port | 7492 | Host port to expose the web UI on |
vapidSubject | mailto:admin@pizzapi.local | VAPID subject for web push notifications |
extraOrigins | (none) | Extra allowed CORS origins, comma-separated |
All settings and persistent data are stored in ~/.pizzapi/web/:
| File | Purpose |
|---|---|
config.json | All web hub settings (port, VAPID keys, origins, etc.) |
compose.yml | Auto-generated Docker Compose config (regenerated each run) |
host-build.json | Host UI pre-build cache state |
compose.override.yml | Optional Docker Compose override (PizzaPi includes it automatically if present) |
VAPID keys for push notifications are generated on first run and stored in config.json. They persist across restarts and config changes β push notification subscriptions wonβt break.
pizzapi usage
Section titled βpizzapi usageβShow API usage and quota information for your authenticated providers.
# Show usage for all providerspizzapi usage
# Filter to a specific providerpizzapi usage anthropicpizzapi usage gemini
# Machine-readable JSON outputpizzapi usage --jsonAnthropic (Claude)
Section titled βAnthropic (Claude)βFor Anthropic OAuth subscriptions, the command fetches quota utilization from the Anthropic API:
Claude usage (OAuth subscription)ββββββββββββββββββββββββββββββββββββββββββββββββββββββ 5-hour window 12.3% (resets 2/24/2026, 2:15:00 PM) 7-day window 8.1% (resets 3/1/2026, 9:00:00 AM) 7-day (OAuth apps) 4.2% (resets 3/1/2026, 9:00:00 AM) 7-day (Opus) 2.0% (resets 3/1/2026, 9:00:00 AM) 7-day (Sonnet) 6.5% (resets 3/1/2026, 9:00:00 AM) 7-day (co-work) 3.0% (resets 3/1/2026, 9:00:00 AM)
Extra usage enabled Monthly limit: $100 Credits used: $12.34 Utilization: 12.3%Gemini (Google Cloud Code Assist)
Section titled βGemini (Google Cloud Code Assist)βFor Gemini OAuth credentials, the command fetches quota buckets from the Google Cloud Code Assist endpoint:
Gemini usage (Google Cloud Code Assist, OAuth) Project: my-project-123ββββββββββββββββββββββββββββββββββββββββββββββββββββββ INPUT / gemini-2.5-pro 85.0% remaining (850 left) resets 3/1/2026, 12:00:00 AM OUTPUT / gemini-2.5-pro 92.3% remaining (923 left) resets 3/1/2026, 12:00:00 AMpizzapi models
Section titled βpizzapi modelsβList all AI models available through the configured providers.
# Human-readable tablepizzapi models
# Machine-readable JSONpizzapi models --jsonExample output:
anthropic claude-opus-4-5 reasoning β’ 200,000 ctx β’ Claude Opus 4.5 claude-sonnet-4-20250514 200,000 ctx β’ Claude Sonnet 4
google gemini-2.5-pro reasoning β’ 1,000,000 ctx β’ Gemini 2.5 Pro
ollama-cloud glm-5.1 reasoning β’ 202,752 ctx β’ GLM 5.1pizzapi plugins
Section titled βpizzapi pluginsβDiscover and manage Claude Code plugins. PizzaPi can load plugins designed for Claude Code β their commands become slash commands, hooks map to pi lifecycle events, and skills are shared via the Agent Skills standard.
# List all discovered plugins (global + project-local)pizzapi plugins
# Trust all untrusted local plugins in the current projectpizzapi plugins trust
# Trust a specific plugin directorypizzapi plugins trust /path/to/plugin
# Remove a plugin from the trust listpizzapi plugins untrust /path/to/plugin
# Clear the entire trust listpizzapi plugins untrust
# Show the current trust listpizzapi plugins trusted
# Show helppizzapi plugins --help| Subcommand | Description |
|---|---|
(none) / list | List all discovered plugins with trust status |
trust [path] | Trust project-local plugins. No path = trust all untrusted in cwd. |
untrust [path] | Remove from trust list. No path = clear entire list. |
trusted | Show the current trust list from ~/.pizzapi/config.json |
marketplace add <source> | Add a marketplace (owner/repo, git URL, or local path) |
marketplace list | List registered marketplaces |
marketplace show <name> | List a marketplaceβs plugins |
marketplace remove <name> | Remove a marketplace and its clone |
install <name[@marketplace]> | Install and enable a plugin from a marketplace |
uninstall <name[@marketplace]> | Remove an installed plugin |
enable / disable <name[@marketplace]> | Toggle a plugin without uninstalling |
installed | List marketplace-installed plugins and their enabled state |
Marketplace state is shared with Claude Code (~/.claude/plugins/). The same operations are
available inside a session via the /plugin command, which also reloads session resources so a
newly installed plugin is usable right away.
Trust model:
- Global plugins in
~/.pizzapi/plugins/and~/.agents/plugins/are always auto-trusted β same as global skills or extensions. Claude Code marketplace plugins installed via~/.claude/plugins/installed_plugins.jsonare discovered through that manifest, not by scanning~/.claude/plugins/directly. - Project-local plugins in
.pizzapi/plugins/,.agents/plugins/, or.claude/plugins/under your project directory can execute shell commands via hooks. They require explicit trust before loading.
There are three ways to trust a local plugin:
- CLI:
pizza plugins trust(pre-approve before starting a session) - TUI: Interactive confirmation dialog at session start
- Web UI: Amber trust banner with Trust & Load / Skip buttons
Once approved by any method, the trust is persisted to ~/.pizzapi/config.json so future sessions auto-load without re-prompting.
pizzapi install, pizzapi remove, pizzapi update, pizzapi list, pizzapi config
Section titled βpizzapi install, pizzapi remove, pizzapi update, pizzapi list, pizzapi configβInstall, update, and manage pi packages β bundles of extensions, skills, prompt templates, and themes that extend the agent. These commands inherit the upstream pi package manager and store packages in ~/.pizzapi/settings.json (or .pizzapi/settings.json for project-local installs).
# Install a package from npm, git, or a local pathpizzapi install npm:@foo/pi-toolspizzapi install git:github.com/user/repopizzapi install ./local/path
# Install into the current project onlypizzapi install npm:@foo/pi-tools -l
# Remove a packagepizzapi remove npm:@foo/pi-toolspizzapi uninstall npm:@foo/pi-tools # alias for remove
# List installed packagespizzapi list
# Update installed packagespizzapi update --extensions
# Update everything (pi packages only; PizzaPi itself is updated via npm)pizzapi update
# Interactively enable/disable package resourcespizzapi config| Command | Description |
|---|---|
install <source> [-l] | Install a package and add it to settings |
remove <source> [-l] | Remove a package from settings |
uninstall <source> [-l] | Alias for remove |
update [source|self|pi] | Update installed packages (self forms print a note and exit; use npm install -g @pizzapi/pizza to update the wrapper) |
update --extensions | Update installed packages only |
update --self | Print a note and exit; self-update is disabled |
list | List installed packages |
config | Interactively enable or disable package resources |
All package commands accept -a/--approve, -na/--no-approve, and --cwd <path>. update additionally accepts --force and --extension <source>.
These commands accept --cwd <path> to target a different project directory and honor agentDir from ~/.pizzapi/config.json.
pizzapi --version
Section titled βpizzapi --versionβPrint the installed version number and exit.
pizzapi --version# pizzapi v1.2.3Agent Tools
Section titled βAgent ToolsβPizzaPi registers several tools that are available in every agent session:
| Tool | Description |
|---|---|
spawn_session | Spawn an independent linked child session on the runner |
list_models | List available models and providers |
set_session_name | Set the session display name |
update_todo | Update the sessionβs todo list |
subagent | Delegate tasks to specialized subagents with isolated context |
subagent
Section titled βsubagentβDelegate tasks to specialized agents in isolated in-process sessions. The tool returns immediately; each result is automatically delivered as a follow-up message when ready, so the parent can keep working without polling.
Modes:
- Single:
{ agent: "name", task: "..." }β invoke one agent - Parallel:
{ tasks: [...] }β run up to 8 agents concurrently, with at most 4 at once - Chain:
{ chain: [...] }β sequential execution with{previous}output substitution
Agent definitions are loaded from ~/.pizzapi/agents/*.md (user scope), ~/.claude/agents/*.md (user backward-compat), .pizzapi/agents/*.md (project scope), and .claude/agents/*.md (project backward-compat). Use agentScope: "both" (or "project") to include project-local definitions.
See the Subagents guide for full documentation.
Global Flags
Section titled βGlobal Flagsβ| Flag | Description |
|---|---|
--help, -h | Show help and exit |
--version, -v | Print version and exit |
--cwd <path> | Override working directory (applies to the default session command) |
Internal Commands
Section titled βInternal CommandsβThese commands are used internally by the daemon and should not be called directly:
| Command | Description |
|---|---|
pizzapi _daemon | Internal daemon entrypoint (spawned by the supervisor) |
pizzapi _worker | Internal worker entrypoint (spawned by the daemon for each session) |
pizzapi _terminal-worker | Internal terminal PTY worker (spawned by the daemon for terminal sessions) |