A small Rust CLI that watches your working directory for file changes and
automatically stages, commits, and pushes them to Git — no manual git add /
git commit required.
It's built for scenarios where you want a continuous, low-friction commit history: pairing with an AI coding agent, screen-recording a live coding session, or just auto-saving work-in-progress to a branch as you edit.
- Recursive filesystem watching of the current directory using
notify. - Debounced commits — bursts of file events (e.g. a save that touches many files, or a build that writes temp files) are collected for 3 seconds and committed as a single batch, rather than one commit per event.
- Pre-flight safety checks before watching starts, so
wacnever commits on top of a messy or out-of-sync repo:- confirms the current directory is a Git repository,
- refuses to start if there are pre-existing staged or unstaged changes,
- refuses to start if there are untracked files,
- fetches from the remote (if one is configured) and verifies
HEADis in sync with its upstream branch, reporting how many commits you are ahead, behind, or diverged.
- Automatic push — after each commit,
wacpushes to the remote if one is configured; if not, it simply commits locally. - Bare-repo auto-initialisation — if
GIT_WORK_TREEandGIT_DIRare set and point at a directory/repo that doesn't exist yet,waccreates the work tree and initialises the bare repository for you. - No-op safe — if a debounced batch of events doesn't actually change the
index (e.g. a file was written back to its original contents),
wacskips the commit instead of creating an empty one.
cargo install watch-and-commitPre-built binaries are published on GitHub Releases and can be fetched directly, skipping compilation:
cargo binstall watch-and-commitbrew install rodolfovillaruz/tap/watch-and-commitwinget install RodolfoVillaruz.WatchAndCommitDownload the .deb asset from the
latest release
and install it:
sudo dpkg -i wac_*.debgit clone https://github.com/rodolfovillaruz/watch-and-commit.git
cd watch-and-commit
cargo build --release
# binary is at target/release/wacAll install methods produce a binary named wac.
Run it from inside the Git repository you want to auto-commit:
wacwac will:
- Run pre-flight checks (clean working tree, no untracked files, in sync with upstream if a remote exists).
- Start watching the current directory (
.) recursively. - On file activity, wait for a 3-second quiet period, then run:
git add . git commit -m "Update" git push # only if a remote is configured
- Repeat until you stop it with
Ctrl+C.
If the pre-flight checks fail (dirty tree, untracked files, or a
diverged/behind/ahead branch), wac prints the reason and exits without
watching anything — commit, stash, push, or pull as needed and re-run it.
You can watch a directory while storing Git metadata in a separate bare repository via the standard Git environment variables:
export GIT_DIR=/path/to/bare/repo.git
export GIT_WORK_TREE=/path/to/watched/files
wacIf either path doesn't exist yet, wac creates the work tree directory and
initialises a bare repository at GIT_DIR automatically before watching
starts.
The project is a small tokio async binary split into three modules:
main.rs— runs the pre-flight checks, sets up thenotifywatcher, and wires filesystem events into anmpscchannel (capacity 100) consumed by the debouncer. Also handles optional bare-repo initialisation viaGIT_WORK_TREE/GIT_DIR.debouncer.rs— receives events from the channel and coalesces bursts of activity: it waits for the first event, then keeps collecting further events (resetting a 3-second timer each time) until things go quiet, then hands the whole batch to the event handler.event_handler.rs— logs a human-readable summary of each event in the batch (created/modified/renamed/removed files), then runsgit add ., checks whether the index actually changed, and if so commits with the message"Update"and pushes if a remote is configured.
Filesystem "access" events (e.g. a file merely being read) are filtered out at the watcher level so they don't trigger commits.
git add .stages all changes in the work tree — rely on.gitignorefor anything that shouldn't be committed.- Every commit uses the fixed message
"Update"; there's no diff summarisation. - Designed for personal/scratch workflows (notes repos, pairing sessions, auto-saved WIP branches) — not intended for shared, production, or protected branches.
A Makefile wraps the common Cargo workflows:
make fmt # cargo fmt --all
make lint # cargo clippy -- -D warnings
make test # cargo test
make build # cargo build --release
make check # fmt + lint + test + build
make verify # cargo verify-project
make dry-run # check + verify + cargo publish --dry-run
make clean # cargo cleanReleases are cut with make tag (tags and pushes vX.Y.Z) followed by
make publish (dry-run, tag, then cargo publish). Pushing a v* tag
triggers .github/workflows/release.yml, which creates a GitHub Release,
uploads cross-platform binaries and a .deb package, and updates the
Homebrew tap and Winget manifest.
MIT — see LICENSE.