| name | literate-review |
|---|---|
| description | Use when the user wants to review code changes interactively. Uses literate markdown documents served in a local web app. Works with one repo or many. Triggers on: 'review PR', 'review branch', 'review changes', 'literate review', 'set up a review', 'create review docs', 'review these branches'. Generates topic-organized markdown files with inline diffs and surrounding context, serves them with syntax highlighting and inline commenting, and watches for reviewer comments that the current Claude Code session can respond to. |
Generate a topic-organized code review experience for changes in one or more git repositories. The output is a set of .diff and literate markdown files served in a local web app where reviewers can leave inline comments that Claude watches and responds to. Works equally well for a single branch in one repo or coordinated changes across many repos.
- Produce raw diffs — save to
docs/as.difffiles (source of truth) - Plan topics — group hunks by functional area, not by repo
- Write literate markdown — diffs are the primary content, prose explains them, context in
<details> - Build the web server — Express + marked + highlight.js + WebSocket live-reload + selection based commenting UI
- Run Playwright tests — verify everything works before presenting, never ask a user to test something you haven’t already tested
- Launch — server + CronCreate for comment monitoring
Ask the user for:
- Repo(s) and branch(es) to compare (e.g.,
main...feature-branch) - Output directory (suggest a sibling directory like
../review-name/) - Topics — learn from reading the diffs. The user can optionally tell you some of the topics they are interested in.
If the user has already provided this, proceed directly.
For each repo, get a full diff and save into docs/ as 00-<repo-name>.diff. These files:
- Appear in the sidebar for quick reference
- Are the source of truth — every hunk must appear in at least one literate doc
- Are commentable by the reviewer, just like the markdown docs
Read the diff files. Group hunks into topics by functional area (not by repo or file). Each topic should tell a coherent story. Propose topics to the user, or let them define them.
The diffs are the primary content. For each topic file:
- Prose intro — what this topic covers and why the changes were made
- For each relevant hunk, create a section:
- Brief prose explaining the change
- The actual
diffcode block (copied verbatim from the.difffiles) - If the diff is too short to understand alone, either increase the surrounding context of the diff a small amount or add a collapsed
<details>block with the full function/class/etc for context
- Cross-reference between topics using relative markdown links
- Add visualizations where they help (ASCII diagrams, tables, sequence annotations). Be creative. Be helpful.
# Topic Title
Prose explaining what this topic covers and why.
## Section Name (repo-name/path/to/file.ext)
Prose explaining this specific change.
\`\`\`diff
context line
-removed line
+added line
\`\`\`
<details>
<summary>Full function for context</summary>
\`\`\`language
function example() { ... }
\`\`\`
</details>
See also [Other Topic](XX-other-topic.md) for related changes.- Every section MUST have a diff block. No exceptions. The reviewer came to see the diffs.
- Diffs are verbatim from
git diff. Never fabricate or rephrase. Copy actual+/-/lines. - Context goes in
<details>. Collapsed by default, available on demand. - For new files, show key hunks as diffs with
+lines. Short files (< 50 lines) get the whole diff. Long files get the important hunks plus a “see full diff” details which expands to show the entire diff for the new file. - Don't duplicate. Include a hunk in one doc, cross-reference from others.
- Lead with prose. Explain why before showing what.
- Justify the changes. Why is this necessary? Why is this worth submitting for review?
- Number the files (01-, 02-, ...) to suggest reading order.
- Be creative with visualizations — ASCII diagrams, tables, sequence annotations. Think whiteboard.
Create server.mjs in the project root. Dependencies: express, marked, marked-highlight, highlight.js, chokidar, ws, etc.
npm init -y # Set "type": "module" for ESM
npm install express marked marked-highlight highlight.js chokidar ws # etc- GET
/— Sidebar with all docs (.mdand.diff), renders first.mdby default - GET
/docs/:name— For.md: renders markdown with syntax highlighting. For.diff: renders with highlight.js diff highlighting, splitting on embedded>blockquote lines to render inline comments. Returns HTML fragment whenX-Requested-With: fetchheader present. - POST
/api/request— Accepts{ file, selectedText, comment }. Generates a 7-char hex short-id. Createsrequests/<short-id>.mdwith frontmatter AND inserts> **Reviewer** (<short-id>): commentinto the doc. Returns{ ok: true, id }. - WebSocket
/ws— Pushes{ type: "reload", file }on file changes indocs/
- Dark theme (GitHub-dark):
#0d1117background,#e6edf3text - Sidebar (280px fixed) with doc links, active state highlighting.
.difffiles shown in italics. - Content layout: Full-width scrollable
<main>with max-width inner wrapper. Scroll works anywhere in the right pane, not just over the text column. - SPA navigation using fetch + pushState. Target the inner wrapper, not the scroll container. Make sure the back/forward buttons work.
- Blockquote styling: Red border for Reviewer, blue border for Claude. Anchor IDs (
comment-<short-id>) on each. - Comment nav: Sticky bar at top with "Comments (N)" dropdown. Lists all blockquotes, click to scroll-and-highlight. Rebuild on navigation and live-reload.
- Split diff toggle: "Split diffs" button parses diff code blocks into side-by-side old/new panes. Widens content to ~1400px. Persists across live-reloads and navigation.
- Commenting: mouseup on selection > 3 chars shows fixed-position "Comment" button. Popover flips above when near viewport bottom. Works on
.mdand.difffiles. Server strips>prefixes and**Reviewer/Claude** (id):markers when matching selected text. - WebSocket auto-reconnect on close (2s delay)
---
file: 05-subscription-changes.md
selectedText: "..."
status: pending
created: 2026-03-17T22:14:03Z
---
The reviewer's comment text.The requests/ directory is the queue. Set up a recurring cron after the server is running:
CronCreate: "*/1 * * * *", recurring: true
The cron prompt should instruct Claude to:
- List
requests/for pending files - For each, read the comment and surrounding doc context
- Determine type (ask or change) and process accordingly
- Delete the request file after processing (audit trail is in the doc blockquotes)
Claude infers the type — no explicit label needed.
Ask — reviewer wants an explanation or has a question. Claude reads the context, reads source files if needed, inserts a > **Claude** (<id>): response blockquote after the reviewer's comment.
Change — reviewer wants code modified. Claude makes the change in the actual repo, regenerates the diff section in the doc (collecting old comments into a collapsed <details> archive), and responds with > **Claude** (<id>): Done — description.
- Collect existing blockquote pairs from the section
- Re-read the source with
git diff main -- path/to/file(includes working tree changes) and update the.difffile that is our source of truth - Rewrite the diff/context blocks across all .md files
- Archive old comments in
<details><summary>Previous review comments (N)</summary>...</details>
Create test.mjs using playwright (not @playwright/test). The test starts its own server, runs checks, then kills it.
Required coverage:
- Server responds with 200
- Sidebar has correct number of links (
.md+.diff) - Each doc renders with headings and code blocks
- Syntax highlighting present (
.hljsclasses) - Diff code blocks present
- Text selection shows comment button
- Comment submission creates request file + blockquote with short-id
- Live reload shows comment without manual refresh
- Commenting on blockquotes works
- Commenting on
.difffiles works (via API) - Screenshots at each stage
npm install playwright && npx playwright install chromium
node test.mjsAfter all tests pass:
- Start server:
nohup node server.mjs & - Set up CronCreate for comment monitoring
- Tell the user the URL and cron job ID
review-project/
├── package.json
├── server.mjs
├── test.mjs
├── docs/
│ ├── 00-repo-name.diff (raw diffs, one per repo)
│ ├── 01-topic-name.md
│ ├── 02-topic-name.md
│ └── ...
├── requests/ (transient queue, files deleted after processing)
└── screenshots/
- Test before presenting — every time. Run
node test.mjsafter every change to the server, UI, or docs. Never tell the user to reload until all tests pass. Non-negotiable. - Audit after generating docs. Run
grep -c '````diff' docs/*.md— every doc must have diffs. Cross-check every hunk in the.difffiles against the docs. No fabricated lines. - UI preferences go in this SKILL file. If the reviewer asks for different styling or layout, implement it AND update this file so future sessions produce the same UI.
- The cron is session-only. Remind the user it dies when Claude exits (3-day auto-expiry).
These went wrong during real usage. Follow them to avoid repeating.
- Escape
\nin template literals. Inside backtick HTML templates,\nbecomes a real newline — use\\n. This is the #1 cause of browser SyntaxErrors. Playwright catches them.
- The scroll container is
#content, notwindow.window.scrollYis always 0. Comment button/popover useposition: fixedwith rawgetBoundingClientRect()values. Clamp to viewport bounds withMath.max(8, ...). - Sticky nav needs
padding-top: 0on#content. Put top padding on#content-innerinstead.
- Comments can land inside code blocks. The server's line search finds text inside fenced code regions. Prefer matches outside triple-backtick regions.
- Selected text from rendered blockquotes won't match raw markdown. Strip
>prefixes and**Reviewer/Claude** (id):markers when searching. - Popover must flip above when near viewport bottom. Check
window.innerHeight - rect.bottombefore positioning.
- Use
git diff main -- path/to/file(notmain...HEAD) to include unstaged changes. - Blank line required between
<details>tag and blockquote content, otherwise marked won't parse the blockquotes.
- Context goes in
<details>, not as the main content. The diff is what the reviewer is here to see. - Don't duplicate hunks across docs. Include once, cross-reference elsewhere.