glassbox 0.17.0 → 0.18.0-beta.1
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 +28 -3
- package/dist/channel.js +2 -0
- package/dist/cli-difftool.js +14 -8
- package/dist/cli.js +8581 -2708
- package/dist/client/app.global.js +44 -44
- package/dist/client/history.global.js +70 -6
- package/dist/client/styles.css +1 -1
- package/package.json +9 -2
package/README.md
CHANGED
|
@@ -87,7 +87,10 @@ Then you run `glassbox` again. Your previous annotations carry forward — match
|
|
|
87
87
|
|
|
88
88
|
- **Split and unified diffs** with syntax-colored add/remove/context lines
|
|
89
89
|
- **Line-level annotations** — click any line to add feedback with a category
|
|
90
|
-
- **Image and SVG diffs** — binary images and SVGs render side-by-side with a **difference overlay**, a **swipeable slice tool**, and pixel-precision zoom/pan. SVGs offer a *Code* / *Rendered* toggle so you can review either the source or the rasterized output.
|
|
90
|
+
- **Image and SVG diffs** — binary images and SVGs render in a **side-by-side** layout (with a left/right or over/under toggle), a **difference overlay**, a **swipeable slice tool**, and pixel-precision synced zoom/pan. SVGs offer a *Code* / *Rendered* toggle so you can review either the source or the rasterized output.
|
|
91
|
+
- **Comment on images** — leave a general comment on any image, or **draw a rectangle region** to anchor feedback to a specific spot (per A/B side), just like a line annotation.
|
|
92
|
+
- **Ground-truth image comparison** — `glassbox --ground-truth <manifest>` compares an **actual** render against an **expected** one (a design spec, a reference, or a previous baseline — even outside the repo), scores the perceptual difference, sorts most-changed-first, and lets you **promote** a new actual to the baseline. Great for catching visual regressions.
|
|
93
|
+
- **Attach files to any comment** — drag, paste, or browse to attach screenshots, logs, or any file to a line comment, image comment, or note reply. Image attachments show a thumbnail and open in a lightbox; the export lists each file's path so your AI tool can read it.
|
|
91
94
|
- **Compare any two paths** — `glassbox --diff <A> <B>` reviews two arbitrary files or two arbitrary folders by path — no git repository required.
|
|
92
95
|
- **Drag and drop** annotations to different lines
|
|
93
96
|
- **Double-click** to edit, click the category badge to reclassify
|
|
@@ -96,13 +99,13 @@ Then you run `glassbox` again. Your previous annotations carry forward — match
|
|
|
96
99
|
- **Resizable sidebar** and word wrap toggle
|
|
97
100
|
- **Keyboard navigation** — `j`/`k` to move between files, `Cmd+Enter` to save
|
|
98
101
|
- **Go-to-definition and a nav stack** — click any symbol to jump to its definition, with back/forward through your trail
|
|
99
|
-
- **Themes** — built-in Dark, Light, High Contrast, Dracula,
|
|
102
|
+
- **Themes** — ten built-in themes (Dark, Light, High Contrast Dark/Light, Dracula, Tokyo Night, One Dark Pro, Solarized Dark/Light, Monokai), plus a custom theme editor with live preview
|
|
100
103
|
- **Session persistence** — reviews survive restarts, pick up where you left off
|
|
101
104
|
- **Smart review reuse** — re-running `glassbox` on the same commit updates diffs in place and migrates annotations to their new line positions
|
|
102
105
|
- **Stale annotation detection** — comments that can't be matched to the updated diff are flagged with a visual indicator
|
|
103
106
|
- **Review history** — browse, reopen, or delete past reviews
|
|
104
107
|
- **Structured export** — markdown output with file paths, line numbers, categories, and instructions for AI consumption
|
|
105
|
-
- **Automatic .gitignore
|
|
108
|
+
- **Automatic .gitignore** — keeps `.glassbox/` out of version control for you at launch, while leaving the per-project `.glassbox/settings.json` tracked
|
|
106
109
|
- **Auto port selection** — if the default port is busy, it finds an open one
|
|
107
110
|
- **Fully local** — no network calls (unless you opt into AI features), no accounts, no telemetry. Your code stays on your machine.
|
|
108
111
|
- **AI review notes** _(optional)_ — render the generating AI's line-anchored rationale and proof, committed alongside the code in `.pr-notes/`, right in the diff — and reply to any note inline
|
|
@@ -110,6 +113,18 @@ Then you run `glassbox` again. Your previous annotations carry forward — match
|
|
|
110
113
|
|
|
111
114
|
---
|
|
112
115
|
|
|
116
|
+
## Review more than code
|
|
117
|
+
|
|
118
|
+
Diffs aren't only text. Glassbox reviews **images** as a first-class diff: a side-by-side layout, a pixel **difference overlay**, and a swipeable slice tool — with synced zoom/pan. Leave a comment on the whole image or draw a region to anchor it to a spot.
|
|
119
|
+
|
|
120
|
+
<img src="assets/demo-image-comparison.png" alt="Image diff with a pixel difference overlay" width="720">
|
|
121
|
+
|
|
122
|
+
And when "correct" means "matches the design," **ground-truth comparison** (`glassbox --ground-truth <manifest>`) puts each **actual** render next to its **expected** one — a design spec, a reference render, or a previous baseline, even outside the repo. Glassbox scores the perceptual difference, hides identical pairs, sorts the rest most-changed-first, and lets you **promote** a new actual to the baseline once a change is intentional. Multi-step flows render as ordered, named sets.
|
|
123
|
+
|
|
124
|
+
<img src="assets/demo-ground-truth.png" alt="Ground-truth comparison: expected vs actual with a perceptual difference score" width="720">
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
113
128
|
## AI-Powered Review Intelligence
|
|
114
129
|
|
|
115
130
|
> Entirely optional. Glassbox is fully functional without it.
|
|
@@ -188,6 +203,12 @@ See [docs/20-ai-review-notes.md](docs/20-ai-review-notes.md) for the format and
|
|
|
188
203
|
|
|
189
204
|
---
|
|
190
205
|
|
|
206
|
+
## For AI tools: integrating with Glassbox
|
|
207
|
+
|
|
208
|
+
If you're an AI coding tool or agent working in a project that uses Glassbox, **[docs/ai-integration.md](docs/ai-integration.md)** is the integration hub — how to launch a review, record line-anchored rationale/proof (`glassbox note`), export ground-truth image proof, consume the exported feedback (`.glassbox/latest-review.md`), and respond to the MCP/Claude channel. The repo's [AGENTS.md](AGENTS.md) is a one-screen router to it (and, separately, to the contributor docs for agents hacking on Glassbox itself).
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
191
212
|
## Install
|
|
192
213
|
|
|
193
214
|
### Desktop app (recommended)
|
|
@@ -249,6 +270,9 @@ glassbox --all
|
|
|
249
270
|
# Compare two arbitrary files or folders by path (no git repo required)
|
|
250
271
|
glassbox --diff ./dist-old ./dist-new
|
|
251
272
|
|
|
273
|
+
# Compare actual images against expected/ground-truth images (no git repo required)
|
|
274
|
+
glassbox --ground-truth ./screenshots/manifest.json
|
|
275
|
+
|
|
252
276
|
# Resume a previous review
|
|
253
277
|
glassbox --resume
|
|
254
278
|
```
|
|
@@ -267,6 +291,7 @@ glassbox --resume
|
|
|
267
291
|
| `--files <patterns>` | Specific files (comma-separated globs) |
|
|
268
292
|
| `--all` | Entire codebase (all tracked files) |
|
|
269
293
|
| `--diff <a> <b>` | Compare two arbitrary files or folders by path — no git repo required |
|
|
294
|
+
| `--ground-truth <m>` | Compare actual vs expected images from a manifest — no git repo required |
|
|
270
295
|
| `--port <number>` | Port to run on (default: 4183) |
|
|
271
296
|
| `--resume` | Resume the latest in-progress review for this mode |
|
|
272
297
|
| `--browser` | Open in browser instead of desktop window |
|
package/dist/channel.js
CHANGED
package/dist/cli-difftool.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { createRequire as __createRequire } from 'module';
|
|
3
|
+
const require = __createRequire(import.meta.url);
|
|
2
4
|
var __defProp = Object.defineProperty;
|
|
3
5
|
var __export = (target2, all) => {
|
|
4
6
|
for (var name in all)
|
|
@@ -14697,6 +14699,13 @@ function planSnapshot(local2, remote2, work, isFile, basename2) {
|
|
|
14697
14699
|
]
|
|
14698
14700
|
};
|
|
14699
14701
|
}
|
|
14702
|
+
function isDirDiffInvocation(local2, stat) {
|
|
14703
|
+
try {
|
|
14704
|
+
return stat(local2).isDirectory();
|
|
14705
|
+
} catch {
|
|
14706
|
+
return false;
|
|
14707
|
+
}
|
|
14708
|
+
}
|
|
14700
14709
|
function launcherShimName(platform) {
|
|
14701
14710
|
if (platform === "darwin") return "glassbox";
|
|
14702
14711
|
if (platform === "linux") return "glassbox-linux";
|
|
@@ -14742,11 +14751,8 @@ if (args.length < 2 || args[0].startsWith("-") || args[1].startsWith("-")) {
|
|
|
14742
14751
|
process.exit(1);
|
|
14743
14752
|
}
|
|
14744
14753
|
var [local, remote, merged, ...extra] = args;
|
|
14745
|
-
var
|
|
14746
|
-
|
|
14747
|
-
localIsFile = statSync2(local).isFile();
|
|
14748
|
-
} catch {
|
|
14749
|
-
}
|
|
14754
|
+
var isDirDiff = isDirDiffInvocation(local, statSync2);
|
|
14755
|
+
var isPerFile = !isDirDiff;
|
|
14750
14756
|
var here = dirname(fileURLToPath(import.meta.url));
|
|
14751
14757
|
var target = resolveLaunchTarget(
|
|
14752
14758
|
here,
|
|
@@ -14779,7 +14785,7 @@ async function runThinClient(start, timeoutMs) {
|
|
|
14779
14785
|
}
|
|
14780
14786
|
function runBlockingLaunch() {
|
|
14781
14787
|
const work = mkdtempSync(join3(tmpdir(), "glassbox-difftool-"));
|
|
14782
|
-
const plan = planSnapshot(local, remote, work,
|
|
14788
|
+
const plan = planSnapshot(local, remote, work, isPerFile, basename);
|
|
14783
14789
|
const cleanup = () => {
|
|
14784
14790
|
try {
|
|
14785
14791
|
rmSync2(work, { recursive: true, force: true });
|
|
@@ -14819,7 +14825,7 @@ var onThinClientError = (err) => {
|
|
|
14819
14825
|
console.error(err instanceof Error ? err.message : String(err));
|
|
14820
14826
|
return process.exit(1);
|
|
14821
14827
|
};
|
|
14822
|
-
if (
|
|
14828
|
+
if (isPerFile && target.kind === "browser") {
|
|
14823
14829
|
const cliPath = target.cli;
|
|
14824
14830
|
void runThinClient(() => {
|
|
14825
14831
|
spawnDetachedBrowserServer(cliPath, process.cwd());
|
|
@@ -14827,7 +14833,7 @@ if (localIsFile && target.kind === "browser") {
|
|
|
14827
14833
|
onThinClientDone,
|
|
14828
14834
|
onThinClientError
|
|
14829
14835
|
);
|
|
14830
|
-
} else if (
|
|
14836
|
+
} else if (isPerFile && target.kind === "desktop") {
|
|
14831
14837
|
const launcher = target.launcher;
|
|
14832
14838
|
void runThinClient(
|
|
14833
14839
|
() => {
|