| name | review |
| description | Reviews code using pi CLI with read-only tools. Delegates the review to pi (dev/pi) with a structured review rubric, running in read-only mode to prevent accidental edits. By default reviews uncommitted working tree changes (git diff HEAD) with pi restricted to the read tool; explicit targets (--branch/--diff/@file/PR) or --explore widen pi to read,grep,find,ls. Use when the user asks to "review code with pi", "pi review", "have pi review", "let pi review", or invokes /pi:review. |
| user-invocable | true |
| argument-hint | [@target] [--branch BRANCH] [--diff RANGE] [--endpoint ENDPOINT] [--model MODEL] [--thinking LEVEL] [--explore] [--with-packages] | --edit-config [--local|--shared|--global] | --list-models |
| allowed-tools | ["Task","Bash(git:*)","Bash(jq:*)","Bash(ls:*)","Bash(find:*)","Bash(cat:*)","Bash(mkdir:*)","Bash(echo:*)","Bash(command -v:*)","Bash(mktemp:*)","Bash(rm:*)","Bash(mv:*)","Bash(sed:*)","Bash(grep:*)","Bash(head:*)","Bash(awk:*)","Bash(tr:*)","Bash(gh:*)","Bash(bash:*)","Bash(vi:*)","Read","Grep","Glob"] |
CRITICAL: pi Code Review
This skill delegates a code review to the pi CLI tool (@earendil-works/pi-coding-agent). pi runs with read-only tools to prevent accidental edits — it analyzes code and returns findings as text.
CRITICAL: The default review target is the uncommitted working tree (git diff HEAD), and pi must NOT be able to explore the whole codebase or run git itself. pi's --tools flag is a hard allowlist — only listed tools are registered (pi's built-in tools are read, grep, find, ls, bash, edit, write; there is no standalone git tool, but bash can run git diff). By default restrict pi to read only so it can inspect files mentioned in the diff but cannot find/grep/ls the repo or run bash/git. Only expand to read,grep,find,ls when an explicit target (--branch, --diff, PR number) or --explore requires it.
Before Execution: Check Installation
command -v pi >/dev/null 2>&1
If not installed, tell the user and stop.
Persistent Settings
User preferences persist across invocations via JSON files. The resolution chain (highest priority first):
- CLI flag (from
$ARGUMENTS)
.claude/pi.local.json — project-specific overrides, gitignored
.claude/pi.json — project shared defaults, committed
~/.claude/pi.local.json — global user-wide defaults
- Built-in defaults (listed below)
Settings files use the format below. Load references/settings.md for the full format, reading logic, --edit-config, and --list-models:
{
"endpoints": {
"my-proxy": {
"provider": "openai",
"baseUrl": "http://10.10.0.195:8317/v1",
"models": ["gemini-3.6-flash-high", "gemini-3.6-pro"]
}
},
"defaultEndpoint": "my-proxy",
"defaultModel": "gemini-3.6-flash-high"
}
Each endpoint key has provider (required), optional baseUrl, and models. Values may reference env vars via $VAR. Read the merged settings with the Reading settings snippet in references/settings.md — it yields ENDPOINT, MODEL, THINKING, PROVIDER, BASE_URL, API_KEY, WITH_PACKAGES.
Before parsing review targets, handle the two settings-only flags from references/settings.md and stop (do not proceed to review):
$ARGUMENTS is exactly --edit-config (with optional scope flag) → open the settings file (see references/settings.md).
$ARGUMENTS is exactly --list-models → print configured endpoints and models (see references/settings.md).
Argument Parsing
Parse $ARGUMENTS to extract the review target and optional flags. The target is everything before the first -- flag. If no flags are present, the entire argument is the target.
| Flag | Description | Source Priority |
|---|
--endpoint | Endpoint key name (must match a key in settings endpoints) | CLI > settings > defaultEndpoint |
--model | Model ID to use for this review | CLI > settings > (endpoint's first model) |
--thinking | Thinking level (off/minimal/low/medium/high/xhigh/max) | CLI > settings > max |
--explore | Force full read-only exploration tools (read,grep,find,ls) even for the default working-tree review. Without this, the default review gets read only. | CLI flag |
--with-packages | Load the user's global pi packages/skills/extensions (default is clean mode: off) | CLI > settings withPackages > false |
Resolution order per flag
For each flag, resolve the value by checking CLI flag first, then settings file, then built-in default:
- Parse
$ARGUMENTS for that flag. If present, use it.
- Otherwise, read from
$CONFIG (the merged settings). If non-null/non-empty, use it.
- Otherwise, use the built-in default.
Endpoint resolution
- If
--endpoint is specified, use it as the key into endpoints config.
- If
--model is specified without --endpoint, scan all endpoints for a model matching the ID — use the first match's endpoint.
- Otherwise, use
defaultEndpoint from settings.
- If the resolved model is empty, use the first model in the resolved endpoint's model list.
- Resolve the pi provider from the endpoint's
provider field (default openai).
Base URL resolution
The pi-agent handles baseUrl — it conditionally writes it into the agent-dir models.json (pi has no --base-url flag) only when it differs from the existing value. The skill just passes the resolved BASE_URL to the agent; it does not write models.json itself.
Review Target
Determine what to review from the parsed arguments. The target can be:
| Pattern | What it reviews | pi tools |
|---|
| No target (default) | git diff HEAD — uncommitted working tree changes (staged + unstaged) | read only |
--branch <name> | git diff main...<branch> | read,grep,find,ls |
--diff <range> | git diff <range> | read,grep,find,ls |
@filepath | Specific file(s) | read,grep,find,ls |
| PR number | gh pr diff <n> | read,grep,find,ls |
--explore (any target) | Overrides the tool set to full read-only exploration | read,grep,find,ls |
Resolution logic
- CRITICAL: Do NOT use
@. — pi does not support passing a directory path as @.. It will error with EISDIR.
- By default (no target), review uncommitted working tree changes — capture
git diff HEAD (staged + unstaged vs HEAD) and pass it to pi. If the diff is empty, report that the working tree is clean and stop. Restrict pi to --tools read so it cannot scan the codebase or run git.
- Only pass
@filepath references when the user explicitly names specific files (target starts with @).
- If the target is a number (e.g.
42), treat it as a GitHub PR number — fetch the diff with gh pr diff <n>.
- If the target starts with
--branch, extract the branch name and capture git diff main...<branch>.
- If the target starts with
--diff, extract the range and capture git diff <range>.
- Otherwise (free-text task description, e.g.
/pi:review "check the auth flow"), pass the text as the task description and still capture git diff HEAD as context so pi reviews your current changes in service of the stated task. Free-text only applies when there is no explicit target and no @file reference — leading tokens up to the first -- flag (so check auth --explore → task "check auth").
- Tool selection: default (no target) →
--tools read. Any explicit target (--branch, --diff, @filepath, PR number) → --tools read,grep,find,ls. If --explore appears in $ARGUMENTS → force --tools read,grep,find,ls regardless of target. Never include bash — the read-only review must not let pi run git or edit files.
File references (when user specifies @filepath)
When the user passes @filepath, pass those file paths directly to pi as @file.ts arguments. pi will read them.
Review Rubric (Embedded in Prompt)
The review prompt given to pi must cover these dimensions. Embed them as part of the task description, not as --append-system-prompt. See references/rubric.md for the full five-dimension rubric — the TASK prompt in the agent launch embeds a condensed version of it.
Context Collection
1. Pass CLAUDE.md as System Prompt Context
Always pass the CLAUDE.md files as system prompt context so pi understands the project and user conventions. --append-system-prompt accepts file paths directly — pi reads them automatically.
CRITICAL: do not accumulate the flags into a space-joined variable and expand it unquoted. Under zsh (the default shell on macOS) that expansion is a single argument, so pi receives the literal string --append-system-prompt /path/CLAUDE.md as one token and appends it as text instead of reading the file. The pi-agent assembles the command as an array, so the skill only needs to hand the agent the resolved context files:
APPEND_PATHS=()
[ -f "$HOME/.claude/CLAUDE.md" ] && APPEND_PATHS+=("$HOME/.claude/CLAUDE.md")
[ -f "CLAUDE.md" ] && APPEND_PATHS+=("CLAUDE.md")
2. Git Context
git status --short
git diff --stat
git log --oneline -20
git branch --show-current
3. Capture the diff
Capture the diff for the resolved target into a temp file, then pass its path via --append-system-prompt (pi reads file paths directly):
DIFF_FILE=$(mktemp /tmp/pi-review-diff.XXXXXX)
HAS_EXPLICIT_TARGET=""
TASK_TEXT=""
FILE_REFS=()
git diff HEAD > "$DIFF_FILE"
if [[ "$ARGUMENTS" == *"--branch"* ]]; then
HAS_EXPLICIT_TARGET="1"
BRANCH_NAME=$(echo "$ARGUMENTS" | sed -n 's/.*--branch[= ]\([^ ]*\).*/\1/p')
git diff main...${BRANCH_NAME//\"/} > "$DIFF_FILE"
fi
if [[ "$ARGUMENTS" == *"--diff"* ]]; then
HAS_EXPLICIT_TARGET="1"
RANGE=$(echo "$ARGUMENTS" | sed -n 's/.*--diff[= ]\([^ ]*\).*/\1/p')
git diff "${RANGE//\"/}" > "$DIFF_FILE"
fi
FIRST_TOKEN=$(echo "$ARGUMENTS" | awk '{print $1}')
if [[ "$FIRST_TOKEN" =~ ^[0-9]+$ ]];
HAS_EXPLICIT_TARGET=
gh diff >
[[ == ** ]];
HAS_EXPLICIT_TARGET=
: >
FILE_REFS=()
IFS= -r ref;
[ -n ] && FILE_REFS+=()
< <( | grep -oE || )
[ -z ] && [[ != ** ]];
TASK_TEXT=$( | sed -E | sed -E )
Then build the diff context — this MUST be run as actual commands in the same shell, not left as prose. Collect context file paths into APPEND_PATHS (CLAUDE.md files from step 1, plus the diff when present) so the pi-agent emits each as its own --append-system-prompt argument:
if [ -s "$DIFF_FILE" ]; then
APPEND_PATHS+=("$DIFF_FILE")
fi
Empty-diff guard (default target only): if git diff HEAD produces no output and no explicit target was given (HAS_EXPLICIT_TARGET empty), the working tree is clean — report "No uncommitted changes to review — the working tree is clean. Use /pi:review --branch <name>, /pi:review --diff <range>, or /pi:review <PR> to review committed code." and stop before invoking pi. Run the guard as a command:
if [ ! -s "$DIFF_FILE" ] && [ -z "$HAS_EXPLICIT_TARGET" ] && [ -z "$TASK_TEXT" ]; then
rm -f "$DIFF_FILE"
echo "No uncommitted changes to review — the working tree is clean. Use --branch, --diff, or a PR number."
exit 0
fi
Execution
Do NOT run pi directly. After resolving settings and capturing the review target, launch the dedicated pi:pi-agent execution layer with the Task tool. It builds the pi command, runs it in the background, and returns pi's stdout.
PREREQUISITE: run the "Reading settings" snippet from references/settings.md first — it defines $PROVIDER, $MODEL, $API_KEY, $THINKING. Then capture the diff (see "Context Collection") into $DIFF_FILE/$GIT_FILE, and resolve $TOOLS:
if [[ "$ARGUMENTS" == *"--explore"* ]] || [ -n "$HAS_EXPLICIT_TARGET" ]; then
TOOLS="read,grep,find,ls"
else
TOOLS="read"
fi
GIT_FILE=$(mktemp /tmp/pi-review-git.XXXXXX)
{ git status --short; git diff --stat; git log --oneline -20; git branch --show-current; } > "$GIT_FILE"
APPEND_PATHS+=("$GIT_FILE")
Then launch pi:pi-agent with the Task tool, passing:
MODE: review
TASK: Review the code in the provided diff${TASK_TEXT:+ (task: $TASK_TEXT)}. Use your tools only to read the files mentioned in the diff for context — do NOT search the rest of the codebase, do NOT run git. Focus on correctness, code quality, security, architecture, and testing. For each issue found, report: file:line: severity (HIGH/MEDIUM/LOW) + description + suggested fix. Group findings by severity. If no issues found, explicitly state that the code looks clean.
PROVIDER: <resolved from settings>
MODEL: <resolved from settings>
ENDPOINT: <resolved endpoint key or empty — lets the pi-agent read credentials from the right endpoint (non-secret)>
THINKING: <resolved, default max>
TOOLS: <$TOOLS — read, or read,grep,find,ls>
WITH_PACKAGES: <true if --with-packages or settings withPackages; empty/false = clean mode>
APPEND_PATHS: <$APPEND_PATHS — CLAUDE.md paths + GIT_FILE + DIFF_FILE; the agent emits each as its own --append-system-prompt>
FILE_REFS: <$FILE_REFS — @file args, one per line; omit if none>
CLEANUP_FILES: <$DIFF_FILE $GIT_FILE — the agent removes them when pi exits>
Do NOT pass API_KEY or BASE_URL — the pi-agent reads them from the settings files itself (so the actual key/URL never enters the model's context). The pi-agent emits --append-system-prompt for every APPEND_PATHS entry, writes baseUrl to the agent-dir models.json when it resolves one, runs pi in the background with --no-session --no-context-files --approve plus default clean mode (--no-extensions --no-skills unless WITH_PACKAGES=true), and reports pi's stdout — which is the review text.
Handling Output
CRITICAL: pi's stdout is the review text
Unlike /pi:delegate where pi edits files, review mode uses read-only tools (read, or read,grep,find,ls with an explicit target) — pi cannot write files or run bash. Its stdout IS the review output. The pi-agent returns this stdout; present it to the user.
On Success (exit code 0)
Present pi's output as the review findings. Format it clearly:
- If pi returned structured findings with severity, present them grouped by severity.
- If pi said "no issues found", report that the code looks clean.
- If stdout is empty but exit was 0, report: "pi completed the review but produced no output. This may indicate the model didn't understand the task. Consider retrying with a more specific prompt."
On Error (exit code 1+)
Show the error message from the pi-agent's report. Common causes:
- pi not configured (no API key)
- Provider/model not available
- Task interrupted or killed
Usage Examples
Review uncommitted working tree changes (default)
/pi:review
Reviews git diff HEAD — all staged and unstaged changes vs the last commit. If the working tree is clean, reports so and stops.
Review with a specific endpoint
/pi:review --endpoint openrouter
Review with a specific model
/pi:review --model gemini-3.6-pro
Review a specific branch
/pi:review --branch feat/new-widget --endpoint local-proxy --model gemini-3.6-flash-high
Review recent changes
/pi:review --diff HEAD~5..HEAD
Review a pull request
/pi:review 42
Review a specific file
/pi:review @src/core/agent.ts
Let pi freely explore the codebase (default review, expanded tools)
/pi:review --explore
Overrides the default read-only restriction to read,grep,find,ls for the working-tree review. pi still cannot edit files or run bash.
List configured endpoints
/pi:review --list-models
Edit project settings
/pi:review --edit-config
Important Notes
- pi runs with read-only tools — it cannot edit files or run bash.
- Default review is restricted to
--tools read — pi can read files mentioned in the diff but cannot grep/find/ls the codebase or run git, so it cannot silently review the whole repo. Explicit targets (--branch, --diff, @filepath, PR number) or --explore expand it to read,grep,find,ls.
- Default behavior reviews uncommitted working tree changes (
git diff HEAD, staged + unstaged). If the working tree is clean, the skill reports it and stops — use --branch <name>, --diff <range>, or a PR number to review committed code.
- Never run pi directly — always delegate to
pi:pi-agent. The agent is the plugin's single execution path and owns backgrounding, verification, and error handling.
- CLAUDE.md context is always passed by pi-agent via
--append-system-prompt as file paths — ~/.claude/CLAUDE.md (user global) and ./CLAUDE.md (project). pi reads them automatically.
- pi only knows built-in provider names (
openai, anthropic, google, etc.). The settings endpoints map is just for user convenience. The pi-agent writes baseUrl to the agent-dir models.json (default ~/.pi/agent/models.json, redirectable via PI_CODING_AGENT_DIR/AGENT_DIR) under the endpoint's provider field, then passes --provider <provider> to pi.
- No shell
timeout — reviews can be heavy and should run to completion.
- The review rubric is embedded in the task description, not
--append-system-prompt, to keep it in pi's context window.
- Git context and diffs go into
--append-system-prompt as structured context.
- PR review requires
gh CLI to be installed and authenticated.
- For large codebases, consider targeting a specific branch, diff range, or file to keep the review focused.