5 releases
Uses new Rust 2024
| new 0.2.3 | Nov 8, 2025 |
|---|---|
| 0.2.2 | Nov 6, 2025 |
| 0.2.1 | Nov 6, 2025 |
| 0.2.0 | Nov 4, 2025 |
| 0.1.0 | Aug 22, 2025 |
#305 in Development tools
430KB
9K
SLoC
Guardy
Fast, secure git hooks in Rust with secret scanning and protected file synchronization.
Features
- 🚀 Fast Security Scanning: Multi-threaded secret detection with entropy analysis
- 🔄 Protected File Synchronization: Keep configuration files in sync across repositories
- 🪝 Git Hook Support: Pre-commit, pre-push, and other git hooks
- ⚙️ Flexible Configuration: YAML, TOML, and JSON configuration support
- 📊 Multiple Output Formats: JSON, HTML, and plain text reporting
- 🔍 Comprehensive Scanning: Detect secrets, credentials, and sensitive data
Installation
From crates.io
cargo install guardy
From source
git clone https://gitlab.com/deepbrain.space/guardy
cd guardy
cargo build --release
Quick Start
1. Initialize in your repository
cd your-repo/
guardy hooks install
This installs git hooks and creates a default configuration.
2. Configure hooks
Guardy supports both custom commands and built-in actions in hooks:
# guardy.yaml
hooks:
pre-commit:
enabled: true
parallel: false # Run commands in parallel (default: false)
# Built-in actions
builtin: ["scan_secrets"]
# Custom commands
custom:
- command: "cargo fmt --check"
description: "Check formatting"
fail_on_error: true
glob: ["*.rs"] # Only run on Rust files (optional)
- command: "eslint {files} --fix"
description: "Fix ESLint issues"
all_files: true # Run on all files matching glob, not just staged
glob: ["*.js", "*.jsx", "*.ts", "*.tsx"]
stage_fixed: true # Auto-stage fixed files
commit-msg:
enabled: true
builtin: ["conventional_commits"] # Validates conventional commits format
pre-push:
enabled: true
builtin: ["ensure_clean"] # Ensure no uncommitted changes before push
parallel: true # Run all commands in parallel for speed
custom:
- command: "cargo check"
description: "Run type check"
fail_on_error: true
- command: "guardy sync update --force --config ./guardy.yaml"
description: "Sync protected files before push"
fail_on_error: true
3. Configure repository sync (optional)
Keep files synchronized from upstream repositories:
# guardy.yaml
sync:
repos:
- name: "shared-configs"
repo: "https://gitlab.com/your-org/shared-configs"
version: "v1.0.0" # Can be tag, branch, or commit
source_path: ".gitlab"
dest_path: "./.gitlab"
include: ["**/*"]
exclude: ["*.md"]
4. Configure scanning (optional)
# guardy.yaml
scanner:
file_extensions:
- "*.rs"
- "*.js"
- "*.py"
ignore_patterns:
- "target/"
- "node_modules/"
entropy_threshold: 3.0
hooks:
pre_commit:
enabled: true
commands:
- scan
3. Use the core features
# Scan files for secrets
guardy scan src/
# Check installation status
guardy status
# Sync configuration files
guardy sync
Commands
Core Commands
guardy hooks install- Install git hooks in the current repositoryguardy scan <PATH>- Scan files/directories for secrets and sensitive dataguardy status- Show installation and configuration statusguardy config- Manage configuration settingsguardy hooks uninstall- Remove all installed git hooks
File Synchronization
guardy sync- Interactively update files from remote repositoriesguardy sync diff- Show differences without making changesguardy sync --force- Update all changes without promptingguardy sync status- Show sync configuration and status
Advanced
guardy hooks run <HOOK>- Manually run a specific git hook for testing
Configuration
Guardy supports multiple configuration formats (YAML, TOML, JSON) with automatic discovery and merging.
Configuration File Discovery
Guardy automatically searches for configuration files in the following locations (highest to lowest priority):
- Current directory:
./.guardy.{json,yaml,yml,toml}or./guardy.{json,yaml,yml,toml} - Parent directories: Searches up to git root or filesystem root
- User config:
~/.config/.guardy.{json,yaml,yml,toml}or~/.config/guardy.{json,yaml,yml,toml} - System config:
/etc/.guardy.{json,yaml,yml,toml}or/etc/guardy.{json,yaml,yml,toml}
Priority Rules:
- Dot-prefixed files (
.guardy.*) take priority over non-prefixed files (guardy.*) - JSON format takes priority over YAML, which takes priority over TOML
- Closer directories (current dir) override farther ones (system config)
Automatic Merging: Guardy automatically merges all discovered config files with higher priority configs overriding lower priority ones. This allows you to:
- Set organization-wide defaults in
/etc/.guardy.yaml - Override with personal preferences in
~/.config/.guardy.yaml - Customize per-project in
./.guardy.yaml
Example Merge Behavior:
If you have:
# /etc/guardy.yaml (lowest priority)
hooks:
pre-commit:
parallel: false
commands:
format-rust:
run: cargo fmt
# ~/.config/.guardy.yaml (medium priority)
hooks:
pre-commit:
parallel: true # Overrides system config
# ./.guardy.yaml (highest priority)
hooks:
pre-commit:
commands:
format-rust:
run: mise exec -- moon run :format # Overrides system config
clippy-check: # Adds new command
run: cargo clippy
The final merged configuration will be:
hooks:
pre-commit:
parallel: true # From user config
commands:
format-rust:
run: mise exec -- moon run :format # From project config
clippy-check: # From project config
run: cargo clippy
Basic Configuration (guardy.yaml)
# Scanner settings
scanner:
file_extensions:
- "*.rs"
- "*.js"
- "*.py"
- "*.go"
ignore_patterns:
- "target/"
- "node_modules/"
- "*.log"
max_file_size: 1048576 # 1MB
entropy_threshold: 3.5
# Git hooks configuration
hooks:
pre-commit:
enabled: true
builtin: ["scan_secrets"] # Built-in secret scanning
custom: [] # Add custom commands here
pre-push:
enabled: true
custom:
- command: "guardy sync update --force --config ./guardy.yaml"
description: "Sync protected files"
fail_on_error: true
# File synchronization
sync:
repos:
- name: "shared-configs"
repo: "https://gitlab.com/yourorg/shared-configs"
version: "main"
source_path: "."
dest_path: "."
include: ["*.yml", "*.json", ".gitignore"]
exclude: [".git", "target/"]
Library Usage
Guardy can be used as a library for building custom security tools:
use guardy::scanner::ScannerConfig;
use guardy::config::GuardyConfig;
// Load configuration
let config = GuardyConfig::load("guardy.yaml", None, 0)?;
let scanner_config = ScannerConfig::from_config(&config)?;
// Scan for secrets
let results = scanner_config.scan_path("src/")?;
// Process findings
for finding in results.findings {
println!(
"Secret found in {}: {} (confidence: {:.2})",
finding.file_path,
finding.secret_type,
finding.confidence
);
}
Git Hooks Integration
Guardy provides flexible git hook management with both built-in actions and custom commands:
Built-in Actions
scan_secrets- Scan staged files for secrets and credentials (pre-commit hook)conventional_commits- Validate commit messages using conventional commits format (commit-msg hook)ensure_clean- Ensure repository has no uncommitted changes before push (pre-push hook)
Hook Features
Parallel Execution
Run commands in parallel for faster execution (enabled by default):
hooks:
pre-push:
parallel: true # Default: true - commands run simultaneously with optimal concurrency
custom:
- command: "cargo check"
- command: "cargo clippy"
- command: "cargo fmt --check"
Guardy automatically profiles your system and workload to determine optimal parallelism:
- Small workloads (≤3 commands): Sequential execution
- Medium workloads (4-5 commands): Conservative parallelism
- Large workloads (6+ commands): Full parallelism (capped at 8 concurrent commands)
- System-aware: Respects available CPU cores and limits concurrency appropriately
Template Variables (Lefthook-Compatible)
Guardy supports template variables in commands and environment variables, fully compatible with Lefthook syntax:
File Placeholders
-
{staged_files}- Staged files filtered by glob patterns (lefthook-compatible!)commands: lint: run: eslint {staged_files} glob: "*.js" # Only staged .js files -
{files}- Custom files fromfiles:command, filtered by glob patternscommands: lint: run: eslint {files} files: "git diff --name-only main...HEAD" # Files changed since main glob: "*.js" # Only .js files from the diffNote:
{files}requires afiles:command. Without it, the command is skipped. -
{all_files}- All tracked files in the repository (no filtering)commands: check-all: run: prettier --check {all_files} -
{push_files}- Files being pushed (pre-push hook only)pre-push: commands: test-changed: run: npm test {push_files}
Command Placeholders
{cmd}- The command itself (useful in env vars){guardy_job_name}- Current command/job name
Hook Argument Placeholders
{0}- All hook arguments as a single space-joined string{1},{2},{3}- Individual hook arguments (1-indexed)
commit-msg:
commands:
validate:
run: ./scripts/validate-msg.sh {1} # First argument is commit message file
Glob Pattern Filtering
Target specific file types with glob patterns:
custom:
- command: "prettier --write {staged_files}"
glob: ["*.js", "*.css", "*.html"]
- command: "black {staged_files}"
glob: ["*.py"]
All Files Mode
Process all matching files, not just staged ones:
custom:
- command: "eslint {files} --fix"
all_files: true # Process all JS files in repo
glob: ["**/*.js"]
stage_fixed: true # Auto-stage corrected files
Conventional Commits Validation
Ensures commit messages follow the conventional commits format using the git-conventional library:
hooks:
commit-msg:
enabled: true
builtin: ["conventional_commits"]
Supported formats:
feat(scope): add new featurefix: resolve bug in authenticationdocs: update READMEchore(deps): update dependencies
Features:
- Full conventional commits specification support
- Helpful error messages with examples
- Optional scope validation warnings
- Automatic comment filtering from commit messages
Clean Repository Validation
Ensures the repository has no uncommitted changes before pushing, preventing accidental pushes of work-in-progress:
hooks:
pre-push:
enabled: true
builtin: ["ensure_clean"]
What it checks:
- Modified files in the worktree
- Deleted files not staged
- Untracked files
- Any uncommitted changes
Features:
- Uses pure Rust
gixlibrary for maximum performance - Shows helpful error messages listing uncommitted files
- Only runs in pre-push hook (shows warning if used elsewhere)
- Fast microsecond-level status checks
Note: This builtin is designed specifically for the pre-push hook. If you need to allow
uncommitted changes in certain workflows, simply remove it from your configuration or use
git push --no-verify to skip hooks.
Installing Specific Hooks
# Install all hooks
guardy install
# Install specific hooks
guardy install --hooks pre-commit,pre-push
# Force overwrite existing hooks
guardy install --force
File Synchronization from other Repositories
Keep configuration files synchronized across multiple repositories:
# Configure sync in guardy.yaml
guardy sync status # Show sync configuration
guardy sync diff # Preview changes without applying
guardy sync # Interactive update with diffs
guardy sync --force # Apply all changes automatically
# Bootstrap from a repository
guardy sync --repo=https://gitlab.com/org/configs --version=main
Automating Sync with Hooks
Integrate sync into your git workflow to ensure files stay synchronized:
# guardy.yaml
sync:
repos:
- name: "shared-configs"
repo: "https://gitlab.com/org/shared-configs"
version: "v1.0.0"
source_path: ".gitlab"
dest_path: "./.gitlab"
include: ["**/*"]
hooks:
pre-push:
enabled: true
custom:
- command: "guardy sync update --force --config ./guardy.yaml"
description: "Ensure configs are synchronized before push"
fail_on_error: true
This ensures synced files are always synchronized before pushing changes.
Features:
- Diff visualization with syntax highlighting
- Interactive updates with per-file control
- Selective sync with include/exclude patterns
- Version pinning to specific tags or commits
- Multi-repository configuration support
- Automatic restoration of modified protected files
Examples
Scanning specific file types
# Scan only Rust files
guardy scan --include="*.rs" src/
# Scan excluding test files
guardy scan --exclude="*test*" .
# Output as JSON
guardy scan --format=json src/ > scan-results.json
Custom git hooks
# guardy.yaml
hooks:
pre-commit:
enabled: true
builtin: ["scan_secrets"]
custom:
- command: "cargo fmt -- --check"
description: "Check formatting"
fail_on_error: true
- command: "cargo clippy -- -D warnings"
description: "Run clippy"
fail_on_error: true
File sync with filters
sync:
repos:
- name: "eslint-config"
repo: "https://gitlab.com/company/eslint-configs"
version: "v2.1.0"
source_path: "configs"
dest_path: "."
include: [".eslintrc*", "prettier.config.js"]
exclude: ["*.local.*"]
Performance
- Multi-threaded: Utilizes all CPU cores for scanning
- Memory efficient: Processes large repositories without high memory usage
- Fast I/O: Optimized file reading with memory-mapped files
- Smart filtering: Skips binary files and respects .gitignore patterns
- OS Cache Optimization: Leverages filesystem caching for dramatic performance improvements
Intelligent Caching Performance
Guardy efficiently utilizes OS-level filesystem caching for exceptional performance:
First Scan (Cold Cache):
- Initial scan reads files from disk storage
- Typical performance: ~1,900 files/second
- OS populates filesystem cache with file data
Subsequent Scans (Warm Cache):
- Files served from RAM instead of disk
- Up to 2.7x faster performance: ~5,200 files/second
- Perfect for CI/CD and iterative development workflows
Real-World Example:
# First run (cold cache)
$ guardy scan ~/code/large-project --stats
⚡ Scan completed in 91.19s (172,832 files scanned)
# Second run (warm cache)
$ guardy scan ~/code/large-project --stats
⚡ Scan completed in 33.37s (172,832 files scanned)
# 🚀 63% faster!
Performance Benchmarks
Typical performance on a modern machine:
- Cold cache: ~1,900 files/second for secret scanning
- Warm cache: ~5,200 files/second (2.7x improvement)
- Memory usage: <200MB for repositories with 100k+ files
- Startup time: <100ms for git hooks
License
MIT License - see LICENSE for details.
Contributing
Contributions welcome! Please see CONTRIBUTING.md for guidelines.
Support
- 📚 Documentation
- 🐛 Issues
- 💬 Discussions
Dependencies
~42–60MB
~1M SLoC