diffprism 0.35.0 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,241 +1,100 @@
1
1
  # DiffPrism
2
2
 
3
- Local-first code review tool for agent-generated code changes. Opens a browser-based diff viewer from the CLI or Claude Code (via MCP).
3
+ Browser-based code review for agent-generated changes. Review what your AI wrote before it ships.
4
4
 
5
- DiffPrism gives you a visual review step for AI-written code — stage your changes, run the tool, and a browser window opens with a full-featured diff viewer. Review inline, leave comments, and your decision is returned as structured JSON.
6
-
7
- ## Features
8
-
9
- - **Syntax-highlighted diffs** — unified or split (side-by-side) view with toggle
10
- - **Inline line-level commenting** — click any line to add comments typed as `must_fix`, `suggestion`, `question`, or `nitpick`
11
- - **File-level review status** — mark each file as reviewed, approved, or needs changes
12
- - **Review briefing bar** — summary stats, complexity scoring, test coverage gaps, pattern flags, and dependency tracking
13
- - **Agent reasoning panel** — see why the AI made each change
14
- - **Dark/light mode** — toggle with theme persistence
15
- - **Keyboard shortcuts** — `j`/`k` navigate files, `s` cycles file status, `Cmd/Ctrl+Enter` saves comments, `?` toggles hotkey guide
16
- - **Four review decisions** — approve, request changes, approve with comments, or dismiss
17
- - **Quick actions** — Approve & Commit or Approve, Commit & PR directly from the review UI via the ⋮ menu; the agent executes the action automatically
18
- - **Branch display** — current git branch shown in the review header
19
- - **Global server mode** — `diffprism server` runs a persistent multi-session review server, multiple agents post reviews to one browser tab
20
- - **Multi-session UI** — session list with live status badges, branch info, file counts, and change stats; stale sessions auto-expire
21
- - **Desktop notifications** — native browser notifications when new review sessions arrive while the tab is backgrounded (global server mode)
22
- - **One-command setup & teardown** — `diffprism setup` configures Claude Code integration, `diffprism teardown` cleanly reverses it
23
-
24
- ## Quick Start
25
-
26
- ### Use with Claude Code (recommended)
27
-
28
- Run this from your project root:
5
+ ## Try It
29
6
 
30
7
  ```bash
31
- npx diffprism setup
8
+ npx diffprism demo
32
9
  ```
33
10
 
34
- This single command configures everything:
35
- - Adds `.diffprism` to `.gitignore`
36
- - Creates `.mcp.json` with the DiffPrism MCP server config
37
- - Creates `.claude/settings.json` with auto-approve permissions for all 3 MCP tools
38
- - Installs a Stop hook for watch mode cleanup
39
- - Installs the `/review` skill so you can type `/review` in Claude Code at any time
40
-
41
- After running, restart Claude Code. The first time you use `/review`, Claude will ask your preferences and save them to `diffprism.config.json`.
11
+ A browser window opens with a sample code review. Click around — leave comments, approve, see how it works. No git repo needed.
42
12
 
43
- To remove DiffPrism from a project:
13
+ ## Setup for Claude Code
44
14
 
45
15
  ```bash
46
- npx diffprism teardown
16
+ npx diffprism setup
47
17
  ```
48
18
 
49
- This reverses all changes made by `setup`: removes DiffPrism entries from `.mcp.json`, permissions, hooks, the skill file, `.gitignore`, and the `.diffprism/` directory. Non-DiffPrism entries are preserved.
19
+ Walks you through configuration. After restarting Claude Code, type `/review` to review your agent's changes.
50
20
 
51
- See the [full setup guide](docs/claude-setup.md) for manual configuration, Claude Desktop config, troubleshooting, and advanced options.
52
-
53
- ### Use from the CLI
54
-
55
- ```bash
56
- # Install globally (or use npx)
57
- npm install -g diffprism
21
+ **Two ways to trigger a review:**
58
22
 
59
- # Review all changes (staged + unstaged, default)
60
- diffprism review
23
+ 1. **Type `/review`** — Claude opens your current changes in DiffPrism's browser UI, waits for your decision, and acts on it (e.g., commits if you approve).
61
24
 
62
- # Review staged changes only
63
- diffprism review --staged
25
+ 2. **Ask Claude to review** — Say "review my changes" or "open a review" and Claude will call the tool.
64
26
 
65
- # Review unstaged changes only
66
- diffprism review --unstaged
27
+ The review blocks Claude until you submit your decision in the browser. If you request changes, Claude reads your comments and fixes them. If you approve via the quick action menu, Claude commits or opens a PR automatically.
67
28
 
68
- # Review a specific ref range
69
- diffprism review HEAD~3
70
- diffprism review main..feature-branch
71
-
72
- # Add a title to the review
73
- diffprism review --staged --title "Add auth middleware"
74
- ```
75
-
76
- A browser window opens with the diff viewer. Review the changes and click **Approve**, **Request Changes**, **Approve with Comments**, or **Dismiss**. Use the ⋮ menu for quick actions like Approve & Commit.
77
-
78
- ### Quick Start (setup + watch in one command)
29
+ ## Use from the CLI
79
30
 
80
31
  ```bash
81
- # Configure Claude Code integration and start watching in one step
82
- diffprism start
83
-
84
- # With flags
85
- diffprism start --staged --title "Working on auth"
32
+ diffprism review # Review all changes (staged + unstaged)
33
+ diffprism review --staged # Staged changes only
34
+ diffprism review HEAD~3 # Last 3 commits
35
+ diffprism review main..feature # Branch diff
86
36
  ```
87
37
 
88
- This runs `diffprism setup` (silently, if already configured) then starts watch mode. Ideal for first-time use or when switching projects.
38
+ ## Multi-Agent Reviews
89
39
 
90
- ### Watch Mode (live-updating)
40
+ Running multiple Claude Code sessions (e.g., in git worktrees)? All reviews appear in one browser tab.
91
41
 
92
- Keep a persistent browser tab that auto-refreshes as files change ideal for reviewing while an agent is working:
42
+ The server starts automatically on first use — no manual setup needed. Each review shows up as a session with status badges, branch info, and change stats. Click to switch between reviews. Desktop notifications alert you when new reviews arrive.
93
43
 
94
44
  ```bash
95
- # Watch staged changes, auto-refresh on every change
96
- diffprism watch --staged
97
-
98
- # Watch all changes with custom poll interval
99
- diffprism watch --interval 2000
100
-
101
- # Watch unstaged changes
102
- diffprism watch --unstaged
45
+ diffprism server status # Check if server is running
46
+ diffprism server stop # Stop the background server
103
47
  ```
104
48
 
105
- When `diffprism watch` is running:
106
- - The browser tab stays open and updates diffs + analysis within 1-2s of file changes
107
- - Submit a review and it stays open, waiting for the next change
108
- - File review statuses are preserved for unchanged files
109
- - Claude Code's `/review` skill automatically detects the watch session and pushes reasoning without blocking
110
-
111
- Stop the watcher with `Ctrl+C`.
112
-
113
- ### Global Server Mode (multi-session)
114
-
115
- Run a persistent server that accepts reviews from multiple Claude Code sessions and displays them in one browser tab:
116
-
117
- ```bash
118
- # Start the global server (auto-runs global setup if needed)
119
- diffprism server
120
-
121
- # Check status and list active sessions
122
- diffprism server status
123
-
124
- # Stop the server
125
- diffprism server stop
126
- ```
49
+ ## Features
127
50
 
128
- When the global server is running, MCP tools automatically detect it and route reviews there instead of opening ephemeral browser tabs. Each review appears as a session in the multi-session UIclick to switch between them. Session status badges update live, and submitted sessions auto-expire after 5 minutes.
51
+ - **Syntax-highlighted diffs**unified or split (side-by-side) view
52
+ - **Inline commenting** — click any line to add `must_fix`, `suggestion`, `question`, or `nitpick` comments
53
+ - **Review briefing** — complexity scores, test coverage gaps, pattern flags, dependency tracking
54
+ - **Agent reasoning panel** — see why the AI made each change
55
+ - **Quick actions** — Approve & Commit or Approve, Commit & PR from the review UI
56
+ - **Multi-session dashboard** — review multiple agents from one browser tab
57
+ - **Desktop notifications** — get alerted when a new review arrives
58
+ - **GitHub PR review** — review any GitHub PR in DiffPrism's UI
59
+ - **Keyboard shortcuts** — `j`/`k` files, `n`/`p` hunks, `c` comment, `s` status, `?` help
60
+ - **Dark/light mode** — toggle with persistence
129
61
 
130
- **Global setup** (optional, `diffprism server` runs this automatically):
62
+ ## Uninstall
131
63
 
132
64
  ```bash
133
- # Configure skill + permissions globally (no git repo required)
134
- diffprism setup --global
135
-
136
- # Remove global configuration
137
- diffprism teardown --global
138
- ```
139
-
140
- Per-project MCP registration (`.mcp.json`) is still needed via `diffprism setup` in each project.
141
-
142
- ## MCP Tool Reference
143
-
144
- The MCP server exposes three tools:
145
-
146
- ### `open_review`
147
-
148
- Opens a browser-based code review. Blocks until the engineer submits their decision.
149
-
150
- | Parameter | Required | Description |
151
- |---------------|----------|-------------------------------------------------------------------|
152
- | `diff_ref` | Yes | `"staged"`, `"unstaged"`, `"working-copy"` (staged+unstaged grouped), or a git ref range (e.g. `"HEAD~3..HEAD"`, `"main..feature"`) |
153
- | `title` | No | Title displayed in the review UI |
154
- | `description` | No | Description of the changes |
155
- | `reasoning` | No | Agent reasoning about why the changes were made (shown in the reasoning panel) |
156
-
157
- ### `update_review_context`
158
-
159
- Pushes reasoning/context to a running DiffPrism session (watch mode or global server). Non-blocking — returns immediately.
160
-
161
- | Parameter | Required | Description |
162
- |---------------|----------|------------------------------------------------|
163
- | `reasoning` | No | Agent reasoning about the current changes |
164
- | `title` | No | Updated title for the review |
165
- | `description` | No | Updated description of the changes |
166
-
167
- ### `get_review_result`
168
-
169
- Fetches the most recent review result from a DiffPrism session (watch mode or global server). The result is marked as consumed after retrieval so it won't be returned again.
170
-
171
- | Parameter | Required | Description |
172
- |-----------|----------|-------------------------------------------------------------------|
173
- | `wait` | No | If `true`, poll until a result is available (blocks up to timeout) |
174
- | `timeout` | No | Max wait time in seconds when `wait=true` (default: 300, max: 600) |
175
-
176
- **Returns (all tools):** A `ReviewResult` JSON object:
177
-
178
- ```json
179
- {
180
- "decision": "approved",
181
- "comments": [
182
- {
183
- "file": "src/index.ts",
184
- "line": 42,
185
- "body": "Consider adding a null check here",
186
- "type": "suggestion"
187
- }
188
- ],
189
- "summary": "Looks good, one minor suggestion."
190
- }
65
+ npx diffprism teardown # Remove from current project
66
+ npx diffprism teardown --global # Remove global config
191
67
  ```
192
68
 
193
- | Field | Description |
194
- |-------|-------------|
195
- | `decision` | `approved`, `changes_requested`, `approved_with_comments`, or `dismissed` |
196
- | `comments` | Array of inline comments with file, line, body, and type (`must_fix`, `suggestion`, `question`, `nitpick`) |
197
- | `summary` | Optional reviewer summary |
198
- | `postReviewAction` | Optional: `"commit"` or `"commit_and_pr"` — set when user selects a quick action from the ⋮ menu |
199
-
200
- ## How It Works
201
-
202
- 1. **Extract** — runs `git diff` and parses the output into a structured `DiffSet`
203
- 2. **Analyze** — generates a `ReviewBriefing`: file stats, complexity scores, test gap detection, pattern flags, dependency changes
204
- 3. **Serve** — starts a Vite dev server (React UI) and WebSocket bridge on random ports
205
- 4. **Review** — opens a browser to the diff viewer, waits for your decision
206
- 5. **Return** — cleans up servers and returns the `ReviewResult`
207
-
208
69
  ## Development
209
70
 
210
71
  ```bash
211
72
  git clone https://github.com/CodeJonesW/diffprism.git
212
73
  cd diffprism
213
74
  pnpm install
214
- pnpm test # Run all tests (Vitest)
215
- pnpm run build # Build all packages
216
- pnpm cli review --staged # Run CLI from source
217
- npx tsc --noEmit -p packages/core/tsconfig.json # Type-check a package
75
+ pnpm test
76
+ pnpm run build
77
+ pnpm cli review --staged # Run CLI from source
218
78
  ```
219
79
 
220
80
  ### Project Structure
221
81
 
222
82
  ```
223
- packages/core — Shared types, pipeline orchestrator, WebSocket bridge, global server
224
- packages/git — Git diff extraction + unified diff parser
225
- packages/analysis — Deterministic review briefing (complexity, test gaps, patterns)
226
- packages/ui — React 19 + Vite 6 + Tailwind + Zustand diff viewer + session list
227
- packages/mcp-server — MCP tool server, auto-routes to global server when available
228
- cli/ Commander CLI (review, start, watch, setup, teardown, server commands)
83
+ packages/core — Server, types, server-client utilities
84
+ packages/git — Git diff extraction + parser
85
+ packages/analysis — Deterministic review briefing
86
+ packages/ui — React 19 + Vite 6 + Tailwind + Zustand
87
+ packages/mcp-server — MCP tool server (9 tools)
88
+ packages/github GitHub PR fetching + review submission
89
+ cli/ — Commander CLI
229
90
  ```
230
91
 
231
92
  ### Requirements
232
93
 
233
94
  - Node.js >= 20
234
- - pnpm (for development)
235
95
  - Git
236
96
 
237
97
  ## Documentation
238
98
 
239
- - [Claude Code / Claude Desktop Setup Guide](docs/claude-setup.md) — detailed MCP configuration, auto-approval, and troubleshooting
240
- - [Workflows Guide](docs/workflows.md) — ephemeral, watch, and global server modes explained
241
- - [UX Design Notes](docs/ux-design-notes.md) — design decisions, CLI defaults rationale, and multi-agent workflow thinking
99
+ - [Claude Code Setup Guide](docs/usage/claude-setup.md) — detailed configuration and troubleshooting
100
+ - [Dev Testing Guide](docs/usage/dev-testing.md) — running from source
package/dist/bin.js CHANGED
@@ -1,18 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  createGitHubClient,
4
- ensureServer,
5
4
  fetchPullRequest,
6
5
  fetchPullRequestDiff,
7
- isServerAlive,
8
6
  normalizePr,
9
7
  parsePrRef,
10
- readServerFile,
11
8
  resolveGitHubToken,
9
+ submitGitHubReview
10
+ } from "./chunk-OR6PCPZX.js";
11
+ import {
12
+ demo
13
+ } from "./chunk-UYZ3A2PB.js";
14
+ import {
15
+ ensureServer,
16
+ isServerAlive,
17
+ readServerFile,
12
18
  startGlobalServer,
13
- submitGitHubReview,
14
19
  submitReviewToServer
15
- } from "./chunk-LUUR6LNP.js";
20
+ } from "./chunk-ITPHDFOS.js";
16
21
  import "./chunk-QGWYCEJN.js";
17
22
  import "./chunk-DHCVZGHE.js";
18
23
  import "./chunk-JSBRDJBE.js";
@@ -34,6 +39,7 @@ async function review(ref, flags) {
34
39
  }
35
40
  try {
36
41
  const serverInfo = await ensureServer({ dev: flags.dev });
42
+ console.log("Opening review in browser...");
37
43
  const { result } = await submitReviewToServer(serverInfo, diffRef, {
38
44
  title: flags.title,
39
45
  cwd: process.cwd(),
@@ -351,7 +357,84 @@ async function setupGitignore(gitRoot) {
351
357
  fs.writeFileSync(filePath, GITIGNORE_ENTRIES.map((e) => e + "\n").join(""));
352
358
  return { action: "created", filePath };
353
359
  }
360
+ async function promptChoice(question, options) {
361
+ const rl = readline2.createInterface({
362
+ input: process.stdin,
363
+ output: process.stdout
364
+ });
365
+ for (let i = 0; i < options.length; i++) {
366
+ console.log(` ${i + 1}. ${options[i]}`);
367
+ }
368
+ return new Promise((resolve) => {
369
+ rl.question(question, (answer) => {
370
+ rl.close();
371
+ const num = parseInt(answer.trim(), 10);
372
+ if (num >= 1 && num <= options.length) {
373
+ resolve(num - 1);
374
+ } else {
375
+ resolve(0);
376
+ }
377
+ });
378
+ });
379
+ }
354
380
  async function setup(flags) {
381
+ const force = flags.force ?? false;
382
+ const global = flags.global ?? false;
383
+ const quiet = flags.quiet ?? false;
384
+ const isInteractive = !global && !force && !quiet && process.stdin.isTTY;
385
+ if (isInteractive) {
386
+ return setupInteractive(flags);
387
+ }
388
+ return setupBatch(flags);
389
+ }
390
+ async function setupInteractive(flags) {
391
+ const dev = flags.dev;
392
+ const gitRoot = findGitRoot(process.cwd());
393
+ console.log("\n Welcome to DiffPrism");
394
+ console.log(" Browser-based code review for agent-generated changes.\n");
395
+ const modeChoice = await promptChoice("\nHow will you use DiffPrism? ", [
396
+ "With Claude Code (recommended)",
397
+ "From the CLI only"
398
+ ]);
399
+ if (modeChoice === 0) {
400
+ if (!gitRoot) {
401
+ console.log("\n Not in a git repository \u2014 configuring globally.\n");
402
+ const outcome2 = await setupBatch({ global: true, quiet: true });
403
+ console.log(" Setting up for Claude Code...");
404
+ console.log(" \u2713 Installed /review skill");
405
+ console.log(" \u2713 Added tool permissions");
406
+ console.log("\n Restart Claude Code, then type /review to start a review.\n");
407
+ await offerDemo(dev);
408
+ return outcome2;
409
+ }
410
+ console.log("\n Setting up for Claude Code...");
411
+ const outcome = await setupBatch({ quiet: true });
412
+ if (outcome.created.length > 0 || outcome.updated.length > 0) {
413
+ console.log(" \u2713 Registered MCP server (.mcp.json)");
414
+ console.log(" \u2713 Added tool permissions (.claude/settings.json)");
415
+ console.log(" \u2713 Installed /review skill");
416
+ console.log(" \u2713 Added .diffprism to .gitignore");
417
+ } else {
418
+ console.log(" \u2713 Already configured");
419
+ }
420
+ console.log("\n Restart Claude Code, then type /review to start a review.\n");
421
+ await offerDemo(dev);
422
+ return outcome;
423
+ }
424
+ console.log("\n DiffPrism is ready to use.");
425
+ console.log(" Run `diffprism review` in any git repo to review changes.\n");
426
+ await offerDemo(dev);
427
+ return { created: [], updated: [], skipped: [] };
428
+ }
429
+ async function offerDemo(dev) {
430
+ const wantsDemo = await promptUser("Try a demo review now? (Y/n) ");
431
+ if (wantsDemo) {
432
+ console.log("");
433
+ const { demo: demo2 } = await import("./demo-JH5YOKTZ.js");
434
+ await demo2({ dev });
435
+ }
436
+ }
437
+ async function setupBatch(flags) {
355
438
  const force = flags.force ?? false;
356
439
  const global = flags.global ?? false;
357
440
  const quiet = flags.quiet ?? false;
@@ -903,14 +986,15 @@ async function serverStop() {
903
986
 
904
987
  // cli/src/index.ts
905
988
  var program = new Command();
906
- program.name("diffprism").description("Local-first code review tool for agent-generated changes").version(true ? "0.35.0" : "0.0.0-dev");
989
+ program.name("diffprism").description("Local-first code review tool for agent-generated changes").version(true ? "0.36.0" : "0.0.0-dev");
990
+ program.command("demo").description("Open a sample review to see DiffPrism in action").option("--dev", "Use Vite dev server").action(demo);
907
991
  program.command("review [ref]").description("Open a browser-based diff review").option("--staged", "Review staged changes").option("--unstaged", "Review unstaged changes").option("-t, --title <title>", "Review title").option("--dev", "Use Vite dev server with HMR instead of static files").action(review);
908
992
  program.command("review-pr <pr>").description("Review a GitHub pull request in DiffPrism").option("-t, --title <title>", "Override review title").option("--reasoning <text>", "Agent reasoning about the PR").option("--dev", "Use Vite dev server with HMR instead of static files").option("--post-to-github", "Automatically post review back to GitHub without prompting").action(reviewPr);
909
993
  program.command("start [ref]").description("Set up DiffPrism and start watching for changes").option("--staged", "Watch staged changes").option("--unstaged", "Watch unstaged changes").option("-t, --title <title>", "Review title").option("--interval <ms>", "Poll interval in milliseconds (default: 1000)").option("--dev", "Use Vite dev server with HMR instead of static files").option("--global", "Install skill globally (~/.claude/skills/)").option("--force", "Overwrite existing configuration files").action(start);
910
994
  program.command("watch [ref]").description("Start a persistent diff watcher with live-updating browser UI").option("--staged", "Watch staged changes").option("--unstaged", "Watch unstaged changes").option("-t, --title <title>", "Review title").option("--interval <ms>", "Poll interval in milliseconds (default: 1000)").option("--dev", "Use Vite dev server with HMR instead of static files").action(watch);
911
995
  program.command("notify-stop").description("Signal the watch server to refresh (used by Claude Code hooks)").action(notifyStop);
912
996
  program.command("serve").description("Start the MCP server for Claude Code integration").action(serve);
913
- program.command("setup").description("Configure DiffPrism for Claude Code integration").option("--global", "Configure globally (skill + permissions, no git repo required)").option("--force", "Overwrite existing configuration files").action((flags) => {
997
+ program.command("setup").description("Configure DiffPrism for Claude Code integration").option("--global", "Configure globally (skill + permissions, no git repo required)").option("--force", "Overwrite existing configuration files").option("--dev", "Use Vite dev server").action((flags) => {
914
998
  setup(flags);
915
999
  });
916
1000
  program.command("teardown").description("Remove DiffPrism configuration from the current project").option("--global", "Remove global configuration (skill + permissions at ~/.claude/)").option("-q, --quiet", "Suppress output").action((flags) => {