delivery-friction-analyzer 0.21.2 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -131,7 +131,7 @@ Each ranked bottleneck example includes source references, workflow-run conclusi
131
131
 
132
132
  Use `--source sample` for the bundled synthetic tutorial data. Use `--source github` for live repository analysis. Existing live commands that pass `--repo`, `--profile`, or `--limit` without `--source` still run as GitHub analysis, but new users should prefer the explicit source flag.
133
133
 
134
- Use `--dry-run` or `--metadata-only` to validate repository access, profile JSON, output directory writability, and sampled API coverage without writing full report artifacts. The output directory may be created during this check, and a temporary probe file may be written and removed.
134
+ Use `--dry-run` or `--metadata-only` with `--source github` to run a live GitHub coverage probe that validates repository access, profile JSON, output directory writability, and sampled API coverage without writing full report artifacts. The output directory may be created during this check, and a temporary probe file may be written and removed.
135
135
 
136
136
  Use `--no-csv` when you want the Markdown, JSON, source, normalized, metrics, and methodology artifacts without spreadsheet-friendly CSV exports.
137
137
 
@@ -139,7 +139,7 @@ Use `--exclude-pr-class <class>` to remove a configured PR class from downstream
139
139
 
140
140
  Use `--json` when automation needs the full machine-readable completion receipt on stdout.
141
141
 
142
- Use `--interactive` only in a terminal when you want prompts. When combined with `--json`, prompts and progress stay off stdout so the final completion receipt remains parseable JSON.
142
+ Use `--interactive` only in a terminal when you want prompts for live GitHub setup. Enter `?` at supported prompts for contextual help without restarting the flow. When combined with `--json`, prompts and progress stay off stdout so the final completion receipt remains parseable JSON.
143
143
 
144
144
  ## How To Read A Report
145
145
 
@@ -1,14 +1,14 @@
1
1
  # Run Presets
2
2
 
3
- Run presets are optional local JSON files for reusing CLI run settings. They are intended for rerunning the same analysis without re-answering interactive prompts.
3
+ Run presets are optional local JSON files for reusing live GitHub CLI run settings. They are intended for rerunning the same live analysis without re-answering interactive prompts. The bundled `--source sample` tutorial path does not save or load presets.
4
4
 
5
- Repository meaning stays in repository profiles. Put file rules, PR class rules, workflow context, branch or release strategy, and contributor-source declarations in a repository profile. A run preset may only point at a profile and store run inputs or preferences such as the target repository, sample size, output directory, dry-run mode, CSV preference, JSON completion preference, validation-target mode, and requested PR class exclusions.
5
+ Repository meaning stays in repository profiles. Put file rules, PR class rules, workflow context, branch or release strategy, and contributor-source declarations in a repository profile. A run preset may only point at a profile and store live run inputs or preferences such as the target repository, pull request limit, output directory, dry-run coverage-probe mode, CSV preference, JSON completion preference, validation-target mode, and requested PR class exclusions.
6
6
 
7
7
  When a preset supplies `profilePath`, the CLI validates that referenced profile exactly as if it had been passed with `--profile`. Presets do not copy, freeze, or override profile rules; fixing profile validation failures means editing the referenced profile or choosing a different profile path.
8
8
 
9
9
  ## Save A Preset
10
10
 
11
- Interactive setup asks whether to save a local run preset near the end of the prompt flow. If you answer yes, you choose the preset path explicitly. The CLI does not invent a global or cloud-synced preset location.
11
+ Interactive live GitHub setup asks whether to save a local run preset near the end of the prompt flow. If you answer yes, you choose the preset path explicitly. The CLI does not invent a global or cloud-synced preset location.
12
12
 
13
13
  Saving a preset may overwrite an existing regular file at that path, but the path must not be a directory, symbolic link, or other special file.
14
14
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "delivery-friction-analyzer",
3
- "version": "0.21.2",
3
+ "version": "0.22.0",
4
4
  "description": "Local GitHub pull request analytics for delivery friction reports.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/release-log.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ### 2026-06-28 — CLI Command Help Clarity
6
+
7
+ - What changed: CLI help now separates the bundled sample, live GitHub analysis, live coverage probes, output controls, interactive setup, and reusable live-run presets, with mode-specific help for `--source sample --help` and `--source github --help`.
8
+ - Why it matters: First-time users and maintainers can choose the right workflow before running into rejected flag combinations, and interactive setup can explain supported prompts without restarting the flow.
9
+ - Who is affected: Users trying the bundled sample, maintainers running live GitHub analysis or dry-run coverage probes, and contributors reviewing CLI setup behavior.
10
+ - Action needed: None.
11
+ - PR: https://github.com/hannasdev/delivery-friction-analyzer/pull/67
12
+
5
13
  ### 2026-06-27 — First-Run Profile Prompt Clarity
6
14
 
7
15
  - What changed: Interactive GitHub setup now explains starter-profile limitations, gives clearer guidance before adding Conventional Commit PR class rules, and only prints the starter-profile completion reminder when a new profile was created.
@@ -135,30 +135,84 @@ const CSV_ARTIFACT_KEYS = new Set([
135
135
  export const USAGE = `Usage:
136
136
  delivery-friction-analyzer --source sample --out <directory>
137
137
  delivery-friction-analyzer --source github --repo <owner/name> --limit <1-100> --profile <path> --out <directory>
138
- delivery-friction-analyzer --repo <owner/name> --limit <1-100> --profile <path> --out <directory>
139
- delivery-friction-analyzer --repo <owner/name> --limit <1-100> --profile <path> --out <directory> --dry-run
140
138
 
141
- Options:
142
- --source <sample|github> Choose the bundled synthetic sample or live GitHub analysis.
139
+ Workflows:
140
+ Sample tutorial:
141
+ Uses bundled synthetic data. Accepts output controls only.
142
+ delivery-friction-analyzer --source sample --out reports/tutorial
143
+
144
+ Live GitHub analysis:
145
+ Collects repository data from GitHub using a repository profile.
146
+ delivery-friction-analyzer --source github --repo owner/name --limit 30 --profile path/to/profile.json --out reports/owner-name
147
+
148
+ Live GitHub coverage probe:
149
+ --dry-run and --metadata-only validate live GitHub access, profile JSON, output writability, and sampled API coverage without report artifacts.
150
+ delivery-friction-analyzer --source github --repo owner/name --limit 30 --profile path/to/profile.json --out reports/owner-name --dry-run
151
+
152
+ Output controls:
153
+ --out <directory> Output directory for generated artifacts.
154
+ --json Print the machine-readable completion receipt to stdout.
155
+ --no-json Disable JSON completion output.
156
+ --csv Enable curated CSV evidence exports when a preset disabled them.
157
+ --no-csv Suppress curated CSV evidence exports.
158
+
159
+ Help:
160
+ --source sample --help Show sample-mode options.
161
+ --source github --help Show live GitHub, dry-run, interactive, and preset options.
162
+ `;
163
+
164
+ export const SAMPLE_USAGE = `Usage:
165
+ delivery-friction-analyzer --source sample --out <directory>
166
+
167
+ Sample tutorial:
168
+ Uses bundled synthetic data and never calls GitHub.
169
+ Sample mode writes the same report bundle shape as a live analysis for tutorial use.
170
+
171
+ Sample output controls:
172
+ --out <directory> Required output directory for generated sample artifacts.
173
+ --json Print the machine-readable completion receipt to stdout.
174
+ --no-json Disable JSON completion output.
175
+ --csv Enable curated CSV evidence exports.
176
+ --no-csv Suppress curated CSV evidence exports.
177
+
178
+ Live-only flags are not supported with --source sample:
179
+ --repo, --limit, --profile, --dry-run, --metadata-only, --validation-target,
180
+ --interactive, --preset, --save-preset, --exclude-pr-class, --allow-product-repository
181
+ `;
182
+
183
+ export const GITHUB_USAGE = `Usage:
184
+ delivery-friction-analyzer --source github --repo <owner/name> --limit <1-100> --profile <path> --out <directory>
185
+ delivery-friction-analyzer --source github --repo <owner/name> --limit <1-100> --profile <path> --out <directory> --dry-run
186
+ delivery-friction-analyzer --interactive --source github
187
+
188
+ Live GitHub analysis:
143
189
  --repo <owner/name> Target GitHub repository to analyze.
144
190
  --limit <1-100> Latest merged pull request count.
145
191
  --profile <path> Repository profile JSON used for file role classification.
146
192
  --out <directory> Output directory for generated artifacts.
147
- --dry-run Validate inputs and sample GitHub coverage without writing artifacts.
148
- --no-dry-run Disable dry-run mode when a preset enabled it.
193
+
194
+ Live GitHub coverage probes:
195
+ --dry-run Validate live GitHub access, profile JSON, output writability, and sampled API coverage without writing report artifacts.
149
196
  --metadata-only Alias for --dry-run.
197
+ --no-dry-run Disable dry-run mode when a preset enabled it.
198
+
199
+ Live filters and metadata:
150
200
  --validation-target Mark output metadata as an internal validation run; does not bypass target validation.
151
201
  --no-validation-target Disable validation-target mode when a preset enabled it.
152
202
  --allow-product-repository
153
203
  Explicit live-analysis override for intentional self-analysis of this product repository.
154
- --exclude-pr-class <cls> Exclude a PR class from normalized, metrics, report, methodology, and CSV artifacts. Repeat or comma-separate values.
155
- --csv Enable curated CSV evidence exports when a preset disabled them.
156
- --no-csv Suppress curated CSV evidence exports.
204
+ --exclude-pr-class <cls> Exclude a configured PR class from downstream normalized, metrics, report, methodology, and CSV artifacts. Repeat or comma-separate values.
205
+
206
+ Output controls:
157
207
  --json Print the machine-readable completion receipt to stdout.
158
208
  --no-json Disable JSON completion output when a preset enabled it.
159
- --interactive Prompt for missing run options in a terminal.
160
- --preset <path> Load local run settings from a saved preset. Explicit CLI flags override preset values.
161
- --save-preset <path> Save local run settings for non-interactive reruns.
209
+ --csv Enable curated CSV evidence exports when a preset disabled them.
210
+ --no-csv Suppress curated CSV evidence exports.
211
+
212
+ Interactive setup and presets:
213
+ --interactive Prompt for missing live GitHub run options in a terminal; enter ? at supported prompts for contextual help.
214
+ --preset <path> Load reusable live GitHub run settings from a saved preset. Explicit CLI flags override preset values.
215
+ --save-preset <path> Save reusable live GitHub run settings for non-interactive reruns.
162
216
  `;
163
217
 
164
218
  export const SOURCE_SELECTION_GUIDANCE = `Choose what to analyze.
@@ -199,6 +253,13 @@ function explicitCliOptionKeys(argv) {
199
253
  }
200
254
 
201
255
  export function parseAnalyzeGithubArgs(argv) {
256
+ if (hasHelpOption(argv)) {
257
+ const parsed = { help: true };
258
+ const source = sourceForHelp(argv);
259
+ if (source !== undefined) parsed.source = source;
260
+ return attachOptionSource(parsed, "explicitCliOptions", new Set(source === undefined ? [] : ["source"]));
261
+ }
262
+
202
263
  const options = {
203
264
  dryRun: false,
204
265
  isValidationTarget: false,
@@ -209,9 +270,6 @@ export function parseAnalyzeGithubArgs(argv) {
209
270
  const explicitOptions = explicitCliOptionKeys(argv);
210
271
  for (let index = 0; index < argv.length; index += 1) {
211
272
  const arg = argv[index];
212
- if (arg === "--help" || arg === "-h") {
213
- return { help: true };
214
- }
215
273
  if (!arg.startsWith("--")) {
216
274
  throw new Error(`Unexpected argument: ${arg}`);
217
275
  }
@@ -268,6 +326,25 @@ export function parseAnalyzeGithubArgs(argv) {
268
326
  return attachOptionSource(parsed, "explicitCliOptions", explicitOptions);
269
327
  }
270
328
 
329
+ function hasHelpOption(argv) {
330
+ return argv.includes("--help") || argv.includes("-h");
331
+ }
332
+
333
+ function sourceForHelp(argv) {
334
+ for (let index = 0; index < argv.length; index += 1) {
335
+ if (argv[index] !== "--source") continue;
336
+ const source = argv[index + 1];
337
+ if (source === "sample" || source === "github") return source;
338
+ }
339
+ return undefined;
340
+ }
341
+
342
+ function usageForOptions(options) {
343
+ if (options?.source === "sample") return SAMPLE_USAGE;
344
+ if (options?.source === "github") return GITHUB_USAGE;
345
+ return USAGE;
346
+ }
347
+
271
348
  function normalizeExcludedPrClasses(values) {
272
349
  return [...new Set(values
273
350
  .flatMap(value => String(value).split(","))
@@ -537,7 +614,7 @@ function rejectSampleLiveOptions(options) {
537
614
  incompatible.push("--exclude-pr-class");
538
615
  }
539
616
  if (!incompatible.length) return;
540
- throw new Error(`--source sample cannot be combined with live GitHub option(s): ${incompatible.join(", ")}. Use only output options such as --out, --json, --csv, or --no-csv.`);
617
+ throw new Error(`--source sample cannot be combined with live GitHub option(s): ${incompatible.join(", ")}. Allowed sample output controls are --out, --json, --no-json, --csv, and --no-csv. Use --source github for live repository, dry-run, interactive, preset, validation, and PR-class filtering options.`);
541
618
  }
542
619
 
543
620
  function targetInputFromRepositorySlug(repository) {
@@ -590,21 +667,22 @@ function formatChoiceList(choices) {
590
667
  }
591
668
 
592
669
  function formatInteractivePrompt(prompt) {
670
+ const helpSuffix = prompt.help ? " Enter ? for help" : "";
593
671
  const suffix = prompt.defaultValue === undefined
594
672
  ? ""
595
673
  : Array.isArray(prompt.defaultValue)
596
674
  ? (prompt.defaultValue.length ? ` [${prompt.defaultValue.join(",")}]` : "")
597
675
  : ` [${prompt.defaultValue}]`;
598
676
  if (prompt.type === "confirm") {
599
- return `${prompt.message}${prompt.defaultValue ? " [Y/n]" : " [y/N]"} `;
677
+ return `${prompt.message}${helpSuffix}${prompt.defaultValue ? " [Y/n]" : " [y/N]"} `;
600
678
  }
601
679
  if (prompt.type === "multi-select" && prompt.choices?.length) {
602
- return `${prompt.message} (${prompt.choices.map(choiceValue).join(",")})${suffix}: `;
680
+ return `${prompt.message}${helpSuffix} (${prompt.choices.map(choiceValue).join(",")})${suffix}: `;
603
681
  }
604
682
  if (prompt.type === "select" && prompt.choices?.length) {
605
- return `${prompt.message}\n${formatChoiceList(prompt.choices)}\nChoose a number or identifier${suffix}: `;
683
+ return `${prompt.message}${helpSuffix}\n${formatChoiceList(prompt.choices)}\nChoose a number or identifier${suffix}: `;
606
684
  }
607
- return `${prompt.message}${suffix}: `;
685
+ return `${prompt.message}${helpSuffix}${suffix}: `;
608
686
  }
609
687
 
610
688
  function createTerminalPromptAdapter({ input, output }) {
@@ -632,6 +710,16 @@ async function callPromptAdapter(promptAdapter, prompt) {
632
710
  async function askUntilValid(promptAdapter, prompt, { normalize, validate, output }) {
633
711
  for (;;) {
634
712
  const raw = await callPromptAdapter(promptAdapter, prompt);
713
+ if (String(raw ?? "").trim() === "?" && prompt.help) {
714
+ if (typeof promptAdapter.writeHelp === "function") {
715
+ promptAdapter.writeHelp(prompt.help);
716
+ } else if (typeof promptAdapter.writeError === "function") {
717
+ promptAdapter.writeError(prompt.help);
718
+ } else if (output?.write) {
719
+ output.write(`${prompt.help}\n`);
720
+ }
721
+ continue;
722
+ }
635
723
  try {
636
724
  const value = normalize(raw, prompt);
637
725
  await validate(value);
@@ -950,6 +1038,7 @@ async function promptConventionalCommitPrClassPreset(promptAdapter, output, prof
950
1038
  id: "addConventionalCommitPrClasses",
951
1039
  type: "confirm",
952
1040
  message,
1041
+ help: "Optional profile setup: add reusable title rules when Conventional Commit prefixes match this repository. This changes profile classification only, not scoring or GitHub collection.",
953
1042
  defaultValue: false,
954
1043
  }, {
955
1044
  output,
@@ -991,6 +1080,7 @@ async function promptWorkflowField(promptAdapter, output, { id, message, choices
991
1080
  id,
992
1081
  type: "select",
993
1082
  message,
1083
+ help: "Workflow context is configured profile metadata. Choose the closest stable repository practice; it helps report interpretation but is not observed GitHub evidence.",
994
1084
  choices: workflowChoices(choices),
995
1085
  defaultValue,
996
1086
  }, {
@@ -1030,6 +1120,7 @@ async function promptWorkflowProfileUpdate(promptAdapter, output, profile, { isN
1030
1120
  id: "releasePrTitleIncludes",
1031
1121
  type: "text",
1032
1122
  message: `Release PR title includes (blank to skip PR class rule; suggested: ${suggestedReleaseTitle})`,
1123
+ help: "Use this only when release PR titles follow a stable phrase. Blank skips the generated release PR class rule.",
1033
1124
  }, {
1034
1125
  output,
1035
1126
  normalize: normalizeTextAnswer,
@@ -1044,6 +1135,7 @@ async function promptWorkflowProfileUpdate(promptAdapter, output, profile, { isN
1044
1135
  id: "updateReleasePrClass",
1045
1136
  type: "confirm",
1046
1137
  message: "Update existing title-based release PR class rule",
1138
+ help: "Updates the existing title-based release PR class rule in the repository profile. Existing unrelated profile rules are kept.",
1047
1139
  defaultValue: false,
1048
1140
  }, {
1049
1141
  output,
@@ -1065,6 +1157,7 @@ async function promptWorkflowProfileUpdate(promptAdapter, output, profile, { isN
1065
1157
  id: "addReleasePrClass",
1066
1158
  type: "confirm",
1067
1159
  message: "Add release PR class rule from title convention",
1160
+ help: "Adds a title-based release PR class rule to the repository profile when that convention matches this repository.",
1068
1161
  defaultValue: true,
1069
1162
  }, {
1070
1163
  output,
@@ -1097,6 +1190,7 @@ async function maybeConfigureInteractiveProfile(promptAdapter, output, profileSt
1097
1190
  id: "createProfile",
1098
1191
  type: "confirm",
1099
1192
  message: `Create repository profile at this path. ${STARTER_PROFILE_PROMPT_COPY}`,
1193
+ help: "A repository profile is required for live GitHub analysis. Interactive setup can create a starter profile at the path you entered, then you can review or refine it before a full run.",
1100
1194
  defaultValue: true,
1101
1195
  }, {
1102
1196
  output,
@@ -1111,6 +1205,7 @@ async function maybeConfigureInteractiveProfile(promptAdapter, output, profileSt
1111
1205
  id: "configureWorkflow",
1112
1206
  type: "confirm",
1113
1207
  message: "Configure repository workflow profile fields",
1208
+ help: "Workflow profile fields are configured context for report interpretation. Choose yes to review merge, release, and branch strategy prompts; choose no to keep the existing profile values.",
1114
1209
  defaultValue: false,
1115
1210
  }, {
1116
1211
  output,
@@ -1220,6 +1315,7 @@ export async function collectInteractiveAnalyzeGithubOptions(options, {
1220
1315
  id: "repository",
1221
1316
  type: "text",
1222
1317
  message: "Target GitHub repository",
1318
+ help: "Enter the live GitHub repository as owner/name. Sample mode is not part of interactive setup; use --source sample --out <directory> for the bundled tutorial.",
1223
1319
  }, {
1224
1320
  output,
1225
1321
  normalize: normalizeTextAnswer,
@@ -1232,6 +1328,7 @@ export async function collectInteractiveAnalyzeGithubOptions(options, {
1232
1328
  id: "limit",
1233
1329
  type: "integer",
1234
1330
  message: "Latest merged pull request count",
1331
+ help: "Choose how many recent merged pull requests to collect from live GitHub. Smaller limits are faster; larger limits give reports more evidence.",
1235
1332
  defaultValue: 30,
1236
1333
  }, {
1237
1334
  output,
@@ -1245,6 +1342,7 @@ export async function collectInteractiveAnalyzeGithubOptions(options, {
1245
1342
  id: "profilePath",
1246
1343
  type: "path",
1247
1344
  message: "Repository profile path",
1345
+ help: "Enter a local repository-profile.v1 JSON path. If the path does not exist, interactive setup can create a starter profile there.",
1248
1346
  });
1249
1347
  profileState = prompted;
1250
1348
  } else {
@@ -1284,6 +1382,7 @@ export async function collectInteractiveAnalyzeGithubOptions(options, {
1284
1382
  id: "outDir",
1285
1383
  type: "path",
1286
1384
  message: "Output directory",
1385
+ help: "Choose where generated artifacts or dry-run probe files should be written. Interactive setup may create the directory and check that it is writable.",
1287
1386
  defaultValue: defaultOutDirForRepository(resolved.repository),
1288
1387
  }, {
1289
1388
  output,
@@ -1299,7 +1398,8 @@ export async function collectInteractiveAnalyzeGithubOptions(options, {
1299
1398
  resolved.dryRun = await askUntilValid(adapter, {
1300
1399
  id: "dryRun",
1301
1400
  type: "confirm",
1302
- message: "Run metadata-only dry run",
1401
+ message: "Run live GitHub metadata-only coverage probe",
1402
+ help: "A dry run is a live GitHub coverage probe. It validates access, profile JSON, output writability, and sampled API coverage without writing report artifacts.",
1303
1403
  defaultValue: false,
1304
1404
  }, {
1305
1405
  output,
@@ -1314,6 +1414,7 @@ export async function collectInteractiveAnalyzeGithubOptions(options, {
1314
1414
  id: "csv",
1315
1415
  type: "confirm",
1316
1416
  message: "Write CSV evidence files",
1417
+ help: "CSV evidence files are optional spreadsheet-friendly artifacts for full report runs. They are not written during dry-run coverage probes.",
1317
1418
  defaultValue: true,
1318
1419
  }, {
1319
1420
  output,
@@ -1328,6 +1429,7 @@ export async function collectInteractiveAnalyzeGithubOptions(options, {
1328
1429
  id: "json",
1329
1430
  type: "confirm",
1330
1431
  message: "Print completion as JSON",
1432
+ help: "JSON completion writes the final machine-readable receipt to stdout. Prompts and progress stay on stderr so automation can parse stdout.",
1331
1433
  defaultValue: false,
1332
1434
  }, {
1333
1435
  output,
@@ -1344,6 +1446,7 @@ export async function collectInteractiveAnalyzeGithubOptions(options, {
1344
1446
  id: "excludedPrClasses",
1345
1447
  type: "multi-select",
1346
1448
  message: "Exclude PR classes (comma-separated, blank for none)",
1449
+ help: "Optionally exclude configured PR classes from downstream normalized data, metrics, reports, methodology, and CSV artifacts. The source bundle still preserves the full collected sample.",
1347
1450
  choices: availablePrClasses,
1348
1451
  defaultValue: [],
1349
1452
  }, {
@@ -1362,6 +1465,7 @@ export async function collectInteractiveAnalyzeGithubOptions(options, {
1362
1465
  id: "saveRunPreset",
1363
1466
  type: "confirm",
1364
1467
  message: "Save local run preset for non-interactive reruns",
1468
+ help: "Run presets store reusable live GitHub run settings such as repo, profile, limit, output, dry-run preference, JSON/CSV preference, and requested PR class exclusions. Sample mode does not save or load presets.",
1365
1469
  defaultValue: false,
1366
1470
  }, {
1367
1471
  output,
@@ -1373,6 +1477,7 @@ export async function collectInteractiveAnalyzeGithubOptions(options, {
1373
1477
  id: "runPresetPath",
1374
1478
  type: "path",
1375
1479
  message: "Run preset path",
1480
+ help: "Choose a local JSON file path for reusable live GitHub run settings. The path must be a regular file path, not a directory or symlink.",
1376
1481
  }, {
1377
1482
  output,
1378
1483
  normalize: normalizeTextAnswer,
@@ -1938,7 +2043,7 @@ export async function runAnalyzeGithubCli(argv, {
1938
2043
  try {
1939
2044
  const parsedOptions = parseAnalyzeGithubArgs(argv);
1940
2045
  if (parsedOptions.help) {
1941
- stdout.write(USAGE);
2046
+ stdout.write(usageForOptions(parsedOptions));
1942
2047
  return null;
1943
2048
  }
1944
2049
  if (parsedOptions.source !== undefined) {