Skip to content

Commit 512fb0d

Browse files
committed
docs(cli): refresh README and help output
Improve the npm-facing README so the core value, quick start, and option groups are clearer to scan. Reformat the CLI help output into spaced sections and make the help-output test resilient to future column-width tweaks. Made-with: Cursor
1 parent 0e2e596 commit 512fb0d

File tree

3 files changed

+228
-134
lines changed

3 files changed

+228
-134
lines changed

README.md

Lines changed: 122 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
<img width="328" height="300" alt="codeowners-audit logo" src="https://github.com/user-attachments/assets/ae21c52c-e923-4c43-8a13-8d22e03bc867" />
33
</p>
44

5-
<p align="center">Generate a polished, interactive HTML report that shows which files in a Git repository are covered by CODEOWNERS rules and where ownership gaps exist. You can also run it in CI or from the command line to fail when files are not covered by CODEOWNERS.</p>
5+
<p align="center">Generate a polished, interactive HTML report for CODEOWNERS coverage, ownership gaps, and GitHub-parity validation. Run it locally for investigation or in CI to fail when files are uncovered.</p>
66

77
<img width="1429" height="681" alt="image" src="https://github.com/user-attachments/assets/abcaddf1-4159-4278-b592-ce96a1235f8e" />
88

9-
## Playground
9+
## Live Example
1010

1111
See how ownership coverage looks in practice with [this interactive report](https://watson.github.io/codeowners-audit/example.html) for the `nodejs/node` repository.
1212

@@ -17,35 +17,51 @@ See how ownership coverage looks in practice with [this interactive report](http
1717
- How much of this repository is actually covered?
1818
- Which directories have the biggest ownership gaps?
1919
- Which specific files have no matching owner rule?
20+
- Which `CODEOWNERS` rules look valid in git, but are ignored or ineffective on GitHub?
2021

21-
`codeowners-audit` scans your repository, applies `CODEOWNERS` matching rules, and produces a single self-contained HTML report you can open locally or upload to a public link.
22+
`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.
2223

2324
## Highlights
2425

25-
- Interactive HTML report with no build step
26-
- Coverage summary: total files, owned, unowned, and percentage
27-
- Directory explorer with filtering, sorting, and drill-down
28-
- Full unowned file list with scope and text filtering
29-
- Ownership explorer with quick chips and file filtering for resolved CODEOWNERS owners, including `@org/team`, `@username`, and email owners
30-
- Matches GitHub `CODEOWNERS` discovery precedence: `.github/`, repository root, then `docs/`
31-
- Detects CODEOWNERS patterns that match no repository paths
32-
- Detects directories with fragile coverage — 100% covered through individual file rules, but new files would lack owners
33-
- Warns when extra or unsupported `CODEOWNERS` files will be ignored by GitHub
34-
- Optional upload to [zenbin.org](https://zenbin.org) for easy sharing
26+
- Self-contained interactive HTML report
27+
- Coverage drill-down by repository, directory, file, and resolved owner
28+
- CI-friendly defaults that can fail builds when files are uncovered
29+
- GitHub-parity validation for ignored `CODEOWNERS` files, missing paths, invalid owners, oversized files, and fragile coverage
30+
- Optional team suggestions for uncovered directories based on git history
31+
- Works on local repositories or remote GitHub repositories with a single command
3532

36-
## Installation
33+
## Quick Start
3734

38-
Run with `npx` (no install):
35+
Run without installing:
3936

4037
```bash
4138
npx codeowners-audit
4239
```
4340

44-
Or install globally:
41+
For repeat use in a repository or CI, add it as a dev dependency:
4542

4643
```bash
47-
npm install -g codeowners-audit
48-
codeowners-audit
44+
npm install --save-dev codeowners-audit
45+
```
46+
47+
Common first runs:
48+
49+
Generate a report for the current repository:
50+
51+
```bash
52+
npx codeowners-audit
53+
```
54+
55+
Fail in CI without writing HTML:
56+
57+
```bash
58+
npx codeowners-audit --no-report
59+
```
60+
61+
Audit a remote GitHub repository:
62+
63+
```bash
64+
npx codeowners-audit watson/codeowners-audit
4965
```
5066

5167
## Usage
@@ -54,106 +70,148 @@ codeowners-audit
5470
codeowners-audit [repo-or-path] [options]
5571
```
5672

57-
The first argument is optional and can be:
73+
The executable name is `codeowners-audit`. If you are running it without installing it as a dependency, prefix commands with `npx`.
5874

59-
- A **remote repository URL** (e.g. `https://github.com/owner/repo`) or **GitHub shorthand** (`owner/repo`) — the repo will be cloned into a temp directory, audited, and the clone removed automatically.
60-
- A **local directory path** (e.g. `~/code/my-repo`) — equivalent to `--cwd`.
61-
- **Omitted** — the current working directory is used.
75+
`[repo-or-path]` is optional and can be:
76+
77+
- A remote repository URL such as `https://github.com/owner/repo`
78+
- GitHub shorthand such as `owner/repo`
79+
- A local directory path such as `~/code/my-repo`
80+
- Omitted, in which case the current working directory is used
6281

6382
By default, the tool:
6483

6584
- analyzes tracked files from `git ls-files`
6685
- writes the report to a temporary path
6786
- prompts you to press Enter before opening the report in your default browser
6887

69-
When standard input is non-interactive (no TTY - e.g. a CI environemnt), the command automatically behaves as if
70-
`--no-open --list-unowned --fail-on-unowned` were specified:
88+
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:
89+
7190
- it never prompts to open a browser
7291
- it prints all unowned file paths to stdout
7392
- it exits non-zero when uncovered files exist
7493

75-
Use `--output` or `--output-dir` for deterministic artifact paths, or `--no-report` to skip writing HTML entirely.
76-
In interactive mode, `--no-report` implies `--list-unowned` so output still stays useful.
94+
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.
95+
96+
## Options
7797

78-
### Options
98+
### Input and Scope
7999

80100
| Option | Description |
81101
| --- | --- |
82-
| `-o, --output <path>` | Output HTML file path |
83-
| `--output-dir <dir>` | Output directory for the generated HTML report |
84102
| `--cwd <dir>` | Run git commands from this directory |
85103
| `--include-untracked` | Include untracked files in the analysis |
104+
| `-g, --glob <pattern>` | Repeatable file filter for report and check scope (default: `**`) |
105+
106+
### Report Output
107+
108+
| Option | Description |
109+
| --- | --- |
110+
| `-o, --output <path>` | Output HTML file path |
111+
| `--output-dir <dir>` | Output directory for the generated HTML report |
86112
| `--no-report` | Skip HTML report generation (implies `--list-unowned`) |
113+
| `--upload` | Upload to zenbin and print a public URL |
114+
115+
### Interaction and Diagnostics
116+
117+
| Option | Description |
118+
| --- | --- |
119+
| `--no-open` | Do not prompt to open the report in your browser |
120+
| `-y, --yes` | Automatically answer yes to interactive prompts |
121+
| `--verbose` | Enable verbose progress output |
122+
| `-h, --help` | Show this help |
123+
| `-v, --version` | Show version |
124+
125+
### Core Coverage Checks
126+
127+
| Option | Description |
128+
| --- | --- |
87129
| `--list-unowned` | Print unowned file paths to stdout |
88130
| `--fail-on-unowned` | Exit non-zero when one or more files are unowned |
131+
132+
### GitHub Validation and Policy Checks
133+
134+
| Option | Description |
135+
| --- | --- |
89136
| `--fail-on-oversized-codeowners` | Exit non-zero when the active `CODEOWNERS` file exceeds GitHub's 3 MB limit |
90-
| `--fail-on-missing-paths` | Exit non-zero when one or more CODEOWNERS paths match no repository files |
137+
| `--fail-on-missing-paths` | Exit non-zero when one or more `CODEOWNERS` paths match no repository files |
91138
| `--validate-github-owners` | Validate `@username` and `@org/team` owners against GitHub and use only validated owners for coverage |
92-
| `--fail-on-invalid-owners` | Exit non-zero when one or more CODEOWNERS rules contain invalid GitHub owners |
93-
| `--fail-on-missing-directory-slashes` | Exit non-zero when directory CODEOWNERS paths do not follow the explicit trailing-slash style |
139+
| `--fail-on-invalid-owners` | Exit non-zero when one or more `CODEOWNERS` rules contain invalid GitHub owners |
140+
| `--fail-on-missing-directory-slashes` | Exit non-zero when directory `CODEOWNERS` paths do not follow the explicit trailing-slash style |
94141
| `--fail-on-location-warnings` | Exit non-zero when extra or ignored `CODEOWNERS` files are found |
95142
| `--fail-on-fragile-coverage` | Exit non-zero when directories have fragile file-by-file coverage |
96-
| `-g, --glob <pattern>` | Repeatable file filter for report/check scope (default: `**`) |
143+
144+
### Team Suggestions
145+
146+
| Option | Description |
147+
| --- | --- |
97148
| `--suggest-teams` | Suggest `@org/team` for uncovered directories |
98149
| `--suggest-window-days <days>` | Git history lookback window for suggestions (default: `365`) |
99150
| `--suggest-top <n>` | Top team suggestions to keep per directory (default: `3`) |
100151
| `--suggest-ignore-teams <list>` | Comma-separated team slugs or `@org/slug` entries to exclude from suggestions |
101152
| `--github-org <org>` | Override GitHub org for team lookups |
102153
| `--github-token <token>` | GitHub token for team lookups (falls back to `GITHUB_TOKEN`, then `GH_TOKEN`) |
103154
| `--github-api-base-url <url>` | GitHub API base URL (default: `https://api.github.com`) |
104-
| `--upload` | Upload to zenbin and print a public URL |
105-
| `-y, --yes` | Automatically answer yes to interactive prompts |
106-
| `--no-open` | Do not prompt to open the report in your browser |
107-
| `--verbose` | Enable verbose progress output |
108-
| `-h, --help` | Show this help |
109-
| `-v, --version` | Show version |
110155

111156
## Examples
112157

113-
Generate report and open it after pressing Enter:
158+
Generate a report and open it after pressing Enter:
114159

115160
```bash
116161
codeowners-audit
117162
```
118163

164+
Write a report to a known path without opening a browser:
165+
166+
```bash
167+
codeowners-audit --output codeowners-gaps-report.html --no-open
168+
```
169+
170+
Run against a repository from another directory:
171+
172+
```bash
173+
codeowners-audit ~/code/my-repo
174+
```
175+
119176
Audit a remote GitHub repository:
120177

121178
```bash
122179
codeowners-audit watson/codeowners-audit
123180
```
124181

125-
Upload report and open the shared URL after pressing Enter:
182+
Upload a report and print the public URL:
126183

127184
```bash
128185
codeowners-audit --upload
129186
```
130187

131-
Write report to repository:
188+
Validate only a subset of files:
132189

133190
```bash
134-
codeowners-audit --output codeowners-gaps-report.html --no-open
191+
codeowners-audit --glob "src/**/*.js" --glob "test/**/*.js"
135192
```
136193

137-
Run against a repository from another directory:
194+
Suggest teams for uncovered directories:
138195

139196
```bash
140-
codeowners-audit ~/code/my-repo
197+
codeowners-audit --suggest-teams
141198
```
142199

143200
## Using in CI
144201

145-
Most CI systems (including GitHub Actions) run in a non-interactive environment (no TTY on stdin).
146-
In non-interactive environments, `codeowners-audit` automatically:
147-
- disables browser prompts (`--no-open`)
148-
- prints unowned files to stdout (`--list-unowned`)
149-
- exits `1` when unowned files exist (`--fail-on-unowned`)
202+
Most CI systems, including GitHub Actions, run in a non-interactive environment. In that mode, `codeowners-audit` automatically:
203+
204+
- disables browser prompts with `--no-open`
205+
- prints unowned files to stdout with `--list-unowned`
206+
- exits `1` when uncovered files exist with `--fail-on-unowned`
150207

151208
Exit code behavior:
152-
- Exit code `0`: all matched files are covered by `CODEOWNERS`, and no enabled validation policy failed.
153-
- Exit code `1`: at least one enforced policy failed. This includes uncovered files and any enabled `--fail-on-*` validation rule described in the [Options](#options) section.
154-
- Exit code `2`: runtime/setup error (for example: not in a Git repository, missing `CODEOWNERS`, invalid arguments).
155209

156-
### Common CI commands
210+
- Exit code `0`: all matched files are covered by `CODEOWNERS`, and no enabled validation policy failed
211+
- Exit code `1`: at least one enforced policy failed, including uncovered files and any enabled `--fail-on-*` validation rule
212+
- Exit code `2`: runtime or setup error, for example not being in a git repository, missing `CODEOWNERS`, or invalid arguments
213+
214+
### Common CI Commands
157215

158216
Validate all tracked files:
159217

@@ -179,64 +237,34 @@ Validate and write reports into an artifact directory:
179237
codeowners-audit --output-dir artifacts
180238
```
181239

182-
Validate only a subset (for example spec files):
240+
Validate only a subset, for example spec files:
183241

184242
```bash
185243
codeowners-audit --glob "**/*.spec.js"
186244
```
187245

188-
Validate multiple subsets in one run (combined as a union):
189-
190-
```bash
191-
codeowners-audit --glob "src/**/*.js" --glob "test/**/*.js"
192-
```
193-
194-
### GitHub Actions example
246+
### GitHub Actions Example
195247

196248
```yaml
197249
- name: Verify CODEOWNERS coverage
198250
run: npx codeowners-audit --no-report
199251
```
200252
201-
## How matching works
253+
## GitHub Compatibility Notes
202254
203-
The report follows practical `CODEOWNERS` resolution behavior:
204-
205-
- A file is considered **owned** if at least one owner is resolved.
206-
- When `--validate-github-owners` is enabled, `@username` and `@org/team` owners only count if GitHub confirms they exist and have write access to the repository.
207-
- The ownership explorer surfaces the resolved owners for each matched file, including email owners.
208-
- Within a single `CODEOWNERS` file, the **last matching rule wins**.
209-
- A pattern line with no owners acts as an ownerless override only when it is the last matching rule for a path, matching GitHub's documented behavior.
210-
- GitHub only considers `CODEOWNERS` at `.github/CODEOWNERS`, `CODEOWNERS`, and `docs/CODEOWNERS`, using the first file found in that order.
211-
- Patterns are always resolved from the repository root, regardless of which supported `CODEOWNERS` location is active.
212-
- Extra `CODEOWNERS` files in supported locations and any `CODEOWNERS` files outside those locations are reported as ignored by GitHub.
213-
- Directory rules match descendant files whether they are written as `/path/to/dir` or `/path/to/dir/`.
214-
- Use `--fail-on-missing-directory-slashes` if you want CI to enforce the explicit `/path/to/dir/` form as a readability and consistency convention.
215-
- GitHub-invalid `CODEOWNERS` syntax is skipped, including negation patterns (`!pattern`), escaped leading `#` patterns such as `\#file`, and bracket expressions such as `[ab]` or `[a-z]`.
255+
- Follows GitHub `CODEOWNERS` discovery order: `.github/CODEOWNERS`, `CODEOWNERS`, then `docs/CODEOWNERS`
256+
- Uses standard last-match-wins behavior, including ownerless overrides when the last matching rule has no owners
257+
- Resolves patterns from the repository root, regardless of which supported `CODEOWNERS` location is active
258+
- Optionally validates `@username` and `@org/team` owners against GitHub with `--validate-github-owners`
259+
- Reports extra or ignored `CODEOWNERS` files, missing paths, fragile coverage, and unsupported syntax that GitHub would not honor
216260

217261
## Requirements
218262

219263
- `git` available on `PATH`
220264

221-
## Upload size note
222-
223-
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.
224-
225-
## Report contents
226-
227-
The generated page includes:
228-
229-
- repository-level ownership metrics and coverage bar
230-
- scoped directory table with coverage bars
231-
- searchable list of unowned files
232-
- ownership explorer for filtering files by resolved CODEOWNERS owner, including `@org/team`, `@username`, and email owners
233-
- active `CODEOWNERS` file and rule count
234-
- warnings for extra or unsupported `CODEOWNERS` files that GitHub will ignore
235-
- warnings for CODEOWNERS patterns that match no repository paths
236-
- warnings for slashless directory entries that do not follow the explicit trailing-slash style
237-
- warnings for directories with fragile coverage (owned through individual file rules only)
265+
## Upload Size Note
238266

239-
The report is self-contained, so it can be opened directly from disk or shared after upload.
267+
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.
240268

241269
## License
242270

0 commit comments

Comments
 (0)