pre-commit language: system Hooks
language: system runs the hook command as-is using whatever is on PATH, with no environment build.
system hooks are the simplest and the most fragile: pre-commit builds nothing, so the tool must already be installed on every machine and runner.
What it does
For language: system, pre-commit does not create any environment. It simply runs entry with the matched filenames on the existing PATH. This is fast but means dependency management is entirely your responsibility.
Common usage
- repo: local
hooks:
- id: cargo-fmt
name: cargo fmt
entry: cargo fmt --
language: system
types: [rust]
pass_filenames: falseKeys
| Key | What it does |
|---|---|
| language: system | Run entry on the existing PATH, no env build |
| entry | Command to execute |
| pass_filenames | Append matched filenames to entry (default true) |
| types / files | Which files trigger the hook |
| require_serial | Run the hook once, not in parallel batches |
In CI
Install the underlying tool in an earlier pipeline step, since pre-commit will not do it for you. For tools that operate on the whole project rather than a file list (cargo fmt, go vet), set pass_filenames: false. system hooks are the usual cause of "works on my machine, fails in CI" when the runner lacks the binary.
Common errors in CI
"[ERROR] Executable <cmd> not found" is the signature system-hook failure: the binary in entry is not installed on the runner. Install it first, or switch to a language pre-commit can provision. If entry runs but processes no files, check pass_filenames and the types/files filters.