diffing 0.1.0 → 0.1.2

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.
Files changed (82) hide show
  1. package/README.md +364 -115
  2. package/dist/cli-agent-DZBvZoXZ.mjs +179 -0
  3. package/dist/cli.mjs +27 -27
  4. package/dist/client/assets/{angular-html-BmBRnRY-.js → angular-html-BABKYppC.js} +1 -1
  5. package/dist/client/assets/{angular-ts-BTywfy8Q.js → angular-ts-CtXLuOQb.js} +1 -1
  6. package/dist/client/assets/{apl-C-Nh4njw.js → apl-DOi69evI.js} +1 -1
  7. package/dist/client/assets/{astro-DGFZsGD0.js → astro-J8Em2tfW.js} +1 -1
  8. package/dist/client/assets/{blade-CK2WgF42.js → blade-B_tOnqRD.js} +1 -1
  9. package/dist/client/assets/{c-MXSr0H4Y.js → c-C0tRZWSi.js} +1 -1
  10. package/dist/client/assets/{cobol-BHSU4T5M.js → cobol-Dj_rkgIY.js} +1 -1
  11. package/dist/client/assets/{coffee-DiFXs9rA.js → coffee-C6Vq4BFF.js} +1 -1
  12. package/dist/client/assets/{cpp-CJWLNzrI.js → cpp-Cno48fgF.js} +1 -1
  13. package/dist/client/assets/{crystal-u5M0TrPu.js → crystal-C7tmDnU1.js} +1 -1
  14. package/dist/client/assets/{css-BMVhDkjX.js → css-0v4o-iNQ.js} +1 -1
  15. package/dist/client/assets/{edge-Di-AS7wq.js → edge-CvULxRem.js} +1 -1
  16. package/dist/client/assets/{elixir-CSMS6Yja.js → elixir-vRTauEw-.js} +1 -1
  17. package/dist/client/assets/{elm-CgUch6k4.js → elm-fLFTu1xn.js} +1 -1
  18. package/dist/client/assets/{erb-BY53XvrH.js → erb-CtItcikB.js} +1 -1
  19. package/dist/client/assets/{git-rebase-Cu4zaEs3.js → git-rebase-5MeRBXZD.js} +1 -1
  20. package/dist/client/assets/{glimmer-js-DgxwVbEv.js → glimmer-js-B7yA-u8_.js} +1 -1
  21. package/dist/client/assets/{glimmer-ts-CQgpMe8l.js → glimmer-ts-B2g1OaHc.js} +1 -1
  22. package/dist/client/assets/{glsl-C6rPllEZ.js → glsl-CqNPWp5Y.js} +1 -1
  23. package/dist/client/assets/{graphql-D0IXKtPr.js → graphql-CF78KbfF.js} +1 -1
  24. package/dist/client/assets/{hack-Bbv4uGLh.js → hack-Dz8fQ8O9.js} +1 -1
  25. package/dist/client/assets/{haml-BEq4fVEe.js → haml-3Gbl257r.js} +1 -1
  26. package/dist/client/assets/{handlebars-CGriKhdR.js → handlebars-5UZnh5L7.js} +1 -1
  27. package/dist/client/assets/{html-DhsWBiF-.js → html-JOaQiIkL.js} +1 -1
  28. package/dist/client/assets/{html-derivative-CU7SM-vj.js → html-derivative-GyX6oYy3.js} +1 -1
  29. package/dist/client/assets/{http-DAZNqWUu.js → http-t6uVAxgS.js} +1 -1
  30. package/dist/client/assets/{hurl-DGP3-RE2.js → hurl-OLQZpg0E.js} +1 -1
  31. package/dist/client/assets/{index-Bsby5xp2.js → index-CghVgrAF.js} +5 -5
  32. package/dist/client/assets/{index-BqD_EVaR.css → index-CmfB2R-C.css} +1 -1
  33. package/dist/client/assets/{java-CoIvfF-o.js → java-BqL_yaya.js} +1 -1
  34. package/dist/client/assets/{javascript-D2G0Bybq.js → javascript-CxBNAxR5.js} +1 -1
  35. package/dist/client/assets/{jinja-BRdOYMmE.js → jinja-CuaK033Z.js} +1 -1
  36. package/dist/client/assets/{jison-CVQZsA0e.js → jison-aL_w2vvo.js} +1 -1
  37. package/dist/client/assets/{json-BTFmVGAb.js → json-Byruj-EC.js} +1 -1
  38. package/dist/client/assets/{jsx-DYLgPaVb.js → jsx-CosY06uG.js} +1 -1
  39. package/dist/client/assets/{julia-CJWtNtRM.js → julia-u1y7fV63.js} +1 -1
  40. package/dist/client/assets/{just-CZyINJ-2.js → just-DS4T9P_K.js} +1 -1
  41. package/dist/client/assets/{latex-mNMnTIv1.js → latex-C9c2IWW4.js} +1 -1
  42. package/dist/client/assets/{liquid-BgSPl0Kv.js → liquid-DcXQgkEV.js} +1 -1
  43. package/dist/client/assets/{lua-rmIsezWJ.js → lua-DWe0hUn1.js} +1 -1
  44. package/dist/client/assets/{marko-Dfkwq7Gv.js → marko-CIW7o2up.js} +1 -1
  45. package/dist/client/assets/{mdc-f53p1REg.js → mdc-DKjGzb4k.js} +1 -1
  46. package/dist/client/assets/{nginx-Cn5ljkEv.js → nginx-CBXzDlkk.js} +1 -1
  47. package/dist/client/assets/{nim-DrAyHk_n.js → nim-CBf_vdee.js} +1 -1
  48. package/dist/client/assets/{perl-BLNIVaG-.js → perl-xC9qc39I.js} +1 -1
  49. package/dist/client/assets/{php-CxDOF44K.js → php-n4vnn5oz.js} +1 -1
  50. package/dist/client/assets/{pug-DGZxLxM3.js → pug-Db536lA_.js} +1 -1
  51. package/dist/client/assets/{qml-Dmqfyov_.js → qml-CrATLnNN.js} +1 -1
  52. package/dist/client/assets/{r-F2CLYuZ7.js → r-DBQ-dydl.js} +1 -1
  53. package/dist/client/assets/{razor-DYbbBV0d.js → razor-C_wvK1iP.js} +1 -1
  54. package/dist/client/assets/{regexp-TyKA4-BB.js → regexp-DowFj0Xd.js} +1 -1
  55. package/dist/client/assets/{rst-CMLF7yP9.js → rst-rY4UPiwe.js} +1 -1
  56. package/dist/client/assets/{ruby-BE4S9bsQ.js → ruby-C4cISY4u.js} +1 -1
  57. package/dist/client/assets/{sas-DOhcrhSM.js → sas-ui1PNNkD.js} +1 -1
  58. package/dist/client/assets/{scss-DZgJ0K1I.js → scss-BZrs95TC.js} +1 -1
  59. package/dist/client/assets/{shellscript-CWMAvx8a.js → shellscript-D9YVFS67.js} +1 -1
  60. package/dist/client/assets/{shellsession-OJxRnKbO.js → shellsession-DK7LMzYg.js} +1 -1
  61. package/dist/client/assets/{soy-C_oQW_S0.js → soy-CNkc-Oji.js} +1 -1
  62. package/dist/client/assets/{sql-DEXpTiLI.js → sql-BvRdqBMa.js} +1 -1
  63. package/dist/client/assets/{stata-BcrmvsDF.js → stata-Bawjgtiz.js} +1 -1
  64. package/dist/client/assets/{surrealql-Dwy3iKjf.js → surrealql-7v7lT5jp.js} +1 -1
  65. package/dist/client/assets/{svelte-BbWN9l2M.js → svelte-p7w_kluv.js} +1 -1
  66. package/dist/client/assets/{templ-BGIeAdtg.js → templ-0Gi_yZZr.js} +1 -1
  67. package/dist/client/assets/{tex-9fSuF3Cs.js → tex-nZ_J3lks.js} +1 -1
  68. package/dist/client/assets/{ts-tags-BcxYxF8C.js → ts-tags-CuG-Aj5j.js} +1 -1
  69. package/dist/client/assets/{tsx-B_z3ONaQ.js → tsx-Cc7GNb_V.js} +1 -1
  70. package/dist/client/assets/{twig-DQ7osXl9.js → twig-BBlmihVM.js} +1 -1
  71. package/dist/client/assets/{typescript-oc7bycaY.js → typescript-aiXwsZhm.js} +1 -1
  72. package/dist/client/assets/{vue-B3o6Rfti.js → vue-Cs5tk2kn.js} +1 -1
  73. package/dist/client/assets/{vue-html-BB_D6k4v.js → vue-html-BEI_B8Ml.js} +1 -1
  74. package/dist/client/assets/{vue-vine-CROD_1yE.js → vue-vine-CpWdOkP4.js} +1 -1
  75. package/dist/client/assets/{xml-BeVKeTE5.js → xml-madLQSkS.js} +1 -1
  76. package/dist/client/assets/{xsl-DaxeysAZ.js → xsl-CqZR37V9.js} +1 -1
  77. package/dist/client/assets/{yaml-DJD0ioac.js → yaml-DHr9ndbK.js} +1 -1
  78. package/dist/client/index.html +3 -3
  79. package/dist/mcp-BQmH_By-.mjs +119 -0
  80. package/dist/mcp-D9E2HQZ9.mjs +119 -0
  81. package/dist/server-lock-DbxpfF3j.mjs +575 -0
  82. package/package.json +18 -16
package/README.md CHANGED
@@ -1,163 +1,412 @@
1
- # diffit
1
+ # diffing
2
2
 
3
- A local code review tool designed for the coding agent workflow. Review AI-generated changes in a GitHub PR-like web UI, leave inline comments, then hand them back to your coding agent to fix.
3
+ A local-first code review tool and double-sided bridge designed for the modern AI coding agent workflow. Review AI-generated changes in a high-fidelity, GitHub-like web UI, leave inline comments, and hand them back to your coding agent to fix in real time.
4
4
 
5
- ![screenshot](https://raw.githubusercontent.com/ahmedragab20/diffit/main/screenshot.png)
5
+ <img width="1840" height="1196" alt="image" src="https://github.com/user-attachments/assets/767d42ed-a497-4b21-aca7-35be8b9a7006" />
6
6
 
7
- ## Install
8
7
 
8
+ ---
9
+
10
+ ## Quick Start
11
+
12
+ ### 1. Install
13
+ Install `diffing` globally via npm:
14
+ ```bash
15
+ npm install -g diffing
16
+ ```
17
+
18
+ ### 2. Run
19
+ Launch it within any active git repository:
9
20
  ```bash
10
- npm install -g @ahmedragab/diffit
21
+ diffing
11
22
  ```
23
+ This instantly spins up a local server, establishes an active repository watcher, and opens your default browser to an interactive code review dashboard.
24
+
25
+ ---
26
+
27
+ ## Web UI Review Dashboard
28
+
29
+ A local Hono-powered review server delivers a full-featured GitHub-like code review interface directly in your browser.
30
+
31
+ - **Split / Unified View** — Toggle between side-by-side (`split`) and inline (`unified`) diff layouts via toolbar or keyboard shortcut `m`.
32
+ - **Syntax Highlighting** — Powered by Shiki via `@pierre/diffs`, with high-fidelity highlighting for 200+ languages.
33
+ - **Interactive File Tree** — Hierarchical file navigation sidebar with collapsible folders, viewed/unviewed tracking, and change-type indicators (added, modified, deleted).
34
+ - **Status Dashboard (Comment Tracker)** — Bottom panel tracking open, replied, and resolved comments with filter tabs and click-to-navigate references to the relevant file and line.
35
+ - **Git Diff Stats** — Toolbar displays repo name, branch, file count, and additions/deletions (`+X/-Y`) computed from the patch.
36
+ - **Resizable Panels** — Drag-to-resize sidebar (240px–640px) and comment tracker panel (100px–600px). Widths and heights persist in localStorage.
37
+ - **Skeleton Loading Screen** — Full shimmer placeholder UI for toolbar, sidebar, search, tree nodes, and file diffs during initial load.
38
+ - **Image Diff Previews** — Visual side-by-side comparison for added, changed, and deleted image files (PNG, JPEG, GIF, WebP, SVG, BMP, ICO, AVIF).
39
+
40
+ ---
12
41
 
13
- ## Usage
42
+ ## Themes
43
+
44
+ 42+ built-in themes powered by Shiki, with instant switching and live preview.
45
+
46
+ | Category | Themes |
47
+ |----------|--------|
48
+ | GitHub Family | GitHub Dark, GitHub Light, GitHub Dark Dimmed, GitHub Dark High Contrast |
49
+ | Popular Dark | Dracula, One Dark Pro, Monokai, Synthwave '84, Material Theme (Ocean/Palenight/Darker) |
50
+ | Tokyo Night | Tokyo Night, Tokyo Night Storm, Tokyo Night Light |
51
+ | Catppuccin | Mocha, Frappe, Macchiato, Latte |
52
+ | Nord Family | Nord |
53
+ | Nightfox Family | Nightfox, Nordfox, Duskfox, Terafox, Carbonfox, Dayfox, Dawnfox |
54
+ | Rose Pine | Rose Pine, Rose Pine Dawn, Rose Pine Moon |
55
+ | Solarized | Solarized Dark, Solarized Light |
56
+ | VS Code | Dark+, Light+, Dark Modern, Light Modern |
57
+ | Others | Andromeeda, Aurora X, Houston, Laserwave, Min Dark/Light, Night Owl, One Light, Plastic, Poimandres, Slack (Dark/Ochre), Vesper, Vitesse Dark/Light, Ayu Dark/Light |
58
+
59
+ - **Searchable Theme Modal** — Press `g` `t` or use the toolbar to open a categorized, searchable theme picker with color swatches and live preview.
60
+ - **Dark/Light Dual Mode** — Each theme maps to corresponding dark and light Shiki themes for accurate syntax highlighting in both modes.
61
+ - **Instant Switching** — CSS transitions suppressed during theme changes for a snappy, lag-free experience.
62
+ - **Persistent Setting** — Theme choice saved to `~/.config/diffing/settings.json` and restored on next launch.
63
+
64
+ <img width="1840" height="1196" alt="image" src="https://github.com/user-attachments/assets/d4905604-e156-4c9b-998e-9015a7c36019" />
65
+
66
+
67
+ ---
68
+
69
+ ## Rust-Powered Code Search (powered by fff)
70
+
71
+ Blazing-fast, native fuzzy code search integrated directly into the sidebar search palette via `@ff-labs/fff-node`:
72
+
73
+ - **Fuzzy File Search** (`Files` scope) — Error-tolerant fuzzy matching on workspace paths using a native Rust engine.
74
+ - **Codebase Grep** (`Text` scope) — Instant case-insensitive text search with full **Regular Expression** support.
75
+ - **Syntactic Symbol Search** (`Symbols` scope) — Finds function declarations, class headers, type definitions, and variable assignments across JavaScript, TypeScript, Go, Rust, and Python (17+ language patterns).
76
+ - **Unified "All" Search** — Concurrent search across files, text, and symbols with automatic deduplication.
77
+ - **Frecency Ranking** — SQLite-backed history database remembers which files you open for specific queries, floating high-value results to the top.
78
+ - **"Changed Only" Filter** — Restricts search scope exclusively to files changed in the active git diff.
79
+ - **Git Status Chips** — Search results display git status indicators (modified, untracked, added, deleted, renamed).
80
+ - **Graceful Degradation** — If the native Rust binary is unavailable, search reports as unavailable without crashing the server.
81
+ - **Auto-Indexing** — The Rust engine maintains its own file system watcher for real-time index updates as the working tree changes.
82
+
83
+ <img width="1840" height="1196" alt="image" src="https://github.com/user-attachments/assets/0830b770-3c7f-44a1-b8ff-a70b2b34144a" />
84
+
85
+
86
+ ---
87
+
88
+ ## Vim-Style Keyboard Navigation
89
+
90
+ Full keyboard-driven navigation with vim-like motions and a modal status bar:
91
+
92
+ ### Scrolling & Diffs
93
+ | Key | Action |
94
+ |-----|--------|
95
+ | `j` / `k` | Scroll down/up by 100px |
96
+ | `Ctrl+d` / `Ctrl+u` | Scroll half-page down/up |
97
+ | `g` `g` | Jump to top of diff |
98
+ | `G` | Jump to bottom of diff |
99
+ | `m` | Toggle split/unified view |
100
+ | `t` | Cycle tab size (2 → 4 → 8) |
101
+ | `w` | Toggle line wrap |
102
+ | `n` | Toggle line numbers |
103
+ | `i` | Cycle diff indicators |
104
+ | `I` | Cycle inline diff type |
105
+
106
+ ### File Navigation & UI
107
+ | Key | Action |
108
+ |-----|--------|
109
+ | `J` / `K` | Jump to next/previous file |
110
+ | `v` | Toggle file viewed/unviewed |
111
+ | `b` | Toggle sidebar visibility |
112
+ | `/` | Open text search |
113
+ | `s` | Open symbol search |
114
+ | `g` `v` | Open file browser |
115
+ | `g` `t` | Open theme picker |
116
+ | `Cmd/Ctrl+K` | Open global command palette |
117
+ | `Cmd/Ctrl+,` | Toggle settings panel |
118
+ | `?` | Show shortcuts help modal |
119
+
120
+ A vim-style status bar at the bottom displays the current mode (NORMAL/INSERT), file path, and a help button. Multi-key sequences use an 800ms key buffer.
121
+
122
+ <img width="1840" height="1196" alt="image" src="https://github.com/user-attachments/assets/d230d020-4fb2-475a-a8a0-0ae11bb271ff" />
123
+
124
+
125
+ ---
126
+
127
+ ## Performance & Speed
128
+
129
+ Built from the ground up for a fast, fluid experience—even in large repositories:
130
+
131
+ - **Rust-Powered Search** — Native engine handles indexing and querying outside the JS event loop.
132
+ - **Async Diff Execution** — Server fetches unstaged, staged, and untracked diffs concurrently via `Promise.all`.
133
+ - **Web Worker Rendering** — `@pierre/diffs` uses a worker pool for syntax highlighting and diff computation off the main thread.
134
+ - **React.memo + useMemo** — Extensive component memoization prevents unnecessary re-renders when files haven't changed.
135
+ - **useTransition** — Settings changes (theme, diff style, font size) wrapped in `startTransition` for non-blocking UI updates.
136
+ - **Compositor-Only Resize** — Sidebar and comment panel resize use GPU-composited transform guides; width/height committed only on mouseup for 60fps feel.
137
+ - **Shiki Pre-Warming** — Highlighter engines preloaded on theme change for instant first paint.
138
+ - **Large Buffer Support** — Git operations use 50–100MB max buffer to handle large diffs.
139
+ - **Object Reference Stability** — Diff metadata reuses previous object references when file contents haven't changed (JSON comparison of hunks).
140
+ - **Stale Project Cleanup** — Project storage directories older than 14 days or with missing repo paths are automatically purged.
141
+
142
+ ---
143
+
144
+ ## Real-Time Communication
145
+
146
+ Bidirectional, event-driven sync between the browser UI and connected AI agents via Server-Sent Events (SSE):
147
+
148
+ ```text
149
+ ┌──────────────┐ SSE (change/comments/agent-status) ┌──────────────┐
150
+ │ │◄───────────────────────────────────────────►│ │
151
+ │ Browser │ │ AI Agent │
152
+ │ UI │ ┌─────────────────────────────┐ │ (CLI/MCP) │
153
+ │ │ │ comments.json │ │ │
154
+ │ │ │ (FileCommentStore on disk) │ │ │
155
+ └──────┬───────┘ └──────────┬──────────────────┘ └──────┬───────┘
156
+ │ user writes comment │ │
157
+ │ ──────────────────────► │ fs.watch detects change │
158
+ │ │ ───────────────────────────────► │
159
+ │ │ agent posts reply │
160
+ │ SSE broadcasts toast │ ◄────────────────────────────── │
161
+ │ ◄───────────────────────│ │
162
+ ```
163
+
164
+ - **Single SSE Endpoint** (`/api/live`) — Multiplexed event stream with named events: `change` (working tree), `comments` (store updated), `agent-status` (agent connect/disconnect/send), `heartbeat` (15s keep-alive).
165
+ - **File System Watcher** — `fs.watch` on repo root (recursive, 200ms debounce) triggers live diff refresh on working tree changes. Skips `.git`, `node_modules`, `dist`, and `.changeset`.
166
+ - **Comment Store Watcher** — `fs.watch` on `comments.json` (120ms debounce) broadcasts updates when agents or humans write comments externally.
167
+ - **Agent Activity Toasts** — Real-time toast notifications when an agent posts a reply, showing model name, file path, and body preview. Clickable to jump to the file; auto-dismisses after 8 seconds.
168
+ - **Agent Status Indicator** — Green dot on the "Send to agent" button when an agent process is connected and waiting (via SSE `agent-status` events).
169
+ - **Bidirectional Sync** — User adds comments in UI → saved to `comments.json` → watcher → SSE broadcast → agent picks up. Agent posts reply → written to `comments.json` → watcher → SSE → UI toast.
170
+
171
+ ---
172
+
173
+ ## AI Agent Collaboration (Handoff Protocol)
174
+
175
+ `diffing` solves the friction of copy-pasting code review notes into LLM chat boxes. It establishes an **"agent waits, human releases"** pipeline using a robust, port-agnostic lockfile mechanism.
176
+
177
+ ```text
178
+ 1. The agent runs a blocking command/tool and enters sleep mode.
179
+ 2. You review code in your browser, leave inline comments, and click "Send to agent".
180
+ 3. The agent wakes up instantly, receives comments as structured XML, applies edits, and posts replies.
181
+ ```
14
182
 
15
- Run in any git repository:
183
+ ### A. CLI Integration (For any terminal-based agent)
184
+ The `diffing` binary acts as a port-agnostic CLI client. It automatically discovers the running server by reading a local repository lockfile:
16
185
 
17
186
  ```bash
18
- diffit
187
+ diffing await-review # Block process until you click "Send to agent"; outputs comments as XML
188
+ diffing comments [--open] [--json] # One-shot query of the comments database
189
+ diffing reply <id> --body "..." # Post an agent response or explanation
190
+ diffing resolve <id> # Mark a comment resolved, updating the UI live
191
+ diffing url # Retrieve the active server base URL
19
192
  ```
20
193
 
21
- This starts a local server and opens your browser with a diff review UI.
194
+ ### B. Model Context Protocol (MCP) Server
195
+ If your agent supports MCP (such as Cursor, Claude Desktop, or Gemini), configure `diffing` as a stdio-based MCP server. No ports need to be configured:
22
196
 
23
- ### Options
197
+ ```json
198
+ {
199
+ "mcpServers": {
200
+ "diffing": {
201
+ "command": "diffing",
202
+ "args": ["mcp"]
203
+ }
204
+ }
205
+ }
206
+ ```
207
+ Exposes four powerful tools directly to your agent: `await_review`, `list_comments`, `reply_to_comment`, and `resolve_comment`.
24
208
 
209
+ ### C. Agent Skills
210
+ You can install diffing skills directly into your AI coding assistant:
211
+ ```bash
212
+ npx skills add ahmedragab20/diffing
25
213
  ```
26
- diffit [options] [-- <git-diff-args>]
27
-
28
- Options:
29
- -p, --port <port> Server port (default: 3433)
30
- --no-open Don't auto-open browser
31
-
32
- Examples:
33
- diffit # Review working tree changes
34
- diffit -p 8080 # Use custom port
35
- diffit -- HEAD~3 # Diff against 3 commits ago
36
- diffit -- main..HEAD # Diff between branches
37
- diffit -- --cached -- src/ # Staged changes in src/
214
+ Provides three primary commands to coordinate reviews:
215
+ 1. **`/diffing-start-review`** — Launches the review server.
216
+ 2. **`/diffing-finish-review`** — Blocks the agent using `await-review` until comments are sent, then applies requested edits.
217
+ 3. **`/diffing-review`** Combined launch-and-wait flow.
218
+
219
+ ### Send Review Popover
220
+ A GitHub-style "finish your review" popover with inline editing of each comment, an optional general/overall comment, and a visual indicator when an agent is waiting. The **"Copy comments"** toolbar button serializes all comments to the XML spec and copies them to the clipboard.
221
+
222
+ ### Port-Agnostic Discovery
223
+ A per-repo lockfile (`server.json`) in `~/.diffing/<repo-hash>/` enables all subcommands and MCP tools to discover the server's port with zero configuration. Stale or crashed server locks are automatically detected and treated as dead via `process.kill(pid, 0)`.
224
+
225
+ ### Monotonic Round Sequencing
226
+ A `ReviewSession` class with a monotonic `round` counter and race-guard logic ensures that if a "Send to agent" lands between polling intervals, the cached payload is delivered immediately. Multiple agents can block on the same review session simultaneously—all are released together on send.
227
+
228
+ ---
229
+
230
+ ## Inline Comment System
231
+
232
+ Rich, real-time comment threads directly on diff lines:
233
+
234
+ - **Inline Threads** — Hover and click the `+` button on any addition or deletion line to start a thread. Supports markdown (GFM + line breaks) with syntax-highlighted fenced code blocks.
235
+ - **Multi-Line Comments** — Select a line range to comment on an entire block of code.
236
+ - **File-Level Comments** — Add general comments scoped to the entire file without targeting a specific line.
237
+ - **Comment Drafts** — LocalStorage-based draft system (`diffing-draft-*` keys) with 7-day TTL, so drafts survive page refreshes.
238
+ - **Agent Attribution** — Replies carry `role` (`user`/`agent`) and the agent's `model` name for clear attribution.
239
+ - **Suggestion Application** — Parse `` ```suggestion `` code blocks from comment bodies and apply them to the file in one click via `POST /api/comments/:id/apply-suggestion`.
240
+ - **Full CRUD API** — REST endpoints for creating, reading, updating, and deleting comments and replies.
241
+
242
+ ---
243
+
244
+ ## Inline Diff Viewer Settings
245
+
246
+ Fine-grained control over how diffs are rendered:
247
+
248
+ | Setting | Options | Description |
249
+ |---------|---------|-------------|
250
+ | **Inline Diff Type** | `word` (default), `word-alt`, `char`, `none` | Pinpoint exactly what changed inside a modified line |
251
+ | **Diff Indicators** | `classic` (+/−), `bars`, `none` | Gutter markers for added and deleted lines |
252
+ | **Line Numbers** | on / off | Toggle gutter line numbers |
253
+ | **Line Wrap** | on / off | Soft-wrap long lines instead of horizontal scrolling |
254
+ | **Hunk Separators** | `simple`, `metadata`, `line-info`, `line-info-basic` | Style of the separator bar between diff hunks |
255
+ | **Line Hover Highlight** | `both`, `line`, `number`, `disabled` | Which element highlights on hover |
256
+ | **Font Size** | 11px – 16px | Configure globally |
257
+ | **Tab Size** | 2 / 4 / 8 | Default tab width (overridden per-file by EditorConfig) |
258
+ | **Expandable Context** | `expandContextByDefault`, `collapsedContextThreshold` (default 10 lines), `expansionLineCount` (default 20) | Control how collapsed context regions behave |
259
+ | **Haptic & Sound Feedback** | on / off | Tactile feedback via `web-haptics` and synthesized audio cues (click, toggle, navigate, open, close, resolve, send, error) |
260
+
261
+ All settings persist to `~/.config/diffing/settings.json` and the UI updates are wrapped in `useTransition` for non-blocking responsiveness.
262
+
263
+ ---
264
+
265
+ ## Merge Conflict Resolution
266
+
267
+ When your repository is in a merge state (`.git/MERGE_HEAD` detected):
268
+
269
+ - **Conflict Banner** — A prominent warning banner appears in the toolbar indicating the repo is in a merge conflict state.
270
+ - **`UnresolvedFile` Rendering** — Conflicted files are rendered using `@pierre/diffs`'s `UnresolvedFile` component with color-coded conflict markers.
271
+ - **Custom Action Buttons** — For each conflict region, choose **Accept Current**, **Accept Incoming**, or **Accept Both**.
272
+ - **Save & Stage** — After resolving all conflicts in a file, click **Save & Stage** to write the resolved content and `git add` it in one step.
273
+ - **Merge Status API** — `GET /api/merge-status` returns conflict state and lists conflicted files via `git diff --name-only --diff-filter=U`.
274
+
275
+ ---
276
+
277
+ ## Hunk Revert & History
278
+
279
+ - **Revert Individual Hunks** — Undo a single hunk from the working tree via `POST /api/revert-hunk` using `git apply --reverse`.
280
+ - **Blame & History** — View `git blame` for deleted lines and recent commit history for any file via `GET /api/hunk-history`, showing who authored deleted code and when.
281
+
282
+ ---
283
+
284
+ ## Advanced Git Operations
285
+
286
+ - **File Open in IDE** — Open any repo file in VS Code, Zed, Vim, Neovim, or the system default editor via `POST /api/open-file`. Configurable in settings.
287
+ - **File Save & Stage** — Write file contents to disk and optionally `git add` in one call via `POST /api/save-file`.
288
+ - **Repository File Lister** — `GET /api/repo-files` lists all known files (tracked + untracked, respecting `.gitignore`).
289
+ - **File Content Retrieval** — `GET /api/file-content` and `GET /api/file-text` return old (HEAD) or new (working tree) file versions as binary buffers or JSON text.
290
+ - **EditorConfig Integration** — Respects your local `.editorconfig` rules (`tab_width`, `indent_size`) for accurate, per-file tab sizing that overrides the default setting.
291
+
292
+ ---
293
+
294
+ ## Git Diff Drop-in Compatibility
295
+
296
+ `diffing` is designed as a **seamless, full drop-in replacement for `git diff`**. It features a comprehensive option parser that understands standard git revisions, options, and pathspecs, forwarding them directly to your local git engine.
297
+
298
+ Whether you are comparing branches, reviewing staged changes, or filtering specific directories, simply swap `git diff` for `diffing` to instantly elevate your review into a premium, interactive browser interface:
299
+
300
+ ```bash
301
+ diffing # Review working tree changes in the browser UI
302
+ diffing --staged # Review staged changes (drop-in for git diff --staged)
303
+ diffing HEAD~3 # Review working tree changes against 3 commits ago
304
+ diffing main..feature # Compare two branches (drop-in for git diff main..feature)
305
+ diffing -- --cached -- src/ # Staged changes specifically in the src/ directory
38
306
  ```
39
307
 
40
- ## Features
308
+ ### Intelligent Output Modes (TTY Auto-Detection)
309
+ To integrate flawlessly with your existing developer shell workflows, build pipelines, and command scripts, `diffing` automatically resolves the optimal output mode based on how stdout is directed:
310
+ - **Web Mode (Default for interactive TTY)**: When executed in an interactive terminal session, it boots the local Hono review server, registers the repository lockfile, and opens your default browser.
311
+ - **Terminal Mode (Default for pipes, redirects, or non-TTY)**: When output is piped (e.g. `diffing | grep "const"`) or redirected to a file, it falls back to behave **exactly like `git diff`**, streaming clean, standard unified diff patch text directly to standard output and exiting.
312
+
313
+ > [!TIP]
314
+ > Any standard output control or format-related flags (such as `--raw`, `--numstat`, `--stat`, `--exit-code`, `--quiet`, or `-o`) will automatically force Terminal Mode fallback.
315
+
316
+ > [!TIP]
317
+ > For a full list of all git option categories (algorithms, whitespace ignoring, context lines, word-level diffs, moved/copied detection, and path filtering) supported by `diffing`, see the [CLI Reference Manual](docs/cli.md).
318
+
319
+ ---
320
+
321
+ ## Integration & Configuration
322
+
323
+ - **Persistent User Settings** — Settings saved to `~/.config/diffing/settings.json`, loaded on startup, synced to server via `PUT /api/settings`.
324
+ - **Custom Host/Port** — `--host 0.0.0.0` exposes the review dashboard to the local network; `--port <port>` overrides random port selection.
325
+ - **`--no-open` Flag** — Prevents auto-browser opening on server start.
326
+ - **Git Config Alias** — Register `diffing` as `git review` via `~/.gitconfig`.
327
+ - **Shell Aliases** — `.zshrc`/`.bashrc` examples: `gd="diffing"`, `gds="diffing --staged"`, `gda="diffing & diffing await-review"`.
328
+ - **Configurable Browser & IDE** — Choose which browser to auto-open (Chrome, Firefox, Edge, Brave, or system default) and which IDE to use for file opening (VS Code, Zed, Vim, Neovim, or system default).
329
+ - **Graceful Shutdown** — `SIGINT`/`SIGTERM` handlers remove the server lockfile on exit.
41
330
 
42
- - **Split / Unified view** — Toggle between side-by-side and inline diff
43
- - **Syntax highlighting** — Powered by Shiki with GitHub themes
44
- - **File tree** — Hierarchical file browser with search filter and file change-type icons
45
- - **Inline comments** — Click the `+` button on any line to add a review comment
46
- - **Comment replies** — AI agents can reply to comments via API, displayed with bot avatar in the UI
47
- - **Comment status tracker** — Sidebar widget showing open, replied, and resolved comment counts with click-to-navigate links
48
- - **Send to agent** — One click hands your comments to a waiting agent automatically — no copy-paste, works with any agent/model via the `diffit` CLI or an MCP server
49
- - **Copy comments** — One-click copy all comments as structured XML for AI coding agents (offline fallback)
50
- - **Image preview** — Side-by-side comparison for added, modified, and deleted images
51
- - **Viewed tracking** — Mark files as reviewed to track progress
52
- - **Staged / Untracked toggles** — Choose which changes to include
53
- - **Custom diff commands** — Pass any `git diff` arguments after `--`
54
- - **EditorConfig support** — Respects `.editorconfig` for per-file tab size
55
- - **Persistent settings** — Your preferences are saved across sessions
331
+ ---
56
332
 
57
- ## Comment Output Format
333
+ ## Comment XML Specification
58
334
 
59
- When you click "Copy comments", the output is structured XML optimized for AI agents, featuring embedded self-documenting instructions, complete metadata, XML safety using CDATA blocks, and reply threads:
335
+ When review comments are exported or streamed to a waiting agent, they are serialized into an optimized, self-documenting XML structure equipped with CDATA blocks:
60
336
 
61
337
  ```xml
62
338
  <code-review-comments>
63
339
  <instructions>
64
- You are an AI coding assistant. You are receiving a structured list of code review comments to address in the repository.
340
+ You are an AI coding assistant receiving a structured list of code review comments to address.
65
341
  For each file, review the inline comments and apply the changes requested.
66
- - Target lines are specified by the "line" attribute (e.g. line="10" or line="10-15").
67
- - "side" indicates whether the comment is on "additions" (added/modified lines) or "deletions" (deleted/old lines).
68
- - "status" indicates whether the comment is "open" or "resolved". Only address comments with status="open".
69
- - The <code> block contains the specific code context at the reviewed lines, prefixed with "+" or "-".
342
+ - Target lines are specified by the "line" attribute (e.g. line="42" for single lines, line="42-45" for multi-line blocks, or line="file" for file-level notes).
343
+ - "side" indicates whether the comment is on "additions" (new code) or "deletions" (old code).
344
+ - "status" indicates whether the comment is "open" or "resolved". Only address "open" comments.
345
+ - The <code> block contains the code context at the reviewed lines.
70
346
  - The <body> tag contains the review feedback or request.
71
- - If developers have replied to the comment, their discussion is captured under the <replies> element.
72
- - The comment "id" attribute can be used to reference or update the comment via API if available.
73
-
74
- HOW TO REPLY OR ASK FOR CLARIFICATION:
75
- If you need to ask for clarification, explain what you did, or reply to any comment:
76
-
77
- Option A: Via the diffit CLI or MCP (Preferred — port-agnostic, no copy-paste)
78
- diffit reply <comment-id> --body "Your response" --model "<your-model-name>"
79
- diffit resolve <comment-id>
80
- (Or the equivalent MCP tools: reply_to_comment, resolve_comment.)
81
-
82
- Option B: Via the local HTTP API (if you know the running port)
83
- POST http://localhost:<port>/api/comments/<comment-id>/replies
84
- Payload: { "body": "Your response or clarification request here", "model": "<your-model-name>" }
85
- PUT http://localhost:<port>/api/comments/<comment-id> Payload: { "status": "resolved" }
86
-
87
- Option C: Via Text Response (Offline / Chat Copy-Paste)
88
- If you do not have local API access, output your comments/replies inside a structured XML block at the end of your response:
89
- <comment-replies>
90
- <reply to="<comment-id>" model="<your-model-name>"><![CDATA[Your reply or clarification request here]]></reply>
91
- </comment-replies>
347
+
348
+ HOW TO REPLY OR MARK AS RESOLVED:
349
+ - Prefer using the diffing CLI or MCP server tools (reply_to_comment / resolve_comment).
350
+ - CLI: `diffing reply <id> --body "..."`
351
+ - CLI: `diffing resolve <id>`
92
352
  </instructions>
353
+
354
+ <!-- [Optional] High-Level General Review Comment -->
355
+ <general-comment>
356
+ <![CDATA[Please refactor the parsing module to improve reliability.]]>
357
+ </general-comment>
358
+
93
359
  <file path="src/utils/parser.ts">
94
- <comment id="c1" line="42" side="additions" status="open" created-at="2026-05-24T22:00:00.000Z">
95
- <code><![CDATA[+ const parsedToken = tokenize(input)]]></code>
96
- <body><![CDATA[Rename `x` to `parsedToken` for clarity.]]></body>
360
+ <!-- [Example A] Multi-Line Selection Addition Comment -->
361
+ <comment id="c1" line="42-45" side="additions" status="open" created-at="2026-05-24T22:00:00.000Z">
362
+ <code><![CDATA[
363
+ + const parsedToken = tokenize(input);
364
+ + if (parsedToken.type === 'EOF') {
365
+ + return null;
366
+ + }
367
+ ]]></code>
368
+ <body><![CDATA[Refactor this tokenization block to check for undefined inputs as well.]]></body>
97
369
  <replies>
98
370
  <reply id="r1" created-at="2026-05-24T22:05:00.000Z" role="agent" model="claude-3-5-sonnet">
99
- <![CDATA[I agree, renamed.]]>
371
+ <![CDATA[I agree, I will add a guard clause for undefined.]]>
100
372
  </reply>
101
373
  </replies>
102
374
  </comment>
103
- <comment id="c2" line="15" side="deletions" status="open" created-at="2026-05-24T22:01:00.000Z">
104
- <code><![CDATA[- if (input != null) {]]></code>
105
- <body><![CDATA[This null check removal may cause a bug when `input` is undefined.]]></body>
375
+
376
+ <!-- [Example B] Whole-File General Comment -->
377
+ <comment id="c2" line="file" side="additions" status="open" created-at="2026-05-24T22:08:00.000Z">
378
+ <body><![CDATA[This parser module needs additional unit tests to cover negative bounds.]]></body>
106
379
  </comment>
107
380
  </file>
108
381
  </code-review-comments>
109
382
  ```
110
383
 
111
- Each comment includes:
112
- - **Instructions**: A detailed system prompt instructing the agent on how to interpret and act on the comments.
113
- - **Attributes**: Every `<comment>` includes its unique `id`, targeted line range (`line`), change `side` (`additions` or `deletions`), comment `status` (`open` or `resolved`), and ISO `created-at` timestamp.
114
- - **CDATA Blocks**: Code snippets (`<code>`) and comment bodies (`<body>`) are wrapped in `<![CDATA[ ... ]]>` to prevent special characters from breaking XML parsers.
115
- - **Replies**: Nested conversation history (if any) is preserved within `<replies>` and `<reply>` elements.
116
-
117
- ## Agent Handoff (no copy-paste)
118
-
119
- Instead of copying comments into a chat, you can hand them to an agent automatically — and it works regardless of which agent/model is active. The model is **"the agent waits, you release it"**:
120
-
121
- 1. The agent runs a blocking command (or MCP tool) and sleeps.
122
- 2. You review in the browser and click **"Send to agent"** in the toolbar (a green dot on the button means an agent is connected and waiting).
123
- 3. The agent instantly receives your comments, applies changes, and replies — the UI updates live as it works. Add more comments and click Send again for another round.
124
-
125
- ### CLI (any agent with a shell)
126
-
127
- The `diffit` binary doubles as a port-agnostic client. Each subcommand discovers the running server for the current repo via a lockfile — no port needed:
128
-
129
- ```bash
130
- diffit await-review # block until you click "Send to agent"; prints comments as XML
131
- diffit comments [--open] [--json] # one-shot dump of current comments
132
- diffit reply <id> --body "…" --model "<name>" # post an agent reply
133
- diffit resolve <id> # mark a comment resolved
134
- diffit url # print the running server's base URL (for raw API calls)
135
- ```
136
-
137
- `await-review` exits `0` when comments arrive (XML on stdout), `2` if it times out (just run it again to keep waiting), and `3` if no server is running.
384
+ ---
138
385
 
139
- ### MCP server (any MCP-capable agent: Claude, Cursor, Codex, Gemini…)
386
+ ## Security
140
387
 
141
- Run `diffit mcp` as an MCP server over stdio. It exposes the tools `await_review`, `list_comments`, `reply_to_comment`, and `resolve_comment`. Configure your client:
388
+ - **Path Traversal Prevention** All file operations validate paths against the repository root, rejecting `..`, null bytes, absolute paths, and URL-encoded bypass attempts.
389
+ - **403 Forbidden Responses** — File operations (`open-file`, `save-file`, `revert-hunk`, `hunk-history`) reject paths outside the repo root.
390
+ - **Attachment Isolation** — Uploaded attachments are restricted to `~/.diffing/<repo>/attachments/`.
391
+ - **Client Directory Isolation** — Static file serving resolves against the client directory and rejects paths outside it.
392
+ - **XSS Prevention** — HTML is escaped before markdown rendering; `marked` is used for safe HTML generation.
393
+ - **Repo Path Verification** — `repo_path.txt` is written to storage directories for cross-checking.
142
394
 
143
- ```json
144
- { "mcpServers": { "diffit": { "command": "diffit", "args": ["mcp"] } } }
145
- ```
395
+ ---
146
396
 
147
- No port configuration is needed — the server is discovered from the repo's lockfile.
397
+ ## Deep-Dive Documentation
148
398
 
149
- ## Agent Skills
150
-
151
- Install the diffit skills to use diffit directly from your AI coding agent:
152
-
153
- ```bash
154
- npx skills add ahmedragab20/diffit
155
- ```
399
+ For advanced features, internal API endpoints, sequence specifications, and configuration parameters, explore the complete guide:
156
400
 
157
- The review workflow uses two commands:
401
+ > [!IMPORTANT]
402
+ > Read the [CLI & Protocol Reference Manual](docs/cli.md) for detailed descriptions of:
403
+ > - TTY Auto-Detection and Output Mode resolution.
404
+ > - The port-agnostic discovery lockfile mechanics.
405
+ > - Monotonic sequence `round` synchronization for race-free polling.
406
+ > - Full Web API endpoints schema (`GET /api/review/await`, `POST /api/comments`, etc.).
407
+ > - Custom git config shell aliases.
158
408
 
159
- 1. **`/diffit-start-review`** — Launches the diffit server and opens the browser. Review your changes and leave inline comments.
160
- 2. **`/diffit-finish-review`** — The agent runs `diffit await-review`, blocks until you click **"Send to agent"**, then applies the requested changes and marks each comment as resolved. The browser UI updates in real time as comments are resolved.
409
+ ---
161
410
 
162
411
  ## License
163
412