Skip to content
milanofthePublic

About

Structural overview of a repository: every non-ignored file as a read-only panel on a zoomable canvas

Topics

Resources

Stars

81 stars

Watchers

0 watching

Forks

Repository files navigation

sanity

sanity opens a folder and shows every file in it at once, as read-only panels on one zoomable canvas, grouped by directory. Zoomed out you see the structure of the project, zoomed in you read the code. When a file changes on disk, its panel flashes and the changed lines are marked.

It is a monitor. It runs next to the agent interface while coding agents work in a repository, so you can see which files they touch, where those sit in the tree, and zoom in to read what changed. It also plays the repository's git history the same way, one commit at a time.

Try it in the browser with a few public repositories, no install: sanity.milanrother.com

the whole project at once, directories named

Install

Releases have a .dmg for macOS (Intel and Apple Silicon), an installer for Windows and an .AppImage for Linux. The builds are not signed yet. On macOS, right click the app and choose Open the first time. On Windows, click More info, then Run anyway. On Linux, chmod +x the file and run it; if it refuses to start, the system has no libfuse2 and ./sanity.AppImage --appimage-extract-and-run runs it without one.

If the window opens at the right size and stays blank on Linux, WebKitGTK could not allocate its buffer through your driver. Start it with WEBKIT_DISABLE_DMABUF_RENDERER=1 in the environment, which is what the app already does for itself on NVIDIA; virtual machines, software rendering and remote sessions hit the same thing and have to be told.

Usage

sanity /path/to/repo

Or open a folder from the Project menu.

  • Space or f fits the whole project, a double click fits a panel.
  • / jumps to search, over file names and contents. Enter goes to the next hit, Escape clears.
  • The left and right arrow keys, or [ and ], step through the git history.
  • Clicking a panel header opens the file in $SANITY_EDITOR, $VISUAL, $EDITOR or the system default.
  • Right click exports the view or the whole project as a 4K PNG, and on a panel shows the file in its folder.
  • The Files menu sets which file types are shown and whether files ignored by git are listed. The View menu sets whether files are coloured by language, whether directories are named over the canvas, whether documents show all their pages, and whether each step through the history fits the whole project. The Theme menu has eight themes.

Watching changes

The folder is watched while it is open. When a file is saved, its panel flashes, the lines that were removed flash red and disappear, and the lines that were added come in green. A new file fades in where the layout puts it, and a deleted one fades out in red. When several files change at once, a commit, a formatter or a save of all open files, they start one after another across the canvas, so you can follow where it went.

The bands are drawn at every zoom level, so even with the whole project on screen you can see where in a file the change was. A file that is rewritten with the same content, by touch or a formatter with nothing to do, does not flash. Moving or renaming a directory is picked up as its files moving.

a change, the added lines coming in green

History

In a git repository a ticker appears next to the search field. Its arrows, the arrow keys, or [ and ], step through the commits, newest first. Each step is played like a save: the lines the commit removed flash red, the ones it added flash green, files it deleted fade out and files it created fade in. Stepping back plays the same commit in reverse. Clicking the commit id returns to the present.

Right click, Export history, renders the replay to an MP4: from the oldest commit to the newest in the length you set, several commits a step when there are more than fit, with each commit's date, id and subject along the bottom. The video is H.264 where the machine can encode it and VP9 where it cannot, which includes the Linux AppImage; both play in browsers, VLC and mpv.

Each commit is laid out for the files it has, so there are no empty places for files that come later or went earlier. When a step adds or removes files, the panels slide to their new places, and by default the view fits the whole project again. The working tree is never touched; the contents come out of git's object store, and the watcher keeps running in the background, so returning to the present shows the folder as it is.

stepping through the history, a commit's four files changing

What it shows

  • Source files with syntax highlighting for 21 languages (tree-sitter), plus Verilog-A and SPICE.
  • Jupyter notebooks as their cells rather than as JSON.
  • Images, SVGs and PDFs as panels in their own proportions. A PDF shows its first page, or all of its pages with Show every page in the View menu, rendered the same way on every platform.
  • Files ignored by git are left out, or listed as placeholders if you switch them on.

It draws only when something changes, so it uses no CPU while idle, and it stays usable up to around 100,000 files.

figures and the first page of a PDF

Search covers file names and the text of every file. Matching panels stay lit, the rest dims, matching lines are banded, and Enter walks through the hits.

532 matches for one word

Building

npm ci && npm ci --prefix web
npm run app            # development build
npm run app:build      # release bundle

macOS and Windows need nothing beyond Rust and Node. Linux links against the system WebKitGTK, which has to be there to build at all. On Debian and Ubuntu that is libwebkit2gtk-4.1-dev librsvg2-dev patchelf file, and on Arch webkit2gtk-4.1 librsvg patchelf. Without them the build stops at a pkg-config error rather than anything about this project.

The AppImage carries the few GStreamer plugins WebKitGTK encodes the history video with, which scripts/appimage-gstreamer.sh picks. On Debian and Ubuntu they come from gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad, on Arch from gst-plugins-base gst-plugins-good gst-plugins-bad.

npm run app:appimage   # Linux release bundle

It sets NO_STRIP=true, since the strip inside linuxdeploy cannot read Arch's libraries, and stops early when patchelf is missing, which linuxdeploy's GStreamer step needs. When the build still ends in nothing more than failed to run linuxdeploy, --verbose shows the real error.

Releasing

npm run release -- 1.13.2 notes.md --dry-run   # the release as it would read
npm run release -- 1.13.2 notes.md

From an up to date main, this sets the version, pushes it and publishes the release with notes.md as its changes. Publishing starts the Release workflow, which attaches the installers about fifteen minutes later.

The web demo is the same app reading pre-built dumps of public repositories over HTTP:

npm run demo           # clone and dump the demo repositories
npm run dev            # http://localhost:5183

The pictures in this README are made by npm run readme-shots, against the dev server.

Checks

npm run check-all

Type checks, clippy, the TypeScript and Rust tests, and a set of scripts in web/scripts that open the app in a real browser and check what it draws: layout, text, pictures, change cues, performance, themes and more.

Repository

crates/sanity-core     scanning, tokenising, git history, the wire format
crates/sanity-watch    watching the folder, debounced into batches
src-tauri              the desktop shell
web/src/lib/canvas     layout and the WebGL2 renderer
web/src/lib/ui         interface components
web/scripts            browser checks and the README pictures

Design decisions and measurements are in the issues.

Licence

MIT, see LICENSE.

About

Structural overview of a repository: every non-ignored file as a read-only panel on a zoomable canvas

Topics

Resources

Stars

81 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages