HookRunner
A cross-platform pre-commit hook system
Install / Use
/learn @ashavijit/HookRunnerREADME
HookRunner
A cross-platform pre-commit hook system with DAG-based execution, policy enforcement, remote policy support, and secret detection.
Table of Contents
- Overview
- Features
- Installation
- Quick Start
- Configuration
- Policy System
- DAG Execution Engine
- CLI Reference
- CI/CD Integration
- Contributing
- License
Overview
HookRunner is a single-binary tool that manages git hooks with a focus on:
- Deterministic execution using DAG-based hook ordering
- Policy enforcement for organizational standards
- Cross-platform support for Windows, macOS, and Linux
- Language-agnostic with presets for Go, Node.js, Python, Java, Ruby, and Rust
Comparison with Other Tools
| Feature | pre-commit | Husky | Lefthook | HookRunner | |---------|------------|-------|----------|------------| | Single Binary | No | No | Yes | Yes | | Policy Engine | No | No | No | Yes | | Remote Policies | No | No | No | Yes | | DAG Execution | No | No | No | Yes | | Multi-language | Yes | No | Yes | Yes | | Cross-platform | No | No | Yes | Yes |
Features
DAG-Based Hook Execution
Hooks are modeled as a directed acyclic graph, enabling:
- Parallel execution of independent hooks
- Explicit dependency ordering via the
afterfield - Deterministic execution order across all platforms
Policy Engine
Enforce organizational rules at commit time:
- Maximum files per commit
- Forbidden directories and files
- Required files
- Commit message format validation
- File size limits
- Content pattern detection
Remote Policy Support
Fetch policies from remote URLs with caching:
- HTTPS-only for security
- ETag-based conditional requests
- SHA256-based disk caching
- Local policy overrides
Tool Management
Automatic tool downloading and caching:
- Platform-specific binary downloads
- SHA256 checksum verification
- Version-specific caching
- Fallback to system PATH
Language Presets
Quick setup for common languages:
| Language | Included Tools | |----------|----------------| | Go | gofmt, govet, golangci-lint | | Node.js | eslint, prettier, npm test | | Python | black, flake8, mypy, pytest | | Java | checkstyle, spotless, maven | | Ruby | rubocop, rspec | | Rust | cargo fmt, clippy, cargo test |
Installation
Using Go
go install github.com/ashavijit/hookrunner/cmd/hookrunner@latest
From Source
git clone https://github.com/ashavijit/hookrunner.git
cd hookrunner
go build -o hookrunner ./cmd/hookrunner
Quick Install Script (Linux/macOS)
curl -sSL https://raw.githubusercontent.com/ashavijit/hookrunner/master/scripts/install.sh | bash
Quick Install Script (Windows PowerShell)
iwr -useb https://raw.githubusercontent.com/ashavijit/hookrunner/master/scripts/install.ps1 | iex
Pre-built Binaries
Download from the Releases page.
Quick Start
1. Initialize Configuration
# Create hooks.yaml with a language preset
hookrunner init --lang go
# Or create a minimal config
hookrunner init
2. Install Git Hooks
hookrunner install
3. Commit Your Code
git add .
git commit -m "feat: add new feature"
# Hooks run automatically
4. Manual Hook Execution
# Run pre-commit hooks
hookrunner run pre-commit
# Run on all files (not just staged)
hookrunner run pre-commit --all-files
# Run with auto-fix enabled
hookrunner run pre-commit --fix
Configuration
HookRunner reads configuration from hooks.yaml, hooks.yml, or hooks.json in your project root.
Complete Configuration Example
# Tool definitions (optional - uses system PATH if not specified)
tools:
golangci-lint:
version: 1.55.2
install:
windows: https://github.com/.../golangci-lint-1.55.2-windows-amd64.zip
linux: https://github.com/.../golangci-lint-1.55.2-linux-amd64.tar.gz
darwin: https://github.com/.../golangci-lint-1.55.2-darwin-amd64.tar.gz
checksum: "sha256:abc123..."
# Policy configuration
policies:
type: raw
# Remote policies (fetched and cached)
policies:
- url: https://policies.example.com/security-baseline.yaml
# Local policies (override remote)
localPolicies:
- name: commit-format
version: local
rules:
max_files_changed: 20
forbid_directories:
- vendor/
- node_modules/
commit_message:
regex: "^(feat|fix|chore|docs|refactor|test):"
error: "Commit must follow conventional format"
# Hook definitions
hooks:
pre-commit:
- name: format
tool: go
args: ["fmt", "./..."]
files: "\\.go$"
- name: lint
tool: golangci-lint
args: ["run"]
after: format
timeout: 2m
env:
GOPROXY: direct
- name: test
tool: go
args: ["test", "./..."]
after: lint
skip: CI
commit-msg:
- name: validate-message
tool: hookrunner
args: ["policy", "check-message"]
Hook Field Reference
| Field | Type | Description |
|-------|------|-------------|
| name | string | Unique identifier for the hook |
| tool | string | Command or tool name to execute |
| args | []string | Arguments passed to the tool |
| fix_args | []string | Arguments used when --fix flag is set |
| files | string | Regex pattern to filter files |
| exclude | string | Regex pattern to exclude files |
| glob | string | Glob pattern for file matching |
| timeout | string | Maximum execution time (e.g., "2m", "30s") |
| after | string | Name of hook that must complete first |
| skip | string | Environment variable that skips this hook if set |
| env | map | Environment variables for execution |
| fail_fast | bool | Stop on first failure (default: true) |
Policy System
Policy Rules Reference
| Rule | Type | Description |
|------|------|-------------|
| max_files_changed | int | Maximum number of files in a commit |
| max_file_size_kb | int | Maximum file size in kilobytes |
| forbid_files | []string | Regex patterns for forbidden files |
| forbid_directories | []string | Forbidden directory paths |
| forbid_file_extensions | []string | Forbidden file extensions |
| required_files | []string | Files that must be present |
| forbid_file_content | []object | Patterns to detect in file content |
| commit_message.regex | string | Regex for commit message validation |
| commit_message.error | string | Custom error message |
| enforce_hooks | []string | Hooks that cannot be skipped |
| hook_time_budget_ms | map | Maximum execution time per hook |
| max_parallel_hooks | int | Limit parallel hook execution |
Forbid File Content Example
forbid_file_content:
- pattern: "password\\s*=\\s*['\"]"
description: "Hardcoded password detected"
- pattern: "TODO.*HACK"
description: "HACK comment found"
Remote Policy Format
Remote policies follow the same schema as local policies:
name: security-baseline
version: 1.2.0
description: Organization security standards
rules:
forbid_files:
- "\\.env$"
- "\\.pem$"
forbid_directories:
- secrets/
max_file_size_kb: 500
commit_message:
regex: "^(feat|fix|chore|docs):"
error: "Use conventional commit format"
metadata:
team: platform
owner: security@example.com
Policy Commands
# List configured policies
hookrunner policy list
# Force refresh remote policies
hookrunner policy fetch
# Clear policy cache
hookrunner policy clear-cache
DAG Execution Engine
How It Works
- Hooks without dependencies run in parallel (Level 1)
- Hooks with
afterfield wait for their dependency - Multiple hooks can depend on the same parent
- Cycle detection prevents infinite loops
Example Execution
hooks:
pre-commit:
- name: format # Level 1 - runs in parallel
- name: lint # Level 1 - runs in parallel
- name: security # Level 1 - runs in parallel
- name: test
after: lint # Level 2 - waits for lint
- name: integration
after: test # Level 3 - waits for test
Execution diagram:
Level 1: [format] [lint] [security] (parallel)
| |
Level 2: +-------+
|
[test]
|
Level 3: [integration]
CLI Reference
Commands
| Command | Description |
|---------|-------------|
| init | Create configuration file |
| init --lang <language> | Create config with language preset
Related Skills
imsg
347.2kiMessage/SMS CLI for listing chats, history, and sending messages via Messages.app.
node-connect
347.2kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
oracle
347.2kBest practices for using the oracle CLI (prompt + file bundling, engines, sessions, and file attachment patterns).
xurl
347.2kA CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.
