Scan the whole monorepo
Find supported pins in nested packages and services while skipping `.git`, `node_modules`, and `vendor` trees.
Four runtimes, one report
Pinset gives platform engineers one read-only audit of Node, Python, Go, and Ruby pins across nested projects, GitHub Actions, and installed toolchains.
View on GitHub$ drift-check . Go go.mod=1.24 .github/workflows/ci.yml=1.23 installed=1.24.3 ⚠ DRIFT Node .nvmrc=20.11.0 .github/workflows/ci.yml=20.11.0 installed=20.11.0 ✓ Python .python-version=3.12 .github/workflows/ci.yml=3.11 installed=3.12.1 ⚠ DRIFT Ruby .ruby-version=3.3.0 Gemfile.lock=3.3.0 installed=3.3.0 ✓ 2 drift(s) found across 4 ecosystem(s).
What the command settles
A toolchain upgrade can touch a pin file, several CI jobs, and every developer machine. Pinset reads those claims together, retains duplicate setup steps, and reports the source of each value instead of returning a bare pass or fail.
Find supported pins in nested packages and services while skipping `.git`, `node_modules`, and `vendor` trees.
Read every matching setup step from root GitHub Actions workflows, even when the language pin lives several directories down.
Show `installed=not found` when a pinned runtime is absent. An incomplete machine never receives a clean report.
Choose aligned terminal output or `--json`. Both modes exit `1` on drift and `0` when every detected claim agrees.
Install and run
Pinset ships as a static Go binary. Install the tagged module, then run the `drift-check` command at the root of the repository you want to inspect.
go install github.com/ctkrug/drift-check@latestdrift-check .Field notes
It is a disagreement between runtime versions named by repository files, CI configuration, or the tools installed on a machine. Pinset lists each source and value on the same report.
Run `drift-check .` at the repository root. Pinset recursively finds supported project pins and compares them with root GitHub Actions setup steps and commands on `PATH`.
Version 1 reads `go.mod`, `.nvmrc`, `.python-version`, `.ruby-version`, and the `RUBY VERSION` stanza in `Gemfile.lock`.
Yes. Its text and JSON modes return a nonzero exit code when drift exists, so a normal workflow step can block a merge without a separate configuration file.