How to List Pre-commit Hooks from YAML Config in Python
Parse a .pre-commit-config.yaml file with PyYAML and print every hook ID paired with its source repository.
pip install pyyaml
Python code
28 linesimport yaml
pre_commit_config = """
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- repo: https://github.com/psf/black
rev: 23.11.0
hooks:
- id: black
"""
def list_hooks(config_text):
config = yaml.safe_load(config_text)
hooks = []
for repo in config.get("repos", []):
repo_url = repo.get("repo", "unknown")
for hook in repo.get("hooks", []):
hooks.append((hook.get("id", "unknown"), repo_url))
return hooks
if __name__ == "__main__":
for hook_id, repo_url in list_hooks(pre_commit_config):
print(f"{hook_id} <- {repo_url}")
Output
trailing-whitespace <- https://github.com/pre-commit/pre-commit-hooks
end-of-file-fixer <- https://github.com/pre-commit/pre-commit-hooks
check-yaml <- https://github.com/pre-commit/pre-commit-hooks
black <- https://github.com/psf/black
How it works
yaml.safe_load converts the YAML text into nested Python dictionaries and lists, making it trivial to walk the repo/hook structure. The get("repos", []) pattern safely handles a missing top-level key so the loop doesn't crash. Nested loops iterate each repository and then each hook inside it, collecting (hook_id, repo_url) tuples. The built-in __name__ == "__main__" guard keeps the print statement from running when the script is imported elsewhere.
Common mistakes
- Using `yaml.load` instead of `yaml.safe_load`, which can execute arbitrary code
- Assuming the `repos` key always exists without using `.get('repos', [])`
- Forgetting that `hook.get('id')` may return None for malformed entries
Variations
- Use `with open('.pre-commit-config.yaml') as f:` then `yaml.safe_load(f)` to read directly from a file instead of a string
- Return a list of only hook IDs (without repo URLs) if you just need names for a quick check
Real-world use cases
- Auditing which hooks a repository has enabled before merging a new contributor's PR.
- Building a CI script that verifies every hook in the config is implemented and up to date.
- Generating documentation that lists all linting and formatting checks for a project.
Sponsored
More from Modern tooling
- Build a Recipe Runner Mock in Python easy
- Build a Textual TUI App Skeleton in Python easy
- Configure ruff linter rules in pyproject.toml with Python easy
- Data Conversion Helper Functions in Python easy
- How to Bind and Mock structlog Context in Python medium
- How to Build a Chainable Filter Helper in Python easy
Keep learning
Related tutorials and quizzes for this topic.