grip-live-diff
Preview Markdown with GitHub's look, and see what changed since you last looked.
What it is
grip-live-diff is a single Go binary that renders a Markdown file in your browser the way GitHub
would, reloads the page whenever the file changes on disk, and highlights what changed, word by word,
inside the rendered document.
It started as a fork of go-grip by Christoph Herb, a Go
reimplementation of grip that renders offline instead of calling
GitHub's API. The rendering engine is still go-grip's. What this fork adds is everything around
reading a document while something else is writing it: an editor, a teammate, or an AI agent rewriting
a spec in place. After an auto-reload the page just looks different and you have to re-read it all to
find the delta. This tool shows the delta.
Install
go install github.com/babs/grip-live-diff@latest
Prebuilt binaries for Linux, macOS and Windows, amd64 and arm64, plus 386 on Linux and Windows, are on the
releases page, as .xz archives (.zip too on Windows) plus a
grip-live-diff.sha256sum. A release binary updates itself in place, after checking the published
checksum:
grip-live-diff update
Usage
grip-live-diff README.md # render one file
grip-live-diff # README.md of the current directory, or a file listing if there is none
The browser opens on http://localhost:6419. The server watches the file's directory, so any .md
under it is served as well, at its own path.
| Flag |
Default |
Effect |
-p, --port |
6419 |
Port to listen on |
-b, --browser |
true |
Open a browser tab on start (-b=false to disable) |
--no-reload |
false |
Do not push a reload to the browser when the file changes |
-H, --host |
localhost |
Host used in the printed and opened URL (the server binds all interfaces) |
--bounding-box |
true |
Draw the GitHub-style box around the document |
--version |
|
Print version and commit |
The page title comes from the file name (my-guide_v2.md becomes My Guide V2). Ctrl-C stops the
server.
Seeing what changed
The ± button in the toolbar switches the diff on and off (key d). It carries a dot as soon as the
file on disk differs from the version you opened, so a reload tells you something moved even before
you look. With the diff on, a second row picks the reference, one click each:
- since open (
?diff=open, key 1), everything that changed since you opened the file;
- last edit (
?diff=last, key 2), only what the most recent save brought;
- HEAD (
?diff=head, key 3), everything not committed yet, against git HEAD. Greyed out
when the file is not served from a git work tree; a file that has never been committed says so
instead of showing the whole document as new.
Switching the diff back on returns to the reference you used last.
Insertions are green, removals are struck through in red, and the comparison is done on words, not
lines, so re-wrapping a paragraph is not a change. Inside a code block indentation still counts. The
diff survives the auto-reload, so the highlights refresh on every save.
Mark as read takes the current disk content as the new reference for since open and last edit.
It is greyed out against HEAD, which is git's to move, and when there is nothing new. The scroll
position is kept.
Minimap
While a diff is on, a minimap of the whole document runs along the right edge, VS Code style: a scaled
rendering with every insertion and removal marked in green and red, and a box for the part on screen.
Click it to jump, drag the box to scroll. On a long document the minimap slides with the page so the
current position stays visible. The button next to Mark as read hides it.
| Button |
Does |
↔ |
Page width: normal (GitHub's 896px), wide (1400px), full (no limit) |
± |
Diff on/off, see above |
| theme |
Light or dark |
Keys: d toggles the diff, 1 2 3 pick the reference.
Width, theme, minimap visibility and the last diff reference are kept in localStorage, so they
survive restarts. The open/closed state of <details> blocks and the scroll position survive a
reload, per tab.
Rendering
Inherited from go-grip, so the output matches GitHub for the things that matter:
- GitHub Flavored Markdown with tables, task lists and footnotes
- syntax highlighting with a copy button on every code block
- GitHub emojis (
:+1:) and #hashtags styled like GitHub
- issue and PR references (
grafana/grafana#22) linked to GitHub
- mermaid diagrams, with zoom
- math, inline (
$...$), block ($$...$$) and in math code fences
- alerts (
> [!NOTE], [!TIP], [!IMPORTANT], [!WARNING], [!CAUTION])
- YAML frontmatter rendered as a table
- a print stylesheet
Open this README in the tool to see three of them:
graph LR;
edit[file changes] --> reload --> diff[diff highlighted]
$$\left( \sum_{k=1}^n a_k b_k \right)^2 \leq \left( \sum_{k=1}^n a_k^2 \right) \left( \sum_{k=1}^n b_k^2 \right)$$
[!TIP]
Set ?diff=head in the URL to review your uncommitted edits to a document before committing.
Development
Tooling is pinned in mise.toml (Go, golangci-lint, prek):
mise run build # -> bin/grip-live-diff
mise run test
mise run lint
Features start as a spec in specs/ before any code. release.sh builds the
release matrix and the checksum file; the Build and release workflow runs it on every v* tag.
Lineage
- grip by Joe Esposito: the original, Python, rendering through
GitHub's API.
- go-grip by Christoph Herb: the offline Go rewrite this
project forks. Rendering, theming, mermaid, math and emoji support are his work.
- grip-live-diff: the live diff, minimap, width toggle, git
HEAD comparison and self-update.
MIT, see LICENSE.