codeowners-audit
v2.9.0
Published
Generate an HTML report for CODEOWNERS ownership gaps and run in CI or from the CLI to fail when files are not covered.
Maintainers
Readme
Live Example
See how ownership coverage looks in practice with this interactive report for the nodejs/node repository.
Why this exists
CODEOWNERS is great for review routing, but it is hard to quickly answer:
- How much of this repository is actually covered?
- Which directories have the biggest ownership gaps?
- Which specific files have no matching owner rule?
- Which
CODEOWNERSrules look valid in git, but are ignored or ineffective on GitHub?
codeowners-audit scans a repository, applies practical CODEOWNERS resolution, and produces a single self-contained HTML report you can open locally, archive in CI, or upload to a public link.
Highlights
- Self-contained interactive HTML report
- Coverage drill-down by repository, directory, file, and resolved owner
- CI-friendly defaults that can fail builds when files are uncovered
- GitHub-parity validation for ignored
CODEOWNERSfiles, missing paths, invalid owners, oversized files, and fragile coverage - Optional team suggestions for uncovered directories based on git history
- Works on local repositories or remote GitHub repositories with a single command
Quick Start
Run without installing:
npx codeowners-auditFor repeat use in a repository or CI, add it as a dev dependency:
npm install --save-dev codeowners-auditCommon first runs:
Generate a report for the current repository:
npx codeowners-auditFail in CI without writing HTML:
npx codeowners-audit --no-reportAudit a remote GitHub repository:
npx codeowners-audit watson/codeowners-auditUsage
codeowners-audit [repo-or-path] [options]The executable name is codeowners-audit. If you are running it without installing it as a dependency, prefix commands with npx.
[repo-or-path] is optional and can be:
- A remote repository URL such as
https://github.com/owner/repo - GitHub shorthand such as
owner/repo - A local directory path such as
~/code/my-repo - Omitted, in which case the current working directory is used
By default, the tool:
- analyzes tracked files from
git ls-files - writes the report to a temporary path
- prompts you to press Enter before opening the report in your default browser
When standard input is non-interactive (no TTY, for example in CI), the command automatically behaves as if --no-open --list-unowned --fail-on-unowned were specified:
- it never prompts to open a browser
- it prints all unowned file paths to stdout
- it exits non-zero when uncovered files exist
Use --output or --output-dir for deterministic artifact paths, or --no-report to skip writing HTML entirely. In interactive mode, --no-report implies --list-unowned so the command still produces useful output.
Options
Input and Scope
| Option | Description |
| --- | --- |
| --cwd <dir> | Run git commands from this directory |
| --include-untracked | Include untracked files in the analysis |
| -g, --glob <pattern> | Repeatable file filter for report and check scope (default: **) |
Report Output
| Option | Description |
| --- | --- |
| -o, --output <path> | Output HTML file path |
| --output-dir <dir> | Output directory for the generated HTML report |
| --no-report | Skip HTML report generation (implies --list-unowned) |
| --upload | Upload to zenbin and print a public URL |
Interaction and Diagnostics
| Option | Description |
| --- | --- |
| --no-open | Do not prompt to open the report in your browser |
| -y, --yes | Automatically answer yes to interactive prompts |
| --verbose | Enable verbose progress output |
| -h, --help | Show this help |
| -v, --version | Show version |
Core Coverage Checks
| Option | Description |
| --- | --- |
| --list-unowned | Print unowned file paths to stdout |
| --fail-on-unowned | Exit non-zero when one or more files are unowned |
GitHub Validation and Policy Checks
| Option | Description |
| --- | --- |
| --fail-on-oversized-codeowners | Exit non-zero when the active CODEOWNERS file exceeds GitHub's 3 MB limit |
| --fail-on-missing-paths | Exit non-zero when one or more CODEOWNERS paths match no repository files |
| --validate-github-owners | Validate @username and @org/team owners against GitHub and use only validated owners for coverage |
| --fail-on-invalid-owners | Exit non-zero when one or more CODEOWNERS rules contain invalid GitHub owners |
| --fail-on-missing-directory-slashes | Exit non-zero when directory CODEOWNERS paths do not follow the explicit trailing-slash style |
| --fail-on-location-warnings | Exit non-zero when extra or ignored CODEOWNERS files are found |
| --fail-on-fragile-coverage | Exit non-zero when directories have fragile file-by-file coverage |
Team Suggestions
| Option | Description |
| --- | --- |
| --suggest-teams | Suggest @org/team for uncovered directories |
| --suggest-window-days <days> | Git history lookback window for suggestions (default: 365) |
| --suggest-top <n> | Top team suggestions to keep per directory (default: 3) |
| --suggest-ignore-teams <list> | Comma-separated team slugs or @org/slug entries to exclude from suggestions |
| --github-org <org> | Override GitHub org for team lookups |
| --github-token <token> | GitHub token for team lookups (falls back to GITHUB_TOKEN, then GH_TOKEN) |
| --github-api-base-url <url> | GitHub API base URL (default: https://api.github.com) |
Examples
Generate a report and open it after pressing Enter:
codeowners-auditWrite a report to a known path without opening a browser:
codeowners-audit --output codeowners-gaps-report.html --no-openRun against a repository from another directory:
codeowners-audit ~/code/my-repoAudit a remote GitHub repository:
codeowners-audit watson/codeowners-auditUpload a report and print the public URL:
codeowners-audit --uploadValidate only a subset of files:
codeowners-audit --glob "src/**/*.js" --glob "test/**/*.js"Suggest teams for uncovered directories:
codeowners-audit --suggest-teamsUsing in CI
Most CI systems, including GitHub Actions, run in a non-interactive environment. In that mode, codeowners-audit automatically:
- disables browser prompts with
--no-open - prints unowned files to stdout with
--list-unowned - exits
1when uncovered files exist with--fail-on-unowned
Exit code behavior:
- Exit code
0: all matched files are covered byCODEOWNERS, and no enabled validation policy failed - Exit code
1: at least one enforced policy failed, including uncovered files and any enabled--fail-on-*validation rule - Exit code
2: runtime or setup error, for example not being in a git repository, missingCODEOWNERS, or invalid arguments
Common CI Commands
Validate all tracked files:
codeowners-auditValidate all tracked files without writing HTML:
codeowners-audit --no-reportValidate and write a report artifact to a known path:
codeowners-audit --output codeowners-gaps-report.htmlValidate and write reports into an artifact directory:
codeowners-audit --output-dir artifactsValidate only a subset, for example spec files:
codeowners-audit --glob "**/*.spec.js"GitHub Actions Example
- name: Verify CODEOWNERS coverage
run: npx codeowners-audit --no-reportGitHub Compatibility Notes
- Follows GitHub
CODEOWNERSdiscovery order:.github/CODEOWNERS,CODEOWNERS, thendocs/CODEOWNERS - Uses standard last-match-wins behavior, including ownerless overrides when the last matching rule has no owners
- Resolves patterns from the repository root, regardless of which supported
CODEOWNERSlocation is active - Optionally validates
@usernameand@org/teamowners against GitHub with--validate-github-owners - Reports extra or ignored
CODEOWNERSfiles, missing paths, fragile coverage, and unsupported syntax that GitHub would not honor
Requirements
gitavailable onPATH
Upload Size Note
zenbin currently rejects request payloads around 1 MiB and larger. Very large repositories can produce HTML reports beyond that limit, in which case --upload will fail with a clear size error. Use the generated local HTML file directly when this happens.
License
MIT
