GROOVE Retains Older Object Versions Effortlessly
A solo-developer save-state tool. Frequent checkpoints, named releases, automatic consolidation. Nothing more.
https://github.com/lucianofedericopereira/groove
Solo development tends toward endless WIP cycles until something ships. Traditional VCS makes this painful — every save needs a message, history becomes noise, consolidating before a release means rebases and squashes.
groove separates two concerns:
wips — anonymous save states, cheap, for undo releases — named versions, permanent, consolidated Between releases you wip freely. On release, all wips collapse into the version. History stays clean without effort.
nimble build cp groove /usr/local/bin/
DAILY COMMANDS
groove wip save current state (undo point) groove undo restore previous wip groove release v1.2 seal version, consolidate all wips groove patch v1.22 delta fix on top of last release groove mark beta pointer on current wip (live/staging/beta) groove log show history groove status show working tree vs last wip groove diff v1 v1.2 diff two versions groove export v1.22 export portable patch file groove sync user@host:path rsync repo to remote
WORKFLOW
groove init
work freely, wip often groove wip groove wip groove undo ← went wrong, back one step groove wip
deploy to staging groove mark beta
wip more groove wip groove wip
ship it — all wips collapse into v1 groove release v1
fix a bug on v1 groove wip groove patch v1.1
next cycle groove wip groove release v2
groove log --json groove status --md groove diff v1 v1.2 --md ← diff report as markdown groove diff v1 v1.2 --json ← machine readable
sync groove uses rsync for transport. blobs are content-addressed so rsync only transfers what changed:
groove sync user@server:backups/myproject wips are stored raw (fast undo). release blobs are gzip compressed. old releases bundle into archive/vX.tar.gz.
groove is single-writer. Don't sync from two machines simultaneously — it's not git.
portable patches share a fix without a shared server:
groove export v1.1 produces v1.1.groove-patch
The export is a self-contained text file. Importing back into another repo (groove apply) is on the roadmap — currently you read the patch file directly and unpack manually.
storage everything is plain text. no database.
manifests are card files — one field per line, human readable with cat.
see SCHEMA.md for the full format specification.
hardware acceleration crc32c hashing uses the hardware instruction when available:
x86_64: SSE4.2 crc32 instruction (runtime detection) Apple Silicon: ARM crc32c instruction (always present on M1+) everything else: software fallback same output across all paths — hardware and software are byte-identical.
using groove alongside git groove is the personal undo layer that sits parallel to git. The two don't know about each other and don't conflict.
groove init automatically adds .groove/ to .gitignore if the directory is a git repo.
The "saves your bacon" pattern:
you're deep in a feature branch
- git checkout feature-x
- code, code, code...
groove wip safety net before risky refactor
refactor explodes groove undo working tree restored, git untouched
urgent bug elsewhere — git stash anxiety not needed
groove wip records current state git checkout main
files unchanged on disk; the wip is just an undo point if you need it
during messy rebase / merge conflicts
Why this works better than git stash:
git stash groove wip visibility opaque stack, easy to lose named, logged, listed pop anxiety yes (conflicts on pop) no — wip never modifies working tree during conflicts flaky works always naming numeric only freeform via mark cross-branch possible but awkward works trivially groove never moves your files. wip is purely additive — records state, leaves disk alone. undo restores. There's nothing to "pop."
When the work is real and shareable, commit to git. groove stays out of the history.
limitations These are intentional, not gaps:
Single writer. Don't sync from two machines simultaneously. groove has no merge. No branches. Linear history per repo. If you need branches, use git. No collaboration. No PRs, no remotes-as-peers. groove is yours alone. No partial checkout. undo and checkout operate on the whole tree. CRC32 hashing. Designed for personal use (~hundreds of releases over years). Not appropriate for repos with millions of artifacts. Path restrictions. Tab and newline characters in filenames are skipped (would corrupt the staging index). Absolute paths in manifests are rejected. No streaming. Files are read fully into memory for hashing. Very large files (multi-GB) will use proportional RAM. If any of these are deal-breakers for your use case, you've outgrown groove — push to git.
design philosophy Solo only. No collaboration model. Mega-stash semantics. Wips are throwaway, releases are permanent. Plain text everything. No database, no opaque formats. rsync is transport. No custom protocol, no server. Don't reimplement git. When you need git, use git. Leverage what's already there. If git is present, use its ignore patterns and file index — never duplicate work, never modify git's state.