Try Live
Add Docs
Rankings
Pricing
Enterprise
Docs
Install
Theme
Install
Docs
Pricing
Enterprise
More...
More...
Try Live
Rankings
Create API Key
Add Docs
Plannotator
https://github.com/backnotprop/plannotator
Admin
Plannotator is an interactive plan and code review tool for AI coding agents that enables visual
...
Tokens:
89,760
Snippets:
1,164
Trust Score:
9.8
Update:
1 week ago
Context
Skills
Chat
Benchmark
77.5
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# Plannotator Plannotator is an interactive plan and code review tool designed for AI coding agents. It provides a visual browser-based UI for reviewing, annotating, and approving plans generated by AI assistants like Claude Code, Copilot CLI, Gemini CLI, OpenCode, Pi, and Codex. The tool intercepts agent plan submissions via hooks, presents them in a rich annotation interface, and sends structured feedback back to the agent for iterative refinement. The core functionality centers around three workflows: plan review (annotating agent-generated implementation plans), code review (reviewing git diffs or GitHub PRs with inline comments), and markdown annotation (reviewing any markdown file, HTML file, or URL). Plans can be shared via URL with end-to-end encryption, and annotations persist across sessions. The tool runs entirely locally with no server-side storage for the core review flow. ## Installation Install the `plannotator` CLI binary on macOS, Linux, or Windows. ```bash # macOS / Linux / WSL curl -fsSL https://plannotator.ai/install.sh | bash # Windows PowerShell irm https://plannotator.ai/install.ps1 | iex # Windows CMD curl -fsSL https://plannotator.ai/install.cmd -o install.cmd && install.cmd && del install.cmd # Pin a specific version curl -fsSL https://plannotator.ai/install.sh | bash -s -- --version v0.19.0 ``` ## Claude Code Plugin Installation Install Plannotator as a Claude Code plugin via the marketplace. ```bash # In Claude Code terminal /plugin marketplace add backnotprop/plannotator /plugin install plannotator@plannotator # Restart Claude Code after installation ``` ## Manual Hook Configuration for Claude Code Configure the ExitPlanMode hook manually in `~/.claude/settings.json` without using the plugin system. ```json { "hooks": { "PermissionRequest": [ { "matcher": "ExitPlanMode", "hooks": [ { "type": "command", "command": "plannotator", "timeout": 345600 } ] } ] } } ``` ## OpenCode Plugin Configuration Add Plannotator to your OpenCode configuration for plan review integration. ```json { "$schema": "https://opencode.ai/config.json", "plugin": ["@plannotator/opencode@latest"] } ``` ## Gemini CLI Hook Configuration Configure the BeforeTool hook for Gemini CLI in `~/.gemini/settings.json`. ```json { "hooks": { "BeforeTool": [ { "matcher": "exit_plan_mode", "hooks": [ { "type": "command", "command": "plannotator", "timeout": 345600 } ] } ] } } ``` ## Pi Extension Installation Install the Plannotator extension for Pi coding agent. ```bash # Install from npm pi install npm:@plannotator/pi-extension # Or try without installing pi -e npm:@plannotator/pi-extension # Start Pi in plan mode pi --plan # Toggle plan mode during session /plannotator # or Ctrl+Alt+P ``` ## Plan Review Command Plan review triggers automatically when the agent calls ExitPlanMode. The flow opens a browser UI for annotation. ```bash # Automatic flow (hook-triggered): # 1. Claude calls ExitPlanMode # 2. Hook intercepts, reads plan from stdin JSON # 3. Browser opens with annotation UI # 4. User reviews and annotates # 5. Approve -> agent proceeds # 6. Send Feedback -> annotations sent back # Direct invocation (expects JSON on stdin) echo '{"tool_input": {"plan": "# My Plan\n- Step 1\n- Step 2"}}' | plannotator ``` ## Code Review Slash Command Review local git changes or GitHub pull requests with inline annotations. ```bash # In agent session (Claude Code, Copilot, Gemini, OpenCode) /plannotator-review # Review uncommitted changes /plannotator-review https://github.com/owner/repo/pull/123 # Review a PR # Standalone CLI plannotator review # Review local changes plannotator review https://github.com/owner/repo/pull/123 # In Codex !plannotator review !plannotator review https://github.com/owner/repo/pull/123 ``` ## Annotate Markdown Command Open any markdown file, HTML file, URL, or folder in the annotation UI. ```bash # In agent session /plannotator-annotate README.md # Markdown file /plannotator-annotate docs/guide.html # HTML file (converts to markdown) /plannotator-annotate https://stripe.com/docs/api # URL (fetches via Jina Reader) /plannotator-annotate ./specs/ # Folder (opens file browser) # Standalone CLI plannotator annotate README.md plannotator annotate index.html plannotator annotate https://example.com/docs plannotator annotate ./docs/ # Disable Jina Reader for URL fetching plannotator annotate https://internal.company.com/docs --no-jina # In Codex !plannotator annotate path/to/file.md ``` ## Annotate Last Message Command Annotate the agent's most recent response with structured feedback. ```bash # In agent session /plannotator-last # Standalone CLI plannotator last # In Codex !plannotator last ``` ## Plan Review Server API The plan review server exposes REST endpoints for the browser UI. ```bash # Get plan content curl http://localhost:PORT/api/plan # Response: { "plan": "# Implementation Plan\n...", "origin": "claude" } # Approve plan curl -X POST http://localhost:PORT/api/approve \ -H "Content-Type: application/json" \ -d '{"savedPath": "/path/to/saved/plan.md"}' # Deny plan with feedback curl -X POST http://localhost:PORT/api/deny \ -H "Content-Type: application/json" \ -d '{"feedback": "# Plan Feedback\n\n## 1. Remove this\n```\nselected text\n```\n> I don'\''t want this."}' # Upload image attachment curl -X POST http://localhost:PORT/api/upload \ -F "file=@screenshot.png" # Response: { "path": "/tmp/plannotator-12345/screenshot.png" } # Get image by path curl "http://localhost:PORT/api/image?path=/tmp/plannotator-12345/screenshot.png" # Detect Obsidian vaults curl http://localhost:PORT/api/obsidian/vaults # Response: { "vaults": [{"name": "Notes", "path": "/Users/me/Notes"}] } ``` ## Code Review Server API The code review server provides endpoints for diff viewing and AI assistance. ```bash # Get diff content curl http://localhost:PORT/api/diff # Response: { "rawPatch": "diff --git...", "gitRef": "HEAD", "origin": "local" } # Submit review feedback curl -X POST http://localhost:PORT/api/feedback \ -H "Content-Type: application/json" \ -d '{"feedback": "# Code Review Feedback\n\n## src/auth.ts:42\n> Add error handling here"}' # Check available AI providers curl http://localhost:PORT/api/ai/capabilities # Response: { "providers": ["claude", "codex", "pi", "opencode"] } # Create AI chat session curl -X POST http://localhost:PORT/api/ai/session \ -H "Content-Type: application/json" \ -d '{"provider": "claude"}' # Response: { "sessionId": "abc123" } # Send AI query (SSE stream) curl -X POST http://localhost:PORT/api/ai/query \ -H "Content-Type: application/json" \ -d '{"sessionId": "abc123", "prompt": "Explain this function", "context": {"file": "auth.ts", "lines": "40-50"}}' # Abort AI query curl -X POST http://localhost:PORT/api/ai/abort \ -H "Content-Type: application/json" \ -d '{"sessionId": "abc123"}' ``` ## Annotate Server API The annotate server provides endpoints for file annotation workflows. ```bash # Get annotate content curl http://localhost:PORT/api/plan # Response: { "plan": "# README\n...", "mode": "annotate", "filePath": "/path/to/file.md", "sourceInfo": {"type": "file", "name": "README.md"} } # Submit annotations curl -X POST http://localhost:PORT/api/feedback \ -H "Content-Type: application/json" \ -d '{"feedback": "# Annotations\n\n## 1. Comment on: \"API endpoint\"\n> Add rate limiting docs"}' # Exit session without feedback curl -X POST http://localhost:PORT/api/exit # Auto-save draft curl -X POST http://localhost:PORT/api/draft \ -H "Content-Type: application/json" \ -d '{"annotations": [{"type": "comment", "text": "selected text", "comment": "my note"}]}' # Get saved draft curl http://localhost:PORT/api/draft # Delete draft curl -X DELETE http://localhost:PORT/api/draft ``` ## Paste Service API The paste service provides end-to-end encrypted short URLs for large plans. ```bash # Create a paste (max 512KB, expires in 7 days) curl -X POST https://plannotator-paste.plannotator.workers.dev/api/paste \ -H "Content-Type: application/json" \ -d '{"data": "base64url-encoded-encrypted-payload"}' # Response: { "id": "aBcDeFgH" } # Retrieve a paste curl https://plannotator-paste.plannotator.workers.dev/api/paste/aBcDeFgH # Response: { "data": "base64url-encoded-encrypted-payload" } # 404 if expired or not found ``` ## Pi Extension Event API Extensions can use the shared event channel to trigger Plannotator flows. ```javascript // Plan review request pi.emit("plannotator:request", { action: "plan-review", payload: { planContent: "# My Plan\n- Step 1\n- Step 2", planFilePath: "/path/to/plan.md" } }); // Immediate response: { status: "handled", result: { status: "pending", reviewId: "abc123" } } // Listen for review result pi.on("plannotator:review-result", (event) => { // { reviewId: "abc123", approved: true, feedback: null, savedPath: "/plans/approved.md" } // or { reviewId: "abc123", approved: false, feedback: "# Feedback\n..." } }); // Check review status pi.emit("plannotator:request", { action: "review-status", payload: { reviewId: "abc123" } }); // Code review request pi.emit("plannotator:request", { action: "code-review", payload: { cwd: "/project", defaultBranch: "main", diffType: "uncommitted" } }); // Annotate file request pi.emit("plannotator:request", { action: "annotate", payload: { filePath: "/path/to/file.md", markdown: true } }); // Annotate last message pi.emit("plannotator:request", { action: "annotate-last", payload: { markdown: true } }); // Open archive browser pi.emit("plannotator:request", { action: "archive", payload: { customPlanPath: "/custom/plans/" } }); ``` ## Pi Extension Configuration Configure per-phase behavior in `plannotator.json` (project-local, global, or built-in). ```json { "defaults": { "model": { "provider": "anthropic", "id": "claude-sonnet-4-5" }, "thinking": "medium", "activeTools": ["read", "bash"], "statusLabel": "Ready", "systemPrompt": "You are a helpful assistant." }, "phases": { "planning": { "model": null, "thinking": null, "activeTools": ["grep", "find", "ls", "plannotator_submit_plan"], "statusLabel": "Planning", "systemPrompt": "[PLANNING]\nPlan file: ${planFilePath}\n\nWrite a detailed plan using markdown checklists." }, "executing": { "model": { "provider": "anthropic", "id": "claude-sonnet-4-5" }, "thinking": "high", "activeTools": [], "statusLabel": "", "systemPrompt": "[EXECUTING]\nProgress: ${completedCount}/${totalCount}\nRemaining:\n${todoList}" }, "reviewing": { "systemPrompt": "Review the completed work." } } } ``` ## Environment Variables Configure Plannotator behavior via environment variables. ```bash # Core configuration export PLANNOTATOR_REMOTE=1 # Force remote mode (SSH/devcontainer) export PLANNOTATOR_PORT=9999 # Fixed server port export PLANNOTATOR_BROWSER="Google Chrome" # Custom browser export PLANNOTATOR_SHARE=disabled # Disable sharing export PLANNOTATOR_SHARE_URL="https://share.mycompany.com" # Self-hosted share portal # Annotation configuration export PLANNOTATOR_JINA=0 # Disable Jina Reader for URLs export JINA_API_KEY="jina_abc123" # Jina API key for higher rate limits # Paste service (self-hosted) export PLANNOTATOR_PASTE_URL="https://paste.mycompany.com" export PASTE_PORT=19433 export PASTE_DATA_DIR=~/.plannotator/pastes export PASTE_TTL_DAYS=7 export PASTE_MAX_SIZE=524288 export PASTE_ALLOWED_ORIGINS="https://share.mycompany.com" # OpenCode specific export PLANNOTATOR_PLAN_TIMEOUT_SECONDS=345600 # 96 hours # Install script export CLAUDE_CONFIG_DIR=~/.custom-claude # Custom Claude config directory ``` ## Devcontainer Configuration Configure Plannotator for containerized development environments. ```json { "containerEnv": { "PLANNOTATOR_REMOTE": "1", "PLANNOTATOR_PORT": "9999" }, "forwardPorts": [9999], "postCreateCommand": "curl -fsSL https://plannotator.ai/install.sh | bash" } ``` ## SSH Port Forwarding Configure SSH port forwarding for remote Plannotator access. ```bash # ~/.ssh/config Host your-server HostName server.example.com User developer LocalForward 9999 localhost:9999 # Connect and use Plannotator ssh your-server export PLANNOTATOR_REMOTE=1 export PLANNOTATOR_PORT=9999 # Open http://localhost:9999 in local browser when prompted ``` ## Feedback Output Format Annotations are exported as structured markdown for agent consumption. ```markdown # Plan Feedback I've reviewed this plan and have 3 pieces of feedback: ## 1. Remove this ``` the selected text to remove ``` > Reason: This step is unnecessary given our existing authentication. ## 2. Replace "WebSocket connection" with: ``` Server-Sent Events (SSE) connection ``` > SSE is simpler and sufficient for one-way updates. ## 3. Feedback on: "Add error handling" > Please be more specific about which errors to catch and how to handle each case. ## Global feedback > Overall the plan looks good, but please add a section about rollback procedures. --- ``` Plannotator serves as a critical human-in-the-loop interface for AI coding agents, ensuring that generated plans are reviewed and refined before execution. The tool bridges the gap between AI-generated code plans and human oversight by providing rich annotation capabilities, collaborative sharing, and structured feedback loops. The integration patterns span multiple AI coding environments through a consistent plugin/hook architecture. Whether using Claude Code's ExitPlanMode hook, OpenCode's submit_plan tool, Gemini CLI's BeforeTool hook, or Pi's extension system, the workflow remains consistent: agent generates plan, hook intercepts, browser UI opens, human reviews, feedback returns. This standardized approach allows teams to adopt Plannotator across their entire AI-assisted development workflow while maintaining consistent review processes and annotation formats.