@kaynooo/cli-doctor 0.5.2 → 0.6.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
@@ -38,10 +38,10 @@ Each bin completes itself through `<bin> __complete`. fish gets a file per bin (
38
38
  ## cli stats
39
39
 
40
40
  ```sh
41
- cli stats [--since 7d] [--json] # runs per bin, failures, and the options usage errors did not know
41
+ cli stats [--since 7d] [--json] # runs per bin and per command, failures (exit 1) apart from usage errors (exit 2), and the options usage errors did not know
42
42
  ```
43
43
 
44
- Every bin records each run in `~/.local/state/kaynooo-cli/usage.jsonl`: the bin, its command, the flag names it saw (never values or arguments), the exit code and, on a usage error, the unknown option. `KAYNOOO_CLI_NO_USAGE=1` turns it off; `guard` never records.
44
+ Every bin records each run in `~/.local/state/kaynooo-cli/usage.jsonl`: the bin, its command, the flag names it saw (never values or arguments), the exit code and, on a usage error, the unknown option (never its message). `KAYNOOO_CLI_NO_USAGE=1` turns it off; `guard` never records.
45
45
 
46
46
  ## cli list
47
47
 
package/dist/cli-bin.js CHANGED
@@ -808,26 +808,38 @@ async function readUsage(path = usagePath(), since = 0) {
808
808
  }
809
809
  });
810
810
  }
811
+ function tally(counts, code) {
812
+ counts.runs++;
813
+ counts.failed += code === 0 || code === 2 ? 0 : 1;
814
+ counts.usageErrors += code === 2 ? 1 : 0;
815
+ }
811
816
  function summarizeUsage(entries) {
812
817
  const bins = new Map;
813
- const errors = new Map;
818
+ const commands = new Map;
819
+ const unknowns = new Map;
814
820
  for (const entry of entries) {
815
821
  const bin = bins.get(entry.bin) ?? { runs: 0, failed: 0, usageErrors: 0 };
816
- bin.runs++;
817
- bin.failed += entry.code === 0 ? 0 : 1;
818
- bin.usageErrors += entry.code === 2 ? 1 : 0;
822
+ tally(bin, entry.code);
819
823
  bins.set(entry.bin, bin);
820
- if (entry.code === 2 && entry.unknown !== undefined) {
824
+ if (entry.command !== undefined) {
825
+ const command = commands.get(`${entry.bin} ${entry.command}`) ?? { bin: entry.bin, command: entry.command, runs: 0, failed: 0, usageErrors: 0 };
826
+ tally(command, entry.code);
827
+ commands.set(`${entry.bin} ${entry.command}`, command);
828
+ }
829
+ if (entry.code !== 2)
830
+ continue;
831
+ if (entry.unknown !== undefined) {
821
832
  const key = `${entry.bin} ${entry.command ?? ""} ${entry.unknown}`;
822
- const error = errors.get(key) ?? { bin: entry.bin, ...entry.command === undefined ? {} : { command: entry.command }, unknown: entry.unknown, count: 0 };
823
- error.count++;
824
- errors.set(key, error);
833
+ const unknown = unknowns.get(key) ?? { bin: entry.bin, ...entry.command === undefined ? {} : { command: entry.command }, unknown: entry.unknown, count: 0 };
834
+ unknown.count++;
835
+ unknowns.set(key, unknown);
825
836
  }
826
837
  }
827
838
  return {
828
839
  runs: entries.length,
829
840
  bins: [...bins].map(([bin, counts]) => ({ bin, ...counts })).toSorted((a, b) => b.runs - a.runs),
830
- usageErrors: [...errors.values()].toSorted((a, b) => b.count - a.count)
841
+ commands: [...commands.values()].toSorted((a, b) => b.runs - a.runs),
842
+ usageErrors: [...unknowns.values()].toSorted((a, b) => b.count - a.count)
831
843
  };
832
844
  }
833
845
 
@@ -931,7 +943,7 @@ function reportThrown(prefix, error, redact = (text) => text, json = false) {
931
943
  const help = error instanceof UsageError ? `run ${prefix} --help for its options` : undefined;
932
944
  const named = error instanceof Error && !(error instanceof Exit) && error.name !== "Error" ? `${error.name}: ${error.message}` : undefined;
933
945
  const cause = error instanceof Error && error.cause instanceof Error ? redact(error.cause.message) : undefined;
934
- if (error instanceof UsageError)
946
+ if (error instanceof Exit && error.code === 2)
935
947
  noteUsageError(error.message);
936
948
  const report = json ? printJsonError : (message, hint, causeText) => printError(prefix, message, hint, causeText);
937
949
  report(redact(named ?? (error instanceof Error ? error.message : String(error))), error instanceof Exit ? error.hint ?? help : undefined, cause);
@@ -1440,11 +1452,11 @@ async function completions(args, host = hostHere()) {
1440
1452
  }
1441
1453
  var STATS_USAGE = `cli stats [--since 7d] [--json]: how often each bin ran, and the usage errors by the option it did not know
1442
1454
 
1443
- Every bin records each run in ~/.local/state/kaynooo-cli/usage.jsonl (or $XDG_STATE_HOME): the bin, its command, the names of the flags it saw (never a value or an argument), the exit code and, on a usage error, the unknown option. Set KAYNOOO_CLI_NO_USAGE=1 to stop recording; \`guard\` never records.
1455
+ Every bin records each run in ~/.local/state/kaynooo-cli/usage.jsonl (or $XDG_STATE_HOME): the bin, its command, the names of the flags it saw (never a value or an argument), the exit code and and, on a usage error, the unknown option (never the message, which carries the values it refused). failed counts exits other than 0 and 2, usage errors are exit 2 (misuse, or a check that could not be made). Set KAYNOOO_CLI_NO_USAGE=1 to stop recording; \`guard\` never records.
1444
1456
  Exits 0 when it printed the summary, 2 on a usage error.`;
1445
1457
  var STATS_OPTIONS = {
1446
1458
  since: { type: "string", description: "only the runs this recent (7d, 12h)" },
1447
- json: jsonOption("{runs, bins: [{bin, runs, failed, usageErrors}], usageErrors: [{bin, command?, unknown, count}]}")
1459
+ json: jsonOption("{runs, bins: [{bin, runs, failed, usageErrors}], commands: [{bin, command, runs, failed, usageErrors}], usageErrors: [{bin, command?, unknown, count}]}")
1448
1460
  };
1449
1461
  async function stats(args, path = usagePath()) {
1450
1462
  const { values } = parse(args, STATS_USAGE, STATS_OPTIONS, { positionals: [], examples: ["cli stats", ["cli stats --since 7d", "the last week"]] });
@@ -1461,6 +1473,11 @@ async function stats(args, path = usagePath()) {
1461
1473
  console.log(`${summary.runs} runs
1462
1474
 
1463
1475
  ${table(summary.bins.map((each) => [each.bin, String(each.runs), `${each.failed} failed`, `${each.usageErrors} usage errors`]))}`);
1476
+ const busy = summary.commands.filter((each) => each.failed + each.usageErrors > 0).toSorted((a, b) => b.failed + b.usageErrors - (a.failed + a.usageErrors)).slice(0, 15);
1477
+ if (busy.length > 0)
1478
+ console.log(`
1479
+ commands with failures or usage errors
1480
+ ${table(busy.map((each) => [`${each.bin} ${each.command}`, String(each.runs), `${each.failed} failed`, `${each.usageErrors} usage errors`]))}`);
1464
1481
  if (summary.usageErrors.length > 0)
1465
1482
  console.log(`
1466
1483
  unknown options
package/dist/cli.js CHANGED
@@ -808,26 +808,38 @@ async function readUsage(path = usagePath(), since = 0) {
808
808
  }
809
809
  });
810
810
  }
811
+ function tally(counts, code) {
812
+ counts.runs++;
813
+ counts.failed += code === 0 || code === 2 ? 0 : 1;
814
+ counts.usageErrors += code === 2 ? 1 : 0;
815
+ }
811
816
  function summarizeUsage(entries) {
812
817
  const bins = new Map;
813
- const errors = new Map;
818
+ const commands = new Map;
819
+ const unknowns = new Map;
814
820
  for (const entry of entries) {
815
821
  const bin = bins.get(entry.bin) ?? { runs: 0, failed: 0, usageErrors: 0 };
816
- bin.runs++;
817
- bin.failed += entry.code === 0 ? 0 : 1;
818
- bin.usageErrors += entry.code === 2 ? 1 : 0;
822
+ tally(bin, entry.code);
819
823
  bins.set(entry.bin, bin);
820
- if (entry.code === 2 && entry.unknown !== undefined) {
824
+ if (entry.command !== undefined) {
825
+ const command = commands.get(`${entry.bin} ${entry.command}`) ?? { bin: entry.bin, command: entry.command, runs: 0, failed: 0, usageErrors: 0 };
826
+ tally(command, entry.code);
827
+ commands.set(`${entry.bin} ${entry.command}`, command);
828
+ }
829
+ if (entry.code !== 2)
830
+ continue;
831
+ if (entry.unknown !== undefined) {
821
832
  const key = `${entry.bin} ${entry.command ?? ""} ${entry.unknown}`;
822
- const error = errors.get(key) ?? { bin: entry.bin, ...entry.command === undefined ? {} : { command: entry.command }, unknown: entry.unknown, count: 0 };
823
- error.count++;
824
- errors.set(key, error);
833
+ const unknown = unknowns.get(key) ?? { bin: entry.bin, ...entry.command === undefined ? {} : { command: entry.command }, unknown: entry.unknown, count: 0 };
834
+ unknown.count++;
835
+ unknowns.set(key, unknown);
825
836
  }
826
837
  }
827
838
  return {
828
839
  runs: entries.length,
829
840
  bins: [...bins].map(([bin, counts]) => ({ bin, ...counts })).toSorted((a, b) => b.runs - a.runs),
830
- usageErrors: [...errors.values()].toSorted((a, b) => b.count - a.count)
841
+ commands: [...commands.values()].toSorted((a, b) => b.runs - a.runs),
842
+ usageErrors: [...unknowns.values()].toSorted((a, b) => b.count - a.count)
831
843
  };
832
844
  }
833
845
 
@@ -931,7 +943,7 @@ function reportThrown(prefix, error, redact = (text) => text, json = false) {
931
943
  const help = error instanceof UsageError ? `run ${prefix} --help for its options` : undefined;
932
944
  const named = error instanceof Error && !(error instanceof Exit) && error.name !== "Error" ? `${error.name}: ${error.message}` : undefined;
933
945
  const cause = error instanceof Error && error.cause instanceof Error ? redact(error.cause.message) : undefined;
934
- if (error instanceof UsageError)
946
+ if (error instanceof Exit && error.code === 2)
935
947
  noteUsageError(error.message);
936
948
  const report = json ? printJsonError : (message, hint, causeText) => printError(prefix, message, hint, causeText);
937
949
  report(redact(named ?? (error instanceof Error ? error.message : String(error))), error instanceof Exit ? error.hint ?? help : undefined, cause);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kaynooo/cli-doctor",
3
3
  "type": "module",
4
- "version": "0.5.2",
4
+ "version": "0.6.0",
5
5
  "description": "doctor: checks the @kaynooo/cli-* install of a host: each bin's version against the registry, tea's login to Forgejo, the Claude Code hooks and the Bun floor; cli list: every bin in one line, read from its own help.",
6
6
  "author": "Kaynooo <contact@kaynooo.fr>",
7
7
  "license": "MIT",
@@ -36,6 +36,6 @@
36
36
  "doctor": "$npm_execpath src/cli.ts"
37
37
  },
38
38
  "devDependencies": {
39
- "@kaynooo/cli-kit": "0.21.0"
39
+ "@kaynooo/cli-kit": "0.21.1"
40
40
  }
41
41
  }