hooksmith 1.13.0

Trivial git hook management tool
Documentation

๐Ÿช 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

  • โš™๏ธ 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

cargo install hooksmith

As a Build Dependency

Add to your Cargo.toml:

[build-dependencies]
hooksmith = "1.10.0"

Create a build.rs file:

use std::path::Path;

fn main() {
    let config_path = Path::new("hooksmith.yaml");
    hooksmith::init(&config_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 parsing
  • console & dialoguer: For beautiful terminal interfaces
  • serde & serde_yaml: For YAML configuration handling
  • thiserror: For ergonomic error handling

๐Ÿš€ Quick Start

  1. Create a hooksmith.yaml file in your project root:
pre-commit:
  commands:
    - cargo fmt --all -- --check
    - cargo clippy -- --deny warnings

pre-push:
  commands:
    - cargo test
  1. Install the hooks:
hooksmith install

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
hooksmith install

# Run a specific hook manually
hooksmith run pre-commit

# Uninstall all hooks or a specific one
hooksmith uninstall
hooksmith uninstall pre-commit

# Compare installed hooks with configuration
hooksmith compare

# Validate hook configuration against Git standards
hooksmith validate

Add --dry-run to any command to preview changes without applying them:

hooksmith install --dry-run

๐Ÿ—‚๏ธ 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-commit and pre-push.
    • pre-commit: uses git diff --name-only --cached.
    • pre-push: diffs @{u}..HEAD when upstream exists, otherwise falls back to HEAD~1..HEAD.
  • Order: All matching path-based blocks run first, then global commands run.
  • 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 commands if 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.