Skip to main content

manage-precommit

A Claude Code skill that builds a repository's .pre-commit-config.yaml from a small curated catalog — and merges into an existing config without clobbering what is already there.

Two invariants:

  • Latest, pinned. Every repo it adds gets the newest release tag, fetched live at run time. Nothing is hardcoded.
  • Never clobber. An existing config keeps its comments, formatting, top-level keys, repo revs, and any hooks outside the catalog. Only missing pieces are added, and nothing is duplicated.

Catalog

Key Adds Files written into the repo
hygiene pre-commit-hooks: trailing whitespace, end-of-file, check-yaml, check-json, large files, merge conflicts, mixed line endings —
yamllint yamllint .yamllint.yaml
markdownlint markdownlint-cli2 .markdownlint.yaml
mermaid local hook validating fenced mermaid blocks scripts/lint-mermaid.mjs
gitleaks gitleaks secret scan —

Mermaid ships no offline linter — its real parser only runs in a browser — so the bundled hook renders each diagram with mermaid-cli and fails the commit on a parse error.

Platforms

Linux and macOS. Not Windows.

The installer itself is cross-platform and CI proves it — manage-precommit install is exercised on Windows and macOS runners every push. The skill is the part that is not: its procedure runs mktemp, rm -f and command -v, and drives pre-commit, which is a POSIX arrangement throughout. Half of it working is not the half that matters, so the package does not claim the platform.

Requirements

  • pre-commit 4.0+
  • Python 3.10+ and git. No third-party Python packages — the skill is installed by symlink and its scripts run under your system python3, so anything it needed would have to be installed by hand on every machine.
  • For the mermaid hook only: Node.js, plus a Chromium/Chrome the hook's mermaid-cli can drive (it downloads one on first use if none is reusable). In CI, a container, or on a distro that restricts unprivileged user namespaces, Chromium's sandbox cannot start — set MERMAID_LINT_NO_SANDBOX=1 to run it without one. Opt-in, because that removes a real boundary around a browser rendering text out of the repository. The hook says so itself when it hits that failure, and reports it as an environment problem rather than an invalid diagram.

Install

Works under Claude Code, Codex and GitHub Copilot CLI. Both routes install a symlink, never a copy — so there is only ever one set of files, and nothing can drift out of sync.

manage-precommit install detects which of the three are on this machine and links the skill where each one looks:

Agent Skills directory
Claude Code ~/.claude/skills/
Codex ~/.agents/skills/
GitHub Copilot CLI ~/.agents/skills/

Codex and Copilot read the same directory, so installing for both writes one link, not two of the same name. --agent NAME (repeatable), --all and --dest DIR overrule the detection; --dry-run prints what would happen, refusals included.

As a package

pipx install manage-precommit
manage-precommit install

The package is an installer and nothing else; all the work lives in the skill files it links. --dry-run prints what would happen, refusals included; --dest DIR overrules the default location; --force acts on something that is not ours. manage-precommit uninstall removes the links and leaves the package alone -- and it sweeps every directory it could have written to, not just the detected ones: a link outlives the product that read it, which is exactly when leaving it behind is worst.

It refuses to touch anything it did not create: a real directory there may be a hand-written skill, and a link pointing elsewhere is not its to remove.

From a checkout

git clone git@github.com:grammy-jiang/manage-precommit.git
cd manage-precommit
make install     # ~/.claude/skills/manage-precommit -> ./src/manage_precommit/skill
make uninstall

This links the working tree, so an edit is live on the next Claude Code restart with no rebuild.

Usage

Invoke the skill and answer the prompts:

/manage-precommit

It scans the repo, proposes hooks (always-on plus ones matching what the repo actually contains), merges the selection, installs the git hook, runs the suite, shows the diff, and — only with confirmation — commits and pushes just the pre-commit setup files.

The engine also runs standalone (S=src/manage_precommit/skill/scripts):

python3 $S/precommit.py --catalog                      # list catalog keys
python3 $S/precommit.py --dir /path/to/repo --detect   # inspect existing config
python3 $S/precommit.py --dir /path/to/repo --recommend  # what the repo calls for, and why
python3 $S/precommit.py --dir /path/to/repo --force \
    --templates-file keys.txt --facts-out /tmp/facts.json

How a run flows

flowchart TD
  A[Scan repo] --> B[Propose hooks]
  B --> C{User selects}
  C --> D[Merge templates<br/>pin latest versions]
  D --> E[Install + run hooks]
  E --> F{All pass?}
  F -->|no| G[Report, stop]
  F -->|yes| H[Review diff]
  H --> I{Commit?}
  I -->|yes| J[Commit setup files only]
  J --> K[Push, with force gated<br/>behind a compare]
  I -->|no| L[Leave in working tree]

Layout

src/manage_precommit/skill/SKILL.md       the procedure Claude Code reads
                    skill/scripts/precommit.py  catalog, detect, recommend, merge, verify
                    skill/scripts/gitwork.py    status, commit, push-plan, push, facts
                    skill/scripts/config.py     the config scanner and additive writer
                    skill/scripts/summary.py    the end-of-run summary
                    skill/scripts/shared.py     sanitiser, no-follow reader, JSON contract
                    skill/templates/            one YAML fragment per catalog entry
                    skill/assets/               files copied into the target repo
                    skill/references/           on-demand detail (force-push, worked example)
tests/                                     pytest suite

The checkout and the installed tree are the same paths: nothing is remapped, so a path in a traceback traces back here by relative position.

How the merge keeps its promise

Each catalog entry is a YAML fragment with a __REV__ or __NPM__ placeholder. The engine substitutes the latest upstream version and inserts the fragment as text — it never re-emits the file. Every byte outside an inserted block is carried across untouched, and the write is rejected unless the original can be reconstructed from the result by deleting exactly the blocks that were added.

Reading is a strict line scanner rather than a YAML library. It refuses anything it cannot prove it understands — anchors, aliases, merge keys, flow sequences where a block is expected, more than one document, tabs — and says which line. A refusal is an exit code; a guess would be a wrong answer that looks right.

Dogfooding

This repo uses its own hooks. scripts/lint-mermaid.mjs is a symlink to src/manage_precommit/skill/assets/lint-mermaid.mjs, so the copy this repo runs and the payload it ships to other repos cannot drift apart.

Development

pip install -e '.[dev]'
python3 -m pytest        # 119 tests; no test touches the network
python3 -m ruff check . && python3 -m ruff format --check .
python3 -m mypy

Metadata

Release files for manage-precommit 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for manage-precommit 0.2.1
File Size Uploaded Provenance Actions
manage_precommit-0.2.1.tar.gz 175.9 kB With provenance Details for manage_precommit-0.2.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for manage-precommit 0.2.1
File Interpreter ABI Platform Actions
manage_precommit-0.2.1-py3-none-any.whl Python 3 none any Details for manage_precommit-0.2.1-py3-none-any.whl

Total release size: 278.8 kB

Release files / manage_precommit-0.2.1.tar.gz

Download URL manage_precommit-0.2.1.tar.gz
Size 175.9 kB
Tags Source
SHA-256 checksum
How to use checksums
d214a414fa841a5bde8be3ca3b357a59ec3b134eaaac7b0dd2c3bca64b5ed4a7
BLAKE2b-256 checksum
How to use checksums
92de02e4327a5655ff47d71df8234e8a6f1c67599f800591511c09964ed38d96
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 15, 2026.

Transparency log

Release files / manage_precommit-0.2.1-py3-none-any.whl

Download URL manage_precommit-0.2.1-py3-none-any.whl
Size 103.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d4d3b6616f901089c11f32a9e2b14f8e0919ff80ec0406c277eccb6095962407
BLAKE2b-256 checksum
How to use checksums
858e961d4ef7580b7fd56a738a43263803a80d0b7d60e03819b123d9d12a88f0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 15, 2026.

Transparency log

Security for manage-precommit 0.2.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for manage_precommit-0.2.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 15, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page