Curated Claude Code catalog
Updated 07.05.2026 · 19:39 CET
01 / Skill
backnotprop

plannotator

Quality
9.0

Plannotator provides a visual UI to mark up and refine AI agent plans or code diffs, offering precise, structured feedback. It excels for developers needing to guide AI coding agents effectively and collaborate with teams on complex development tasks.

USP

It uniquely supports multiple CLIs (Claude Code, Copilot, Gemini, OpenCode, Pi, Codex) with a visual annotation UI and secure, end-to-end encrypted sharing for team collaboration without server-side data storage.

Use cases

  • 01Reviewing AI agent development plans
  • 02Providing structured feedback to AI agents
  • 03Collaborating on code reviews
  • 04Annotating files or URLs for agent context
  • 05Reviewing GitHub pull requests

Detected files (8)

  • apps/skills/plannotator-annotate/SKILL.mdskill
    Show content (677 bytes)
    ---
    name: plannotator-annotate
    description: Open Plannotator's annotation UI for a markdown file, converted HTML file, URL, or folder and then respond to the returned annotations.
    ---
    
    # Plannotator Annotate
    
    Use this skill when the user wants to annotate a document in Plannotator instead of reviewing it inline in chat.
    
    Run:
    
    ```bash
    plannotator annotate <path-or-url>
    ```
    
    Behavior:
    
    1. Launch the command with Bash.
    2. Wait for the browser review to finish.
    3. If annotations are returned, address them directly.
    4. If the session closes without feedback, say so briefly and continue.
    
    Do not ask the user to paste a shell command into the chat. Run the command yourself.
    
  • .agents/skills/pierre-guard/SKILL.mdskill
    Show content (6925 bytes)
    ---
    name: pierre-guard
    description: Guard against breaking the @pierre/diffs integration in Plannotator's code review UI. Use this skill whenever modifying DiffViewer.tsx, upgrading the @pierre/diffs package, changing unsafeCSS injection, adding new props to FileDiff, or touching shadow DOM selectors or CSS variables that cross into Pierre's shadow boundary. Also trigger when someone asks "will this break the diff viewer", "is this safe to change", or when reviewing PRs that touch the review-editor package.
    ---
    
    # Pierre Integration Guard
    
    Plannotator's code review UI wraps `@pierre/diffs` — an open-source diff renderer that uses Shadow DOM. The integration is concentrated in a single file but relies on undocumented internals (shadow DOM selectors, CSS variable names, grid layout assumptions). This skill helps verify changes don't break that contract.
    
    ## Source of Truth
    
    - **Upstream repo**: https://github.com/pierrecomputer/pierre/tree/main/packages/diffs
    - **Local types**: `node_modules/@pierre/diffs/dist/` (`.d.ts` files)
    - **Integration point**: `packages/review-editor/components/DiffViewer.tsx`
    - **Current version**: check `packages/review-editor/package.json` for the pinned version
    
    Always verify against the upstream repo or local `.d.ts` files — don't rely on memory of the API shape.
    
    ## What We Import
    
    ```typescript
    import { FileDiff } from '@pierre/diffs/react';
    import { getSingularPatch, processFile } from '@pierre/diffs';
    ```
    
    These are the only three imports. `DiffViewer.tsx` is the only file that touches Pierre.
    
    ## API Surface to Guard
    
    ### 1. Component Props (`FileDiff`)
    
    Read the current prop types from `node_modules/@pierre/diffs/dist/react/index.d.ts` or the upstream source. The props we use:
    
    | Prop | Type | Notes |
    |------|------|-------|
    | `fileDiff` | `FileDiffMetadata` | From `getSingularPatch()` or `processFile()` |
    | `options` | `FileDiffOptions<T>` | See options table below |
    | `lineAnnotations` | `DiffLineAnnotation<T>[]` | `{ side, lineNumber, metadata }` |
    | `selectedLines` | `SelectedLineRange \| null` | `{ start, end, side }` |
    | `renderAnnotation` | `(ann) => ReactNode` | Custom inline annotation renderer |
    | `renderHoverUtility` | `(getHoveredLine) => ReactNode` | The `+` button on hover (deprecated upstream — watch for removal) |
    
    ### 2. Options Object
    
    | Option | Value We Pass | Risk |
    |--------|--------------|------|
    | `themeType` | `'dark' \| 'light'` | Low — standard enum |
    | `unsafeCSS` | CSS string | **High** — targets internal selectors |
    | `diffStyle` | `'split' \| 'unified'` | Low — standard enum |
    | `diffIndicators` | `'bars'` | Low |
    | `hunkSeparators` | `'line-info'` | Low |
    | `enableLineSelection` | `true` | Low |
    | `enableHoverUtility` | `true` | Medium — deprecated prop |
    | `onLineSelectionEnd` | callback | Medium — signature could change |
    
    ### 3. Shadow DOM Selectors (via `unsafeCSS`)
    
    These are the selectors we inject CSS rules against. They target `data-*` attributes inside Pierre's shadow DOM. If Pierre renames or removes any of these, our styling breaks silently.
    
    **Currently used:**
    - `:host` — shadow root
    - `[data-diff]` — root diff container
    - `[data-file]` — file wrapper
    - `[data-diffs-header]` — header bar
    - `[data-error-wrapper]` — error display
    - `[data-virtualizer-buffer]` — virtual scroll buffer
    - `[data-file-info]` — file metadata row
    - `[data-column-number]` — line number gutter
    - `[data-diffs-header] [data-title]` — title (we hide it)
    - `[data-diff-type='split']` — split layout mode
    - `[data-overflow='scroll']` / `[data-overflow='wrap']` — overflow mode
    
    ### 4. CSS Variables We Override
    
    We override these `--diffs-*` variables to theme Pierre:
    
    - `--diffs-bg`, `--diffs-fg` — base colors
    - `--diffs-dark-bg`, `--diffs-light-bg` — theme-specific backgrounds
    - `--diffs-dark`, `--diffs-light` — theme-specific foregrounds
    
    ### 5. CSS Variables We Inject (Custom)
    
    We set these on a wrapper div outside the shadow DOM, relying on CSS custom property inheritance:
    
    - `--split-left`, `--split-right` — control the split pane grid ratio
    
    The `unsafeCSS` grid override references these: `grid-template-columns: var(--split-left, 1fr) var(--split-right, 1fr)`. The `1fr` fallback ensures the layout is safe if the variables aren't set.
    
    ### 6. Grid Layout Assumption
    
    Pierre's split view uses CSS Grid with `grid-template-columns: 1fr 1fr`. We override this for the resizable split pane. If Pierre changes its layout engine (e.g., to flexbox or a different grid structure), the override will stop working.
    
    **How to verify:** In the upstream source, search for `grid-template-columns` in the diff component styles.
    
    ## Verification Checklist
    
    When reviewing changes that touch the Pierre integration, check:
    
    ### Props & Types
    - [ ] Read the current `.d.ts` files to confirm prop names and types haven't changed
    - [ ] Check if `renderHoverUtility` is still supported (it's deprecated — may be removed)
    - [ ] Verify `DiffLineAnnotation` still uses `side: 'deletions' | 'additions'` (not `'old' | 'new'`)
    - [ ] Confirm `SelectedLineRange` shape: `{ start, end, side? }`
    
    ### Shadow DOM Selectors
    - [ ] Grep the upstream source for each `data-*` attribute we target in `unsafeCSS`
    - [ ] If upgrading the package version, diff the old and new CSS/HTML output for renamed attributes
    - [ ] Test both `split` and `unified` views — selectors are layout-dependent
    
    ### CSS Variables
    - [ ] Grep upstream for `--diffs-bg`, `--diffs-fg`, and other variables we override
    - [ ] Verify the variable names haven't been renamed or removed
    - [ ] Check that `!important` is still needed (Pierre may change specificity)
    
    ### Theme Compliance
    - [ ] New UI elements must use theme tokens (`bg-border`, `bg-primary`, etc.), not hardcoded colors like `bg-blue-500`
    - [ ] The existing `ResizeHandle` component in `packages/ui/components/ResizeHandle.tsx` sets the visual convention — match it
    
    ### Build & Runtime
    - [ ] Run `bun run dev:review` and verify the diff renders in both split and unified modes
    - [ ] Check the browser console for Pierre warnings (e.g., `parseLineType: Invalid firstChar`)
    - [ ] Test with add-only and delete-only files (Pierre doesn't render split grid for these)
    - [ ] If changing UI code, remember build order: `bun run --cwd apps/review build && bun run build:hook`
    
    ## When Upgrading @pierre/diffs
    
    1. Check the upstream changelog / commit history at https://github.com/pierrecomputer/pierre
    2. Diff the `.d.ts` files between old and new versions:
       ```bash
       # Before upgrading, snapshot current types
       cp -r node_modules/@pierre/diffs/dist /tmp/pierre-old
       # After upgrading
       diff -r /tmp/pierre-old node_modules/@pierre/diffs/dist
       ```
    3. Search for renamed/removed data attributes in the new version
    4. Run through the full verification checklist above
    5. Test the resizable split pane — it depends on grid layout internals
    
  • .agents/skills/release/SKILL.mdskill
    Show content (12500 bytes)
    ---
    name: release-plannotator
    description: Prepare and execute a Plannotator release — draft release notes with full contributor credit, bump versions across all package files, build in dependency order, and kick off the tag-driven release pipeline. Use this skill whenever the user mentions preparing a release, bumping versions, writing release notes, tagging a release, or publishing. Also trigger when the user says things like "let's ship", "prep a release", "what's changed since last release", or "time to cut a new version".
    ---
    
    # Plannotator Release
    
    The process has four phases. Phase 1 (release notes) is where most of the work happens — present the draft for review before proceeding to later phases.
    
    ## Phase 1: Draft Release Notes
    
    This is the most important phase. The release notes are the public face of each version and the primary way the community sees their contributions recognized.
    
    ### Step 1: Determine scope
    
    1. Find the latest release tag: `git tag --sort=-v:refname | head -1`
    2. Determine the new version number. Ask the user if unclear (patch, minor, or major).
    3. Gather all changes since the last tag:
       - `git log --oneline <last-tag>..HEAD` for commit history
       - `git log --merges --oneline <last-tag>..HEAD` for merged PRs
    4. For each PR, use `gh pr view <number> --json title,author,body,closedIssues,labels` to get details.
    
    ### Step 2: Research contributors
    
    This is critical. Every person who participated in the release gets credit — not just PR authors.
    
    For each PR and linked issue, collect:
    - **PR authors** — the person who wrote the code
    - **Issue reporters** — who filed the bug or feature request
    - **Issue commenters** — who participated in the discussion with useful context
    - **Discussion creators** — who started relevant GitHub Discussions
    - **Feature requestors** — check the linked "closes #N" issues and their authors
    
    Use the GitHub API via `gh`:
    ```bash
    # Get issue details including author
    gh issue view <number> --json author,title,body
    
    # Get issue comments to find participants
    gh api repos/backnotprop/plannotator/issues/<number>/comments --jq '.[].user.login'
    
    # Get PR review comments
    gh api repos/backnotprop/plannotator/pulls/<number>/comments --jq '.[].user.login'
    ```
    
    ### Step 3: Write the release notes
    
    Read the reference release notes in `references/` for the canonical template structure. These are real release notes from previous versions — match their tone, structure, and level of detail.
    
    - `release-notes-v0.13.0.md` — large release, 14 PRs, 3 first-time contributors, "New Contributors" + narrative "Contributors" section
    - `release-notes-v0.12.0.md` — large community release, 14 PRs, 10 external, detailed narrative "Contributors" section
    - `release-notes-v0.13.1.md` — small patch release, 2 PRs, no external authors, "Community" section focused on issue reporters
    
    Pay attention to how each reference handles contributor crediting differently. Pick the pattern that fits the release's contributor profile — a release with many external PRs warrants a narrative "Contributors" section; a patch driven by issue reports uses a lighter "Community" section.
    
    Write the file to the repo root as `RELEASE_NOTES_v<VERSION>.md`.
    
    #### Structure
    
    1. **X/Twitter follow link** — first line, always the same:
       ```
       Follow [@plannotator](https://x.com/plannotator) on X for updates
       ```
    
    2. **"Missed recent releases?"** collapsible table — copy from the previous release's notes, then:
       - Add the previous release (the one you're succeeding) as the newest row
       - Keep roughly 10-12 rows; drop the oldest if needed
       - Each row: version link + comma-separated feature highlights (short phrases)
    
    3. **"What's New in vX.Y.Z"** — the heart of the notes
       - Open with 1-3 sentences summarizing the release theme and scope. Mention how many PRs, how many from external contributors, any first-timers.
       - Each major feature/fix gets its own `###` subsection with:
         - A descriptive heading (not the PR title verbatim — rephrase for clarity)
         - 1-4 paragraphs explaining what changed and why it matters. Be specific and concrete. Describe the problem that existed before, what the change does, and how users experience it.
         - Credit line at the bottom: PR link, linked issues with `closing [#N]`, and contributor attribution
       - Minor changes go under `### Additional Changes` as bold-titled bullets
    
    4. **Install / Update** — standard block, read from the previous release notes and reuse verbatim
    
    5. **"What's Changed"** — bullet list of every PR in the release:
       ```
       - feat: descriptive PR title by @author in [#N](url)
       ```
    
    6. **"New Contributors"** — if any first-time contributors:
       ```
       - @username made their first contribution in [#N](url)
       ```
    
    7. **"Contributors" or "Community"** — narrative section recognizing everyone who participated:
       - PR authors get a sentence about what they built
       - Issue reporters and commenters get listed with what they reported/discussed
       - Group community issue reporters in a bullet list at the end
    
    8. **Full Changelog link**:
       ```
       **Full Changelog**: https://github.com/backnotprop/plannotator/compare/<prev-tag>...<new-tag>
       ```
    
    #### Writing guidelines
    
    - **Narrative over noise.** Write in clear, readable prose. Not marketing-speak, not changelog-dump. Explain what changed and why someone should care, in plain language.
    - **Bullets where they help.** Use bullet lists for enumerating discrete items (additional changes, contributor lists). Use paragraphs for explaining features.
    - **No cliches or buzzwords.** Don't say "exciting", "game-changing", "seamless", "powerful". Just describe what happened.
    - **No punchlines.** Don't end sections with a clever quip or a summary zinger. Let the feature speak for itself.
    - **Speak through practical benefit.** Describe what changed and what it means for the user in concrete, reliable terms. Not aspirational, not hype — just what it does.
    - **Don't overuse em dashes.** One or two per release is fine. If you notice them stacking up, restructure the sentence instead.
    - **Grammatical structure matters.** Vary sentence structure. Active voice. Concrete subjects and verbs.
    - **Contributor tags.** Use `@username` — bare at-mentions, not markdown links like `[@user](url)`. GitHub renders bare `@mentions` with avatar icons in release notes. This is important for community recognition.
    - **Every contributor counts.** Everyone who filed an issue, left a comment that shaped a decision, or participated in a discussion gets mentioned. This project's community is its lifeblood.
    
    ### Step 4: Present for review
    
    Write the draft to `RELEASE_NOTES_v<VERSION>.md` in the repo root and tell the user it's ready for review. Do not `git add` or commit this file — release notes are kept untracked by design. Wait for their feedback before proceeding to Phase 2.
    
    ---
    
    ## Phase 2: Version Bump
    
    Bump the version string in these **7 files** (and only these — other package.json files use stub versions):
    
    | File | Field |
    |------|-------|
    | `package.json` (root) | `"version"` |
    | `apps/opencode-plugin/package.json` | `"version"` |
    | `apps/pi-extension/package.json` | `"version"` |
    | `apps/hook/.claude-plugin/plugin.json` | `"version"` |
    | `apps/copilot/plugin.json` | `"version"` |
    | `openpackage.yml` (root) | `version:` |
    | `packages/server/package.json` | `"version"` |
    
    Read each file, confirm the current version matches expectations, then update all 7 atomically.
    
    Do not bump the VS Code extension (`apps/vscode-extension/package.json`) — it has independent versioning.
    
    ---
    
    ## Phase 3: Build
    
    Run builds in dependency order:
    
    ```bash
    bun run build:review    # 1. Code review editor (standalone Vite build)
    bun run build:hook      # 2. Plan review + hook server (copies review's built HTML into hook dist)
    bun run build:opencode  # 3. OpenCode plugin (copies built HTML from hook + review)
    bun run build:pi        # 4. Pi extension (chains review → hook → pi internally, safe to run after 1-2)
    ```
    
    `build:pi` chains review and hook internally, so after steps 1-2 it only runs the pi-specific build.
    
    Verify all builds succeed before proceeding.
    
    ### Pi Parity Gate
    
    After builds pass, audit the Pi extension to ensure all server-side imports resolve in the published package. This catches missing files before they reach npm.
    
    1. **Check imports vs `files` array.** Trace all local imports (starting with `./` or `../`) from `index.ts`, `server.ts`, `tool-scope.ts`, and every file in `server/`. Verify each target is covered by a pattern in the `files` array of `apps/pi-extension/package.json`.
    
    2. **Check `vendor.sh` covers all shared/ai imports.** Every `../generated/*.js` import in the server files must have a corresponding entry in `vendor.sh`'s copy loops. If a new shared module or AI module was added to `packages/shared/` or `packages/ai/` and is imported by Pi's server code, it must be added to `vendor.sh`.
    
    3. **Dry-run the pack.** Run `cd apps/pi-extension && bun pm pack --dry-run` and verify the output includes every file the server imports. Look specifically for any newly added files since the last release.
    
    4. **Quick smoke test.** Confirm `generated/` contains all expected files after build, especially any new ones (e.g., a new shared module added in this release cycle).
    
    If anything is missing, fix it before proceeding to Phase 4. Common fixes:
    - Add the file to `vendor.sh`'s copy loop
    - Add the file or directory to the `files` array in `package.json`
    - Add an import path fix (Pi uses `../generated/` not `@plannotator/shared` or `@plannotator/ai`)
    
    ---
    
    ## Phase 4: Commit, Tag, and Release
    
    1. **Commit the version bump:**
       ```
       chore: bump version to X.Y.Z
       ```
       Stage only the 7 version-bumped files. Do not stage the release notes file (it's untracked by design).
    
    2. **Create and push the tag:**
       ```bash
       git tag vX.Y.Z
       git push origin main
       git push origin vX.Y.Z
       ```
       The `v*` tag push triggers the release pipeline (`.github/workflows/release.yml`).
    
    3. **The pipeline handles everything else:**
       - Runs tests
       - Cross-compiles binaries for 6 platforms (macOS ARM64/x64, Linux x64/ARM64, Windows x64/ARM64)
       - Compiles paste service binaries (same 6 platforms)
       - Generates SLSA build provenance attestations for all 12 binaries via `actions/attest-build-provenance` (signed through Sigstore, recorded in Rekor)
       - Creates the GitHub Release with all binaries attached
       - Publishes `@plannotator/opencode` and `@plannotator/pi-extension` to npm with provenance
    
       **Note on immutable releases:** The repo has GitHub Immutable Releases enabled, so once the `v*` tag is pushed and the release is created, the tag→commit and tag→asset bindings are permanent. You cannot delete and re-create a tag to "fix" a bad release — you must ship a new version. Release notes remain editable (see step 5), but everything else is locked.
    
    4. **Monitor the pipeline:**
       Watch the release workflow run until it completes:
       ```bash
       gh run list --workflow=release.yml --limit=1
       gh run view <run-id> --log
       ```
       Verify:
       - All jobs pass (test, build, release, npm-publish)
       - The GitHub Release was created with all binary artifacts
       - npm packages published successfully (check with `npm view @plannotator/opencode version` and `npm view @plannotator/pi-extension version`)
    
       If anything fails, investigate the logs and report to the user before retrying.
    
    5. **Replace the release notes:**
       Once the release is live and verified, replace the auto-generated notes body with the drafted release notes:
       ```bash
       gh release edit vX.Y.Z --notes-file RELEASE_NOTES_v<VERSION>.md
       ```
    
    ---
    
    ## Checklist
    
    Before tagging, verify:
    - [ ] All 7 version files bumped consistently
    - [ ] Release notes drafted and reviewed
    - [ ] `bun run build:review` succeeded
    - [ ] `bun run build:hook` succeeded
    - [ ] `bun run build:opencode` succeeded
    - [ ] `bun run build:pi` succeeded (or pi-specific build step)
    - [ ] Version bump committed
    - [ ] Pi parity gate passed (imports, vendor.sh, dry-run pack)
    - [ ] No stale build artifacts (clean builds, no cache issues — run `bun install` first if dependencies changed)
    
    After tagging, verify:
    - [ ] Release workflow completed (all 4 jobs green)
    - [ ] GitHub Release created with all binaries
    - [ ] npm packages published at correct version
    - [ ] Release notes replaced via `gh release edit`
    
  • apps/skills/plannotator-compound/SKILL.mdskill
    Show content (26601 bytes)
    ---
    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.
    ---
    
    # Compound Planning Analysis
    
    You are conducting a comprehensive research analysis of a user's Plannotator plan
    archive. The goal: extract patterns from their denied plans, reduce
    them into actionable insights, and produce an elegant HTML dashboard report.
    
    This is a multi-phase process. Each phase must complete fully before the next begins.
    Research integrity is paramount — every file must be read, no skipping.
    
    ## Source Selection
    
    Before starting the analysis, determine which data source is available.
    
    1. **Plannotator mode (first-class)** — Check `~/.plannotator/plans/`. If it
       exists and contains `*-denied.md` files, use this mode. The entire workflow
       below is written for Plannotator data.
    
    2. **Claude Code fallback mode** — If the Plannotator archive is absent or
       contains no denied plans, check `~/.claude/projects/`. If present, read
       [references/claude-code-fallback.md](references/claude-code-fallback.md)
       before continuing. That reference explains how to use the bundled parser at
       [scripts/extract_exit_plan_mode_outcomes.py](scripts/extract_exit_plan_mode_outcomes.py)
       to extract denial reasons from Claude Code JSONL transcripts. Every phase
       below has a short note explaining what changes in fallback mode — the
       reference file has the details.
    
    3. **Neither available** — Ask the user for their Plannotator plans directory or
       Claude Code projects directory. Do not guess.
    
    ## Phase 0: Locate Plans & Check for Previous Reports
    
    Use the mode chosen in Source Selection above.
    
    **Plannotator mode:** Verify the plans directory contains `*-denied.md` files. If
    none exist, fall back to Claude Code mode before stopping.
    
    **Claude Code fallback mode:** Run the bundled parser per the fallback reference to
    build the denial-reason dataset. Create `/tmp/compound-planning/` if needed.
    
    In either mode, proceed to Previous Report Detection below.
    
    ### Previous Report Detection
    
    After locating the plans directory, check for existing reports:
    
    ```
    ls ~/.plannotator/plans/compound-planning-report*.html
    ```
    
    Reports follow a versioned naming scheme:
    - First report: `compound-planning-report.html`
    - Subsequent reports: `compound-planning-report-v2.html`, `compound-planning-report-v3.html`, etc.
    
    If one or more reports exist, determine the **latest** one (highest version number).
    Get its filesystem modification date using `stat` (macOS: `stat -f %Sm -t %Y-%m-%d`,
    Linux: `stat -c %y | cut -d' ' -f1`). This is the **cutoff date**.
    
    Present the user with a choice:
    
    > "I found a previous report (`compound-planning-report-v{N}.html`) last updated
    > on {CUTOFF_DATE}. I can either:
    >
    > 1. **Incremental** — Only analyze files dated after {CUTOFF_DATE}, saving tokens
    >    and building on previous findings
    > 2. **Full** — Re-analyze the entire archive from scratch
    >
    > Which would you prefer?"
    
    Wait for the user's response before proceeding.
    
    **If incremental:** Filter all subsequent phases to only process files with dates
    after the cutoff date. The new report version will note in its header narrative that
    it covers the period from {CUTOFF_DATE} to present, and reference the previous
    report for earlier findings. The inventory (Phase 1) should still count ALL files
    for overall stats, but clearly separate "new since last report" counts.
    
    **If full:** Proceed normally with all files, but still use the next version number
    for the output filename.
    
    **If no previous report exists:** Proceed normally. The output filename will be
    `compound-planning-report.html` (no version suffix for the first report).
    
    ## Phase 1: Inventory
    
    Count and report the dataset. **Always count ALL files** for overall stats,
    regardless of whether this is an incremental or full run:
    
    ```
    - *-approved.md files (count)
    - *-denied.md files (count)
    - Date range (earliest to latest date found in filenames)
    - Total days spanned
    - Revision rate: denied / (approved + denied) — this is the "X% of plans
      revised before coding" stat used in dashboard section 1
    ```
    
    **Note:** Ignore `*.annotations.md` files entirely. Denied files already contain
    the full plan text plus all reviewer feedback appended after a `---` separator.
    Annotation files are redundant subsets of this content — reading both would
    double-count feedback.
    
    **If incremental mode:** After the total counts, separately report the counts for
    files dated after the cutoff date only:
    
    ```
    New since {CUTOFF_DATE}:
    - *-denied.md files: X (of Y total)
    - New date range: {CUTOFF_DATE} to {LATEST_DATE}
    - New days spanned: N
    ```
    
    If fewer than 3 new denied files exist since the cutoff, warn the user:
    > "Only {N} new denied plans since the last report. The incremental analysis may
    > be thin. Would you like to proceed or switch to a full analysis?"
    
    Also run `wc -l` across all `*-approved.md` files to get average lines per
    approved plan. This tells the user whether their plans are staying lightweight
    or bloating over time. You do not need to read approved plan contents — just
    their line counts. If possible, break this down by time period (e.g., monthly)
    to show whether plan size changed.
    
    Dates appear in filenames in YYYY-MM-DD format, sometimes as a prefix
    (2026-01-07-name-approved.md) and sometimes embedded (name-2026-03-15-approved.md).
    Extract dates from all filenames.
    
    Tell the user what you found and that you're beginning the extraction.
    
    **Claude Code fallback mode:** The Plannotator inventory fields above do not apply.
    Follow the inventory instructions in
    [references/claude-code-fallback.md](references/claude-code-fallback.md) instead —
    report the denial-reason dataset assembled by the parser.
    
    ## Phase 2: Map — Parallel Extraction
    
    This is the most time-intensive phase. You must read EVERY `*-denied.md` file
    **in scope**. Do not skip files. Do not summarize early.
    
    **In scope** means: all denied files if running a full analysis, or only denied
    files dated after the cutoff date if running incrementally. In incremental mode,
    only process files whose embedded YYYY-MM-DD date is strictly after the cutoff.
    
    **Claude Code fallback mode:** The parser output is the clean source dataset. Read
    the fallback reference for the extraction prompt and batching strategy specific to
    JSON part files. Do not go back to raw `.jsonl` logs unless the parser fails or the
    user asks for audit-level verification.
    
    **Important:** Only read `*-denied.md` files. Do NOT read approved plans,
    annotation files, or diff files. Each denied file contains the full plan text
    followed by a `---` separator and the reviewer's feedback — everything needed
    for analysis is in one file.
    
    ### Batching Strategy
    
    All extraction agents should use `model: "haiku"` — they're doing straightforward
    file reading and structured extraction, not reasoning. Haiku is faster and cheaper
    for this work.
    
    The approach depends on dataset size:
    
    **Tiny datasets (≤ 10 total files):** Read all files directly in the main agent —
    no need for sub-agents. Just read them sequentially and proceed to Phase 3.
    
    **Small datasets (11-30 files):** Launch 2-3 parallel Haiku agents, splitting
    files roughly evenly.
    
    **Medium datasets (31-80 files):** Launch 4-6 parallel Haiku agents (~10-15 files
    each). Split by file type and/or time period.
    
    **Large datasets (80+ files):** Launch as many parallel Haiku agents as needed to
    keep each batch around 10-15 files. Split by the natural time boundaries in the
    data (months, quarters, or whatever groupings produce balanced batches). If one
    time period dominates (e.g., the most recent month has 3x the files), split that
    period into multiple batches.
    
    Launch all extraction agents in parallel using the Agent tool with
    `run_in_background: true` and `model: "haiku"`.
    
    ### Output Files
    
    Each extraction agent must write its results to a clean output file rather than
    relying on the agent task output (which contains interleaved JSONL framework
    logs that are difficult to parse). Instruct each agent to write to:
    
    ```
    /tmp/compound-planning/extraction-{batch-name}.md
    ```
    
    Create the `/tmp/compound-planning/` directory before launching agents. The
    reduce agent in Phase 3 will read these clean files directly.
    
    ### Extraction Prompt
    
    Each agent receives this instruction (adapt the time period, file list, and
    output path):
    
    ```
    You are extracting structured data from denied plan files for a pattern analysis.
    
    Directory: [PLANS DIRECTORY]
    Files to read: [LIST OF SPECIFIC *-denied.md FILES]
    Output: Write your complete results to [OUTPUT FILE PATH]
    
    Each denied file contains two parts separated by a --- line:
    1. The plan text (above the ---)
    2. The reviewer's feedback and annotations (below the ---)
    
    Read EVERY file in your list. For EACH file, extract:
    - The plan name/topic (from the plan text above the ---)
    - The denial reason or feedback given (from below the --- — capture the actual
      words used)
    - What was specifically asked to change
    - The type of feedback (let the content determine the category — don't force-fit
      into predefined types. Common types include things like: scope concerns,
      approach disagreements, missing information, process requirements, quality
      concerns, UX/design issues, naming disputes, clarification requests,
      testing/procedural denials — but the user's actual patterns may differ)
    - Any specific phrases or recurring language from the reviewer
    - Individual annotations if present (numbered feedback items with quoted text
      and reviewer comments)
    - The date (extracted from the filename)
    
    Do NOT skip any files. One entry per file.
    
    Format each entry as:
    **[filename]**
    - Date: ...
    - Topic: ...
    - Denial reason: ...
    - Feedback type: ...
    - Specific asks: ...
    - Notable phrases: ...
    - Annotations: [count, with brief summary of each]
    ---
    
    After processing all files, write the complete results to [OUTPUT FILE PATH].
    State the total file count at the end of the file.
    ```
    
    ### While Agents Run
    
    Track completion. As each agent finishes, note the count of files it processed.
    Verify the total matches the inventory from Phase 1. If any agent's count is
    short, flag it and consider re-launching for the missing files.
    
    If an agent times out (possible with large batches — a batch of 128 files can
    take 8+ minutes), re-launch it for just the unprocessed files. Check the output
    file to see how far it got before timing out.
    
    ## Phase 3: Reduce — Pattern Analysis
    
    Once ALL extraction agents have completed (or all files have been read for tiny
    datasets), proceed with the reduction. Reduction agents should use `model: "sonnet"`
    — this phase requires real analytical reasoning, not just file reading.
    
    ### Reduction Strategy
    
    The approach depends on how many extraction files were produced:
    
    **Standard (≤ 20 extraction files):** Launch a single Sonnet agent to read all
    extraction files and produce the full analysis. This covers most datasets.
    
    **Large (21+ extraction files):** Use a two-stage reduce:
    
    1. **Stage 1 — Partial reduces:** Split the extraction files into groups of 4-6.
       Launch parallel Sonnet agents, each reading one group and producing a partial
       analysis with the same sections listed below. Each writes to
       `/tmp/compound-planning/partial-reduce-{N}.md`.
    
    2. **Stage 2 — Final reduce:** A single Sonnet agent reads all partial reduce
       files and synthesizes them into the final comprehensive analysis. This agent
       merges taxonomies, combines counts, deduplicates patterns, and reconciles any
       conflicting categorizations across partials.
    
    **Claude Code fallback mode:** The reduction phase is the same. The only upstream
    difference is that extraction files were derived from normalized denial-reason JSON
    instead of Plannotator markdown files.
    
    ### Reduction Prompt
    
    Give each reduction agent this prompt (adapt file paths for single vs multi-stage):
    
    ```
    You are a data scientist conducting the reduction phase of a map-reduce analysis
    across a user's denied plan archive.
    
    Read ALL extraction files at [FILE PATHS]
    
    These files contain structured extractions from every denied plan file. Each
    extraction includes the plan topic, denial feedback, annotations, and reviewer
    language. Your job: aggregate everything, find patterns, cluster into a taxonomy,
    and produce a comprehensive analysis.
    
    Be exhaustive. Use real counts. Quote real phrases from the data. This is
    research — no hand-waving, no fabrication.
    
    Write your complete results to [OUTPUT FILE PATH].
    
    Produce the following sections:
    [... sections listed below ...]
    ```
    
    The reduction agent's job is to let the data speak. Do not impose a predetermined
    framework — discover what's actually there. The analysis must produce:
    
    ### 1. Denial Reason Taxonomy
    Categorize every denial into a finite set of types that emerge from the data. Count
    occurrences. Show percentages. Include real example quotes for each type. Aim for
    8-15 categories — enough to be specific, few enough to be scannable. Let the user's
    actual feedback determine what the categories are.
    
    ### 2. Top Feedback Patterns (ranked by frequency)
    The 5-10 most recurring patterns. For each: what the reviewer consistently asks for,
    3+ example quotes from different files, and whether the pattern changed over time.
    
    ### 3. Recurring Phrases
    Exact phrases the reviewer uses repeatedly, with counts and what they signal. These
    are the reviewer's vocabulary — their shorthand for what they care about.
    
    ### 4. What the Reviewer Values (implicit preferences)
    Derived from patterns — what does this specific person care about most? Quality?
    Speed? Narrative? Architecture? Process? Simplicity? Rank by evidence strength.
    This section should feel like a personality profile of the reviewer's standards.
    
    ### 5. What Agents Consistently Get Wrong
    The flip side — what recurring mistakes trigger denials? What should agents stop
    doing for this reviewer?
    
    ### 6. Structural Requests
    What plan structure does the reviewer consistently demand? Required sections,
    ordering, format preferences, level of detail expected.
    
    ### 7. Evolution Over Time
    How feedback patterns changed across the time span. Group by whatever natural time
    boundaries exist in the data (weeks for short spans, months for longer ones). Did
    expectations mature? Did new patterns emerge? What shifted? If the dataset spans
    less than a month, note that evolution analysis is limited but still look for any
    progression from early to late files.
    
    ### 8. Actionable Prompt Instructions
    The most important output. Based on all patterns: specific numbered instructions
    that could be embedded in a planning prompt to prevent the most common denial
    reasons. Write these as actual directives an agent could follow. Be specific to
    this user's patterns — generic advice like "write good plans" is worthless. Each
    instruction should trace back to a real, frequent denial pattern.
    
    After writing the instructions, calculate what percentage of denials they would
    address (count how many denials fall into categories covered by the instructions
    vs total denials). Report this percentage — it will be different for every user.
    
    ## Phase 4: Generate the HTML Dashboard
    
    Build a single, self-contained HTML file as the final deliverable. Save it to
    the user's plans directory with a versioned filename:
    
    - First ever report: `compound-planning-report.html`
    - Second report: `compound-planning-report-v2.html`
    - Third report: `compound-planning-report-v3.html`
    - And so on.
    
    The version number was determined in Phase 0 based on existing reports found.
    
    **If this is an incremental report**, the header should indicate the analysis
    period (e.g., "March 15 – March 31, 2026") and include a subtitle noting
    "Incremental analysis — see v{N-1} for earlier findings." The narrative in
    section 1 should frame findings as what's new or changed since the last report,
    not as a complete picture. Overall stats in the header (file counts, revision
    rate) should still reflect the full archive for context.
    
    Read the template at `assets/report-template.html` for the **design language
    only**. The template contains example data from a previous analysis — ignore all
    data values, quotes, and percentages in the template. Use only its visual design:
    colors, typography, spacing, component styles, and layout patterns.
    
    ### Design Language (from template)
    
    - **Palette:** Light mode, warm off-white (#FDFCFB), text in slate scale, amber
      for highlights/accents, emerald for positive, rose for negative, indigo for
      action elements
    - **Typography:** Playfair Display (serif, for narrative headings), Inter (sans,
      for body/data), JetBrains Mono (mono, for code/phrases) — Google Fonts CDN
    - **Layout:** Single-column, max-width 1024px, generous vertical whitespace (128px
      between major sections), editorial/narrative-first aesthetic
    - **Tone:** Calm, reflective, authoritative. Like a personal retrospective journal,
      not a monitoring dashboard.
    
    ### Page Frame (header + footer)
    
    Before the 7 sections, the page has:
    
    - **Header:** Report title on the left (Playfair Display, ~36px), project name +
      date range below it in light meta text. On the right: file counts in mono
      (e.g., "223 denials · 71 days"). Separated from content by
      a bottom border. Generous bottom padding before section 1.
    
    - **Footer:** After section 7. Top border, centered italic Playfair Display tagline
      summarizing the corpus (e.g., "Analysis of X denied plans from the Plannotator
      archive.").
    
    ### Dashboard Section Order (7 sections)
    
    The report follows this exact section order. Each section builds on the previous
    one — the flow moves from "what happened" through "why" to "what to do about it":
    
    1. **The story in the data** — An editorial narrative paragraph (Playfair Display
       serif, ~26px) that tells the headline finding in prose. Not bullet points — a
       real paragraph that reads like the opening of an article. Alongside it, a KPI
       sidebar with 3 key metrics (the top denial percentage, the overall revision
       rate, and the number of distinct denial categories found). Use an amber inline
       highlight on the most striking number in the narrative.
    
    2. **Why plans get denied** — The taxonomy as a ranked list. Each row: rank number
       (mono), category label, a thin 4px progress bar (top item in amber-500, rest
       in slate-300), percentage (mono), and for the top entries, a real italic quote
       from the data below the label. Show the top 10 categories or however many the
       data supports (minimum 5).
    
    3. **How expectations evolved** — One card per natural time period. Each card has:
       the period name in serif, a theme phrase in colored uppercase (different color
       per period to show progression), a description paragraph, and a stat line at
       the bottom (e.g., "X denials · Y narrative requests"). If the data spans less
       than 3 distinct periods, use 2 cards or even a single card with internal
       progression noted.
    
    4. **What works vs what doesn't** — Two side-by-side cards. Left: green-tinted
       (emerald-50/50 bg, emerald-100 border) with traits of plans that succeed for
       this reviewer. Right: red-tinted (rose-50/50 bg, rose-100 border) with what
       agents keep getting wrong. Both derived from the reduction analysis. Bulleted
       with small colored dots. 5-8 items per card.
    
    5. **The actionable output** — The diagnostic payoff. Opens with a Playfair
       Display narrative sentence stating how many prompt instructions were derived
       and what estimated percentage of denials they address (use the real calculated
       percentage from Phase 3, not a generic number). Then the top 3 most impactful
       improvements as numbered items, each with an amber number, bold title, and
       one-line description. This section bridges the analysis and the full prompt
       that follows.
    
    6. **Your most-used phrases** — Grid of chips (2-col mobile, 3-col desktop). Each
       chip: monospace quoted phrase on the left, frequency count on the right. White
       bg, slate-200 border, rounded-12px. Show 9-12 of the most recurring phrases
       found. These should be the reviewer's actual words — their verbal fingerprint.
    
    7. **The corrective prompt** — Dark panel (slate-900 bg, white text, rounded-3xl,
       shadow-xl). Opens with a Playfair intro sentence about the instructions. Then
       a dark code block (slate-800/80 bg, amber-200 monospace text) containing the
       full numbered prompt instructions from Phase 3. Include a copy-to-clipboard
       button that works (JS included). Below the code block: a gradient glow card
       (indigo-to-purple blurred halo behind a white card) with a closing message
       that these instructions are personal — derived from the user's own feedback,
       their own language, their own standards.
    
    ### Adaptation Rules
    
    - If the user has < 3 months of data, reduce the evolution section to fewer cards
    - If most denied files lack feedback below the `---` (bare denials with no
      annotations), note this in the narrative — the analysis will be thinner
    - **Claude Code fallback mode:** Explicitly label the report source as Claude Code
      `ExitPlanMode` denial reasons. Do not fabricate Plannotator-only fields such as
      annotation counts or approved-plan line counts. See the fallback reference for
      KPI substitutes and footer/provenance guidance.
    - If fewer than 5 denial categories emerge, combine the taxonomy and patterns
      sections into one
    - If the dataset is very small (< 20 files), the narrative should acknowledge the
      limited sample size and frame findings as preliminary
    - The number of prompt instructions will vary per user — could be 8 or 20. Don't
      force exactly 17. Let the data determine the count.
    - The top 3 actionable items in section 5 must be the 3 that cover the largest
      share of denials, not the 3 that sound most impressive
    
    ### Key Rules
    
    1. Every number must come from the real analysis — no fabricated data
    2. Every quote must be a real quote from a real file
    3. The taxonomy percentages must be calculated from real counts
    4. The prompt instructions must trace back to actual denial patterns
    5. The copy button on the prompt block must work (include the JS)
    
    After generating, open the file in the user's browser.
    
    ## Phase 5: Summary
    
    Tell the user:
    - How many denied files were analyzed
    - If incremental: how many were new since the last report
    - The top 3 denial patterns found
    - The estimated percentage of denials the prompt instructions would address
    - The single most impactful prompt improvement
    - Where the report was saved (including version number)
    - If incremental: remind the user that earlier findings are in the previous report
    
    **Claude Code fallback mode:** Adapt the summary per the fallback reference —
    report human denial reasons analyzed and total `ExitPlanMode` attempts scanned
    instead of Plannotator file counts.
    
    ## Phase 6: Improvement Hook
    
    After presenting the summary, ask the user if they want to enable an **improvement
    hook** — this takes the corrective prompt instructions from section 7 of the report
    and writes them to a file that Plannotator's `EnterPlanMode` hook can inject into
    every future planning session automatically.
    
    > "Would you like to enable the improvement hook? This will save the corrective
    > prompt instructions to a file that gets automatically injected into all future
    > planning sessions — so Claude sees your feedback patterns before writing any plan."
    
    **If yes:**
    
    The hook file lives at:
    
    ```
    ~/.plannotator/hooks/compound/enterplanmode-improve-hook.txt
    ```
    
    Create the `~/.plannotator/hooks/compound/` directory if it doesn't exist.
    
    The file contents should be the corrective prompt instructions from Phase 3 —
    the same numbered list that appears in section 7 of the HTML report. Write them
    as plain text, one instruction per line, prefixed with their number. No HTML, no
    markdown fences, no preamble — just the instructions themselves. The hook system
    will inject this file's contents as-is into the planning context.
    
    **If the file already exists:**
    
    Read the existing file and present the user with a choice:
    
    > "An improvement hook already exists from a previous analysis. I can:
    >
    > 1. **Replace** — Overwrite with the new instructions (the old ones are gone)
    > 2. **Merge** — Combine both, deduplicating overlapping instructions and
    >    keeping the best version of each
    > 3. **Keep existing** — Leave the current hook as-is, skip this step
    >
    > Which would you prefer?"
    
    - **Replace:** Overwrite the file with the new instructions.
    - **Merge:** Read the existing instructions, compare with the new ones, and
      produce a merged set. Remove duplicates (same intent even if worded differently).
      When two instructions cover the same pattern, keep the more specific or
      actionable version. Re-number the final list sequentially. Write the merged
      result to the file. Show the user what changed (added N new, removed N
      redundant, kept N existing).
    - **Keep existing:** Do nothing, move on.
    
    **If no:** Skip this phase entirely.
    
    ## Important Notes
    
    - **Data source priority:** Plannotator is the first-class path. Claude Code log
      analysis is the secondary path for users without Plannotator archives.
    - **Research integrity:** Every file must be read. The value of this analysis comes
      from completeness. Sampling or skipping undermines the findings.
    - **Real data only:** Never fabricate quotes, percentages, or patterns. If the data
      doesn't show a clear pattern, say so honestly rather than inventing one.
    - **Let the data lead:** The taxonomy, patterns, and instructions should emerge from
      what's actually in the files. Different users will have completely different
      denial patterns. A user building mobile apps will have different feedback than
      one building APIs. Don't assume what the patterns will be.
    - **Agent parallelization:** For large datasets, maximize parallel agents to reduce
      wall-clock time. The bottleneck is the largest batch — split it.
    - **Structured extraction format:** Ask extraction agents to return structured text
      with consistent delimiters so the reduce agent can parse reliably.
    - **The report is the artifact:** The HTML dashboard is what the user keeps. It
      should be beautiful, honest, and useful. Every section should feel like it was
      written about them specifically, because it was.
    
  • .agents/skills/review-renovate/SKILL.mdskill
    Show content (2559 bytes)
    ---
    name: review-renovate
    description: Review Renovate bot PRs that update GitHub Actions dependencies. Verifies supply chain integrity by checking pinned commit SHAs against upstream tagged releases, reviews changelogs for breaking changes, and confirms compatibility with existing workflow configurations. Use when a Renovate PR updates GitHub Actions in .github/workflows/.
    ---
    
    # Review Renovate GitHub Actions PRs
    
    You are reviewing a Renovate bot PR that updates GitHub Actions dependencies. Your job is to verify supply chain integrity and ensure the upgrades won't break CI/CD workflows.
    
    ## Inputs
    
    You will be given a PR number or URL. Use `gh` CLI to fetch PR details and diff.
    
    ## Steps
    
    ### 1. Fetch PR metadata and diff
    
    ```
    gh pr view <PR> --json title,body,files,commits,author,headRefName
    gh pr diff <PR>
    ```
    
    Confirm the PR author is `app/renovate`. If not, flag this immediately — it may not be an automated dependency update.
    
    ### 2. Identify all action version changes
    
    From the diff, extract each changed action:
    - Full action name (e.g., `oven-sh/setup-bun`)
    - Old version tag and pinned SHA
    - New version tag and pinned SHA
    - Update type (patch, minor, major)
    
    ### 3. Verify pinned SHAs against upstream tags
    
    For every action being updated, verify **both old and new** SHAs match the claimed version tags:
    
    ```
    gh api repos/{owner}/{repo}/git/ref/tags/{version} --jq '.object.sha'
    ```
    
    Compare each result against the SHA in the workflow file. If any SHA does not match, **stop and report a supply chain integrity failure**. Do not approve the PR.
    
    ### 4. Review changelogs for breaking changes
    
    From the PR body (Renovate includes release notes), check each updated action for:
    - Removed inputs or outputs that the workflows currently use
    - Changed default behavior for inputs the workflows rely on
    - New required inputs
    - Major version bumps (these almost always have breaking changes)
    
    ### 5. Check workflow compatibility
    
    Read the affected workflow files and verify:
    - No removed or renamed inputs are being used
    - No changed defaults affect current behavior
    - The action's runtime requirements are still met (e.g., Node.js version compatibility)
    
    ### 6. Report findings
    
    Present a summary table:
    
    | Action | Old | New | Type | SHA verified |
    |--------|-----|-----|------|-------------|
    | ... | ... | ... | patch/minor/major | yes/NO |
    
    Then state:
    - Whether all SHAs are verified
    - Whether any breaking changes were found
    - Whether the workflows remain compatible
    - A clear **safe to merge** or **do not merge** recommendation
    
  • .agents/skills/update-deps/SKILL.mdskill
    Show content (7288 bytes)
    ---
    name: update-deps
    description: Audit and update npm/Bun dependencies with supply chain integrity checks — verifies maintainers, publish age, tarball diffs, and provenance before bumping. Defers risky packages to ~/.supply-chain/notes/.
    disable-model-invocation: true
    ---
    
    # Update Dependencies
    
    Audit outdated packages, verify supply chain integrity, bump what's safe, defer what needs review, and log everything.
    
    This process has three phases: discovery, integrity audit, and execution. The integrity audit is the most important — every package gets checked before it touches the lockfile.
    
    ## Phase 1: Discovery
    
    Run `bun outdated` to get the full list of packages with available updates.
    
    ```bash
    bun outdated
    ```
    
    Parse the output into a structured list. For each package, note:
    - Package name
    - Current version
    - Available update version
    - Whether it's age-gated (indicated by `*` in the output — the footnote "The * indicates that version isn't true latest due to minimum release age" confirms this)
    - Whether it's a runtime dep, dev dep, or peer dep
    
    Also check whether any packages are blocked entirely by the age gate (like `@pierre/diffs` was when its minimum semver range couldn't resolve). Flag these separately — they may need `minimumReleaseAgeExcludes` in `bunfig.toml`.
    
    ## Phase 2: Integrity Audit
    
    This is the core of the process. Spawn one **Sonnet sub-agent per package** to run the integrity check in parallel. Sonnet is used here because these are independent, structured verification tasks that don't need heavier reasoning.
    
    Each sub-agent receives the package name, current version, and target version, and performs the following checks:
    
    ### Sub-agent prompt template
    
    For each outdated package, spawn a Sonnet agent with this task:
    
    ```
    You are auditing the npm package "{package}" for a version bump from {current} to {target}.
    
    Run these checks and report back with a JSON object:
    
    1. **Maintainer verification**: Check if maintainers changed between versions.
       npm view {package}@{current} maintainers --json
       npm view {package}@{target} maintainers --json
       Compare the two lists. Flag any additions or removals.
    
    2. **Publish date and age**: Get the publish timestamp.
       npm view {package} time --json
       Extract the date for version {target}. Calculate days since publication.
       Flag if younger than 7 days.
    
    3. **Provenance**: Check if the package has registry signatures or attestations.
       npm audit signatures (if not already run this session)
       Note whether the package has provenance attestations.
    
    4. **Tarball diff**: Show what actually changed in the published package.
       npm diff --diff={package}@{current} --diff={package}@{target}
       Summarize the changes:
       - How many files changed
       - Are changes limited to version bumps, deps, and rebuilt dist? Or are there meaningful source changes?
       - Any new runtime dependencies added?
       - Any suspicious patterns (obfuscated code, eval(), network calls in unexpected places)
    
    5. **Release notes**: Try to find what changed.
       Check the package's repository for release notes or changelog:
       npm view {package}@{target} repository.url
       gh release view v{target} --repo <owner/repo> (try with and without v prefix)
       Summarize the changelog if found.
    
    Report your findings as JSON:
    
    {{
      "package": "{package}",
      "from": "{current}",
      "to": "{target}",
      "age_days": <number>,
      "maintainers_changed": <boolean>,
      "maintainers_added": [],
      "maintainers_removed": [],
      "provenance": <boolean>,
      "new_runtime_deps": [],
      "files_changed": <number>,
      "has_source_changes": <boolean>,
      "changelog_summary": "<brief summary>",
      "suspicious_patterns": [],
      "verdict": "safe" | "review" | "defer",
      "verdict_reason": "<one sentence explanation>"
    }}
    
    Verdict guidelines:
    - "safe": Same maintainers, no new runtime deps, changes match what changelog describes, no suspicious patterns
    - "review": Minor concerns (e.g., new maintainer who is clearly from the same org, small new dep from known publisher)
    - "defer": Maintainer changes from unknown accounts, new runtime deps with unclear purpose, suspicious code patterns, substantive API changes that need integration testing
    ```
    
    ### Collecting results
    
    As sub-agents complete, collect their JSON reports. If a sub-agent fails or times out, mark that package as "defer" with reason "audit failed".
    
    ### Tier classification
    
    After collecting all results, classify packages into tiers. This helps the user understand the risk profile at a glance:
    
    | Tier | Description | Typical action |
    |------|-------------|----------------|
    | **Runtime, high surface** | Libraries your code calls directly (parsers, diff engines, UI libs) | Check provenance, review diff, run tests |
    | **SDK/API deps** | Third-party service SDKs (agent SDKs, platform integrations) | Read changelog for API changes, test integration |
    | **Dev-only** | Type definitions, build tools, test frameworks | Update freely — these don't ship |
    | **Build toolchain** | Bun itself, compilers, bundlers | Most caution — breakage affects all outputs |
    
    ## Phase 3: Execution
    
    ### Bump safe packages
    
    For all packages with verdict "safe":
    
    ```bash
    bun update pkg1@version1 pkg2@version2 ...
    ```
    
    If the update fails due to age gate conflicts (a package's minimum semver can't resolve), add it to `minimumReleaseAgeExcludes` in `bunfig.toml` and document why.
    
    ### Log to supply chain notes
    
    Write the full audit results to `~/.supply-chain/notes/<YYYY-MM-DD>.json`:
    
    ```json
    {
      "date": "YYYY-MM-DD",
      "project": "plannotator",
      "bumped": [
        {
          "package": "...",
          "from": "...",
          "to": "...",
          "age_days": 0,
          "maintainers_changed": false,
          "provenance": false,
          "notes": "..."
        }
      ],
      "deferred": [
        {
          "package": "...",
          "current": "...",
          "available": "...",
          "age_days": 0,
          "maintainers_changed": false,
          "reason": "...",
          "review_by": "YYYY-MM-DD"
        }
      ],
      "excluded_from_age_gate": [
        {
          "package": "...",
          "reason": "..."
        }
      ]
    }
    ```
    
    Set `review_by` to 7 days from today for deferred packages.
    
    ### Check previously deferred packages
    
    Read all files in `~/.supply-chain/notes/` and collect any deferred packages from previous audits that are still at the same version in the current lockfile. These are packages that were deferred before and still haven't been updated.
    
    To check: for each previously deferred entry, see if the current installed version matches the `current` field from the deferral note. If it does, the package is still deferred.
    
    ## Phase 4: Recap
    
    Present a clear summary to the user:
    
    ### Updated
    List each bumped package with version change and one-line reason it was safe.
    
    ### Deferred
    List each deferred package with version change and reason for deferral.
    
    ### Still Deferred (from previous audits)
    List any packages that were deferred in previous audit sessions and still haven't been bumped. Include the original deferral date and reason. This is the "you've been putting this off" section — it keeps deferred packages from being forgotten.
    
    If the still-deferred list is empty, say so — that's a good sign.
    
    ### Age Gate Exclusions
    If any packages were added to `minimumReleaseAgeExcludes`, note them and why.
    
  • .claude-plugin/marketplace.jsonmarketplace
    Show content (338 bytes)
    {
      "name": "plannotator",
      "owner": {
        "name": "backnotprop"
      },
      "plugins": [
        {
          "name": "plannotator",
          "source": "./apps/hook",
          "description": "Interactive Plan Review: Mark up and refine your plans using a UI, easily share for team collaboration, automatically integrates with plan mode hooks."
        }
      ]
    }
    
  • .github/plugin/marketplace.jsonmarketplace
    Show content (416 bytes)
    {
      "name": "plannotator",
      "owner": {
        "name": "backnotprop"
      },
      "metadata": {
        "description": "Interactive Plan & Code Review plugins"
      },
      "plugins": [
        {
          "name": "plannotator-copilot",
          "source": "./apps/copilot",
          "description": "Interactive Plan & Code Review for GitHub Copilot CLI. Visual annotations, team sharing, structured feedback.",
          "version": "0.17.0"
        }
      ]
    }
    

README

Plannotator

Plannotator

Interactive Plan & Code Review for AI Coding Agents. Mark up and refine your plans or code diffs using a visual UI, share for team collaboration, and seamlessly integrate with Claude Code, Copilot CLI, Gemini CLI, OpenCode, Pi, and Codex.

Plan Mode Demos:

Claude Code

Claude Code Demo

Watch Demo

OpenCode

OpenCode Demo

Watch Demo

Annotate: Plans, specs, folders, files, urls. send feedback directly to agents.

New: Code Review

  • send your feedback to agents
  • built-in:
    • ask ai
    • agent code reviews

Features

Visual Plan ReviewBuilt-in hookApprove or deny agent plans with inline annotations
Plan DiffAutomaticSee what changed when the agent revises a plan
Code Review/plannotator-reviewView git diffs or remote PRs. Package annotations and ask AI about the code as you review.
Annotate Any File/plannotator-annotate <file|folder|url>Annotate markdown, HTML, URLs, or folders and send feedback to your agent
Annotate Last Message/plannotator-lastAnnotate the agent's last response and send structured feedback

Sharing Plans

Plannotator lets you privately share plans, annotations, and feedback with colleagues. For example, a colleague can annotate a shared plan, and you can import their feedback to send directly back to the coding agent.

Small plans are encoded entirely in the URL hash. No server involved, nothing stored anywhere.

Large plans use a short link service with end-to-end encryption. Your plan is encrypted with AES-256-GCM in your browser before upload. The server stores only ciphertext it cannot read. The decryption key lives only in the URL you share. Pastes auto-delete after 7 days.

  • Zero-knowledge storage, similar to PrivateBin
  • Fully open source and self-hostable (see docs)

Install

Install for Claude Code

Install the plannotator command:

macOS / Linux / WSL:

curl -fsSL https://plannotator.ai/install.sh | bash

Windows PowerShell:

irm https://plannotator.ai/install.ps1 | iex

Then in Claude Code:

/plugin marketplace add backnotprop/plannotator

Restart Claude Code after plugin install.

Pin a specific version or verify provenance
curl -fsSL https://plannotator.ai/install.sh | bash -s -- --version vX.Y.Z
& ([scriptblock]::Create((irm https://plannotator.ai/install.ps1))) -Version vX.Y.Z

Every released binary ships with a SHA256 sidecar (verified automatically). SLSA provenance verification is supported from v0.17.2 onwards — see the installation docs for details.

See apps/hook/README.md for detailed installation instructions including a manual hook approach.


Install for Copilot CLI

Install the plannotator command:

macOS / Linux / WSL:

curl -fsSL https://plannotator.ai/install.sh | bash

Windows PowerShell:

irm https://plannotator.ai/install.ps1 | iex

Then in Copilot CLI:

/plugin marketplace add backnotprop/plannotator
/plugin install plannotator-copilot@plannotator

Restart Copilot CLI after plugin install. Plan review activates automatically when you use plan mode (Shift+Tab to enter plan mode).

See apps/copilot/README.md for details.


Install for Gemini CLI

Install the plannotator command:

macOS / Linux / WSL:

curl -fsSL https://plannotator.ai/install.sh | bash

Windows PowerShell:

irm https://plannotator.ai/install.ps1 | iex

The installer auto-detects Gemini CLI (checks for ~/.gemini) and configures the plan review hook and policy. It also installs /plannotator-review and /plannotator-annotate slash commands.

Then in Gemini CLI:

/plan                              # Enter plan mode — plans open in your browser
/plannotator-review                # Code review for current changes
/plannotator-review <pr-url>       # Review a GitHub pull request
/plannotator-annotate <file.md>    # Annotate a markdown file

Requires Gemini CLI 0.36.0 or later.

See apps/gemini/README.md for details.


Install for OpenCode

Add to your opencode.json:

{
  "plugin": ["@plannotator/opencode@latest"]
}

Run the install script to get /plannotator-review:

curl -fsSL https://plannotator.ai/install.sh | bash

Windows:

irm https://plannotator.ai/install.ps1 | iex

This also clears any cached plugin versions. Then restart OpenCode.


Install for Pi

pi install npm:@plannotator/pi-extension

Then start Pi with --plan to enter plan mode, or toggle it during a session with /plannotator.

See apps/pi-extension/README.md for full usage details, commands, and flags.


Install for Codex

Install the plannotator command:

macOS / Linux / WSL:

curl -fsSL https://plannotator.ai/install.sh | bash

The installer also enables Codex Stop hooks when Codex is installed or ~/.codex already exists. Restart Codex Desktop after installing or changing hooks.

Windows PowerShell:

irm https://plannotator.ai/install.ps1 | iex

Codex plan review is automatic on macOS, Linux, and WSL. Codex hooks are currently disabled on Windows in the official Codex docs, so the Windows installer does not enable them automatically; the direct !plannotator commands still work.

Then in Codex — feedback flows back into the agent loop automatically:

$plannotator-review          # Code review skill for current changes
$plannotator-annotate        # Annotate a markdown file, URL, or folder
$plannotator-last            # Annotate the last agent message
!plannotator review           # Code review for current changes
!plannotator review <pr-url>  # Review a GitHub pull request
!plannotator annotate file.md # Annotate a markdown file
!plannotator last             # Annotate the last agent message

Plan review uses Codex's experimental Stop hook on macOS, Linux, and WSL.

See apps/codex/README.md for details.


How It Works

When your AI agent finishes planning, Plannotator:

  1. Opens the Plannotator UI in your browser
  2. Lets you annotate the plan visually (delete, insert, replace, comment)
  3. Approve → Agent proceeds with implementation
  4. Request changes → Your annotations are sent back as structured feedback

(Similar flow for code review, except you can also comment on specific lines of code diffs)


License

Copyright 2025-2026 backnotprop

This project is licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Development

To make the global plannotator command run from this checkout:

bun install
bun link

After linking, commands like plannotator review use apps/hook/server/index.ts from your local repo. Rebuild the bundled HTML when changing UI code:

bun run --cwd apps/review build && bun run build:hook