ecliptic

How it stays light

  • Never writes to repositories: git runs with optional locks and the diff index refresh off, so it never takes index.lock from under an agent.
  • One background worker per column watches the working tree with inotify and refreshes once changes settle: after twice what its last refresh cost (100 ms to 1 s), so an edit shows in about 0.1 s and refreshing never takes more than a third of a core while an agent keeps writing. Paths git ignores (target/, node_modules/) never trigger a refresh. No timers: an idle repository costs nothing, even one with 485k files. Linked worktrees and submodules are watched through their git directories too, and a folder that is not a repository is not watched at all. A folder inside a repository that cannot be read (a container's data volume, say) is left out of the watch, not the whole repository; when watching fails anyway, the Repositories row shows a warning and says why.
  • The watcher already knows which paths changed, so an edit reads the status of those paths alone and merges it into the last one (git's own fsmonitor would need to write the index). History is read again only when HEAD or a ref moves, and without --topo-order unless the repository has a commit-graph file (otherwise git walks the whole history first).
  • A model thread turns snapshots into row edits and wakes a column only when a flash ends or its "changed … ago" label turns over; the UI thread only applies the edits and draws.
  • Line counts follow the status in a second snapshot, so an edit shows as fast as before and its +12 −3 a moment later (counting walks the index again: about as long as the status of the edited paths). New files are counted directly, up to 2,000 of them and 4 MiB each.
  • Diffs are capped at 5,000 lines, 8 MiB and 2,000 characters per line.

Measured on a Firefox checkout (485k files, 1M commits) and seven columns:

before after
Refresh after an edit (Firefox) 8.2 s 0.19 s
Refresh after an edit (small repo) 12 ms 2 ms
Edit to snapshot 300 ms 100 ms
Idle model tick, 10k changed files × 7 95 ms 1 µs
UI thread, hovering rows 31% 4%
UI thread, scrolling continuously 74% 15%
Idle 0% CPU, 0 frames/s the same

The 1.0.0 release build, with two columns at 1600×1000 on an Xvfb display (toolbox threads, 5 s windows): the UI thread sits below 0.5% of a core at idle, at 2.4% while the pointer sweeps the rows and at 3.4% while the graph scrolls continuously.

cargo run --release -p scm-core --example bench -- REPO… times the git phases; cargo test --release -p ecliptic bench_ -- --ignored --nocapture times the model and the UI updates. The toolbox keeps the measuring repeatable: toolbox bench saves a baseline and compares a later run against it, toolbox threads prints the per-thread shares in the table above, and toolbox profile builds with frame pointers, records with perf and folds the stacks.