Pre-Commit Configuration
The PreCommitConfigConfigFile manages the .pre-commit-config.yaml file for
automated code quality checks before commits.
Overview
Creates a pre-commit configuration that:
- Runs linting with Ruff
- Formats code with Ruff
- Checks types with
ty - Scans for security issues with Bandit
- Lints markdown with rumdl
- Uses local hooks (no external repositories)
- Runs on every commit automatically
Inheritance
Inherits from: YamlConfigFile
What this means:
- Uses YAML format for configuration
- Loads/dumps with PyYAML
- Validation checks if all required hooks exist
- Users can add additional hooks
- File is considered correct if it's a superset of required configuration
File Location
Path: .pre-commit-config.yaml (project root)
Extension: .yaml - Standard pre-commit configuration file extension.
Special filename handling: get_filename() transforms the class name by
adding a dot prefix and replacing underscores with hyphens:
PreCommitConfigConfigFile → .pre-commit-config.
How It Works
Automatic Generation
When initialized via uv run pyrig mkroot, the .pre-commit-config.yaml file
is created with:
- Local repository configuration: All hooks run locally using system tools
- Code quality check hooks: Linting, formatting, type checking, security scanning, and markdown linting
- Automatic execution: Hooks run on every commit before changes are committed
Generated Configuration
repos:
- repo: local
hooks:
- id: lint-code
name: lint-code
entry: ruff check --fix
language: system
always_run: true
pass_filenames: false
- id: format-code
name: format-code
entry: ruff format
language: system
always_run: true
pass_filenames: false
- id: check-types
name: check-types
entry: ty check
language: system
always_run: true
pass_filenames: false
- id: check-security
name: check-security
entry: bandit -c pyproject.toml -r .
language: system
always_run: true
pass_filenames: false
- id: check-markdown
name: check-markdown
entry: rumdl check --fix
language: system
always_run: true
pass_filenames: false
Hook Configuration
Each hook is configured with these key settings:
- language: "system" - Uses tools from your environment (not isolated)
- always_run: true - Runs on every commit, even if no matching files changed
- pass_filenames: false - Runs on entire codebase, not just changed files
This ensures comprehensive quality checks on every commit.
Configured Hooks
| Hook | Command | Purpose |
|---|---|---|
lint-code |
ruff check --fix |
Linting with auto-fix |
format-code |
ruff format |
Code formatting |
check-types |
ty check |
Type checking |
check-security |
bandit -c pyproject.toml -r . |
Security vulnerability scanning |
check-markdown |
rumdl check --fix |
Markdown linting with auto-fix |
Each hook uses language: system (runs tools from your environment),
always_run: true (runs on every commit), and pass_filenames: false
(checks entire codebase).
Usage
Installation
Pre-commit hooks are automatically installed when you run:
uv run pyrig init
Or when running tests
uv run pytest
This runs pre-commit install to set up the Git hooks.
Manual Installation
uv run pre-commit install
Running Hooks Manually
Run all hooks on all files:
uv run pre-commit run --all-files
Run a specific hook:
uv run pre-commit run lint-code
Run with verbose output:
uv run pre-commit run --all-files --verbose
Automatic Execution
Once installed, hooks run automatically:
- On commit: When you run
git commit, all hooks execute - Before commit completes: If any hook fails, the commit is aborted
- Fix and retry: Fix the issues and commit again
Example workflow:
git add .
git commit -m "Add new feature"
# Hooks run automatically...
# If they pass, commit succeeds
# If they fail, commit is aborted and you see the errors
Skipping Hooks
To skip hooks for a specific commit (not recommended):
git commit --no-verify -m "Emergency fix"
Adding Custom Hooks
You can extend the configuration with additional hooks:
repos:
- repo: local
hooks:
# ... existing pyrig hooks ...
- id: check-yaml
name: check-yaml
entry: check-yaml
language: system
types: [yaml]
- id: check-json
name: check-json
entry: check-json
language: system
types: [json]
Or add hooks from external repositories:
repos:
- repo: local
hooks:
# ... existing pyrig hooks ...
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-added-large-files
Best Practices
- Keep pyrig hooks: Don't remove the default hooks - they ensure code quality
- Run manually before committing: Use
uv run pre-commit run --all-filesto catch issues early - Fix issues, don't skip: Avoid
--no-verify- fix the actual problems - Keep tools updated: Update tool versions in
pyproject.tomlto get latest features - Use in CI/CD: pyrig runs the same hooks in CI/CD pipeline health check
Why Local Hooks?
Pyrig uses repo: local instead of external repositories because:
- Version consistency: Uses the exact tool versions from your
pyproject.toml - No network dependency: Works offline, no downloading hook repositories
- Faster execution: No repository cloning or environment setup
- Custom tools: Can use pyrig-specific tools like
ty check - Simpler configuration: All tools managed by
uvin one place
Integration with CI/CD
The same hooks run in GitHub Actions workflows. See the workflow documentation for how pre-commit integrates with continuous integration.
Example from a workflow:
- name: Run pre-commit hooks
run: uv run pre-commit run --all-files
This ensures the same quality checks run locally and in CI.
Troubleshooting
- Hook fails: Run the tool directly (e.g.,
uv run ruff check --fix) for details - Hooks slow: Hooks check entire codebase; modify
always_runandpass_filenamesto only check changed files - Hooks not running: Run
uv run pre-commit installto reinstall - Tools not found: Run
uv syncto install dependencies