Plannotator

repository·main·Indexed 27 days ago

https://github.com/backnotprop/plannotator

A local, browser-based review surface for AI coding agents that allows developers to visually annotate plans, markdown, code diffs, and HTML artifacts. It provides structured feedback to agents to drive implementation and integrates with tools including Claude Code (via Amp), Codex, GitHub Copilot CLI, Droid, and Gemini CLI. Version 0.25.0.

Tokens
110.7K
Snippets
253
Records
634
Agent score
92%

What's inside plannotator

  1. Overview of Plannotator features

    main

    Plannotator is a plan review UI designed for Claude Code that intercepts ExitPlanMode via hooks. It provides an interactive browser-based interface to review plans, select text for annotations, and provide structured feedback such as deletions, comments, global comments, quick labels, and "looks good" approvals.

    Key Capabilities:

    • Plan Review: Intercepts ExitPlanMode to open a rich annotation UI.
    • Code Review: Review uncommitted changes using a diff viewer.
    • Markdown Annotation: Annotate any markdown file.
    • Sharing: Share plans and annotations via URL without requiring a backend.
    • Obsidian Integration: Automatically saves reviewed plans to your Obsidian vault.
  2. Understand Plannotator System Components

    main

    The Plannotator system consists of three components. You only need the Hook for basic functionality, but the Share Portal and Paste Service enable advanced sharing capabilities.

    ComponentRequiredDescription
    HookYesA local binary that intercepts ExitPlanMode and runs the review UI.
    Share PortalOptionalA static site that renders shared plans. This is what users see in their browser when opening a share link.
    Paste ServiceOptionalA storage backend for the Share Portal. It holds compressed, encrypted data for large plans that cannot fit in a URL.

    Sharing Logic

    • Small plans: Encoded entirely in the URL hash. No backend is required, and data remains private as it never leaves the URL.
    • Large plans: Encrypted in the browser (AES-256-GCM) and sent to the Paste Service. The service only stores ciphertext. The decryption key is passed via the URL fragment (#key=...) and is never sent to the server, ensuring end-to-end encryption.
  3. Understand Live PR Context Update Behavior

    main

    Plannotator implements a server-side live context model for Pull Requests (PRs) to ensure data freshness without multiplying provider traffic (GitHub/GitLab).

    Key behaviors include:

    • Automatic Subscriptions: When a PR-mode browser tab is open, it automatically subscribes to context updates via SSE (Server-Sent Events).
    • Interval Refreshing: The server refreshes the watched PR on a fixed interval (defaulting to 30 seconds).
    • Single Refresh per URL: Multiple tabs open on the same PR URL share a single server-side refresh to minimize rate-limit risks.
    • Action-Triggered Refresh: Posting a review or comment via /api/pr-action triggers an immediate PR refresh and broadcast.
    • Lifecycle Management: The refresh timer stops when no tabs are watching a PR, but the last successful value is kept in the session cache.
    • Error Handling: If a provider fails, the system shows the last successful value along with an error/stale state and retries automatically (respecting rate limits).
  4. Design Philosophy for Visual Explainers

    main

    When creating any visual content (Plans, PRs, or General), adhere to these core principles:

    • Whitespace is a feature: Use generous padding and large section gaps. If content feels cramped, increase space rather than shrinking text.
    • One idea per viewport: Structure content so that only one major idea (e.g., a hero section, a diagram, or a detail grid) is prominent at a time.
    • Show, don't describe: Use timelines for sequencing, diagrams for relationships, and code blocks for interfaces instead of long prose descriptions.
    • No time estimates: Timelines should show phases and dependencies only. Never include hour or day estimates.
  5. Understand the Plannotator prompt structure

    main

    Plannotator's review agents (Claude, Codex, and Code Tour) structure their requests using three distinct layers. This ensures that the agentic exploration of the CLI is combined with a machine-readable output format.

    1. System prompt: Owned and managed by the underlying CLI (e.g., Claude Code or codex-rs). Plannotator does not modify this.
    2. User message: A single concatenated string sent by Plannotator consisting of a static review prompt and a dynamic user prompt, separated by ---.
    3. Output schema: A JSON schema passed as a flag to the CLI to force the final assistant response into a specific, machine-readable shape.
  6. Understand the Plannotator for Pi state machine

    main

    The extension manages a state machine that controls agent capabilities.

    Default behavior: idleplanningexecutingidle.

    With external execution enabled: idleplanningidle (emits a handoff event).

    Capabilities by state:

    • Planning: All tools from other extensions remain available. Bash is unrestricted (though the system prompt guides the agent to avoid destructive commands). Writes and edits are restricted to the plan file only.
    • Executing: Full tool access is granted (read, bash, edit, write). Progress is tracked using [DONE:n] markers in agent responses. The plan is re-read from disk during every turn to ensure synchronization.
  7. Understand the Code Tour provider pattern

    main
    The Code Tour provider follows a specific pattern for implementing agent-based review features. It encapsulates the system prompt, JSON schema, user-message construction, CLI command building (for both Claude and Codex engines), and output parsing within a single module. This module is managed via a session object that provides a unified interface for the jobs engine to interact with, handling both command generation and result parsing.
  8. Understand Agent Terminal Runtime Architecture

    main

    The Agent Terminal feature uses a hybrid runtime model to ensure production reliability:

    1. Plannotator (Bun): Acts as the main server and owns the browser-facing API endpoints.
    2. Node.js Sidecar: A separate process (agent-terminal-node-sidecar.mjs) that manages the actual PTY. This is necessary because the PTY requires Node.js modules like node-pty and ws which cannot be imported from Bun's virtual filesystem.
    3. WebTUI: Provides the terminal behavior and UI logic via @plannotator/webtui.

    In production, the Node sidecar runs from a managed directory (typically ~/.plannotator/vendor/agent-terminal/) to ensure all dependencies are available on disk.

  9. Analyze Plannotator plan archives with plannotator-compound

    main

    The plannotator-compound skill performs a multi-phase research analysis of a user's Plannotator plan archive. It extracts denial patterns, feedback taxonomy, and evolution over time to produce an HTML dashboard report.

    Supported Data Sources:

    1. Plannotator mode (Primary): Uses the directory specified by $PLANNOTATOR_DATA_DIR (defaults to ~/.plannotator). It looks for *-denied.md files in the plans/ subdirectory.
    2. Claude Code fallback mode: If Plannotator data is missing, it uses the bundled parser scripts/extract_exit_plan_mode_outcomes.py to extract denial reasons from Claude Code JSONL transcripts located in ~/.claude/projects/.
    3. Manual: If neither is found, the user must provide the directory path.
    --- 
    name: plannotator-compound
    disable-model-invocation: true
    description: >
      Analyze a user's Plannotator plan archive to extract denial patterns, feedback
      taxonomy, evolution over time, and actionable prompt improvements — then produce
      a polished HTML dashboard report. Falls back to Claude Code ExitPlanMode denial
      reasons when Plannotator data is unavailable.
    ---
  10. Share plans with teammates

    main

    You can share plans via room.plannotator.ai.

    • Small plans: Encoded in the URL hash (no server involved).
    • Large plans: Encrypted with AES-256-GCM and sent via a short-link service. The server only stores ciphertext; the key remains in your URL fragment.

    To disable sharing entirely, set the environment variable PLANNOTATOR_SHARE=disabled.

  11. Integrate Guided Review UI using the Layout Takeover pattern

    main

    The Guided Review UI is implemented as a layout branch in App.tsx rather than an overlay. To prevent destroying the existing panel/tab layout (which happens if <DockviewReact> is unmounted), the takeover must CSS-hide the dock wrapper and the file tree instead of unmounting them.

    Key implementation details:

    • The guide is a conditional branch in the main content row in App.tsx (around line 2671).
    • Use CSS to hide the dock (e.g., App.tsx:2793) to keep diff-switch epoch guards and draft deduplication decoupled from the guideOpen state.
    • The guide surface consumes the single SSE connection from useAgentJobs() via props or context.
  12. Setup Plannotator in Devcontainers or Docker

    main

    To use Plannotator in containerized environments, set the PLANNOTATOR_REMOTE and PLANNOTATOR_PORT environment variables and forward the specified port. If the browser does not open automatically, manually navigate to http://localhost:<PORT> when submit_plan is called.

    {
      "containerEnv": {
        "PLANNOTATOR_REMOTE": "1",
        "PLANNOTATOR_PORT": "9999"
      },
      "forwardPorts": [9999]
    }