๐ช Hooksmith
Hooksmith is a lightweight, easy-to-use tool that simplifies Git hook management. Define your hooks in a simple YAML file and let Hooksmith handle the rest.
๐ Table of Contents
- โจ Features
- โก Why Hooksmith?
- ๐ง Installation
- ๐ Quick Start
- ๐ Usage
- ๐๏ธ Path-based Blocks
- ๐ Command Reference
- ๐ค Contributing
- ๐ License
โจ Features
- โ๏ธ Automatic Installation - Set up hooks through your build scripts with
build.rs - ๐งช Local Testing - Run hooks manually without triggering Git events
- ๐ Dry Run Mode - Preview what would happen without making changes
- โ Hook Validation - Ensure your hooks comply with Git standards
- ๐ Simple Configuration - Define all your hooks in a clean YAML format
- ๐จ Beautiful CLI - Enjoy a polished terminal interface with clear output
- ๐ Shell Completion - Built-in Fish shell completions for improved productivity
- ๐ Version Control - Easily track hook changes with your repository
- ๐ฆ Error Handling - Robust error handling with clear, actionable messages
โก Why Hooksmith?
- Minimal Dependencies - Lightweight with only essential dependencies
- Rust Powered - Fast, reliable, and type-safe
- Team Friendly - Version control your hook configurations
- Seamless Integration - Works naturally with your Git workflow
- Low Learning Curve - Simple commands and clear documentation
๐ง Installation
Using Cargo
As a Build Dependency
Add to your Cargo.toml:
[]
= "1.10.0"
Create a build.rs file:
use Path;
๐ก Note: Hooksmith includes shell completions for Fish. After installation, they become available automatically.
Dependencies
Hooksmith is built with minimal but powerful dependencies:
clap: For robust command-line argument parsingconsole&dialoguer: For beautiful terminal interfacesserde&serde_yaml: For YAML configuration handlingthiserror: For ergonomic error handling
๐ Quick Start
- Create a
hooksmith.yamlfile in your project root:
pre-commit:
commands:
- cargo fmt --all -- --check
- cargo clippy -- --deny warnings
pre-push:
commands:
- cargo test
- Install the hooks:
That's it! Your Git hooks are now ready to use.
๐ Usage
Configuration File
Hooksmith uses a YAML configuration file (default: hooksmith.yaml) to define your hooks:
# Format and lint code before committing
pre-commit:
commands:
- cargo fmt --all -- --check
- cargo clippy --workspace --all-features -- --deny warnings
# Run tests before pushing
pre-push:
commands:
- cargo test --all-features
- cargo build --verbose
# Validate commit messages
commit-msg:
commands:
# Use custom script to validate commit messages
- ./scripts/verify-commit-message.sh $1
Common Commands
# Install all hooks defined in configuration
# Run a specific hook manually
# Uninstall all hooks or a specific one
# Compare installed hooks with configuration
# Validate hook configuration against Git standards
Add --dry-run to any command to preview changes without applying them:
๐๏ธ Path-based Blocks
Define commands that only run when files within specific paths have changed. This lets you scope expensive checks to the parts of the repository they affect.
YAML structure
pre-commit:
# Global commands: always run
commands:
- cargo fmt --all -- --check
# Path-based blocks: run only if matching files changed
paths:
src/:
commands:
- cargo clippy --workspace -- -D warnings
crates/api/:
working_directory: crates/api
commands:
- npm ci
- npm test
How it works
- Matching: A block runs when any changed file path starts with its key (simple prefix match). Use paths relative to the repo root; prefer a trailing slash (e.g.,
src/). - Supported hooks: Change detection is implemented for
pre-commitandpre-push.pre-commit: usesgit diff --name-only --cached.pre-push: diffs@{u}..HEADwhen upstream exists, otherwise falls back toHEAD~1..HEAD.
- Order: All matching path-based blocks run first, then global
commandsrun. - Working directory: Inside a path block,
working_directory(optional) sets the directory for those commands only. Global commands run in the current directory. - No matches: If no paths match, only global commands run. Omit
commandsif you want nothing to run in that case. - Multiple matches: If a file matches several prefixes, all matching blocks run. The order between blocks is not guaranteed; the order of commands within a block is preserved.
๐ Command Reference
| Command | Description |
|---|---|
install |
Install all hooks from configuration file |
run <hook> |
Run a specific hook manually |
uninstall [hook] |
Uninstall all hooks or a specific one |
compare |
Compare installed hooks with configuration |
validate |
Validate hook configuration against Git standards |
Global Options
| Option | Description |
|---|---|
--config-path <PATH> |
Specify a custom configuration file path |
--dry-run |
Preview changes without applying them |
--verbose |
Show detailed output during execution |
--help |
Display help information |
๐ค Contributing
Contributions are welcome! Feel free to:
- Report bugs and suggest features
- Submit pull requests
- Improve documentation
- Share your use cases and feedback
๐ License
This project is dual-licensed under either:
at your option.