codrift
Audit a CODEOWNERS file against the repository it claims to govern: which paths have no
owner, which owners have gone quiet, which rules match nothing, and whether every new path
will start unowned.
Validators check the syntax of a CODEOWNERS file, or that an owner exists on GitHub. None of them answer the question a review actually depends on: will this path get a reviewer? A pattern matching no tracked file protects nothing. A rule pointing at a team that has not committed in a year guarantees a stalled review. Neither is a syntax error, so nothing catches either.
pipx install codeowners-drift
What it reports
A repository whose CODEOWNERS drifted the way real ones do: no catch-all, a dead team, and a rule for a directory that no longer exists.
$ codrift . --days 180
codrift: 5 finding(s) in ., worst high
3 rule(s) over 5 tracked file(s)
[HIGH] unowned-path .github/CODEOWNERS
why: no rule matches, so no reviewer is guaranteed
[HIGH] unowned-path migrations.py
why: no rule matches, so no reviewer is guaranteed
[HIGH] unowned-path tools/release.sh
why: no rule matches, so no reviewer is guaranteed
[MEDIUM] missing-default
why: no '*' catch-all rule, so new paths start unowned
[LOW] orphaned-pattern /legacy/
rule: line 4
why: matches no tracked file, so it protects nothing
The owner-side check, on a repository where everyone is covered but one owner has gone quiet:
$ codrift . --days 180
codrift: 2 finding(s) in ., worst medium
4 rule(s) over 5 tracked file(s)
[MEDIUM] quiet-owner
why: @adaenonche92 last committed 304 days ago, past the 180 day threshold
[LOW] orphaned-pattern /api/v2/*.py
rule: line 5
why: matches no tracked file, so it protects nothing
Rules
| Severity | Rule | Why it matters |
|---|---|---|
| high | unowned-path |
no rule matches this tracked file, so review is not guaranteed |
| medium | missing-default |
no * catch-all, so every new path starts unowned |
| medium | quiet-owner |
this owner has not committed inside the threshold |
| low | orphaned-pattern |
this rule matches no tracked file, so it protects nothing |
How it works
It reads the CODEOWNERS file (CODEOWNERS, .github/CODEOWNERS or docs/CODEOWNERS), takes
the tracked files from git ls-files, and applies the documented CODEOWNERS semantics: the
last matching rule wins, a leading slash anchors to the root, a trailing slash means the
directory and everything under it, ** crosses directories while * does not, and a pattern
with no slash matches that name at any depth including the root.
Nothing is guessed about an owner who never committed. If git cannot find a commit by that
owner, the owner is reported as unknown, not inactive, because absent evidence is not the
same as absence of work. Team handles (@org/team) are skipped for the same reason: git has
no way to resolve a team to people.
Options
| Flag | Meaning |
|---|---|
--days N |
how quiet an owner must be before it counts (default 180) |
--fail-on high|medium|low|none |
lowest severity that exits 1 (default high) |
--max-unowned N |
cap the unowned paths listed, with a count of the rest (default 200) |
--json |
machine-readable report for a bot or an agent |
Exit codes: 0 clean, 1 findings at or above --fail-on, 2 usage error, no CODEOWNERS,
or not a git repository. The CODEOWNERS file itself is checked like any other path, since
protecting the file that decides who reviews is worth a rule.
Limits
This is a static audit of a text file and a git history, so it cannot know what a team is actually doing: an owner active in other repositories reads as quiet here. It does not verify that an owner exists on GitHub, which needs the API; that is the one thing the existing validators do well. It reads the first CODEOWNERS file it finds, not several.
The report says what it found, not that review is safe. 0 means no drift this check
recognises.
Development
git clone https://github.com/mgkvibez/codeowners-drift
cd codeowners-drift
python3 -m pip install -e ".[dev]"
bash scripts/verify.sh # the same six checks CI runs
python3 -m pytest -q # 17 tests
Zero runtime dependencies, Python 3.9+.
License
MIT
Metadata
Release files for codeowners-drift 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| codeowners_drift-0.1.0.tar.gz | 9.8 kB | With provenance | Details for codeowners_drift-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| codeowners_drift-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for codeowners_drift-0.1.0-py3-none-any.whl |
Total release size: 19.1 kB
Release files / codeowners_drift-0.1.0.tar.gz
| Download URL | codeowners_drift-0.1.0.tar.gz |
|---|---|
| Size | 9.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
67348a369c6d1dde8864cbe3024840b2d14ca10bb946c642e2866d97fc5da1f3
|
|
BLAKE2b-256 checksum How to use checksums |
f3f850ad97cf027a8ec054c617bd7e0c4b2fe19fe407b307c2160d34e17634c6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Nov 2, 2026.
Transparency logRelease files / codeowners_drift-0.1.0-py3-none-any.whl
| Download URL | codeowners_drift-0.1.0-py3-none-any.whl |
|---|---|
| Size | 9.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a9bc81c73b3e0d258885a6c9468bf2d05c5ba83921bd8756a8bcb5be2457ab5f
|
|
BLAKE2b-256 checksum How to use checksums |
5b8fca9a9b135d225f730af3b7470a76ed68add2c69fa40aad9fe319639de7c0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Nov 2, 2026.
Transparency logSecurity for codeowners-drift 0.1.0
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.
Attestation for codeowners_drift-0.1.0.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 Nov 2, 2026.
Transparency logA 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.