@crafter/cli-tree 0.1.2 → 0.1.3

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/dist/cli.js CHANGED
@@ -28,7 +28,7 @@ import"./chunk-q4se2rwe.js";
28
28
  // src/cli.ts
29
29
  var args = process.argv.slice(2);
30
30
  var subcommand = args[0];
31
- var HELP_SUBCOMMANDS = new Set(["flow", "mine", "archaeology"]);
31
+ var HELP_SUBCOMMANDS = new Set(["flow", "mine", "archaeology", "safe-help"]);
32
32
  var isHelpFlag = args.includes("--help") || args.includes("-h");
33
33
  if (!subcommand || isHelpFlag && !HELP_SUBCOMMANDS.has(subcommand ?? "")) {
34
34
  printMainHelp();
@@ -41,6 +41,8 @@ if (isHelpFlag) {
41
41
  printMineHelp();
42
42
  else if (subcommand === "archaeology")
43
43
  printArchaeologyHelp();
44
+ else if (subcommand === "safe-help")
45
+ printSafeHelpHelp();
44
46
  else
45
47
  printMainHelp();
46
48
  process.exit(0);
@@ -51,6 +53,8 @@ if (subcommand === "flow") {
51
53
  await runMine(args.slice(1));
52
54
  } else if (subcommand === "archaeology") {
53
55
  await runArchaeologyCmd(args.slice(1));
56
+ } else if (subcommand === "safe-help") {
57
+ await runSafeHelp(args.slice(1));
54
58
  } else {
55
59
  await runTree(args);
56
60
  }
@@ -63,21 +67,58 @@ function printMainHelp() {
63
67
  clitree flow <file> [options] Render a workflow YAML as a DAG
64
68
  clitree mine <binary> [options] Mine shell history for workflows
65
69
  clitree archaeology <binary> [options] Full analysis: tree + mining + (LLM)
70
+ clitree safe-help <binary> [sub...] Fetch clean help for any CLI (no pager, no overstriking)
66
71
 
67
72
  Examples:
68
73
  clitree docker # basic tree
69
74
  clitree mine git # "what workflows do I repeat with git?"
70
75
  clitree archaeology bun # tree + mining + LLM archaeology
76
+ clitree safe-help git commit # avoid the git man-page pager trap
71
77
 
72
78
  Subcommands:
73
79
  tree Parse --help output (default; passing a binary name invokes this)
74
80
  flow Render a workflow YAML file as an ASCII DAG
75
81
  mine Discover workflows from your shell history
76
82
  archaeology Run full analysis (tree + mine + LLM proposals when available)
83
+ safe-help Return inline help for any CLI, handling pager/overstrike edge cases
77
84
 
78
85
  Help for a subcommand: clitree <subcommand> --help
79
86
  `);
80
87
  }
88
+ function printSafeHelpHelp() {
89
+ console.log(`
90
+ clitree safe-help — Fetch clean help output for any CLI
91
+
92
+ Usage:
93
+ clitree safe-help <binary> [subcommand...] [options]
94
+
95
+ Why this exists:
96
+ Running '<cli> --help' directly is a minefield on agents and scripts:
97
+ - 'git commit --help' opens a pager in a TTY and hangs
98
+ - Piping 'git <sub> --help' returns nroff with overstrike (ffiixxuupp)
99
+ - Some CLIs use 'help <sub>' instead of '<sub> --help'
100
+ - macOS man pages emit \\b sequences that need col -bx
101
+
102
+ safe-help tries the right variants in order, cleans overstrikes, and
103
+ returns plain text every time.
104
+
105
+ Strategy (in order):
106
+ 1. <cli> <sub> -h — short inline help
107
+ 2. <cli> <sub> --help — long help (captured, overstrike-stripped)
108
+ 3. <cli> help <sub> — alternate syntax
109
+ 4. MANPAGER=cat man <cli>-<sub> | col -bx — final man fallback
110
+
111
+ Examples:
112
+ clitree safe-help git commit
113
+ clitree safe-help docker run
114
+ clitree safe-help kubectl get pods
115
+ clitree safe-help bun install
116
+
117
+ Options:
118
+ --no-color Disable ANSI codes (auto-detects non-TTY)
119
+ -h, --help Show this help
120
+ `);
121
+ }
81
122
  function printMineHelp() {
82
123
  console.log(`
83
124
  clitree mine — Mine your shell history for CLI workflows
@@ -273,6 +314,117 @@ async function readStdin() {
273
314
  }
274
315
  return Buffer.concat(chunks).toString("utf-8");
275
316
  }
317
+ function stripOverstrike(text) {
318
+ return text.replace(/(.)\b\1/g, "$1").replace(/_\b(.)/g, "$1").replace(/\b/g, "").replace(/\x1b\[[0-9;]*[a-zA-Z]/g, "");
319
+ }
320
+ function looksLikeHelp(text) {
321
+ if (!text.trim())
322
+ return false;
323
+ if (text.length < 40)
324
+ return false;
325
+ const firstChunk = text.slice(0, 200).toLowerCase();
326
+ if (/(unknown|invalid|no such|not a \w+ command|flag needs an argument|unrecognized)/.test(firstChunk)) {
327
+ return false;
328
+ }
329
+ if (/run '.+' for more information/.test(firstChunk))
330
+ return false;
331
+ return true;
332
+ }
333
+ async function tryHelpVariant(binary, argv, timeoutMs = 5000) {
334
+ try {
335
+ const proc = Bun.spawn([binary, ...argv], {
336
+ stdout: "pipe",
337
+ stderr: "pipe",
338
+ env: { ...process.env, PAGER: "cat", MANPAGER: "cat", GIT_PAGER: "cat" }
339
+ });
340
+ const timer = setTimeout(() => proc.kill(), timeoutMs);
341
+ const [stdout, stderr] = await Promise.all([
342
+ new Response(proc.stdout).text(),
343
+ new Response(proc.stderr).text()
344
+ ]);
345
+ clearTimeout(timer);
346
+ await proc.exited;
347
+ const combined = stdout || stderr;
348
+ if (!looksLikeHelp(combined))
349
+ return null;
350
+ return stripOverstrike(combined);
351
+ } catch {
352
+ return null;
353
+ }
354
+ }
355
+ async function tryManPage(binary, subPath, timeoutMs = 5000) {
356
+ const candidates = [
357
+ subPath.length > 0 ? [`${binary}-${subPath.join("-")}`] : [binary],
358
+ [binary, ...subPath]
359
+ ];
360
+ for (const args2 of candidates) {
361
+ try {
362
+ const proc = Bun.spawn(["man", ...args2], {
363
+ stdout: "pipe",
364
+ stderr: "pipe",
365
+ env: { ...process.env, MANPAGER: "cat", PAGER: "cat" }
366
+ });
367
+ const timer = setTimeout(() => proc.kill(), timeoutMs);
368
+ const [stdout] = await Promise.all([
369
+ new Response(proc.stdout).text(),
370
+ new Response(proc.stderr).text()
371
+ ]);
372
+ clearTimeout(timer);
373
+ await proc.exited;
374
+ if (looksLikeHelp(stdout))
375
+ return stripOverstrike(stdout);
376
+ } catch {}
377
+ }
378
+ return null;
379
+ }
380
+ async function runSafeHelp(args2) {
381
+ let binary = null;
382
+ const subPath = [];
383
+ for (const arg of args2) {
384
+ if (arg === "--no-color" || arg === "--help" || arg === "-h")
385
+ continue;
386
+ if (!binary) {
387
+ binary = arg;
388
+ } else {
389
+ subPath.push(arg);
390
+ }
391
+ }
392
+ if (!binary) {
393
+ console.error("Error: provide a binary name");
394
+ console.error("Run 'clitree safe-help --help' for usage");
395
+ process.exit(1);
396
+ }
397
+ const variants = [
398
+ { label: "short help (-h)", args: [...subPath, "-h"] },
399
+ { label: "long help (--help)", args: [...subPath, "--help"] }
400
+ ];
401
+ if (subPath.length > 0) {
402
+ variants.push({ label: "help subcommand", args: ["help", ...subPath] });
403
+ }
404
+ for (const variant of variants) {
405
+ const output = await tryHelpVariant(binary, variant.args);
406
+ if (output) {
407
+ process.stdout.write(output);
408
+ if (!output.endsWith(`
409
+ `))
410
+ process.stdout.write(`
411
+ `);
412
+ return;
413
+ }
414
+ }
415
+ const manOutput = await tryManPage(binary, subPath);
416
+ if (manOutput) {
417
+ process.stdout.write(manOutput);
418
+ if (!manOutput.endsWith(`
419
+ `))
420
+ process.stdout.write(`
421
+ `);
422
+ return;
423
+ }
424
+ console.error(`Error: could not fetch help for ${binary} ${subPath.join(" ")}`);
425
+ console.error("Tried: -h, --help, help subcommand, and man page.");
426
+ process.exit(1);
427
+ }
276
428
  function shouldUseColor(args2) {
277
429
  if (args2.includes("--no-color"))
278
430
  return false;
@@ -470,4 +622,4 @@ ${C.bold}${C.yellow}\uD83D\uDCA1 Skill suggestions:${C.reset}`);
470
622
  }
471
623
  }
472
624
 
473
- //# debugId=FADAD3DCBCB5252964756E2164756E21
625
+ //# debugId=6575AA9BC14C249964756E2164756E21
package/dist/cli.js.map CHANGED
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/cli.ts"],
4
4
  "sourcesContent": [
5
- "#!/usr/bin/env bun\nimport { parseHelpRecursive, parseHelp } from \"./parse\";\nimport { printTree, treeToString, treeToHtml } from \"./index\";\nimport type { TreeOptions } from \"./types\";\nimport { parseWorkflow, validateWorkflow, flowToAnsi, flowToString, flowToHtml } from \"./flow\";\nimport type { FlowRenderOptions } from \"./flow/types\";\nimport { mineCli, minedToFlowWorkflow } from \"./miner\";\nimport { runArchaeology, NullDelegate } from \"./archaeology\";\n\nconst args = process.argv.slice(2);\nconst subcommand = args[0];\n\nconst HELP_SUBCOMMANDS = new Set([\"flow\", \"mine\", \"archaeology\"]);\nconst isHelpFlag = args.includes(\"--help\") || args.includes(\"-h\");\n\nif (!subcommand || (isHelpFlag && !HELP_SUBCOMMANDS.has(subcommand ?? \"\"))) {\n\tprintMainHelp();\n\tprocess.exit(0);\n}\n\nif (isHelpFlag) {\n\tif (subcommand === \"flow\") printFlowHelp();\n\telse if (subcommand === \"mine\") printMineHelp();\n\telse if (subcommand === \"archaeology\") printArchaeologyHelp();\n\telse printMainHelp();\n\tprocess.exit(0);\n}\n\nif (subcommand === \"flow\") {\n\tawait runFlow(args.slice(1));\n} else if (subcommand === \"mine\") {\n\tawait runMine(args.slice(1));\n} else if (subcommand === \"archaeology\") {\n\tawait runArchaeologyCmd(args.slice(1));\n} else {\n\tawait runTree(args);\n}\n\nfunction printMainHelp() {\n\tconsole.log(`\n clitree — Visualize and explore any CLI\n\n Usage:\n clitree <binary> [options] Render command tree from --help\n clitree flow <file> [options] Render a workflow YAML as a DAG\n clitree mine <binary> [options] Mine shell history for workflows\n clitree archaeology <binary> [options] Full analysis: tree + mining + (LLM)\n\n Examples:\n clitree docker # basic tree\n clitree mine git # \"what workflows do I repeat with git?\"\n clitree archaeology bun # tree + mining + LLM archaeology\n\n Subcommands:\n tree Parse --help output (default; passing a binary name invokes this)\n flow Render a workflow YAML file as an ASCII DAG\n mine Discover workflows from your shell history\n archaeology Run full analysis (tree + mine + LLM proposals when available)\n\n Help for a subcommand: clitree <subcommand> --help\n`);\n}\n\nfunction printMineHelp() {\n\tconsole.log(`\n clitree mine — Mine your shell history for CLI workflows\n\n Usage:\n clitree mine <binary> [options]\n\n Examples:\n clitree mine git\n clitree mine docker --min-support 5 --with-flow\n clitree mine bun --format json > bun-flows.json\n clitree mine git --no-color | tee report.txt\n\n Options:\n --min-support <n> Minimum occurrences to count as a workflow (default: 3)\n --history-path <p> Custom shell history path (default: ~/.zsh_history)\n --format <fmt> Output format: ansi (default), json\n --max-paths <n> Max workflows to show (default: 10)\n --with-flow Always render the top workflow as an ASCII DAG\n --no-flow Never render the DAG (overrides auto-detect)\n --no-color Disable ANSI colors (also auto-disabled when stdout is not a TTY)\n -h, --help Show this help\n\n By default, the top workflow is rendered as a DAG only when it has 3+ steps.\n Use --with-flow to force it on even for 2-step chains, or --no-flow to skip.\n`);\n}\n\nfunction printArchaeologyHelp() {\n\tconsole.log(`\n clitree archaeology — Full CLI analysis: tree + mining + LLM archaeology\n\n Usage:\n clitree archaeology <binary> [options]\n\n When run from the command line without a delegate, only the deterministic\n phases run (help parsing + shell history mining). LLM archaeology requires\n running inside the clitree skill (see ./skill/SKILL.md).\n\n Examples:\n clitree archaeology git # help + history\n clitree archaeology docker --no-cache # bypass cache\n clitree archaeology bun --format json # JSON output\n\n Options:\n --no-cache Skip cache, always re-run\n --max-depth <n> Max --help recursion depth (default: 2)\n --format <fmt> Output format: ansi (default), json\n --no-color Disable ANSI colors (also auto-disabled when stdout is not a TTY)\n -h, --help Show this help\n`);\n}\n\nfunction printFlowHelp() {\n\tconsole.log(`\n cli-tree flow — Render a CLI workflow YAML as a DAG\n\n Usage:\n cli-tree flow <file> [options]\n\n Examples:\n cli-tree flow workflows/git-pr-flow.yml\n cli-tree flow my-workflow.yml --format html > flow.html\n cli-tree flow workflows/docker-deploy.yml --compact --no-color\n\n Options:\n --compact Hide description and legend\n --no-color Disable colors\n --format <fmt> Output format: ansi (default), string, html\n --no-validate Skip validation\n -h, --help Show this help\n`);\n}\n\nasync function runTree(args: string[]) {\n\tconst opts: TreeOptions = {\n\t\tcolor: true,\n\t\tshowFlags: true,\n\t\tshowArgs: true,\n\t\tshowDescriptions: true,\n\t\tshowTypes: true,\n\t\tshowDefaults: true,\n\t\tcompact: false,\n\t};\n\n\tlet depth = 2;\n\tlet format: \"ansi\" | \"string\" | \"html\" | \"json\" = \"ansi\";\n\tlet stdinName: string | null = null;\n\tlet binary: string | null = null;\n\n\topts.color = shouldUseColor(args);\n\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i]!;\n\t\tif (arg === \"--depth\" && args[i + 1]) {\n\t\t\tdepth = Number.parseInt(args[++i]!, 10);\n\t\t} else if (arg === \"--compact\") {\n\t\t\topts.compact = true;\n\t\t\topts.showDescriptions = false;\n\t\t} else if (arg === \"--no-flags\") {\n\t\t\topts.showFlags = false;\n\t\t} else if (arg === \"--no-args\") {\n\t\t\topts.showArgs = false;\n\t\t} else if (arg === \"--no-color\") {\n\t\t\topts.color = false;\n\t\t} else if (arg === \"--format\" && args[i + 1]) {\n\t\t\tformat = args[++i] as \"ansi\" | \"string\" | \"html\" | \"json\";\n\t\t} else if (arg === \"--stdin\" && args[i + 1]) {\n\t\t\tstdinName = args[++i]!;\n\t\t} else if (!arg.startsWith(\"-\")) {\n\t\t\tbinary = arg;\n\t\t}\n\t}\n\n\ttry {\n\t\tlet tree;\n\t\tif (stdinName) {\n\t\t\tconst input = await readStdin();\n\t\t\ttree = parseHelp(stdinName, input);\n\t\t} else if (binary) {\n\t\t\ttree = await parseHelpRecursive(binary, [], depth);\n\t\t} else {\n\t\t\tconsole.error(\"Error: provide a binary name or use --stdin <name>\");\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tif (format === \"json\") {\n\t\t\tconsole.log(JSON.stringify(tree, null, 2));\n\t\t} else if (format === \"html\") {\n\t\t\tconsole.log(treeToHtml(tree, opts));\n\t\t} else if (format === \"string\") {\n\t\t\tconsole.log(treeToString(tree, opts));\n\t\t} else {\n\t\t\tprintTree(tree, opts);\n\t\t}\n\t} catch (err: any) {\n\t\tconsole.error(`Error: ${err.message}`);\n\t\tprocess.exit(1);\n\t}\n}\n\nasync function runFlow(args: string[]) {\n\tconst opts: FlowRenderOptions = {\n\t\tcolor: true,\n\t\tshowDescriptions: true,\n\t\tshowCommands: true,\n\t\tcompact: false,\n\t};\n\n\tlet format: \"ansi\" | \"string\" | \"html\" = \"ansi\";\n\tlet file: string | null = null;\n\tlet skipValidate = false;\n\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i]!;\n\t\tif (arg === \"--compact\") {\n\t\t\topts.compact = true;\n\t\t\topts.showDescriptions = false;\n\t\t} else if (arg === \"--no-color\") {\n\t\t\topts.color = false;\n\t\t} else if (arg === \"--no-validate\") {\n\t\t\tskipValidate = true;\n\t\t} else if (arg === \"--format\" && args[i + 1]) {\n\t\t\tformat = args[++i] as \"ansi\" | \"string\" | \"html\";\n\t\t} else if (!arg.startsWith(\"-\")) {\n\t\t\tfile = arg;\n\t\t}\n\t}\n\n\tif (!file) {\n\t\tconsole.error(\"Error: provide a workflow YAML file\");\n\t\tconsole.error(\"Run 'cli-tree flow --help' for usage\");\n\t\tprocess.exit(1);\n\t}\n\n\ttry {\n\t\tconst text = await Bun.file(file).text();\n\t\tconst workflow = parseWorkflow(text);\n\n\t\tif (!skipValidate) {\n\t\t\tconst result = validateWorkflow(workflow);\n\t\t\tfor (const err of result.errors) {\n\t\t\t\tconst prefix = err.severity === \"error\" ? \"\\x1b[31m✗\" : \"\\x1b[33m⚠\";\n\t\t\t\tconst reset = \"\\x1b[0m\";\n\t\t\t\tconst location = err.node ? ` [${err.node}]` : err.edge ? ` [${err.edge.from}→${err.edge.to}]` : \"\";\n\t\t\t\tconsole.error(`${prefix}${location} ${err.message}${reset}`);\n\t\t\t}\n\t\t\tif (!result.valid) process.exit(1);\n\t\t}\n\n\t\tif (format === \"html\") {\n\t\t\tconsole.log(flowToHtml(workflow, opts));\n\t\t} else if (format === \"string\") {\n\t\t\tconsole.log(flowToString(workflow, opts));\n\t\t} else {\n\t\t\tconsole.log(flowToAnsi(workflow, opts));\n\t\t}\n\t} catch (err: any) {\n\t\tconsole.error(`Error: ${err.message}`);\n\t\tprocess.exit(1);\n\t}\n}\n\nasync function readStdin(): Promise<string> {\n\tconst chunks: Buffer[] = [];\n\tfor await (const chunk of process.stdin) {\n\t\tchunks.push(chunk as Buffer);\n\t}\n\treturn Buffer.concat(chunks).toString(\"utf-8\");\n}\n\nfunction shouldUseColor(args: string[]): boolean {\n\tif (args.includes(\"--no-color\")) return false;\n\tif (process.env.NO_COLOR) return false;\n\tif (process.env.FORCE_COLOR) return true;\n\treturn !!process.stdout.isTTY;\n}\n\nfunction makeColors(enabled: boolean) {\n\tif (!enabled) {\n\t\treturn { reset: \"\", bold: \"\", dim: \"\", cyan: \"\", green: \"\", yellow: \"\", red: \"\", magenta: \"\", gray: \"\" };\n\t}\n\treturn {\n\t\treset: \"\\x1b[0m\",\n\t\tbold: \"\\x1b[1m\",\n\t\tdim: \"\\x1b[2m\",\n\t\tcyan: \"\\x1b[36m\",\n\t\tgreen: \"\\x1b[32m\",\n\t\tyellow: \"\\x1b[33m\",\n\t\tred: \"\\x1b[31m\",\n\t\tmagenta: \"\\x1b[35m\",\n\t\tgray: \"\\x1b[90m\",\n\t};\n}\n\nasync function runMine(args: string[]) {\n\tlet binary: string | null = null;\n\tlet minSupport = 3;\n\tlet historyPath: string | undefined;\n\tlet format: \"ansi\" | \"json\" = \"ansi\";\n\tlet maxPaths = 10;\n\tlet withFlow: \"auto\" | \"on\" | \"off\" = \"auto\";\n\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i]!;\n\t\tif (arg === \"--min-support\" && args[i + 1]) {\n\t\t\tminSupport = Number.parseInt(args[++i]!, 10);\n\t\t} else if (arg === \"--history-path\" && args[i + 1]) {\n\t\t\thistoryPath = args[++i]!;\n\t\t} else if (arg === \"--format\" && args[i + 1]) {\n\t\t\tformat = args[++i] as \"ansi\" | \"json\";\n\t\t} else if (arg === \"--max-paths\" && args[i + 1]) {\n\t\t\tmaxPaths = Number.parseInt(args[++i]!, 10);\n\t\t} else if (arg === \"--with-flow\" || arg === \"--flow\") {\n\t\t\twithFlow = \"on\";\n\t\t} else if (arg === \"--no-flow\") {\n\t\t\twithFlow = \"off\";\n\t\t} else if (arg !== \"--no-color\" && !arg.startsWith(\"-\")) {\n\t\t\tbinary = arg;\n\t\t}\n\t}\n\n\tif (!binary) {\n\t\tconsole.error(\"Error: provide a binary name\");\n\t\tconsole.error(\"Run 'clitree mine --help' for usage\");\n\t\tprocess.exit(1);\n\t}\n\n\ttry {\n\t\tconst result = await mineCli(binary, { minSupport, historyPath });\n\n\t\tif (format === \"json\") {\n\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\treturn;\n\t\t}\n\n\t\tconst C = makeColors(shouldUseColor(args));\n\n\t\tconsole.log(`\\n${C.bold}${C.magenta}${binary}${C.reset} ${C.gray}— shell history analysis${C.reset}\\n`);\n\t\tconsole.log(`${C.bold}Usage:${C.reset}`);\n\t\tconsole.log(` ${C.dim}Invocations:${C.reset} ${C.cyan}${result.stats.totalInvocations}${C.reset}`);\n\t\tconsole.log(` ${C.dim}Subcommands:${C.reset} ${C.cyan}${result.stats.uniqueSubcommands}${C.reset}`);\n\t\tconsole.log(` ${C.dim}Sessions:${C.reset} ${C.cyan}${result.sessionsAnalyzed}${C.reset}\\n`);\n\n\t\tif (result.stats.topSubcommands.length > 0) {\n\t\t\tconsole.log(`${C.bold}Top subcommands:${C.reset}`);\n\t\t\tconst max = result.stats.topSubcommands[0]!.count;\n\t\t\tfor (const { subcommand, count } of result.stats.topSubcommands.slice(0, 5)) {\n\t\t\t\tconst bar = \"█\".repeat(Math.max(1, Math.round((count / max) * 30)));\n\t\t\t\tconsole.log(` ${C.green}${subcommand.padEnd(20)}${C.reset} ${C.cyan}${bar}${C.reset} ${C.dim}${count}${C.reset}`);\n\t\t\t}\n\t\t\tconsole.log();\n\t\t}\n\n\t\tif (result.workflows.length > 0) {\n\t\t\tconsole.log(`${C.bold}Discovered workflows:${C.reset}`);\n\t\t\tfor (const wf of result.workflows.slice(0, maxPaths)) {\n\t\t\t\tconst chain = wf.path[0]!.map(p => `${C.green}${p}${C.reset}`).join(` ${C.gray}→${C.reset} `);\n\t\t\t\tconsole.log(` ${chain} ${C.dim}(${wf.support}×)${C.reset}`);\n\t\t\t}\n\t\t\tconsole.log();\n\t\t}\n\n\t\tif (result.suggestions.length > 0) {\n\t\t\tconsole.log(`${C.bold}${C.yellow}💡 Skill suggestions:${C.reset}`);\n\t\t\tfor (const s of result.suggestions.slice(0, 3)) {\n\t\t\t\tconst badge =\n\t\t\t\t\ts.priority === \"high\"\n\t\t\t\t\t\t? `${C.green}[HIGH]${C.reset}`\n\t\t\t\t\t\t: s.priority === \"medium\"\n\t\t\t\t\t\t\t? `${C.yellow}[MED]${C.reset}`\n\t\t\t\t\t\t\t: `${C.dim}[LOW]${C.reset}`;\n\t\t\t\tconsole.log(`\\n ${badge} ${C.bold}/${s.name}${C.reset} — ${s.description}`);\n\t\t\t\tconsole.log(` ${C.dim}${s.reason}${C.reset}`);\n\t\t\t\tconsole.log(` ${C.dim}${s.commands.join(\" && \")}${C.reset}`);\n\t\t\t}\n\t\t\tconsole.log();\n\t\t}\n\n\t\t// Pick the top workflow worth visualizing as a DAG.\n\t\t// In \"auto\" mode, prefer the highest-support workflow with 3+ steps —\n\t\t// 2-step chains are more readable as text than as boxed diagrams.\n\t\t// In \"on\" mode, render whatever is the top regardless of length.\n\t\t// In \"off\" mode, skip.\n\t\tif (withFlow !== \"off\") {\n\t\t\tconst minSteps = withFlow === \"on\" ? 2 : 3;\n\t\t\tconst topForFlow = pickWorkflowForFlow(result.workflows, minSteps);\n\t\t\tif (topForFlow) {\n\t\t\t\tconst flowWorkflow = minedToFlowWorkflow(topForFlow);\n\t\t\t\tconst rendered = shouldUseColor(args) ? flowToAnsi(flowWorkflow) : flowToString(flowWorkflow);\n\t\t\t\tconsole.log(`${C.bold}Top workflow (visualized):${C.reset}`);\n\t\t\t\tconsole.log(rendered);\n\t\t\t\tconsole.log();\n\t\t\t}\n\t\t}\n\t} catch (err: any) {\n\t\tconsole.error(`Error: ${err.message}`);\n\t\tprocess.exit(1);\n\t}\n}\n\nfunction pickWorkflowForFlow<T extends { path: string[][]; support: number }>(\n\tworkflows: T[],\n\tminSteps = 3,\n): T | null {\n\tfor (const wf of workflows) {\n\t\tconst len = wf.path[0]?.length ?? 0;\n\t\tif (len >= minSteps) return wf;\n\t}\n\treturn null;\n}\n\nasync function runArchaeologyCmd(args: string[]) {\n\tlet binary: string | null = null;\n\tlet skipCache = false;\n\tlet maxDepth = 2;\n\tlet format: \"ansi\" | \"json\" = \"ansi\";\n\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i]!;\n\t\tif (arg === \"--no-cache\") {\n\t\t\tskipCache = true;\n\t\t} else if (arg === \"--max-depth\" && args[i + 1]) {\n\t\t\tmaxDepth = Number.parseInt(args[++i]!, 10);\n\t\t} else if (arg === \"--format\" && args[i + 1]) {\n\t\t\tformat = args[++i] as \"ansi\" | \"json\";\n\t\t} else if (arg !== \"--no-color\" && !arg.startsWith(\"-\")) {\n\t\t\tbinary = arg;\n\t\t}\n\t}\n\n\tif (!binary) {\n\t\tconsole.error(\"Error: provide a binary name\");\n\t\tconsole.error(\"Run 'clitree archaeology --help' for usage\");\n\t\tprocess.exit(1);\n\t}\n\n\tconst C = makeColors(shouldUseColor(args));\n\n\ttry {\n\t\tconsole.error(`${C.dim}⚠ LLM archaeology requires running inside the clitree skill.${C.reset}`);\n\t\tconsole.error(`${C.dim} Running deterministic phases only (help + history mining).${C.reset}`);\n\t\tconsole.error(\"\");\n\n\t\tconst [arch, mine] = await Promise.all([\n\t\t\trunArchaeology(binary, new NullDelegate(), { skipCache, maxHelpDepth: maxDepth }),\n\t\t\tmineCli(binary, { minSupport: 3 }).catch(() => null),\n\t\t]);\n\n\t\tif (format === \"json\") {\n\t\t\tconsole.log(JSON.stringify({ archaeology: arch, mining: mine }, null, 2));\n\t\t\treturn;\n\t\t}\n\n\t\tconsole.log(`${C.bold}${C.magenta}${binary}${C.reset}`);\n\t\tif (arch.tree.description) {\n\t\t\tconsole.log(`${C.gray}${arch.tree.description}${C.reset}`);\n\t\t}\n\t\tconsole.log();\n\n\t\tconsole.log(`${C.bold}Tree:${C.reset}`);\n\t\tconsole.log(` ${C.dim}Commands:${C.reset} ${C.cyan}${arch.stats.helpCommands}${C.reset}`);\n\t\tconsole.log(` ${C.dim}Cached:${C.reset} ${arch.fromCache ? `${C.green}yes${C.reset}` : `${C.dim}no${C.reset}`}`);\n\t\tconsole.log();\n\n\t\tif (mine) {\n\t\t\tconsole.log(`${C.bold}Usage from shell history:${C.reset}`);\n\t\t\tconsole.log(` ${C.dim}Invocations:${C.reset} ${C.cyan}${mine.stats.totalInvocations}${C.reset}`);\n\t\t\tconsole.log(` ${C.dim}Subcommands:${C.reset} ${C.cyan}${mine.stats.uniqueSubcommands}${C.reset}`);\n\n\t\t\tif (mine.workflows.length > 0) {\n\t\t\t\tconsole.log(`\\n${C.bold}Workflows you repeat:${C.reset}`);\n\t\t\t\tfor (const wf of mine.workflows.slice(0, 5)) {\n\t\t\t\t\tconst chain = wf.path[0]!.map(p => `${C.green}${p}${C.reset}`).join(` ${C.gray}→${C.reset} `);\n\t\t\t\t\tconsole.log(` ${chain} ${C.dim}(${wf.support}×)${C.reset}`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (mine.suggestions.length > 0) {\n\t\t\t\tconsole.log(`\\n${C.bold}${C.yellow}💡 Skill suggestions:${C.reset}`);\n\t\t\t\tfor (const s of mine.suggestions.slice(0, 3)) {\n\t\t\t\t\tconsole.log(` ${C.bold}/${s.name}${C.reset} — ${s.description}`);\n\t\t\t\t\tconsole.log(` ${C.dim}${s.reason}${C.reset}`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconsole.log();\n\t\tconsole.log(`${C.dim}Install the clitree skill for full LLM archaeology:${C.reset}`);\n\t\tconsole.log(`${C.dim} bash ./skill/install.sh${C.reset}`);\n\t\tconsole.log();\n\t} catch (err: any) {\n\t\tconsole.error(`${C.red}Error: ${err.message}${C.reset}`);\n\t\tprocess.exit(1);\n\t}\n}\n"
5
+ "#!/usr/bin/env bun\nimport { parseHelpRecursive, parseHelp } from \"./parse\";\nimport { printTree, treeToString, treeToHtml } from \"./index\";\nimport type { TreeOptions } from \"./types\";\nimport { parseWorkflow, validateWorkflow, flowToAnsi, flowToString, flowToHtml } from \"./flow\";\nimport type { FlowRenderOptions } from \"./flow/types\";\nimport { mineCli, minedToFlowWorkflow } from \"./miner\";\nimport { runArchaeology, NullDelegate } from \"./archaeology\";\n\nconst args = process.argv.slice(2);\nconst subcommand = args[0];\n\nconst HELP_SUBCOMMANDS = new Set([\"flow\", \"mine\", \"archaeology\", \"safe-help\"]);\nconst isHelpFlag = args.includes(\"--help\") || args.includes(\"-h\");\n\nif (!subcommand || (isHelpFlag && !HELP_SUBCOMMANDS.has(subcommand ?? \"\"))) {\n\tprintMainHelp();\n\tprocess.exit(0);\n}\n\nif (isHelpFlag) {\n\tif (subcommand === \"flow\") printFlowHelp();\n\telse if (subcommand === \"mine\") printMineHelp();\n\telse if (subcommand === \"archaeology\") printArchaeologyHelp();\n\telse if (subcommand === \"safe-help\") printSafeHelpHelp();\n\telse printMainHelp();\n\tprocess.exit(0);\n}\n\nif (subcommand === \"flow\") {\n\tawait runFlow(args.slice(1));\n} else if (subcommand === \"mine\") {\n\tawait runMine(args.slice(1));\n} else if (subcommand === \"archaeology\") {\n\tawait runArchaeologyCmd(args.slice(1));\n} else if (subcommand === \"safe-help\") {\n\tawait runSafeHelp(args.slice(1));\n} else {\n\tawait runTree(args);\n}\n\nfunction printMainHelp() {\n\tconsole.log(`\n clitree — Visualize and explore any CLI\n\n Usage:\n clitree <binary> [options] Render command tree from --help\n clitree flow <file> [options] Render a workflow YAML as a DAG\n clitree mine <binary> [options] Mine shell history for workflows\n clitree archaeology <binary> [options] Full analysis: tree + mining + (LLM)\n clitree safe-help <binary> [sub...] Fetch clean help for any CLI (no pager, no overstriking)\n\n Examples:\n clitree docker # basic tree\n clitree mine git # \"what workflows do I repeat with git?\"\n clitree archaeology bun # tree + mining + LLM archaeology\n clitree safe-help git commit # avoid the git man-page pager trap\n\n Subcommands:\n tree Parse --help output (default; passing a binary name invokes this)\n flow Render a workflow YAML file as an ASCII DAG\n mine Discover workflows from your shell history\n archaeology Run full analysis (tree + mine + LLM proposals when available)\n safe-help Return inline help for any CLI, handling pager/overstrike edge cases\n\n Help for a subcommand: clitree <subcommand> --help\n`);\n}\n\nfunction printSafeHelpHelp() {\n\tconsole.log(`\n clitree safe-help — Fetch clean help output for any CLI\n\n Usage:\n clitree safe-help <binary> [subcommand...] [options]\n\n Why this exists:\n Running '<cli> --help' directly is a minefield on agents and scripts:\n - 'git commit --help' opens a pager in a TTY and hangs\n - Piping 'git <sub> --help' returns nroff with overstrike (ffiixxuupp)\n - Some CLIs use 'help <sub>' instead of '<sub> --help'\n - macOS man pages emit \\\\b sequences that need col -bx\n\n safe-help tries the right variants in order, cleans overstrikes, and\n returns plain text every time.\n\n Strategy (in order):\n 1. <cli> <sub> -h — short inline help\n 2. <cli> <sub> --help — long help (captured, overstrike-stripped)\n 3. <cli> help <sub> — alternate syntax\n 4. MANPAGER=cat man <cli>-<sub> | col -bx — final man fallback\n\n Examples:\n clitree safe-help git commit\n clitree safe-help docker run\n clitree safe-help kubectl get pods\n clitree safe-help bun install\n\n Options:\n --no-color Disable ANSI codes (auto-detects non-TTY)\n -h, --help Show this help\n`);\n}\n\nfunction printMineHelp() {\n\tconsole.log(`\n clitree mine — Mine your shell history for CLI workflows\n\n Usage:\n clitree mine <binary> [options]\n\n Examples:\n clitree mine git\n clitree mine docker --min-support 5 --with-flow\n clitree mine bun --format json > bun-flows.json\n clitree mine git --no-color | tee report.txt\n\n Options:\n --min-support <n> Minimum occurrences to count as a workflow (default: 3)\n --history-path <p> Custom shell history path (default: ~/.zsh_history)\n --format <fmt> Output format: ansi (default), json\n --max-paths <n> Max workflows to show (default: 10)\n --with-flow Always render the top workflow as an ASCII DAG\n --no-flow Never render the DAG (overrides auto-detect)\n --no-color Disable ANSI colors (also auto-disabled when stdout is not a TTY)\n -h, --help Show this help\n\n By default, the top workflow is rendered as a DAG only when it has 3+ steps.\n Use --with-flow to force it on even for 2-step chains, or --no-flow to skip.\n`);\n}\n\nfunction printArchaeologyHelp() {\n\tconsole.log(`\n clitree archaeology — Full CLI analysis: tree + mining + LLM archaeology\n\n Usage:\n clitree archaeology <binary> [options]\n\n When run from the command line without a delegate, only the deterministic\n phases run (help parsing + shell history mining). LLM archaeology requires\n running inside the clitree skill (see ./skill/SKILL.md).\n\n Examples:\n clitree archaeology git # help + history\n clitree archaeology docker --no-cache # bypass cache\n clitree archaeology bun --format json # JSON output\n\n Options:\n --no-cache Skip cache, always re-run\n --max-depth <n> Max --help recursion depth (default: 2)\n --format <fmt> Output format: ansi (default), json\n --no-color Disable ANSI colors (also auto-disabled when stdout is not a TTY)\n -h, --help Show this help\n`);\n}\n\nfunction printFlowHelp() {\n\tconsole.log(`\n cli-tree flow — Render a CLI workflow YAML as a DAG\n\n Usage:\n cli-tree flow <file> [options]\n\n Examples:\n cli-tree flow workflows/git-pr-flow.yml\n cli-tree flow my-workflow.yml --format html > flow.html\n cli-tree flow workflows/docker-deploy.yml --compact --no-color\n\n Options:\n --compact Hide description and legend\n --no-color Disable colors\n --format <fmt> Output format: ansi (default), string, html\n --no-validate Skip validation\n -h, --help Show this help\n`);\n}\n\nasync function runTree(args: string[]) {\n\tconst opts: TreeOptions = {\n\t\tcolor: true,\n\t\tshowFlags: true,\n\t\tshowArgs: true,\n\t\tshowDescriptions: true,\n\t\tshowTypes: true,\n\t\tshowDefaults: true,\n\t\tcompact: false,\n\t};\n\n\tlet depth = 2;\n\tlet format: \"ansi\" | \"string\" | \"html\" | \"json\" = \"ansi\";\n\tlet stdinName: string | null = null;\n\tlet binary: string | null = null;\n\n\topts.color = shouldUseColor(args);\n\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i]!;\n\t\tif (arg === \"--depth\" && args[i + 1]) {\n\t\t\tdepth = Number.parseInt(args[++i]!, 10);\n\t\t} else if (arg === \"--compact\") {\n\t\t\topts.compact = true;\n\t\t\topts.showDescriptions = false;\n\t\t} else if (arg === \"--no-flags\") {\n\t\t\topts.showFlags = false;\n\t\t} else if (arg === \"--no-args\") {\n\t\t\topts.showArgs = false;\n\t\t} else if (arg === \"--no-color\") {\n\t\t\topts.color = false;\n\t\t} else if (arg === \"--format\" && args[i + 1]) {\n\t\t\tformat = args[++i] as \"ansi\" | \"string\" | \"html\" | \"json\";\n\t\t} else if (arg === \"--stdin\" && args[i + 1]) {\n\t\t\tstdinName = args[++i]!;\n\t\t} else if (!arg.startsWith(\"-\")) {\n\t\t\tbinary = arg;\n\t\t}\n\t}\n\n\ttry {\n\t\tlet tree;\n\t\tif (stdinName) {\n\t\t\tconst input = await readStdin();\n\t\t\ttree = parseHelp(stdinName, input);\n\t\t} else if (binary) {\n\t\t\ttree = await parseHelpRecursive(binary, [], depth);\n\t\t} else {\n\t\t\tconsole.error(\"Error: provide a binary name or use --stdin <name>\");\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tif (format === \"json\") {\n\t\t\tconsole.log(JSON.stringify(tree, null, 2));\n\t\t} else if (format === \"html\") {\n\t\t\tconsole.log(treeToHtml(tree, opts));\n\t\t} else if (format === \"string\") {\n\t\t\tconsole.log(treeToString(tree, opts));\n\t\t} else {\n\t\t\tprintTree(tree, opts);\n\t\t}\n\t} catch (err: any) {\n\t\tconsole.error(`Error: ${err.message}`);\n\t\tprocess.exit(1);\n\t}\n}\n\nasync function runFlow(args: string[]) {\n\tconst opts: FlowRenderOptions = {\n\t\tcolor: true,\n\t\tshowDescriptions: true,\n\t\tshowCommands: true,\n\t\tcompact: false,\n\t};\n\n\tlet format: \"ansi\" | \"string\" | \"html\" = \"ansi\";\n\tlet file: string | null = null;\n\tlet skipValidate = false;\n\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i]!;\n\t\tif (arg === \"--compact\") {\n\t\t\topts.compact = true;\n\t\t\topts.showDescriptions = false;\n\t\t} else if (arg === \"--no-color\") {\n\t\t\topts.color = false;\n\t\t} else if (arg === \"--no-validate\") {\n\t\t\tskipValidate = true;\n\t\t} else if (arg === \"--format\" && args[i + 1]) {\n\t\t\tformat = args[++i] as \"ansi\" | \"string\" | \"html\";\n\t\t} else if (!arg.startsWith(\"-\")) {\n\t\t\tfile = arg;\n\t\t}\n\t}\n\n\tif (!file) {\n\t\tconsole.error(\"Error: provide a workflow YAML file\");\n\t\tconsole.error(\"Run 'cli-tree flow --help' for usage\");\n\t\tprocess.exit(1);\n\t}\n\n\ttry {\n\t\tconst text = await Bun.file(file).text();\n\t\tconst workflow = parseWorkflow(text);\n\n\t\tif (!skipValidate) {\n\t\t\tconst result = validateWorkflow(workflow);\n\t\t\tfor (const err of result.errors) {\n\t\t\t\tconst prefix = err.severity === \"error\" ? \"\\x1b[31m✗\" : \"\\x1b[33m⚠\";\n\t\t\t\tconst reset = \"\\x1b[0m\";\n\t\t\t\tconst location = err.node ? ` [${err.node}]` : err.edge ? ` [${err.edge.from}→${err.edge.to}]` : \"\";\n\t\t\t\tconsole.error(`${prefix}${location} ${err.message}${reset}`);\n\t\t\t}\n\t\t\tif (!result.valid) process.exit(1);\n\t\t}\n\n\t\tif (format === \"html\") {\n\t\t\tconsole.log(flowToHtml(workflow, opts));\n\t\t} else if (format === \"string\") {\n\t\t\tconsole.log(flowToString(workflow, opts));\n\t\t} else {\n\t\t\tconsole.log(flowToAnsi(workflow, opts));\n\t\t}\n\t} catch (err: any) {\n\t\tconsole.error(`Error: ${err.message}`);\n\t\tprocess.exit(1);\n\t}\n}\n\nasync function readStdin(): Promise<string> {\n\tconst chunks: Buffer[] = [];\n\tfor await (const chunk of process.stdin) {\n\t\tchunks.push(chunk as Buffer);\n\t}\n\treturn Buffer.concat(chunks).toString(\"utf-8\");\n}\n\nfunction stripOverstrike(text: string): string {\n\t// Strip nroff bold via char\\bchar, underline via _\\bchar, and stray control chars.\n\t// This is what `col -bx` does.\n\treturn text\n\t\t.replace(/(.)\\b\\1/g, \"$1\")\n\t\t.replace(/_\\b(.)/g, \"$1\")\n\t\t.replace(/\\b/g, \"\")\n\t\t.replace(/\\x1b\\[[0-9;]*[a-zA-Z]/g, \"\");\n}\n\nfunction looksLikeHelp(text: string): boolean {\n\tif (!text.trim()) return false;\n\tif (text.length < 40) return false;\n\tconst firstChunk = text.slice(0, 200).toLowerCase();\n\t// Error messages from unknown subcommands or unsupported flags\n\tif (/(unknown|invalid|no such|not a \\w+ command|flag needs an argument|unrecognized)/.test(firstChunk)) {\n\t\treturn false;\n\t}\n\t// \"Run '... --help' for more information\" is a hint, not the help itself\n\tif (/run '.+' for more information/.test(firstChunk)) return false;\n\treturn true;\n}\n\nasync function tryHelpVariant(binary: string, argv: string[], timeoutMs = 5000): Promise<string | null> {\n\ttry {\n\t\tconst proc = Bun.spawn([binary, ...argv], {\n\t\t\tstdout: \"pipe\",\n\t\t\tstderr: \"pipe\",\n\t\t\tenv: { ...process.env, PAGER: \"cat\", MANPAGER: \"cat\", GIT_PAGER: \"cat\" },\n\t\t});\n\n\t\tconst timer = setTimeout(() => proc.kill(), timeoutMs);\n\n\t\tconst [stdout, stderr] = await Promise.all([\n\t\t\tnew Response(proc.stdout).text(),\n\t\t\tnew Response(proc.stderr).text(),\n\t\t]);\n\t\tclearTimeout(timer);\n\t\tawait proc.exited;\n\n\t\tconst combined = stdout || stderr;\n\t\tif (!looksLikeHelp(combined)) return null;\n\t\treturn stripOverstrike(combined);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function tryManPage(binary: string, subPath: string[], timeoutMs = 5000): Promise<string | null> {\n\t// Try 'man binary-sub' (git-commit), then 'man binary sub' as a fallback.\n\tconst candidates = [\n\t\tsubPath.length > 0 ? [`${binary}-${subPath.join(\"-\")}`] : [binary],\n\t\t[binary, ...subPath],\n\t];\n\n\tfor (const args of candidates) {\n\t\ttry {\n\t\t\tconst proc = Bun.spawn([\"man\", ...args], {\n\t\t\t\tstdout: \"pipe\",\n\t\t\t\tstderr: \"pipe\",\n\t\t\t\tenv: { ...process.env, MANPAGER: \"cat\", PAGER: \"cat\" },\n\t\t\t});\n\n\t\t\tconst timer = setTimeout(() => proc.kill(), timeoutMs);\n\t\t\tconst [stdout] = await Promise.all([\n\t\t\t\tnew Response(proc.stdout).text(),\n\t\t\t\tnew Response(proc.stderr).text(),\n\t\t\t]);\n\t\t\tclearTimeout(timer);\n\t\t\tawait proc.exited;\n\n\t\t\tif (looksLikeHelp(stdout)) return stripOverstrike(stdout);\n\t\t} catch {}\n\t}\n\treturn null;\n}\n\nasync function runSafeHelp(args: string[]) {\n\tlet binary: string | null = null;\n\tconst subPath: string[] = [];\n\n\tfor (const arg of args) {\n\t\tif (arg === \"--no-color\" || arg === \"--help\" || arg === \"-h\") continue;\n\t\tif (!binary) {\n\t\t\tbinary = arg;\n\t\t} else {\n\t\t\tsubPath.push(arg);\n\t\t}\n\t}\n\n\tif (!binary) {\n\t\tconsole.error(\"Error: provide a binary name\");\n\t\tconsole.error(\"Run 'clitree safe-help --help' for usage\");\n\t\tprocess.exit(1);\n\t}\n\n\t// Strategy in order of preference:\n\t// 1. `<cli> <sub> -h` — short inline help, no pager\n\t// 2. `<cli> <sub> --help` — long form, overstrike-stripped\n\t// 3. `<cli> help <sub>` — alternate syntax (git, go, bun)\n\t// 4. `man <cli>-<sub>` or `man <cli> <sub>` — final fallback\n\tconst variants: Array<{ label: string; args: string[] }> = [\n\t\t{ label: \"short help (-h)\", args: [...subPath, \"-h\"] },\n\t\t{ label: \"long help (--help)\", args: [...subPath, \"--help\"] },\n\t];\n\n\tif (subPath.length > 0) {\n\t\tvariants.push({ label: \"help subcommand\", args: [\"help\", ...subPath] });\n\t}\n\n\tfor (const variant of variants) {\n\t\tconst output = await tryHelpVariant(binary, variant.args);\n\t\tif (output) {\n\t\t\tprocess.stdout.write(output);\n\t\t\tif (!output.endsWith(\"\\n\")) process.stdout.write(\"\\n\");\n\t\t\treturn;\n\t\t}\n\t}\n\n\t// Last resort: man page\n\tconst manOutput = await tryManPage(binary, subPath);\n\tif (manOutput) {\n\t\tprocess.stdout.write(manOutput);\n\t\tif (!manOutput.endsWith(\"\\n\")) process.stdout.write(\"\\n\");\n\t\treturn;\n\t}\n\n\tconsole.error(`Error: could not fetch help for ${binary} ${subPath.join(\" \")}`);\n\tconsole.error(\"Tried: -h, --help, help subcommand, and man page.\");\n\tprocess.exit(1);\n}\n\nfunction shouldUseColor(args: string[]): boolean {\n\tif (args.includes(\"--no-color\")) return false;\n\tif (process.env.NO_COLOR) return false;\n\tif (process.env.FORCE_COLOR) return true;\n\treturn !!process.stdout.isTTY;\n}\n\nfunction makeColors(enabled: boolean) {\n\tif (!enabled) {\n\t\treturn { reset: \"\", bold: \"\", dim: \"\", cyan: \"\", green: \"\", yellow: \"\", red: \"\", magenta: \"\", gray: \"\" };\n\t}\n\treturn {\n\t\treset: \"\\x1b[0m\",\n\t\tbold: \"\\x1b[1m\",\n\t\tdim: \"\\x1b[2m\",\n\t\tcyan: \"\\x1b[36m\",\n\t\tgreen: \"\\x1b[32m\",\n\t\tyellow: \"\\x1b[33m\",\n\t\tred: \"\\x1b[31m\",\n\t\tmagenta: \"\\x1b[35m\",\n\t\tgray: \"\\x1b[90m\",\n\t};\n}\n\nasync function runMine(args: string[]) {\n\tlet binary: string | null = null;\n\tlet minSupport = 3;\n\tlet historyPath: string | undefined;\n\tlet format: \"ansi\" | \"json\" = \"ansi\";\n\tlet maxPaths = 10;\n\tlet withFlow: \"auto\" | \"on\" | \"off\" = \"auto\";\n\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i]!;\n\t\tif (arg === \"--min-support\" && args[i + 1]) {\n\t\t\tminSupport = Number.parseInt(args[++i]!, 10);\n\t\t} else if (arg === \"--history-path\" && args[i + 1]) {\n\t\t\thistoryPath = args[++i]!;\n\t\t} else if (arg === \"--format\" && args[i + 1]) {\n\t\t\tformat = args[++i] as \"ansi\" | \"json\";\n\t\t} else if (arg === \"--max-paths\" && args[i + 1]) {\n\t\t\tmaxPaths = Number.parseInt(args[++i]!, 10);\n\t\t} else if (arg === \"--with-flow\" || arg === \"--flow\") {\n\t\t\twithFlow = \"on\";\n\t\t} else if (arg === \"--no-flow\") {\n\t\t\twithFlow = \"off\";\n\t\t} else if (arg !== \"--no-color\" && !arg.startsWith(\"-\")) {\n\t\t\tbinary = arg;\n\t\t}\n\t}\n\n\tif (!binary) {\n\t\tconsole.error(\"Error: provide a binary name\");\n\t\tconsole.error(\"Run 'clitree mine --help' for usage\");\n\t\tprocess.exit(1);\n\t}\n\n\ttry {\n\t\tconst result = await mineCli(binary, { minSupport, historyPath });\n\n\t\tif (format === \"json\") {\n\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\treturn;\n\t\t}\n\n\t\tconst C = makeColors(shouldUseColor(args));\n\n\t\tconsole.log(`\\n${C.bold}${C.magenta}${binary}${C.reset} ${C.gray}— shell history analysis${C.reset}\\n`);\n\t\tconsole.log(`${C.bold}Usage:${C.reset}`);\n\t\tconsole.log(` ${C.dim}Invocations:${C.reset} ${C.cyan}${result.stats.totalInvocations}${C.reset}`);\n\t\tconsole.log(` ${C.dim}Subcommands:${C.reset} ${C.cyan}${result.stats.uniqueSubcommands}${C.reset}`);\n\t\tconsole.log(` ${C.dim}Sessions:${C.reset} ${C.cyan}${result.sessionsAnalyzed}${C.reset}\\n`);\n\n\t\tif (result.stats.topSubcommands.length > 0) {\n\t\t\tconsole.log(`${C.bold}Top subcommands:${C.reset}`);\n\t\t\tconst max = result.stats.topSubcommands[0]!.count;\n\t\t\tfor (const { subcommand, count } of result.stats.topSubcommands.slice(0, 5)) {\n\t\t\t\tconst bar = \"█\".repeat(Math.max(1, Math.round((count / max) * 30)));\n\t\t\t\tconsole.log(` ${C.green}${subcommand.padEnd(20)}${C.reset} ${C.cyan}${bar}${C.reset} ${C.dim}${count}${C.reset}`);\n\t\t\t}\n\t\t\tconsole.log();\n\t\t}\n\n\t\tif (result.workflows.length > 0) {\n\t\t\tconsole.log(`${C.bold}Discovered workflows:${C.reset}`);\n\t\t\tfor (const wf of result.workflows.slice(0, maxPaths)) {\n\t\t\t\tconst chain = wf.path[0]!.map(p => `${C.green}${p}${C.reset}`).join(` ${C.gray}→${C.reset} `);\n\t\t\t\tconsole.log(` ${chain} ${C.dim}(${wf.support}×)${C.reset}`);\n\t\t\t}\n\t\t\tconsole.log();\n\t\t}\n\n\t\tif (result.suggestions.length > 0) {\n\t\t\tconsole.log(`${C.bold}${C.yellow}💡 Skill suggestions:${C.reset}`);\n\t\t\tfor (const s of result.suggestions.slice(0, 3)) {\n\t\t\t\tconst badge =\n\t\t\t\t\ts.priority === \"high\"\n\t\t\t\t\t\t? `${C.green}[HIGH]${C.reset}`\n\t\t\t\t\t\t: s.priority === \"medium\"\n\t\t\t\t\t\t\t? `${C.yellow}[MED]${C.reset}`\n\t\t\t\t\t\t\t: `${C.dim}[LOW]${C.reset}`;\n\t\t\t\tconsole.log(`\\n ${badge} ${C.bold}/${s.name}${C.reset} — ${s.description}`);\n\t\t\t\tconsole.log(` ${C.dim}${s.reason}${C.reset}`);\n\t\t\t\tconsole.log(` ${C.dim}${s.commands.join(\" && \")}${C.reset}`);\n\t\t\t}\n\t\t\tconsole.log();\n\t\t}\n\n\t\t// Pick the top workflow worth visualizing as a DAG.\n\t\t// In \"auto\" mode, prefer the highest-support workflow with 3+ steps —\n\t\t// 2-step chains are more readable as text than as boxed diagrams.\n\t\t// In \"on\" mode, render whatever is the top regardless of length.\n\t\t// In \"off\" mode, skip.\n\t\tif (withFlow !== \"off\") {\n\t\t\tconst minSteps = withFlow === \"on\" ? 2 : 3;\n\t\t\tconst topForFlow = pickWorkflowForFlow(result.workflows, minSteps);\n\t\t\tif (topForFlow) {\n\t\t\t\tconst flowWorkflow = minedToFlowWorkflow(topForFlow);\n\t\t\t\tconst rendered = shouldUseColor(args) ? flowToAnsi(flowWorkflow) : flowToString(flowWorkflow);\n\t\t\t\tconsole.log(`${C.bold}Top workflow (visualized):${C.reset}`);\n\t\t\t\tconsole.log(rendered);\n\t\t\t\tconsole.log();\n\t\t\t}\n\t\t}\n\t} catch (err: any) {\n\t\tconsole.error(`Error: ${err.message}`);\n\t\tprocess.exit(1);\n\t}\n}\n\nfunction pickWorkflowForFlow<T extends { path: string[][]; support: number }>(\n\tworkflows: T[],\n\tminSteps = 3,\n): T | null {\n\tfor (const wf of workflows) {\n\t\tconst len = wf.path[0]?.length ?? 0;\n\t\tif (len >= minSteps) return wf;\n\t}\n\treturn null;\n}\n\nasync function runArchaeologyCmd(args: string[]) {\n\tlet binary: string | null = null;\n\tlet skipCache = false;\n\tlet maxDepth = 2;\n\tlet format: \"ansi\" | \"json\" = \"ansi\";\n\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i]!;\n\t\tif (arg === \"--no-cache\") {\n\t\t\tskipCache = true;\n\t\t} else if (arg === \"--max-depth\" && args[i + 1]) {\n\t\t\tmaxDepth = Number.parseInt(args[++i]!, 10);\n\t\t} else if (arg === \"--format\" && args[i + 1]) {\n\t\t\tformat = args[++i] as \"ansi\" | \"json\";\n\t\t} else if (arg !== \"--no-color\" && !arg.startsWith(\"-\")) {\n\t\t\tbinary = arg;\n\t\t}\n\t}\n\n\tif (!binary) {\n\t\tconsole.error(\"Error: provide a binary name\");\n\t\tconsole.error(\"Run 'clitree archaeology --help' for usage\");\n\t\tprocess.exit(1);\n\t}\n\n\tconst C = makeColors(shouldUseColor(args));\n\n\ttry {\n\t\tconsole.error(`${C.dim}⚠ LLM archaeology requires running inside the clitree skill.${C.reset}`);\n\t\tconsole.error(`${C.dim} Running deterministic phases only (help + history mining).${C.reset}`);\n\t\tconsole.error(\"\");\n\n\t\tconst [arch, mine] = await Promise.all([\n\t\t\trunArchaeology(binary, new NullDelegate(), { skipCache, maxHelpDepth: maxDepth }),\n\t\t\tmineCli(binary, { minSupport: 3 }).catch(() => null),\n\t\t]);\n\n\t\tif (format === \"json\") {\n\t\t\tconsole.log(JSON.stringify({ archaeology: arch, mining: mine }, null, 2));\n\t\t\treturn;\n\t\t}\n\n\t\tconsole.log(`${C.bold}${C.magenta}${binary}${C.reset}`);\n\t\tif (arch.tree.description) {\n\t\t\tconsole.log(`${C.gray}${arch.tree.description}${C.reset}`);\n\t\t}\n\t\tconsole.log();\n\n\t\tconsole.log(`${C.bold}Tree:${C.reset}`);\n\t\tconsole.log(` ${C.dim}Commands:${C.reset} ${C.cyan}${arch.stats.helpCommands}${C.reset}`);\n\t\tconsole.log(` ${C.dim}Cached:${C.reset} ${arch.fromCache ? `${C.green}yes${C.reset}` : `${C.dim}no${C.reset}`}`);\n\t\tconsole.log();\n\n\t\tif (mine) {\n\t\t\tconsole.log(`${C.bold}Usage from shell history:${C.reset}`);\n\t\t\tconsole.log(` ${C.dim}Invocations:${C.reset} ${C.cyan}${mine.stats.totalInvocations}${C.reset}`);\n\t\t\tconsole.log(` ${C.dim}Subcommands:${C.reset} ${C.cyan}${mine.stats.uniqueSubcommands}${C.reset}`);\n\n\t\t\tif (mine.workflows.length > 0) {\n\t\t\t\tconsole.log(`\\n${C.bold}Workflows you repeat:${C.reset}`);\n\t\t\t\tfor (const wf of mine.workflows.slice(0, 5)) {\n\t\t\t\t\tconst chain = wf.path[0]!.map(p => `${C.green}${p}${C.reset}`).join(` ${C.gray}→${C.reset} `);\n\t\t\t\t\tconsole.log(` ${chain} ${C.dim}(${wf.support}×)${C.reset}`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (mine.suggestions.length > 0) {\n\t\t\t\tconsole.log(`\\n${C.bold}${C.yellow}💡 Skill suggestions:${C.reset}`);\n\t\t\t\tfor (const s of mine.suggestions.slice(0, 3)) {\n\t\t\t\t\tconsole.log(` ${C.bold}/${s.name}${C.reset} — ${s.description}`);\n\t\t\t\t\tconsole.log(` ${C.dim}${s.reason}${C.reset}`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconsole.log();\n\t\tconsole.log(`${C.dim}Install the clitree skill for full LLM archaeology:${C.reset}`);\n\t\tconsole.log(`${C.dim} bash ./skill/install.sh${C.reset}`);\n\t\tconsole.log();\n\t} catch (err: any) {\n\t\tconsole.error(`${C.red}Error: ${err.message}${C.reset}`);\n\t\tprocess.exit(1);\n\t}\n}\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "FADAD3DCBCB5252964756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "6575AA9BC14C249964756E2164756E21",
9
9
  "names": []
10
10
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crafter/cli-tree",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Explore and map any CLI tool deeply. Parse --help trees, mine shell history for repeated workflows, surface hidden flags via LLM archaeology, and suggest new agent skills from your usage patterns.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/skill/SKILL.md CHANGED
@@ -87,7 +87,15 @@ Read the result. You get:
87
87
  $CLITREE mine "$TARGET_BINARY"
88
88
  ```
89
89
 
90
- This prints a colorized block with **ASCII bar charts** for top subcommands and a ranked list of discovered workflows with frequency counts. **Capture this entire block — you'll paste it verbatim inside a fenced code block in the `## Your usage` section of the final report.** Do not re-type it; the bar chart is the value.
90
+ This prints a single rich block containing **three visualizations at once**:
91
+
92
+ 1. **ASCII bar charts** for the user's top subcommands (ranked with Unicode `██` bars)
93
+ 2. **A ranked workflow list** with frequency counts (`add → commit → push (64×)`)
94
+ 3. **An ASCII DAG** of the top non-trivial workflow — boxed nodes with arrows, rendered with the same engine as the bundled workflow YAMLs
95
+
96
+ **Capture this entire block — you'll paste it verbatim inside a fenced code block in the `## Your usage` section of the final report.** Do not re-type any part of it. The bars, the workflow list, and the DAG are all value-dense visuals that don't translate well to prose.
97
+
98
+ The DAG auto-renders when the top workflow has 3+ steps. Pass `--with-flow` to force it on for 2-step chains, or `--no-flow` to skip it entirely.
91
99
 
92
100
  Three scenarios from the invocation count:
93
101
 
@@ -116,24 +124,77 @@ For detailed prompt templates that help you think through each category systemat
116
124
 
117
125
  ## Phase 4 — Validate every proposal
118
126
 
119
- This is the step that separates archaeology from hallucination. For each flag you propose, verify it exists:
127
+ This is the step that separates archaeology from hallucination. For each flag you propose, verify it exists.
128
+
129
+ ### The right way to query help
130
+
131
+ **Short help vs long help matters.** Most CLIs have two help outputs:
132
+
133
+ - `<cli> <sub> -h` → **short inline help** (fast, plain text, no pager)
134
+ - `<cli> <sub> --help` → **long help / man page** (slow, may open a pager, often has overstrike formatting)
135
+
136
+ For **git specifically**, `git <cmd> --help` is equivalent to `man git-<cmd>`, which:
137
+ - Opens a pager in a TTY (hangs the agent)
138
+ - Pipes raw `nroff` output with overstrike sequences (`\b`) in a non-TTY — you get `ffiixxuupp` instead of `fixup`
139
+
140
+ **Always prefer `-h` first.** Fall back to `--help` only if `-h` doesn't exist for that CLI.
141
+
142
+ ### Recommended validation patterns
143
+
144
+ **The easy way — use the `safe-help` subcommand.** It tries `-h`, `--help`, `help <sub>`, and man pages in order, strips overstrike formatting, kills pagers, and returns clean text every time:
120
145
 
121
146
  ```bash
122
- # Primary check: is it in --help?
123
- "$TARGET_BINARY" "$SUBCOMMAND" --help 2>&1 | grep -E "(--<flag>|-<short>\\b)"
147
+ # Fetch clean help for any CLI subcommand
148
+ $CLITREE safe-help git commit | grep -E -- "--fixup|--amend|--no-verify"
149
+ $CLITREE safe-help docker run | grep -E -- "--gpus|--platform"
150
+ $CLITREE safe-help kubectl get | grep -E -- "--selector|--output"
151
+ ```
152
+
153
+ **Always prefer `safe-help` over raw `--help`.** It handles:
154
+ - `git <cmd> --help` opening a man pager and hanging
155
+ - macOS nroff overstriking (`ffiixxuupp` → `fixup`)
156
+ - CLIs where `-h` isn't supported (like docker subcommands)
157
+ - CLIs where the help lives under `help <sub>` syntax (like git's own internal convention)
158
+
159
+ **If you must call the binary directly** (e.g. the user's CLI isn't mainstream), follow this precedence:
160
+
161
+ ```bash
162
+ # Pattern 1 (preferred): short help, inline, no pager
163
+ "$TARGET_BINARY" "$SUBCOMMAND" -h 2>&1 | grep -E -- "--<flag>|-<short>\b"
124
164
 
125
- # Fallback: man page
126
- man "$TARGET_BINARY" 2>/dev/null | grep -E "(--<flag>|-<short>\\b)" | head -5
165
+ # Pattern 2 (git-safe): force man page through col to strip overstrikes
166
+ MANPAGER=cat PAGER=cat man "git-$SUBCOMMAND" 2>/dev/null | col -bx | grep -E -- "--<flag>|-<short>\b"
167
+
168
+ # Pattern 3 (fallback): man for non-git binaries
169
+ MANPAGER=cat PAGER=cat man "$TARGET_BINARY" 2>/dev/null | col -bx | grep -E -- "--<flag>|-<short>\b"
127
170
  ```
128
171
 
172
+ **Key details:**
173
+ - `--` before the pattern tells grep the rest isn't options (otherwise `-S` in the pattern breaks grep)
174
+ - `col -bx` strips overstrike/bold formatting → no more `ffiixxuupp`
175
+ - `MANPAGER=cat PAGER=cat` prevents pagers from opening in edge cases
176
+ - `2>&1` captures stderr so grep sees error messages too
177
+
178
+ ### What to do with each result
179
+
129
180
  Mark each finding:
130
- - **`verified`** — appears in `--help`
131
- - **`verified-by-man`** — not in help, but man confirms
181
+ - **`verified`** — appears in `<cli> <sub> -h`
182
+ - **`verified-by-man`** — not in short help, but man confirms after `col -bx`
132
183
  - **`unconfirmed`** — neither confirms; keep only if you're highly confident AND can explain the evidence (e.g. "shown in docker/docker#12345")
133
184
  - **`rejected`** — fail to validate → drop it silently, never include in final output
134
185
 
135
186
  Better to surface 3 verified flags than 10 unconfirmed ones. **Your credibility is built on rejection rate.** When you mark something unconfirmed, explain why you still believe it.
136
187
 
188
+ ### Pitfalls observed in the wild
189
+
190
+ - **`git commit --help` opens a man page**, not inline help. Use `git commit -h` instead.
191
+ - **`docker --help` pipes fine**, but `docker run --help` is long and truncates at tty width if piped through `head`.
192
+ - **`kubectl <sub> --help`** is safe and inline — no pager issues.
193
+ - **`bun <sub> --help`** is safe and inline.
194
+ - **`pnpm <sub> --help`** is safe and inline.
195
+ - **BSD/macOS `man` overstrikes bold text with `\b`.** Always pipe through `col -bx` when parsing man output.
196
+ - **Never paste raw man output into the report.** If you see `ffiixxuupp`, that's overstriking — filter it first or use `-h` instead.
197
+
137
198
  ## Phase 5 — Render the report
138
199
 
139
200
  Produce this exact structure. Consistency matters — the user learns the shape and scans it quickly on future runs.
package/src/cli.ts CHANGED
@@ -10,7 +10,7 @@ import { runArchaeology, NullDelegate } from "./archaeology";
10
10
  const args = process.argv.slice(2);
11
11
  const subcommand = args[0];
12
12
 
13
- const HELP_SUBCOMMANDS = new Set(["flow", "mine", "archaeology"]);
13
+ const HELP_SUBCOMMANDS = new Set(["flow", "mine", "archaeology", "safe-help"]);
14
14
  const isHelpFlag = args.includes("--help") || args.includes("-h");
15
15
 
16
16
  if (!subcommand || (isHelpFlag && !HELP_SUBCOMMANDS.has(subcommand ?? ""))) {
@@ -22,6 +22,7 @@ if (isHelpFlag) {
22
22
  if (subcommand === "flow") printFlowHelp();
23
23
  else if (subcommand === "mine") printMineHelp();
24
24
  else if (subcommand === "archaeology") printArchaeologyHelp();
25
+ else if (subcommand === "safe-help") printSafeHelpHelp();
25
26
  else printMainHelp();
26
27
  process.exit(0);
27
28
  }
@@ -32,6 +33,8 @@ if (subcommand === "flow") {
32
33
  await runMine(args.slice(1));
33
34
  } else if (subcommand === "archaeology") {
34
35
  await runArchaeologyCmd(args.slice(1));
36
+ } else if (subcommand === "safe-help") {
37
+ await runSafeHelp(args.slice(1));
35
38
  } else {
36
39
  await runTree(args);
37
40
  }
@@ -45,22 +48,60 @@ function printMainHelp() {
45
48
  clitree flow <file> [options] Render a workflow YAML as a DAG
46
49
  clitree mine <binary> [options] Mine shell history for workflows
47
50
  clitree archaeology <binary> [options] Full analysis: tree + mining + (LLM)
51
+ clitree safe-help <binary> [sub...] Fetch clean help for any CLI (no pager, no overstriking)
48
52
 
49
53
  Examples:
50
54
  clitree docker # basic tree
51
55
  clitree mine git # "what workflows do I repeat with git?"
52
56
  clitree archaeology bun # tree + mining + LLM archaeology
57
+ clitree safe-help git commit # avoid the git man-page pager trap
53
58
 
54
59
  Subcommands:
55
60
  tree Parse --help output (default; passing a binary name invokes this)
56
61
  flow Render a workflow YAML file as an ASCII DAG
57
62
  mine Discover workflows from your shell history
58
63
  archaeology Run full analysis (tree + mine + LLM proposals when available)
64
+ safe-help Return inline help for any CLI, handling pager/overstrike edge cases
59
65
 
60
66
  Help for a subcommand: clitree <subcommand> --help
61
67
  `);
62
68
  }
63
69
 
70
+ function printSafeHelpHelp() {
71
+ console.log(`
72
+ clitree safe-help — Fetch clean help output for any CLI
73
+
74
+ Usage:
75
+ clitree safe-help <binary> [subcommand...] [options]
76
+
77
+ Why this exists:
78
+ Running '<cli> --help' directly is a minefield on agents and scripts:
79
+ - 'git commit --help' opens a pager in a TTY and hangs
80
+ - Piping 'git <sub> --help' returns nroff with overstrike (ffiixxuupp)
81
+ - Some CLIs use 'help <sub>' instead of '<sub> --help'
82
+ - macOS man pages emit \\b sequences that need col -bx
83
+
84
+ safe-help tries the right variants in order, cleans overstrikes, and
85
+ returns plain text every time.
86
+
87
+ Strategy (in order):
88
+ 1. <cli> <sub> -h — short inline help
89
+ 2. <cli> <sub> --help — long help (captured, overstrike-stripped)
90
+ 3. <cli> help <sub> — alternate syntax
91
+ 4. MANPAGER=cat man <cli>-<sub> | col -bx — final man fallback
92
+
93
+ Examples:
94
+ clitree safe-help git commit
95
+ clitree safe-help docker run
96
+ clitree safe-help kubectl get pods
97
+ clitree safe-help bun install
98
+
99
+ Options:
100
+ --no-color Disable ANSI codes (auto-detects non-TTY)
101
+ -h, --help Show this help
102
+ `);
103
+ }
104
+
64
105
  function printMineHelp() {
65
106
  console.log(`
66
107
  clitree mine — Mine your shell history for CLI workflows
@@ -272,6 +313,138 @@ async function readStdin(): Promise<string> {
272
313
  return Buffer.concat(chunks).toString("utf-8");
273
314
  }
274
315
 
316
+ function stripOverstrike(text: string): string {
317
+ // Strip nroff bold via char\bchar, underline via _\bchar, and stray control chars.
318
+ // This is what `col -bx` does.
319
+ return text
320
+ .replace(/(.)\b\1/g, "$1")
321
+ .replace(/_\b(.)/g, "$1")
322
+ .replace(/\b/g, "")
323
+ .replace(/\x1b\[[0-9;]*[a-zA-Z]/g, "");
324
+ }
325
+
326
+ function looksLikeHelp(text: string): boolean {
327
+ if (!text.trim()) return false;
328
+ if (text.length < 40) return false;
329
+ const firstChunk = text.slice(0, 200).toLowerCase();
330
+ // Error messages from unknown subcommands or unsupported flags
331
+ if (/(unknown|invalid|no such|not a \w+ command|flag needs an argument|unrecognized)/.test(firstChunk)) {
332
+ return false;
333
+ }
334
+ // "Run '... --help' for more information" is a hint, not the help itself
335
+ if (/run '.+' for more information/.test(firstChunk)) return false;
336
+ return true;
337
+ }
338
+
339
+ async function tryHelpVariant(binary: string, argv: string[], timeoutMs = 5000): Promise<string | null> {
340
+ try {
341
+ const proc = Bun.spawn([binary, ...argv], {
342
+ stdout: "pipe",
343
+ stderr: "pipe",
344
+ env: { ...process.env, PAGER: "cat", MANPAGER: "cat", GIT_PAGER: "cat" },
345
+ });
346
+
347
+ const timer = setTimeout(() => proc.kill(), timeoutMs);
348
+
349
+ const [stdout, stderr] = await Promise.all([
350
+ new Response(proc.stdout).text(),
351
+ new Response(proc.stderr).text(),
352
+ ]);
353
+ clearTimeout(timer);
354
+ await proc.exited;
355
+
356
+ const combined = stdout || stderr;
357
+ if (!looksLikeHelp(combined)) return null;
358
+ return stripOverstrike(combined);
359
+ } catch {
360
+ return null;
361
+ }
362
+ }
363
+
364
+ async function tryManPage(binary: string, subPath: string[], timeoutMs = 5000): Promise<string | null> {
365
+ // Try 'man binary-sub' (git-commit), then 'man binary sub' as a fallback.
366
+ const candidates = [
367
+ subPath.length > 0 ? [`${binary}-${subPath.join("-")}`] : [binary],
368
+ [binary, ...subPath],
369
+ ];
370
+
371
+ for (const args of candidates) {
372
+ try {
373
+ const proc = Bun.spawn(["man", ...args], {
374
+ stdout: "pipe",
375
+ stderr: "pipe",
376
+ env: { ...process.env, MANPAGER: "cat", PAGER: "cat" },
377
+ });
378
+
379
+ const timer = setTimeout(() => proc.kill(), timeoutMs);
380
+ const [stdout] = await Promise.all([
381
+ new Response(proc.stdout).text(),
382
+ new Response(proc.stderr).text(),
383
+ ]);
384
+ clearTimeout(timer);
385
+ await proc.exited;
386
+
387
+ if (looksLikeHelp(stdout)) return stripOverstrike(stdout);
388
+ } catch {}
389
+ }
390
+ return null;
391
+ }
392
+
393
+ async function runSafeHelp(args: string[]) {
394
+ let binary: string | null = null;
395
+ const subPath: string[] = [];
396
+
397
+ for (const arg of args) {
398
+ if (arg === "--no-color" || arg === "--help" || arg === "-h") continue;
399
+ if (!binary) {
400
+ binary = arg;
401
+ } else {
402
+ subPath.push(arg);
403
+ }
404
+ }
405
+
406
+ if (!binary) {
407
+ console.error("Error: provide a binary name");
408
+ console.error("Run 'clitree safe-help --help' for usage");
409
+ process.exit(1);
410
+ }
411
+
412
+ // Strategy in order of preference:
413
+ // 1. `<cli> <sub> -h` — short inline help, no pager
414
+ // 2. `<cli> <sub> --help` — long form, overstrike-stripped
415
+ // 3. `<cli> help <sub>` — alternate syntax (git, go, bun)
416
+ // 4. `man <cli>-<sub>` or `man <cli> <sub>` — final fallback
417
+ const variants: Array<{ label: string; args: string[] }> = [
418
+ { label: "short help (-h)", args: [...subPath, "-h"] },
419
+ { label: "long help (--help)", args: [...subPath, "--help"] },
420
+ ];
421
+
422
+ if (subPath.length > 0) {
423
+ variants.push({ label: "help subcommand", args: ["help", ...subPath] });
424
+ }
425
+
426
+ for (const variant of variants) {
427
+ const output = await tryHelpVariant(binary, variant.args);
428
+ if (output) {
429
+ process.stdout.write(output);
430
+ if (!output.endsWith("\n")) process.stdout.write("\n");
431
+ return;
432
+ }
433
+ }
434
+
435
+ // Last resort: man page
436
+ const manOutput = await tryManPage(binary, subPath);
437
+ if (manOutput) {
438
+ process.stdout.write(manOutput);
439
+ if (!manOutput.endsWith("\n")) process.stdout.write("\n");
440
+ return;
441
+ }
442
+
443
+ console.error(`Error: could not fetch help for ${binary} ${subPath.join(" ")}`);
444
+ console.error("Tried: -h, --help, help subcommand, and man page.");
445
+ process.exit(1);
446
+ }
447
+
275
448
  function shouldUseColor(args: string[]): boolean {
276
449
  if (args.includes("--no-color")) return false;
277
450
  if (process.env.NO_COLOR) return false;