seendiff
v0.0.2
Published
Local, point-in-time diff tool with persistent review state (Node.js port)
Maintainers
Readme
seendiff (Node.js port)
A Node.js/Fastify port of seendiff — a local, point-in-time diff tool with persistent review state. Faithful 1:1 port of the original Python/FastAPI tool, including block/section splitting, walkthrough mode, syntax highlighting, and search.
Install & run
No install needed — run directly with npx from inside any git repo:
npx seendiffOr install globally:
npm install -g seendiff
seendiffOr from this source tree:
npm install
npm link
seendiffUsage
usage: seendiff [-h] [--fetch] [--clear] [--no-auto-seen] [--no-highlight]
[--section-min N] [--section-max N] [--port PORT]
[--no-browser] [--walkthrough PATH]
[--check-walkthrough PATH]
[base]
positional arguments:
base base ref (default: origin/master, with fallbacks)
options:
-h, --help show this help message and exit
--fetch run git fetch before diffing (never implicit)
--clear clear review state for this scope, then continue
--no-auto-seen
--no-highlight
--section-min N smallest review section, in changed lines (default 12)
--section-max N largest review section, in changed lines (default 48)
--port PORT
--no-browser
--walkthrough PATH open a walkthrough JSON in walkthrough mode
--check-walkthrough PATH
validate a walkthrough JSON, print diagnostics, exit 0/1Run seendiff from inside a git repo with local commits ahead of
origin/master/origin/main. It opens a browser tab with a diff viewer
that groups changes into reviewable blocks, tracks seen/reviewed state
per-block in a local SQLite database (survives rebases via content hashing),
and supports syntax-highlighted search across the whole change.
Architecture
| Module | Purpose |
| -------------------- | ------------------------------------------------------------------------------------------------------ |
| src/git.js | Ref resolution, diff invocation, unified-diff parsing, block grouping/splitting (the core algorithm) |
| src/store.js | SQLite review-state persistence via node:sqlite |
| src/highlight.js | Syntax highlighting via highlight.js, mapped to Pygments-compatible CSS classes |
| src/theme.js | Serves pre-generated theme CSS (src/theme-base.css), built once from real Pygments for visual parity |
| src/walkthrough.js | JSON walkthrough-script loading, validation, ref resolution |
| src/server.js | Fastify app — all API routes, caching, host-allowlist guard |
| src/cli.js | Argument parsing, free-port selection, browser launch |
| bin/seendiff.js | npx/global-install entry point |
| static/index.html | Frontend — copied unmodified from upstream (backend-agnostic, talks only via fetch) |
Notable porting decisions
node:sqliteinstead of a third-party driver — zero extra native dependencies, matches the "local, no server infra" spirit of the original.highlight.jsinstead of Pygments (Python-only) for tokenization, with a class-mapping layer so the frontend's existing Pygments-derived CSS selectors (.hl .k,.hl .nf,.hl .c1, etc.) work unchanged.- Theme CSS is not hand-approximated —
src/theme-base.csswas generated by actually running Pygments'HtmlFormatteragainst the same six styles the original uses (default,github-dark,solarized-dark,solarized-light,nord,coffee), so highlighting is visually identical to the Python tool, not a lookalike. - Custom unified-diff parser — rather than pull in a generic npm unidiff
library,
src/git.jsparses exactly thegit diff -U0 --find-renamessubset seendiff needs (headers, renames, binary markers, hunks), which is easier to verify against the original's behavior line-for-line. - Fastify's
listen()doesn't block like uvicorn'srun()does — the CLI intentionally never resolves after a successful listen, so the process stays alive for the life of the server.
Testing
npm install
node --test test/Port-fidelity was verified by:
- Translating the original's
test_sections.pyintotest/sections.test.js(all 7 cases pass) — validates the block/section-splitting algorithm, the trickiest part of the port. - A/B differential testing: running the real Python server and this Node port side-by-side against identical repos/diffs and byte-comparing every API response. Covered a 33-file/4,093-line synthetic stress diff (25/25 checks passed: file listing, per-file status, full row-by-row content, search, seen/reviewed mutation, host guard, prefs) and a targeted edge-case repo covering renames-with-edits, binary files, CRLF line endings, no-trailing-newline files, and Unicode filenames (34/34 checks passed after two real bugs were found and fixed — see below).
- Walkthrough parity:
--check-walkthroughdiagnostics, live/api/walkthroughpayload (including content digest), and a subtle ordering-dependent validation quirk in the original (a step following one with an invalid ref skips duplicate-id detection) were confirmed to match exactly.
License
MIT
