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.mdskillShow 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.mdskillShow 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.mdskillShow 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.mdskillShow 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.mdskillShow 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.mdskillShow 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.jsonmarketplaceShow 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.jsonmarketplaceShow 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
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
|
OpenCode
|
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 Review | Built-in hook | Approve or deny agent plans with inline annotations |
| Plan Diff | Automatic | See what changed when the agent revises a plan |
| Code Review | /plannotator-review | View 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-last | Annotate 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:
- Opens the Plannotator UI in your browser
- Lets you annotate the plan visually (delete, insert, replace, comment)
- Approve → Agent proceeds with implementation
- 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
- Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (http://opensource.org/licenses/MIT)
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