Status: design locked, implementation in progress.
Inspired by Diff.Net / WinMerge / Beyond Compare. Two flavours:
- File compare — side-by-side text diff of two files
- Folder compare — side-by-side tree of two directories
Both render as new tabs (not modals), so they can coexist with editing.
| Question | Answer |
|---|---|
| File-diff engine | Monaco's built-in createDiffEditor (already in our stack) |
| Folder-diff engine | dir-compare npm package (~150 k weekly downloads, MIT) |
| Where the result goes | A new tab of type 'diff' (files) or 'folder-diff' (folders) |
| Default view | File-diff: side-by-side, syntax-highlighted. Folder-diff: side-by-side tree, colour-coded |
| Entry points | File → Compare → ... menu + right-click tab → "Select for Compare" / "Compare with Selected" |
| Skip in folder-diff | node_modules, .git, dist, build, out, .next, .cache, .vscode, .idea, __pycache__ |
| Compare mode (folder) | Filename + size + content-hash. Equal if all match. |
Tab title: ⇆ left.js ↔ right.js
─────────────────────────────────────────────────
Toolbar: [⇆ Swap] [≡ Inline] [↑ Prev] [↓ Next] [↻ Reload]
─────────────────────────────────────────────────
┌──── left.js ────────────────┬──── right.js ──────────────┐
│ Monaco diff editor │ │
│ - removed lines red │ + added lines green │
│ - modified lines yellow │ + modified lines yellow │
│ - syntax-highlighted │ - syntax-highlighted │
│ - line numbers │ - line numbers │
│ - overview ruler shows │ │
│ change density │ │
└─────────────────────────────┴────────────────────────────┘
- Shortcuts inside the tab:
F7next change,Shift+F7previous,Ctrl+Shift+Itoggle inline ↔ side-by-side - Refresh re-reads both files from disk
- Swap reverses left/right
- Closing the tab disposes the diff models cleanly
Tab title: ⇆ /left/folder ↔ /right/folder
─────────────────────────────────────────────────
Toolbar: [⇆ Swap] [☑ Show only changes] [↻ Reload]
Summary: 12 added · 8 removed · 5 differ · 247 equal
─────────────────────────────────────────────────
┌──── /left/folder ───────────┬──── /right/folder ─────────┐
│ 📁 src │ 📁 src │
│ 📄 main.js ✎ │ 📄 main.js ✎ │
│ 📄 old.js ⊖ │ (missing) │
│ (missing) │ 📄 new.js ⊕ │
│ 📄 package.json │ 📄 package.json │
└─────────────────────────────┴────────────────────────────┘
Status icons + colours:
- 🟢
⊕Added — only in RIGHT (left cell empty, right cell green) - 🔴
⊖Removed — only in LEFT (left red, right empty) - 🟡
✎Modified — in both, content differs (both yellow) - ⚪ Equal — in both, identical (no highlight)
Click a file row that's marked Modified → opens that file's diff in a new tab. Click a folder row → expand/collapse.
| Where | Action |
|---|---|
File → Compare → Compare Files… |
Two file pickers → opens diff tab |
File → Compare → Compare with Saved… |
Compare current tab content vs a picked file |
File → Compare → Compare Folders… |
Two folder pickers → opens folder-diff tab |
| Right-click a tab → Select for Compare | Marks the tab as "left" |
| Right-click another tab → Compare with Selected | Opens diff (current as right) |
| Channel | Purpose |
|---|---|
compare-folders |
dir-compare invocation in main; returns a flat array of entries with status |
(File compare reads via existing read-file IPC — no new handler needed.)
- Three-way merge view
- Inline editing in the diff view (it's read-only)
- Saving diff result as a patch file
- Compare two arbitrary tabs that are already open via drag-and-drop
- Folder-diff content hashing for very large files (we skip >10 MB binary files)