# Guardy
[](https://crates.io/crates/guardy)
[](https://docs.rs/guardy)
[](https://opensource.org/licenses/MIT)
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
```bash
cargo install guardy
```
### From source
```bash
git clone https://gitlab.com/deepbrain.space/guardy
cd guardy
cargo build --release
```
## Quick Start
### 1. Initialize in your repository
```bash
cd your-repo/
guardy install
```
This installs git hooks and creates a default configuration.
### 2. Configure hooks
Guardy supports both custom commands and built-in actions in hooks:
```yaml
# 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
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:
```yaml
# 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)
```yaml
# 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
```bash
# 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 repository
- `guardy scan <PATH>` - Scan files/directories for secrets and sensitive data
- `guardy status` - Show installation and configuration status
- `guardy config` - Manage configuration settings
- `guardy hooks uninstall` - Remove all installed git hooks
### File Synchronization
- `guardy sync` - Interactively update files from remote repositories
- `guardy sync diff` - Show differences without making changes
- `guardy sync --force` - Update all changes without prompting
- `guardy 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):
1. **Current directory**: `./.guardy.{json,yaml,yml,toml}` or `./guardy.{json,yaml,yml,toml}`
2. **Parent directories**: Searches up to git root or filesystem root
3. **User config**: `~/.config/.guardy.{json,yaml,yml,toml}` or
`~/.config/guardy.{json,yaml,yml,toml}`
4. **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:
```yaml
# /etc/guardy.yaml (lowest priority)
hooks:
pre-commit:
parallel: false
commands:
format-rust:
run: cargo fmt
```
```yaml
# ~/.config/.guardy.yaml (medium priority)
hooks:
pre-commit:
parallel: true # Overrides system config
```
```yaml
# ./.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:
```yaml
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)
```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:
```rust
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
- `conventional_commits` - Validate commit messages using conventional commits format
### Hook Features
#### Parallel Execution
Run commands in parallel for faster execution (enabled by default):
```yaml
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!)
```yaml
commands:
lint:
run: eslint {staged_files}
glob: "*.js" # Only staged .js files
```
- **`{files}`** - Custom files from `files:` command, filtered by glob patterns
```yaml
commands:
lint:
run: eslint {files}
files: "git diff --name-only main...HEAD" # Files changed since main
glob: "*.js" # Only .js files from the diff
```
Note: `{files}` requires a `files:` command. Without it, the command is skipped.
- **`{all_files}`** - All tracked files in the repository (no filtering)
```yaml
commands:
check-all:
run: prettier --check {all_files}
```
- **`{push_files}`** - Files being pushed (pre-push hook only)
```yaml
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)
```yaml
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:
```yaml
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:
```yaml
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:
```yaml
hooks:
commit-msg:
enabled: true
builtin: ["conventional_commits"]
```
**Supported formats:**
- `feat(scope): add new feature`
- `fix: resolve bug in authentication`
- `docs: update README`
- `chore(deps): update dependencies`
**Features:**
- Full conventional commits specification support
- Helpful error messages with examples
- Optional scope validation warnings
- Automatic comment filtering from commit messages
### Installing Specific Hooks
```bash
# 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:
```bash
# 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:
```yaml
# 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
```bash
# 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
```yaml
# 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
```yaml
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:**
```bash
# 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](../../LICENSE) for details.
## Contributing
Contributions welcome! Please see [CONTRIBUTING.md](../../CONTRIBUTING.md) for guidelines.
## Support
- 📚 [Documentation](https://docs.rs/guardy)
- 🐛 [Issues](https://gitlab.com/deepbrain.space/guardy/-/issues)
- 💬 [Discussions](https://gitlab.com/deepbrain.space/guardy/-/issues)