Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

305 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🦀 Rusty Commit Saver

Rust License: MIT Documentation codecov Codecov Test Analytics

🔍 CI - Quality & Coverage 🎯 Release 📚 Documentation


✨ A Rust flake to automatically log al Git commits into Obsidian. ✨

Rusty Commit Saver captures each commit’s:

  • Timestamp
  • Commit message
  • Repository URL
  • Branch name
  • Commit hash

and appends it to a dated diary entry in your Wiki directory.

Table of Contents:


Features 🚀

  • Automatic diary entry creation with YAML frontmatter and table header
  • Timestamped commit rows formatted for Obsidian
  • Customizable storage path under 📅 Diaries/0. Commits/YYYY/MM-MMMM/
  • Preconfigured hooks (via Nix + pre-commit) to ensure code quality

Installation 📦

  1. Clone the repository

    git clone https://github.com/chess-seventh/rusty-commit-saver.git
    cd rusty-commit-saver
  2. Enter the Nix development shell

    devenv shell
  3. Build the project

    cargo build --release
  4. (Optional) Install the binary to your PATH

    cargo install --path .

Usage 🛞

Simply commit as usual. The hooks will:

  1. Run linters (clippy, rustfmt, etc.) inside the Nix shell — pre-commit
  2. Invoke Rusty Commit Saver to log the commit — post-commit, once the commit exists, which is why nothing this tool does can cost you a commit

If you prefer manual invocation:

rusty-commit-saver

Your commit will be appended to, where Obsidian should be:

~/Documents/Wiki/📅 Diaries/0. Commits/YYYY/MM-MMMM/YYYY-MM-DD.md

Configuration 🛠

  • rust-toolchain.toml pins Rust 1.89.0
  • devenv.nix provisions Rust, Clippy, rustfmt, and Git hooks
  • .pre-commit-config.yaml defines all pre-commit checks
  • treefmt.toml configures treefmt and formatters

Runtime config (INI)

Runtime settings live in an INI file at ~/.config/rusty-commit-saver/rusty-commit-saver.ini:

[obsidian]
root_path_dir = ~/Documents/Obsidian
commit_path = Diaries/Commits

[templates]
commit_date_path = %Y/%m-%B/%F.md
commit_datetime = %H:%M:%S

# Optional: repositories to skip, by canonical repo name (comma-separated).
# A commit made in one of these repos writes nothing to the diary.
[exclude]
repos = claude-src

The [exclude] section is optional. Each entry is matched, case-sensitively, against the committing repository's canonical name — taken from its origin remote URL (…/claude-src.gitclaude-src), falling back to the working-directory name for a repo with no usable origin. Because the origin is the same from every checkout, one entry covers the main clone and every git worktree of that repo, from any subdirectory.

[obsidian] and [templates] are required; a config missing either one is fatal. Any other section is ignored, with a line on stderr naming it, never fatal. One INI file is shared by every checkout on the machine, so a section written for a newer release must not break a binary that predates it — which is exactly what adding [exclude] did to every checkout older than 4.17.0.

The stderr line matters: a misspelt section ([excludes]) is ignored too, so without it your exclusions would silently stop applying.

Keys work the same way, for the same reason:

  • A key this binary does not understand is ignored and named on stderr (ignoring unrecognised config keys [templates] commit_datetimes). It used to be ignored in complete silence, so a typo applied nothing and said nothing.

  • The four keys in [obsidian] and [templates] are required, and so is a non-empty value for each — commit_path = counts as missing. Without them there is no destination to write to, and a hook that quietly journals nothing looks exactly like a quiet day, so this one stays fatal. ([exclude] repos is optional, like its section.)

  • The two [templates] values must be formats chrono can actually render, and that is checked when the config is read. A bad specifier used to surface from inside the writer as a formatting trait implementation returned an error, naming nothing, after an empty diary file had already been created.

  • The fatal message names the config file, the key and its section, plus any unrecognised key in that same section, since a misspelt commit_paths is the usual reason commit_path is missing:

    rusty-commit-saver: /home/you/.config/rusty-commit-saver/rusty-commit-saver.ini:
    missing required key 'commit_path' in section [obsidian];
    unrecognised in [obsidian]: commit_paths
    

None of this can cost you a commit: the tool runs as a post-commit hook, and git ignores that hook's exit status. A config fault costs you the diary entry and prints on stderr; the commit itself always stands.

Checking hook behaviour by hand

tests/hook-gate.sh drives a real commit through a real post-commit hook, in a throwaway repo and vault, and prints what a human would see:

cargo build
./tests/hook-gate.sh good             # journals, says nothing
./tests/hook-gate.sh unknown-key      # journals, names the key on stderr
./tests/hook-gate.sh missing-key      # journals nothing, names file + key
./tests/hook-gate.sh blank-key        # same, for a key with an empty value
./tests/hook-gate.sh bad-format       # same, for a format chrono cannot render
./tests/hook-gate.sh unknown-section  # journals, names the section

Roadmap & Improvements 📈

There are many enhancements planned:

  • Configurable Obsidian path
  • Configurable year/day/month on where to save the commit
  • Interactive CLI flags and richer metadata (author, files changed)
  • Improved error handling and user feedback
  • Unit tests and CI pipeline for automated releases

Contributions welcome! Feel free to open issues or submit PRs.


Contributing 💖

  1. Fork the repo
  2. Create a feature branch
  3. Write tests and update README.md
  4. Submit a pull request

License 📄

MIT © 2026 Chess7th

About

Commit Saver

Resources

Code of conduct

Security policy

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages