@kaynooo/cli-out 0.7.0 → 0.7.1

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.
Files changed (2) hide show
  1. package/dist/cli.js +211 -153
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -2,11 +2,10 @@
2
2
  // @bun
3
3
 
4
4
  // src/cli.ts
5
- import process11 from "process";
5
+ import process13 from "process";
6
6
 
7
7
  // ../kit/src/args.ts
8
- import { fstatSync } from "fs";
9
- import process3 from "process";
8
+ import process4 from "process";
10
9
  import { parseArgs } from "util";
11
10
 
12
11
  // ../kit/src/format.ts
@@ -344,6 +343,55 @@ function printJson(value) {
344
343
  console.log(JSON.stringify(value, undefined, 2));
345
344
  }
346
345
 
346
+ // ../kit/src/help.ts
347
+ import process3 from "process";
348
+ var OPTIONAL = /\[[^\]]+\]/g;
349
+ var USAGE_PREFIX = /^usage:\s*/i;
350
+ var FULL_STOP = /\.$/;
351
+ function usageLine(usage, colors = paint(process3.stdout)) {
352
+ return `${colors.bold("Usage:")} ${usage.replace(USAGE_PREFIX, "").replaceAll(OPTIONAL, (part) => colors.dim(part))}`;
353
+ }
354
+ function helpText(usage, options, colors = paint(process3.stdout), { examples = [], replaces } = {}) {
355
+ return [usageLine(usage, colors), ...replacesRows(replaces, colors), "", colors.bold("Options:"), ...optionRows(options, colors), ...exampleRows(examples, colors)].join(`
356
+ `);
357
+ }
358
+ function replacesRows(replaces, colors = paint(process3.stdout)) {
359
+ return replaces === undefined ? [] : ["", `${colors.bold("Instead of:")} ${replaces}`];
360
+ }
361
+ function wantsHelpJson(env = process3.env) {
362
+ return env.KIT_HELP === "json";
363
+ }
364
+ function description(usage, { examples = [], replaces } = {}) {
365
+ const lines = usage.replace(USAGE_PREFIX, "").split(`
366
+ `);
367
+ const first = lines[0];
368
+ const colon = first.indexOf(": ");
369
+ const prose = lines[lines.indexOf("") + 1] ?? "";
370
+ const fallback = lines.includes("") ? `${prose.charAt(0).toLowerCase()}${prose.slice(1)}`.replace(FULL_STOP, "") : "";
371
+ return {
372
+ synopsis: colon === -1 ? first : first.slice(0, colon),
373
+ summary: colon === -1 ? fallback : first.slice(colon + 2),
374
+ ...replaces === undefined ? {} : { replaces },
375
+ examples: examples.map((example) => typeof example === "string" ? { line: example } : { line: example[0], note: example[1] })
376
+ };
377
+ }
378
+ function exampleRows(examples, colors = paint(process3.stdout)) {
379
+ if (examples.length === 0)
380
+ return [];
381
+ return ["", colors.bold("Examples:"), ...examples.map((example) => typeof example === "string" ? ` ${example}` : ` ${example[0]} ${colors.dim(`# ${example[1]}`)}`)];
382
+ }
383
+ function optionRows(options, colors = paint(process3.stdout)) {
384
+ const rows = Object.entries(options).map(([name, option]) => {
385
+ const short = option.short === undefined ? " " : `${colors.cyan(`-${option.short}`)}, `;
386
+ const named = option.choices === undefined ? "<value>" : `<${option.choices.join("|")}>`;
387
+ const placeholder = option.optional === undefined ? named : `[${named}]`;
388
+ const value = option.type === "string" ? ` ${colors.dim(placeholder)}` : "";
389
+ return { flag: `${short}${colors.cyan(`--${name}`)}${value}`, width: `-x, --${name}`.length + (option.type === "string" ? placeholder.length + 1 : 0), description: option.description ?? "" };
390
+ });
391
+ const width = Math.max(0, ...rows.map((row) => row.width));
392
+ return rows.map((row) => row.description === "" ? ` ${row.flag}` : ` ${row.flag}${" ".repeat(width - row.width)} ${colors.dim(row.description)}`);
393
+ }
394
+
347
395
  // ../kit/src/text.ts
348
396
  var ANSI = new RegExp(`${String.fromCharCode(27)}\\[[\\d;?]*[a-z]`, "gi");
349
397
  function stripAnsi(text) {
@@ -366,8 +414,35 @@ function closest(name, names) {
366
414
  const [best] = names.map((known) => ({ known, far: distance(name, known) })).sort((a, b) => a.far - b.far);
367
415
  return best !== undefined && best.far <= (name.length < 4 ? 1 : 2) ? best.known : undefined;
368
416
  }
417
+ // ../kit/src/input.ts
418
+ import { fstatSync } from "fs";
419
+ var WHOLE = /^\d+$/;
420
+ function wholeNumber(value, name, fallback, min = 1) {
421
+ if (value === undefined)
422
+ return fallback;
423
+ const number = Number(value);
424
+ if (!WHOLE.test(value) || !Number.isSafeInteger(number) || number < min)
425
+ badUsage(`${name.startsWith("<") ? name : `--${name}`} takes a whole number from ${min}, not ${value}`);
426
+ return number;
427
+ }
428
+ var DURATION = /^(\d+(?:\.\d+)?)(ms|[smhd])?$/;
429
+ var UNIT_MS = { ms: 1, s: 1000, m: 60000, h: 3600000, d: 86400000 };
430
+ function duration(value, name, fallback, unit = "s") {
431
+ if (value === undefined)
432
+ return fallback;
433
+ const match = DURATION.exec(value.trim());
434
+ const ms = match === null ? 0 : Number(match[1]) * UNIT_MS[match[2] ?? unit];
435
+ if (ms < 1)
436
+ badUsage(`--${name} takes a duration such as 30s, 5m, 1h or 7d, not ${value}`);
437
+ return ms;
438
+ }
439
+ function isStdinPiped() {
440
+ const stat = fstatSync(0);
441
+ return stat.isFIFO() || stat.isFile();
442
+ }
369
443
 
370
444
  // ../kit/src/args.ts
445
+ var DASHES = /^-+/;
371
446
  function jsonOption(holds) {
372
447
  return { type: "boolean", description: holds === undefined ? "print JSON" : `print JSON: ${holds}` };
373
448
  }
@@ -411,58 +486,11 @@ class Completing {
411
486
  }
412
487
  }
413
488
  var completion = { active: false };
414
- var OPTIONAL = /\[[^\]]+\]/g;
415
- var USAGE_PREFIX = /^usage:\s*/i;
416
- var FULL_STOP = /\.$/;
417
- var DASHES = /^-+/;
418
- function usageLine(usage, colors = paint(process3.stdout)) {
419
- return `${colors.bold("Usage:")} ${usage.replace(USAGE_PREFIX, "").replaceAll(OPTIONAL, (part) => colors.dim(part))}`;
420
- }
421
- function helpText(usage, options, colors = paint(process3.stdout), { examples = [], replaces } = {}) {
422
- return [usageLine(usage, colors), ...replacesRows(replaces, colors), "", colors.bold("Options:"), ...optionRows(options, colors), ...exampleRows(examples, colors)].join(`
423
- `);
424
- }
425
- function replacesRows(replaces, colors = paint(process3.stdout)) {
426
- return replaces === undefined ? [] : ["", `${colors.bold("Instead of:")} ${replaces}`];
427
- }
428
- function wantsHelpJson(env = process3.env) {
429
- return env.KIT_HELP === "json";
430
- }
431
- function description(usage, { examples = [], replaces } = {}) {
432
- const lines = usage.replace(USAGE_PREFIX, "").split(`
433
- `);
434
- const first = lines[0];
435
- const colon = first.indexOf(": ");
436
- const prose = lines[lines.indexOf("") + 1] ?? "";
437
- const fallback = lines.includes("") ? `${prose.charAt(0).toLowerCase()}${prose.slice(1)}`.replace(FULL_STOP, "") : "";
438
- return {
439
- synopsis: colon === -1 ? first : first.slice(0, colon),
440
- summary: colon === -1 ? fallback : first.slice(colon + 2),
441
- ...replaces === undefined ? {} : { replaces },
442
- examples: examples.map((example) => typeof example === "string" ? { line: example } : { line: example[0], note: example[1] })
443
- };
444
- }
445
- function exampleRows(examples, colors = paint(process3.stdout)) {
446
- if (examples.length === 0)
447
- return [];
448
- return ["", colors.bold("Examples:"), ...examples.map((example) => typeof example === "string" ? ` ${example}` : ` ${example[0]} ${colors.dim(`# ${example[1]}`)}`)];
449
- }
450
- function optionRows(options, colors = paint(process3.stdout)) {
451
- const rows = Object.entries(options).map(([name, option]) => {
452
- const short = option.short === undefined ? " " : `${colors.cyan(`-${option.short}`)}, `;
453
- const named = option.choices === undefined ? "<value>" : `<${option.choices.join("|")}>`;
454
- const placeholder = option.optional === undefined ? named : `[${named}]`;
455
- const value = option.type === "string" ? ` ${colors.dim(placeholder)}` : "";
456
- return { flag: `${short}${colors.cyan(`--${name}`)}${value}`, width: `-x, --${name}`.length + (option.type === "string" ? placeholder.length + 1 : 0), description: option.description ?? "" };
457
- });
458
- const width = Math.max(0, ...rows.map((row) => row.width));
459
- return rows.map((row) => row.description === "" ? ` ${row.flag}` : ` ${row.flag}${" ".repeat(width - row.width)} ${colors.dim(row.description)}`);
460
- }
461
489
  var OUTPUT_OPTIONS = {
462
490
  color: { type: "string", description: "auto (on a terminal alone), always or never" },
463
491
  plain: { type: "boolean", description: "plain text, no colour or spinner: --color never" }
464
492
  };
465
- function applyOutput(color, plain, env = process3.env) {
493
+ function applyOutput(color, plain, env = process4.env) {
466
494
  const when = plain === true ? "never" : color ?? "auto";
467
495
  if (when === "auto")
468
496
  return;
@@ -619,33 +647,9 @@ function nearestOption(message, options, allowNegative) {
619
647
  const meant = closest(word, known.map((flag) => flag.replace(DASHES, "")));
620
648
  return meant === undefined ? undefined : `did you mean ${known.find((flag) => flag.replace(DASHES, "") === meant)}?`;
621
649
  }
622
- var WHOLE = /^\d+$/;
623
- function wholeNumber(value, name, fallback, min = 1) {
624
- if (value === undefined)
625
- return fallback;
626
- const number = Number(value);
627
- if (!WHOLE.test(value) || !Number.isSafeInteger(number) || number < min)
628
- badUsage(`${name.startsWith("<") ? name : `--${name}`} takes a whole number from ${min}, not ${value}`);
629
- return number;
630
- }
631
- var DURATION = /^(\d+(?:\.\d+)?)(ms|[smhd])?$/;
632
- var UNIT_MS = { ms: 1, s: 1000, m: 60000, h: 3600000, d: 86400000 };
633
- function duration(value, name, fallback, unit = "s") {
634
- if (value === undefined)
635
- return fallback;
636
- const match = DURATION.exec(value.trim());
637
- const ms = match === null ? 0 : Number(match[1]) * UNIT_MS[match[2] ?? unit];
638
- if (ms < 1)
639
- badUsage(`--${name} takes a duration such as 30s, 5m, 1h or 7d, not ${value}`);
640
- return ms;
641
- }
642
- function isStdinPiped() {
643
- const stat = fstatSync(0);
644
- return stat.isFIFO() || stat.isFile();
645
- }
646
650
  // ../kit/src/process.ts
647
651
  import { constants } from "os";
648
- import process4 from "process";
652
+ import process5 from "process";
649
653
  var KILL_GRACE_MS = 2000;
650
654
  var SIGNALS = ["SIGINT", "SIGTERM", "SIGHUP"];
651
655
  function exitCodeOf(code, signal) {
@@ -667,7 +671,7 @@ function holdSignals(cleanup) {
667
671
  },
668
672
  release: () => {
669
673
  for (const signal of SIGNALS)
670
- process4.off(signal, onSignal);
674
+ process5.off(signal, onSignal);
671
675
  }
672
676
  };
673
677
  function onSignal(signal) {
@@ -680,10 +684,10 @@ function holdSignals(cleanup) {
680
684
  return;
681
685
  held.release();
682
686
  cleanup(signal);
683
- process4.kill(process4.pid, signal);
687
+ process5.kill(process5.pid, signal);
684
688
  }
685
689
  for (const signal of SIGNALS)
686
- process4.on(signal, onSignal);
690
+ process5.on(signal, onSignal);
687
691
  return held;
688
692
  }
689
693
  async function runCommand(argv, { cwd, env, stdin = "ignore", timeoutMs, signal, maxBytes = Infinity, onChunk, onStart } = {}) {
@@ -697,7 +701,7 @@ async function runCommand(argv, { cwd, env, stdin = "ignore", timeoutMs, signal,
697
701
  return;
698
702
  try {
699
703
  if (grouped)
700
- process4.kill(-proc.pid, killing);
704
+ process5.kill(-proc.pid, killing);
701
705
  else
702
706
  proc.kill(killing);
703
707
  } catch {}
@@ -771,15 +775,114 @@ var ESCAPE_CODE = new RegExp(`${ESC}(?:\\[[\\x30-\\x3F]*[\\x20-\\x2F]*[\\x40-\\x
771
775
  var RESET_STYLE = `${ESC}[0m`;
772
776
  var CLOSE_LINK = `${ESC}]8;;${ESC}\\`;
773
777
  // ../kit/src/cli.ts
774
- import process5 from "process";
778
+ import process8 from "process";
779
+
780
+ // ../kit/src/usage.ts
781
+ import { appendFileSync, mkdirSync } from "fs";
782
+ import { homedir as homedir2 } from "os";
783
+ import { dirname, isAbsolute, join as join2 } from "path";
784
+ import process7 from "process";
785
+
786
+ // ../kit/src/logs.ts
787
+ import { lstatSync, openSync } from "fs";
788
+ import { mkdir, mkdtemp, readdir, rm, stat } from "fs/promises";
789
+ import { homedir, tmpdir } from "os";
790
+ import { join } from "path";
791
+ import process6 from "process";
792
+ var DAY_MS = 24 * 60 * 60 * 1000;
793
+ var CLI_FOLDER = "kaynooo-cli";
794
+ function isPrivateDirectory(path) {
795
+ try {
796
+ const info = lstatSync(path, { throwIfNoEntry: false });
797
+ return info !== undefined && info.isDirectory() && info.uid === (process6.getuid?.() ?? info.uid) && (info.mode & 63) === 0;
798
+ } catch {
799
+ return false;
800
+ }
801
+ }
802
+ async function privateLogDirectory(name, env = process6.env) {
803
+ const runtime = env.XDG_RUNTIME_DIR;
804
+ const base = runtime === undefined || runtime === "" ? join(homedir(), ".cache", CLI_FOLDER) : join(runtime, CLI_FOLDER);
805
+ const path = join(base, name);
806
+ try {
807
+ await mkdir(path, { recursive: true, mode: 448 });
808
+ if (isPrivateDirectory(path))
809
+ return path;
810
+ } catch {}
811
+ return mkdtemp(join(tmpdir(), `${name.replaceAll("/", "-")}-`));
812
+ }
813
+ async function sweepLogs(dir, maxAgeMs = DAY_MS, now = Date.now()) {
814
+ let names;
815
+ try {
816
+ names = await readdir(dir);
817
+ } catch {
818
+ return;
819
+ }
820
+ for (const name of names) {
821
+ const path = join(dir, name);
822
+ try {
823
+ const info = await stat(path);
824
+ if (info.isDirectory())
825
+ await sweepLogs(path, maxAgeMs, now);
826
+ if (now - info.mtimeMs > maxAgeMs)
827
+ await rm(path, { force: true, recursive: info.isDirectory() });
828
+ } catch {
829
+ continue;
830
+ }
831
+ }
832
+ }
833
+ function createLog(path) {
834
+ return openSync(path, "wx", 384);
835
+ }
836
+
837
+ // ../kit/src/usage.ts
838
+ var UNKNOWN_OPTION2 = /unknown option '(--[a-z][a-z0-9-]*)[=']/;
839
+ var FLAG_NAME = /^(?:--[a-z][a-z0-9-]*|-[a-zA-Z])$/;
840
+ var LONGEST_NAME = 40;
841
+ var usageError;
842
+ function noteUsageError(message) {
843
+ usageError = message;
844
+ }
845
+ function stateHome(env = process7.env) {
846
+ const dir = env.XDG_STATE_HOME;
847
+ return dir !== undefined && isAbsolute(dir) ? dir : join2(homedir2(), ".local", "state");
848
+ }
849
+ function usagePath(env = process7.env) {
850
+ return join2(stateHome(env), CLI_FOLDER, "usage.jsonl");
851
+ }
852
+ function usageRecorded(env = process7.env) {
853
+ const off = env.KAYNOOO_CLI_NO_USAGE;
854
+ return env.NODE_ENV !== "test" && (off === undefined || off === "" || off === "0");
855
+ }
856
+ function flagNames(argv) {
857
+ const end = argv.indexOf("--");
858
+ const names = (end === -1 ? argv : argv.slice(0, end)).filter((word) => word.startsWith("-") && word !== "-").map((word) => word.includes("=") ? word.slice(0, word.indexOf("=")) : word);
859
+ return [...new Set(names)].filter((name) => name.length <= LONGEST_NAME && FLAG_NAME.test(name));
860
+ }
861
+ function usageEntry(bin, command, argv, code, now = new Date) {
862
+ const unknown = code === 2 && usageError !== undefined ? UNKNOWN_OPTION2.exec(usageError)?.[1] : undefined;
863
+ usageError = undefined;
864
+ return { at: now.toISOString(), bin, ...command === undefined ? {} : { command }, flags: flagNames(argv), code, ...unknown === undefined ? {} : { unknown } };
865
+ }
866
+ function recordUsage(entry, env = process7.env) {
867
+ if (!usageRecorded(env))
868
+ return;
869
+ try {
870
+ const path = usagePath(env);
871
+ mkdirSync(dirname(path), { recursive: true, mode: 448 });
872
+ appendFileSync(path, `${JSON.stringify(entry)}
873
+ `, { mode: 384 });
874
+ } catch {}
875
+ }
876
+
877
+ // ../kit/src/cli.ts
775
878
  var LEVEL_OPTIONS = {
776
879
  ...OUTPUT_OPTIONS,
777
880
  help: { type: "boolean", short: "h", description: "show this help" }
778
881
  };
779
882
  var TOP_OPTIONS = { ...LEVEL_OPTIONS, version: { type: "boolean", short: "v", description: "print the version" } };
780
883
  function printError(prefix, message, hint, cause) {
781
- const colors = paint(process5.stderr);
782
- const styled = takesControlCodes(process5.stderr);
884
+ const colors = paint(process8.stderr);
885
+ const styled = takesControlCodes(process8.stderr);
783
886
  const head = styled ? `${colors.red.bold("error")} ${colors.dim(`${prefix}:`)}` : `error: ${prefix}:`;
784
887
  const under = (label, text, tint) => text === undefined ? "" : `
785
888
  ${styled ? tint(label) : `${label}:`} ${text}`;
@@ -798,6 +901,8 @@ function reportThrown(prefix, error, redact = (text) => text, json = false) {
798
901
  const help = error instanceof UsageError ? `run ${prefix} --help for its options` : undefined;
799
902
  const named = error instanceof Error && !(error instanceof Exit) && error.name !== "Error" ? `${error.name}: ${error.message}` : undefined;
800
903
  const cause = error instanceof Error && error.cause instanceof Error ? redact(error.cause.message) : undefined;
904
+ if (error instanceof UsageError)
905
+ noteUsageError(error.message);
801
906
  const report = json ? printJsonError : (message, hint, causeText) => printError(prefix, message, hint, causeText);
802
907
  report(redact(named ?? (error instanceof Error ? error.message : String(error))), error instanceof Exit ? error.hint ?? help : undefined, cause);
803
908
  return error instanceof Exit ? error.code : 1;
@@ -859,68 +964,22 @@ async function printCandidates(found) {
859
964
  console.log(line);
860
965
  return 0;
861
966
  }
862
- async function runMain({ name, version, run, redact }, argv = process5.argv.slice(2)) {
967
+ async function runMain({ name, version, run, redact, usage }, argv = process8.argv.slice(2)) {
863
968
  if (argv[0] === COMPLETE)
864
969
  return printCandidates(leafCandidates(run, argv.slice(1)));
865
970
  if (argv.length === 1 && (argv[0] === "--version" || argv[0] === "-v")) {
866
971
  console.log(version);
867
972
  return 0;
868
973
  }
974
+ let code;
869
975
  try {
870
- return await run(argv);
976
+ code = await run(argv);
871
977
  } catch (error) {
872
- return reportThrown(name, error, redact, wantsJson(argv));
873
- }
874
- }
875
- // ../kit/src/logs.ts
876
- import { lstatSync, openSync } from "fs";
877
- import { mkdir, mkdtemp, readdir, rm, stat } from "fs/promises";
878
- import { homedir, tmpdir } from "os";
879
- import { join } from "path";
880
- import process6 from "process";
881
- var DAY_MS = 24 * 60 * 60 * 1000;
882
- var CLI_FOLDER = "kaynooo-cli";
883
- function isPrivateDirectory(path) {
884
- try {
885
- const info = lstatSync(path, { throwIfNoEntry: false });
886
- return info !== undefined && info.isDirectory() && info.uid === (process6.getuid?.() ?? info.uid) && (info.mode & 63) === 0;
887
- } catch {
888
- return false;
889
- }
890
- }
891
- async function privateLogDirectory(name, env = process6.env) {
892
- const runtime = env.XDG_RUNTIME_DIR;
893
- const base = runtime === undefined || runtime === "" ? join(homedir(), ".cache", CLI_FOLDER) : join(runtime, CLI_FOLDER);
894
- const path = join(base, name);
895
- try {
896
- await mkdir(path, { recursive: true, mode: 448 });
897
- if (isPrivateDirectory(path))
898
- return path;
899
- } catch {}
900
- return mkdtemp(join(tmpdir(), `${name.replaceAll("/", "-")}-`));
901
- }
902
- async function sweepLogs(dir, maxAgeMs = DAY_MS, now = Date.now()) {
903
- let names;
904
- try {
905
- names = await readdir(dir);
906
- } catch {
907
- return;
978
+ code = reportThrown(name, error, redact, wantsJson(argv));
908
979
  }
909
- for (const name of names) {
910
- const path = join(dir, name);
911
- try {
912
- const info = await stat(path);
913
- if (info.isDirectory())
914
- await sweepLogs(path, maxAgeMs, now);
915
- if (now - info.mtimeMs > maxAgeMs)
916
- await rm(path, { force: true, recursive: info.isDirectory() });
917
- } catch {
918
- continue;
919
- }
920
- }
921
- }
922
- function createLog(path) {
923
- return openSync(path, "wx", 384);
980
+ if (usage !== false)
981
+ recordUsage(usageEntry(name, undefined, argv, code));
982
+ return code;
924
983
  }
925
984
  // ../kit/src/secrets.ts
926
985
  var SECRET_WORDS = new Set(["key", "pass", "pwd", "auth", "salt", "cookie", "session", "jwt", "ssn", "iban", "card", "cvv", "otp"]);
@@ -929,7 +988,7 @@ var {Glob } = globalThis.Bun;
929
988
  var SESSION_FILES = new Glob("*.json");
930
989
  var ACCOUNT_DIRS = new Glob("*/sessions");
931
990
  // package.json
932
- var version = "0.7.0";
991
+ var version = "0.7.1";
933
992
 
934
993
  // src/shape.ts
935
994
  var HEX_LITERAL = /\b0x[0-9a-f]+\b/gi;
@@ -1111,11 +1170,11 @@ function fold(text, { threshold, logPath }) {
1111
1170
 
1112
1171
  // src/run.ts
1113
1172
  import { closeSync, rmSync, writeSync } from "fs";
1114
- import process10 from "process";
1173
+ import process12 from "process";
1115
1174
 
1116
1175
  // src/logs.ts
1117
- import { join as join2 } from "path";
1118
- import process8 from "process";
1176
+ import { join as join3 } from "path";
1177
+ import process10 from "process";
1119
1178
  var MAX_AGE_MS = 24 * 60 * 60 * 1000;
1120
1179
  async function logDir() {
1121
1180
  return privateLogDirectory("out");
@@ -1124,7 +1183,7 @@ async function cleanLogs(dir, now = Date.now()) {
1124
1183
  await sweepLogs(dir, MAX_AGE_MS, now);
1125
1184
  }
1126
1185
  function newLog(dir) {
1127
- const path = join2(dir, `${new Date().toISOString().replaceAll(/[:.]/g, "-")}-${process8.pid}.log`);
1186
+ const path = join3(dir, `${new Date().toISOString().replaceAll(/[:.]/g, "-")}-${process10.pid}.log`);
1128
1187
  return { path, fd: createLog(path) };
1129
1188
  }
1130
1189
 
@@ -1379,10 +1438,9 @@ function filtered(text, stages) {
1379
1438
  }
1380
1439
 
1381
1440
  // src/stats.ts
1382
- import { appendFileSync, mkdirSync } from "fs";
1383
- import { homedir as homedir2 } from "os";
1384
- import { basename, dirname, join as join3 } from "path";
1385
- import process9 from "process";
1441
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync2 } from "fs";
1442
+ import { basename, dirname as dirname2, join as join4 } from "path";
1443
+ import process11 from "process";
1386
1444
  var BYTES_PER_TOKEN = 4;
1387
1445
  var KEY_WORD = /^[a-z][a-z:_-]*$/;
1388
1446
  var KEY_WORDS = 3;
@@ -1391,8 +1449,8 @@ var ASSIGNMENT = /^\w+=/;
1391
1449
  var CHAIN = /&&|\|\||;/;
1392
1450
  var SHELLS2 = new Set(["sh", "bash", "zsh"]);
1393
1451
  var TOP = 10;
1394
- function statsPath(env = process9.env) {
1395
- return join3(env.XDG_STATE_HOME ?? join3(homedir2(), ".local", "state"), CLI_FOLDER, "out", "stats.jsonl");
1452
+ function statsPath(env = process11.env) {
1453
+ return join4(stateHome(env), CLI_FOLDER, "out", "stats.jsonl");
1396
1454
  }
1397
1455
  function commandKey(command) {
1398
1456
  const [program = "", ...rest] = command.slice(Math.max(0, command.findIndex((word) => !ASSIGNMENT.test(word))));
@@ -1410,8 +1468,8 @@ function commandKey(command) {
1410
1468
  }
1411
1469
  function record(entry, path = statsPath()) {
1412
1470
  try {
1413
- mkdirSync(dirname(path), { recursive: true, mode: 448 });
1414
- appendFileSync(path, `${JSON.stringify(entry)}
1471
+ mkdirSync2(dirname2(path), { recursive: true, mode: 448 });
1472
+ appendFileSync2(path, `${JSON.stringify(entry)}
1415
1473
  `, { mode: 384 });
1416
1474
  } catch {}
1417
1475
  }
@@ -1537,11 +1595,11 @@ ${decode(this.tail)}`;
1537
1595
  }
1538
1596
  function replay(chunks) {
1539
1597
  for (const { stream, data } of chunks)
1540
- process10[stream].write(data);
1598
+ process12[stream].write(data);
1541
1599
  }
1542
1600
  function count(recorder, shown, recorded) {
1543
1601
  const baseline = recorded.was.length === 0 || recorder.overflowing ? undefined : filtered(recorder.text, recorded.was);
1544
- record({ at: new Date().toISOString(), dir: process10.cwd(), command: recorded.command, bytes: recorder.bytes, baseline: baseline === undefined ? recorder.bytes : Buffer.byteLength(baseline), shown, folded: shown !== recorder.bytes });
1602
+ record({ at: new Date().toISOString(), dir: process12.cwd(), command: recorded.command, bytes: recorder.bytes, baseline: baseline === undefined ? recorder.bytes : Buffer.byteLength(baseline), shown, folded: shown !== recorder.bytes });
1545
1603
  }
1546
1604
  async function run(command, threshold, was = []) {
1547
1605
  const dir = await logDir();
@@ -1605,7 +1663,7 @@ function present(recorder, threshold) {
1605
1663
  replay(recorder.chunks);
1606
1664
  return recorder.bytes;
1607
1665
  }
1608
- process10.stdout.write(printed);
1666
+ process12.stdout.write(printed);
1609
1667
  return Buffer.byteLength(printed);
1610
1668
  }
1611
1669
 
@@ -1654,4 +1712,4 @@ async function main(argv) {
1654
1712
  ${USAGE}`);
1655
1713
  return run(command, lines, was);
1656
1714
  }
1657
- process11.exitCode = await runMain({ name: "out", version, run: main });
1715
+ process13.exitCode = await runMain({ name: "out", version, run: main });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kaynooo/cli-out",
3
3
  "type": "module",
4
- "version": "0.7.0",
4
+ "version": "0.7.1",
5
5
  "description": "out: shortens noisy command output for Claude Code, folding long logs and keeping errors, with the full log saved to a file.",
6
6
  "author": "Kaynooo <contact@kaynooo.fr>",
7
7
  "license": "MIT",
@@ -28,6 +28,6 @@
28
28
  "out": "$npm_execpath src/cli.ts"
29
29
  },
30
30
  "devDependencies": {
31
- "@kaynooo/cli-kit": "0.18.0"
31
+ "@kaynooo/cli-kit": "0.20.0"
32
32
  }
33
33
  }