@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 +154 -2
- package/dist/cli.js.map +3 -3
- package/package.json +1 -1
- package/skill/SKILL.md +69 -8
- package/src/cli.ts +174 -1
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=
|
|
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": "
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AASA,IAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,IAAM,aAAa,KAAK;AAExB,IAAM,mBAAmB,IAAI,IAAI,CAAC,QAAQ,QAAQ,eAAe,WAAW,CAAC;AAC7E,IAAM,aAAa,KAAK,SAAS,QAAQ,KAAK,KAAK,SAAS,IAAI;AAEhE,IAAI,CAAC,cAAe,cAAc,CAAC,iBAAiB,IAAI,cAAc,EAAE,GAAI;AAAA,EAC3E,cAAc;AAAA,EACd,QAAQ,KAAK,CAAC;AACf;AAEA,IAAI,YAAY;AAAA,EACf,IAAI,eAAe;AAAA,IAAQ,cAAc;AAAA,EACpC,SAAI,eAAe;AAAA,IAAQ,cAAc;AAAA,EACzC,SAAI,eAAe;AAAA,IAAe,qBAAqB;AAAA,EACvD,SAAI,eAAe;AAAA,IAAa,kBAAkB;AAAA,EAClD;AAAA,kBAAc;AAAA,EACnB,QAAQ,KAAK,CAAC;AACf;AAEA,IAAI,eAAe,QAAQ;AAAA,EAC1B,MAAM,QAAQ,KAAK,MAAM,CAAC,CAAC;AAC5B,EAAO,SAAI,eAAe,QAAQ;AAAA,EACjC,MAAM,QAAQ,KAAK,MAAM,CAAC,CAAC;AAC5B,EAAO,SAAI,eAAe,eAAe;AAAA,EACxC,MAAM,kBAAkB,KAAK,MAAM,CAAC,CAAC;AACtC,EAAO,SAAI,eAAe,aAAa;AAAA,EACtC,MAAM,YAAY,KAAK,MAAM,CAAC,CAAC;AAChC,EAAO;AAAA,EACN,MAAM,QAAQ,IAAI;AAAA;AAGnB,SAAS,aAAa,GAAG;AAAA,EACxB,QAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAwBZ;AAAA;AAGD,SAAS,iBAAiB,GAAG;AAAA,EAC5B,QAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CA+BZ;AAAA;AAGD,SAAS,aAAa,GAAG;AAAA,EACxB,QAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAwBZ;AAAA;AAGD,SAAS,oBAAoB,GAAG;AAAA,EAC/B,QAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAqBZ;AAAA;AAGD,SAAS,aAAa,GAAG;AAAA,EACxB,QAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAiBZ;AAAA;AAGD,eAAe,OAAO,CAAC,OAAgB;AAAA,EACtC,MAAM,OAAoB;AAAA,IACzB,OAAO;AAAA,IACP,WAAW;AAAA,IACX,UAAU;AAAA,IACV,kBAAkB;AAAA,IAClB,WAAW;AAAA,IACX,cAAc;AAAA,IACd,SAAS;AAAA,EACV;AAAA,EAEA,IAAI,QAAQ;AAAA,EACZ,IAAI,SAA8C;AAAA,EAClD,IAAI,YAA2B;AAAA,EAC/B,IAAI,SAAwB;AAAA,EAE5B,KAAK,QAAQ,eAAe,KAAI;AAAA,EAEhC,SAAS,IAAI,EAAG,IAAI,MAAK,QAAQ,KAAK;AAAA,IACrC,MAAM,MAAM,MAAK;AAAA,IACjB,IAAI,QAAQ,aAAa,MAAK,IAAI,IAAI;AAAA,MACrC,QAAQ,OAAO,SAAS,MAAK,EAAE,IAAK,EAAE;AAAA,IACvC,EAAO,SAAI,QAAQ,aAAa;AAAA,MAC/B,KAAK,UAAU;AAAA,MACf,KAAK,mBAAmB;AAAA,IACzB,EAAO,SAAI,QAAQ,cAAc;AAAA,MAChC,KAAK,YAAY;AAAA,IAClB,EAAO,SAAI,QAAQ,aAAa;AAAA,MAC/B,KAAK,WAAW;AAAA,IACjB,EAAO,SAAI,QAAQ,cAAc;AAAA,MAChC,KAAK,QAAQ;AAAA,IACd,EAAO,SAAI,QAAQ,cAAc,MAAK,IAAI,IAAI;AAAA,MAC7C,SAAS,MAAK,EAAE;AAAA,IACjB,EAAO,SAAI,QAAQ,aAAa,MAAK,IAAI,IAAI;AAAA,MAC5C,YAAY,MAAK,EAAE;AAAA,IACpB,EAAO,SAAI,CAAC,IAAI,WAAW,GAAG,GAAG;AAAA,MAChC,SAAS;AAAA,IACV;AAAA,EACD;AAAA,EAEA,IAAI;AAAA,IACH,IAAI;AAAA,IACJ,IAAI,WAAW;AAAA,MACd,MAAM,QAAQ,MAAM,UAAU;AAAA,MAC9B,OAAO,UAAU,WAAW,KAAK;AAAA,IAClC,EAAO,SAAI,QAAQ;AAAA,MAClB,OAAO,MAAM,mBAAmB,QAAQ,CAAC,GAAG,KAAK;AAAA,IAClD,EAAO;AAAA,MACN,QAAQ,MAAM,oDAAoD;AAAA,MAClE,QAAQ,KAAK,CAAC;AAAA;AAAA,IAGf,IAAI,WAAW,QAAQ;AAAA,MACtB,QAAQ,IAAI,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,IAC1C,EAAO,SAAI,WAAW,QAAQ;AAAA,MAC7B,QAAQ,IAAI,WAAW,MAAM,IAAI,CAAC;AAAA,IACnC,EAAO,SAAI,WAAW,UAAU;AAAA,MAC/B,QAAQ,IAAI,aAAa,MAAM,IAAI,CAAC;AAAA,IACrC,EAAO;AAAA,MACN,UAAU,MAAM,IAAI;AAAA;AAAA,IAEpB,OAAO,KAAU;AAAA,IAClB,QAAQ,MAAM,UAAU,IAAI,SAAS;AAAA,IACrC,QAAQ,KAAK,CAAC;AAAA;AAAA;AAIhB,eAAe,OAAO,CAAC,OAAgB;AAAA,EACtC,MAAM,OAA0B;AAAA,IAC/B,OAAO;AAAA,IACP,kBAAkB;AAAA,IAClB,cAAc;AAAA,IACd,SAAS;AAAA,EACV;AAAA,EAEA,IAAI,SAAqC;AAAA,EACzC,IAAI,OAAsB;AAAA,EAC1B,IAAI,eAAe;AAAA,EAEnB,SAAS,IAAI,EAAG,IAAI,MAAK,QAAQ,KAAK;AAAA,IACrC,MAAM,MAAM,MAAK;AAAA,IACjB,IAAI,QAAQ,aAAa;AAAA,MACxB,KAAK,UAAU;AAAA,MACf,KAAK,mBAAmB;AAAA,IACzB,EAAO,SAAI,QAAQ,cAAc;AAAA,MAChC,KAAK,QAAQ;AAAA,IACd,EAAO,SAAI,QAAQ,iBAAiB;AAAA,MACnC,eAAe;AAAA,IAChB,EAAO,SAAI,QAAQ,cAAc,MAAK,IAAI,IAAI;AAAA,MAC7C,SAAS,MAAK,EAAE;AAAA,IACjB,EAAO,SAAI,CAAC,IAAI,WAAW,GAAG,GAAG;AAAA,MAChC,OAAO;AAAA,IACR;AAAA,EACD;AAAA,EAEA,IAAI,CAAC,MAAM;AAAA,IACV,QAAQ,MAAM,qCAAqC;AAAA,IACnD,QAAQ,MAAM,sCAAsC;AAAA,IACpD,QAAQ,KAAK,CAAC;AAAA,EACf;AAAA,EAEA,IAAI;AAAA,IACH,MAAM,OAAO,MAAM,IAAI,KAAK,IAAI,EAAE,KAAK;AAAA,IACvC,MAAM,WAAW,cAAc,IAAI;AAAA,IAEnC,IAAI,CAAC,cAAc;AAAA,MAClB,MAAM,SAAS,iBAAiB,QAAQ;AAAA,MACxC,WAAW,OAAO,OAAO,QAAQ;AAAA,QAChC,MAAM,SAAS,IAAI,aAAa,UAAU,cAAa;AAAA,QACvD,MAAM,QAAQ;AAAA,QACd,MAAM,WAAW,IAAI,OAAO,KAAK,IAAI,UAAU,IAAI,OAAO,KAAK,IAAI,KAAK,QAAO,IAAI,KAAK,QAAQ;AAAA,QAChG,QAAQ,MAAM,GAAG,SAAS,YAAY,IAAI,UAAU,OAAO;AAAA,MAC5D;AAAA,MACA,IAAI,CAAC,OAAO;AAAA,QAAO,QAAQ,KAAK,CAAC;AAAA,IAClC;AAAA,IAEA,IAAI,WAAW,QAAQ;AAAA,MACtB,QAAQ,IAAI,WAAW,UAAU,IAAI,CAAC;AAAA,IACvC,EAAO,SAAI,WAAW,UAAU;AAAA,MAC/B,QAAQ,IAAI,aAAa,UAAU,IAAI,CAAC;AAAA,IACzC,EAAO;AAAA,MACN,QAAQ,IAAI,WAAW,UAAU,IAAI,CAAC;AAAA;AAAA,IAEtC,OAAO,KAAU;AAAA,IAClB,QAAQ,MAAM,UAAU,IAAI,SAAS;AAAA,IACrC,QAAQ,KAAK,CAAC;AAAA;AAAA;AAIhB,eAAe,SAAS,GAAoB;AAAA,EAC3C,MAAM,SAAmB,CAAC;AAAA,EAC1B,iBAAiB,SAAS,QAAQ,OAAO;AAAA,IACxC,OAAO,KAAK,KAAe;AAAA,EAC5B;AAAA,EACA,OAAO,OAAO,OAAO,MAAM,EAAE,SAAS,OAAO;AAAA;AAG9C,SAAS,eAAe,CAAC,MAAsB;AAAA,EAG9C,OAAO,KACL,QAAQ,YAAY,IAAI,EACxB,QAAQ,WAAW,IAAI,EACvB,QAAQ,OAAO,EAAE,EACjB,QAAQ,0BAA0B,EAAE;AAAA;AAGvC,SAAS,aAAa,CAAC,MAAuB;AAAA,EAC7C,IAAI,CAAC,KAAK,KAAK;AAAA,IAAG,OAAO;AAAA,EACzB,IAAI,KAAK,SAAS;AAAA,IAAI,OAAO;AAAA,EAC7B,MAAM,aAAa,KAAK,MAAM,GAAG,GAAG,EAAE,YAAY;AAAA,EAElD,IAAI,kFAAkF,KAAK,UAAU,GAAG;AAAA,IACvG,OAAO;AAAA,EACR;AAAA,EAEA,IAAI,gCAAgC,KAAK,UAAU;AAAA,IAAG,OAAO;AAAA,EAC7D,OAAO;AAAA;AAGR,eAAe,cAAc,CAAC,QAAgB,MAAgB,YAAY,MAA8B;AAAA,EACvG,IAAI;AAAA,IACH,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,GAAG,IAAI,GAAG;AAAA,MACzC,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,KAAK,KAAK,QAAQ,KAAK,OAAO,OAAO,UAAU,OAAO,WAAW,MAAM;AAAA,IACxE,CAAC;AAAA,IAED,MAAM,QAAQ,WAAW,MAAM,KAAK,KAAK,GAAG,SAAS;AAAA,IAErD,OAAO,QAAQ,UAAU,MAAM,QAAQ,IAAI;AAAA,MAC1C,IAAI,SAAS,KAAK,MAAM,EAAE,KAAK;AAAA,MAC/B,IAAI,SAAS,KAAK,MAAM,EAAE,KAAK;AAAA,IAChC,CAAC;AAAA,IACD,aAAa,KAAK;AAAA,IAClB,MAAM,KAAK;AAAA,IAEX,MAAM,WAAW,UAAU;AAAA,IAC3B,IAAI,CAAC,cAAc,QAAQ;AAAA,MAAG,OAAO;AAAA,IACrC,OAAO,gBAAgB,QAAQ;AAAA,IAC9B,MAAM;AAAA,IACP,OAAO;AAAA;AAAA;AAIT,eAAe,UAAU,CAAC,QAAgB,SAAmB,YAAY,MAA8B;AAAA,EAEtG,MAAM,aAAa;AAAA,IAClB,QAAQ,SAAS,IAAI,CAAC,GAAG,UAAU,QAAQ,KAAK,GAAG,GAAG,IAAI,CAAC,MAAM;AAAA,IACjE,CAAC,QAAQ,GAAG,OAAO;AAAA,EACpB;AAAA,EAEA,WAAW,SAAQ,YAAY;AAAA,IAC9B,IAAI;AAAA,MACH,MAAM,OAAO,IAAI,MAAM,CAAC,OAAO,GAAG,KAAI,GAAG;AAAA,QACxC,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,KAAK,KAAK,QAAQ,KAAK,UAAU,OAAO,OAAO,MAAM;AAAA,MACtD,CAAC;AAAA,MAED,MAAM,QAAQ,WAAW,MAAM,KAAK,KAAK,GAAG,SAAS;AAAA,MACrD,OAAO,UAAU,MAAM,QAAQ,IAAI;AAAA,QAClC,IAAI,SAAS,KAAK,MAAM,EAAE,KAAK;AAAA,QAC/B,IAAI,SAAS,KAAK,MAAM,EAAE,KAAK;AAAA,MAChC,CAAC;AAAA,MACD,aAAa,KAAK;AAAA,MAClB,MAAM,KAAK;AAAA,MAEX,IAAI,cAAc,MAAM;AAAA,QAAG,OAAO,gBAAgB,MAAM;AAAA,MACvD,MAAM;AAAA,EACT;AAAA,EACA,OAAO;AAAA;AAGR,eAAe,WAAW,CAAC,OAAgB;AAAA,EAC1C,IAAI,SAAwB;AAAA,EAC5B,MAAM,UAAoB,CAAC;AAAA,EAE3B,WAAW,OAAO,OAAM;AAAA,IACvB,IAAI,QAAQ,gBAAgB,QAAQ,YAAY,QAAQ;AAAA,MAAM;AAAA,IAC9D,IAAI,CAAC,QAAQ;AAAA,MACZ,SAAS;AAAA,IACV,EAAO;AAAA,MACN,QAAQ,KAAK,GAAG;AAAA;AAAA,EAElB;AAAA,EAEA,IAAI,CAAC,QAAQ;AAAA,IACZ,QAAQ,MAAM,8BAA8B;AAAA,IAC5C,QAAQ,MAAM,0CAA0C;AAAA,IACxD,QAAQ,KAAK,CAAC;AAAA,EACf;AAAA,EAOA,MAAM,WAAqD;AAAA,IAC1D,EAAE,OAAO,mBAAmB,MAAM,CAAC,GAAG,SAAS,IAAI,EAAE;AAAA,IACrD,EAAE,OAAO,sBAAsB,MAAM,CAAC,GAAG,SAAS,QAAQ,EAAE;AAAA,EAC7D;AAAA,EAEA,IAAI,QAAQ,SAAS,GAAG;AAAA,IACvB,SAAS,KAAK,EAAE,OAAO,mBAAmB,MAAM,CAAC,QAAQ,GAAG,OAAO,EAAE,CAAC;AAAA,EACvE;AAAA,EAEA,WAAW,WAAW,UAAU;AAAA,IAC/B,MAAM,SAAS,MAAM,eAAe,QAAQ,QAAQ,IAAI;AAAA,IACxD,IAAI,QAAQ;AAAA,MACX,QAAQ,OAAO,MAAM,MAAM;AAAA,MAC3B,IAAI,CAAC,OAAO,SAAS;AAAA,CAAI;AAAA,QAAG,QAAQ,OAAO,MAAM;AAAA,CAAI;AAAA,MACrD;AAAA,IACD;AAAA,EACD;AAAA,EAGA,MAAM,YAAY,MAAM,WAAW,QAAQ,OAAO;AAAA,EAClD,IAAI,WAAW;AAAA,IACd,QAAQ,OAAO,MAAM,SAAS;AAAA,IAC9B,IAAI,CAAC,UAAU,SAAS;AAAA,CAAI;AAAA,MAAG,QAAQ,OAAO,MAAM;AAAA,CAAI;AAAA,IACxD;AAAA,EACD;AAAA,EAEA,QAAQ,MAAM,mCAAmC,UAAU,QAAQ,KAAK,GAAG,GAAG;AAAA,EAC9E,QAAQ,MAAM,mDAAmD;AAAA,EACjE,QAAQ,KAAK,CAAC;AAAA;AAGf,SAAS,cAAc,CAAC,OAAyB;AAAA,EAChD,IAAI,MAAK,SAAS,YAAY;AAAA,IAAG,OAAO;AAAA,EACxC,IAAI,QAAQ,IAAI;AAAA,IAAU,OAAO;AAAA,EACjC,IAAI,QAAQ,IAAI;AAAA,IAAa,OAAO;AAAA,EACpC,OAAO,CAAC,CAAC,QAAQ,OAAO;AAAA;AAGzB,SAAS,UAAU,CAAC,SAAkB;AAAA,EACrC,IAAI,CAAC,SAAS;AAAA,IACb,OAAO,EAAE,OAAO,IAAI,MAAM,IAAI,KAAK,IAAI,MAAM,IAAI,OAAO,IAAI,QAAQ,IAAI,KAAK,IAAI,SAAS,IAAI,MAAM,GAAG;AAAA,EACxG;AAAA,EACA,OAAO;AAAA,IACN,OAAO;AAAA,IACP,MAAM;AAAA,IACN,KAAK;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,SAAS;AAAA,IACT,MAAM;AAAA,EACP;AAAA;AAGD,eAAe,OAAO,CAAC,OAAgB;AAAA,EACtC,IAAI,SAAwB;AAAA,EAC5B,IAAI,aAAa;AAAA,EACjB,IAAI;AAAA,EACJ,IAAI,SAA0B;AAAA,EAC9B,IAAI,WAAW;AAAA,EACf,IAAI,WAAkC;AAAA,EAEtC,SAAS,IAAI,EAAG,IAAI,MAAK,QAAQ,KAAK;AAAA,IACrC,MAAM,MAAM,MAAK;AAAA,IACjB,IAAI,QAAQ,mBAAmB,MAAK,IAAI,IAAI;AAAA,MAC3C,aAAa,OAAO,SAAS,MAAK,EAAE,IAAK,EAAE;AAAA,IAC5C,EAAO,SAAI,QAAQ,oBAAoB,MAAK,IAAI,IAAI;AAAA,MACnD,cAAc,MAAK,EAAE;AAAA,IACtB,EAAO,SAAI,QAAQ,cAAc,MAAK,IAAI,IAAI;AAAA,MAC7C,SAAS,MAAK,EAAE;AAAA,IACjB,EAAO,SAAI,QAAQ,iBAAiB,MAAK,IAAI,IAAI;AAAA,MAChD,WAAW,OAAO,SAAS,MAAK,EAAE,IAAK,EAAE;AAAA,IAC1C,EAAO,SAAI,QAAQ,iBAAiB,QAAQ,UAAU;AAAA,MACrD,WAAW;AAAA,IACZ,EAAO,SAAI,QAAQ,aAAa;AAAA,MAC/B,WAAW;AAAA,IACZ,EAAO,SAAI,QAAQ,gBAAgB,CAAC,IAAI,WAAW,GAAG,GAAG;AAAA,MACxD,SAAS;AAAA,IACV;AAAA,EACD;AAAA,EAEA,IAAI,CAAC,QAAQ;AAAA,IACZ,QAAQ,MAAM,8BAA8B;AAAA,IAC5C,QAAQ,MAAM,qCAAqC;AAAA,IACnD,QAAQ,KAAK,CAAC;AAAA,EACf;AAAA,EAEA,IAAI;AAAA,IACH,MAAM,SAAS,MAAM,QAAQ,QAAQ,EAAE,YAAY,YAAY,CAAC;AAAA,IAEhE,IAAI,WAAW,QAAQ;AAAA,MACtB,QAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,MAC3C;AAAA,IACD;AAAA,IAEA,MAAM,IAAI,WAAW,eAAe,KAAI,CAAC;AAAA,IAEzC,QAAQ,IAAI;AAAA,EAAK,EAAE,OAAO,EAAE,UAAU,SAAS,EAAE,SAAS,EAAE,+BAA8B,EAAE;AAAA,CAAS;AAAA,IACrG,QAAQ,IAAI,GAAG,EAAE,aAAa,EAAE,OAAO;AAAA,IACvC,QAAQ,IAAI,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,OAAO,OAAO,MAAM,mBAAmB,EAAE,OAAO;AAAA,IACnG,QAAQ,IAAI,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,OAAO,OAAO,MAAM,oBAAoB,EAAE,OAAO;AAAA,IACpG,QAAQ,IAAI,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,OAAO,OAAO,mBAAmB,EAAE;AAAA,CAAS;AAAA,IAE/F,IAAI,OAAO,MAAM,eAAe,SAAS,GAAG;AAAA,MAC3C,QAAQ,IAAI,GAAG,EAAE,uBAAuB,EAAE,OAAO;AAAA,MACjD,MAAM,MAAM,OAAO,MAAM,eAAe,GAAI;AAAA,MAC5C,aAAa,yBAAY,WAAW,OAAO,MAAM,eAAe,MAAM,GAAG,CAAC,GAAG;AAAA,QAC5E,MAAM,MAAM,IAAG,OAAO,KAAK,IAAI,GAAG,KAAK,MAAO,QAAQ,MAAO,EAAE,CAAC,CAAC;AAAA,QACjE,QAAQ,IAAI,KAAK,EAAE,QAAQ,YAAW,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,MAAM,EAAE,SAAS,EAAE,MAAM,QAAQ,EAAE,OAAO;AAAA,MAClH;AAAA,MACA,QAAQ,IAAI;AAAA,IACb;AAAA,IAEA,IAAI,OAAO,UAAU,SAAS,GAAG;AAAA,MAChC,QAAQ,IAAI,GAAG,EAAE,4BAA4B,EAAE,OAAO;AAAA,MACtD,WAAW,MAAM,OAAO,UAAU,MAAM,GAAG,QAAQ,GAAG;AAAA,QACrD,MAAM,QAAQ,GAAG,KAAK,GAAI,IAAI,OAAK,GAAG,EAAE,QAAQ,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE,QAAO,EAAE,QAAQ;AAAA,QAC3F,QAAQ,IAAI,KAAK,SAAS,EAAE,OAAO,GAAG,YAAW,EAAE,OAAO;AAAA,MAC3D;AAAA,MACA,QAAQ,IAAI;AAAA,IACb;AAAA,IAEA,IAAI,OAAO,YAAY,SAAS,GAAG;AAAA,MAClC,QAAQ,IAAI,GAAG,EAAE,OAAO,EAAE,wCAA6B,EAAE,OAAO;AAAA,MAChE,WAAW,KAAK,OAAO,YAAY,MAAM,GAAG,CAAC,GAAG;AAAA,QAC/C,MAAM,QACL,EAAE,aAAa,SACZ,GAAG,EAAE,cAAc,EAAE,UACrB,EAAE,aAAa,WACd,GAAG,EAAE,cAAc,EAAE,UACrB,GAAG,EAAE,WAAW,EAAE;AAAA,QACvB,QAAQ,IAAI;AAAA,IAAO,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAU,EAAE,aAAa;AAAA,QAC1E,QAAQ,IAAI,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO;AAAA,QAC/C,QAAQ,IAAI,OAAO,EAAE,MAAM,EAAE,SAAS,KAAK,MAAM,IAAI,EAAE,OAAO;AAAA,MAC/D;AAAA,MACA,QAAQ,IAAI;AAAA,IACb;AAAA,IAOA,IAAI,aAAa,OAAO;AAAA,MACvB,MAAM,WAAW,aAAa,OAAO,IAAI;AAAA,MACzC,MAAM,aAAa,oBAAoB,OAAO,WAAW,QAAQ;AAAA,MACjE,IAAI,YAAY;AAAA,QACf,MAAM,eAAe,oBAAoB,UAAU;AAAA,QACnD,MAAM,WAAW,eAAe,KAAI,IAAI,WAAW,YAAY,IAAI,aAAa,YAAY;AAAA,QAC5F,QAAQ,IAAI,GAAG,EAAE,iCAAiC,EAAE,OAAO;AAAA,QAC3D,QAAQ,IAAI,QAAQ;AAAA,QACpB,QAAQ,IAAI;AAAA,MACb;AAAA,IACD;AAAA,IACC,OAAO,KAAU;AAAA,IAClB,QAAQ,MAAM,UAAU,IAAI,SAAS;AAAA,IACrC,QAAQ,KAAK,CAAC;AAAA;AAAA;AAIhB,SAAS,mBAAoE,CAC5E,WACA,WAAW,GACA;AAAA,EACX,WAAW,MAAM,WAAW;AAAA,IAC3B,MAAM,MAAM,GAAG,KAAK,IAAI,UAAU;AAAA,IAClC,IAAI,OAAO;AAAA,MAAU,OAAO;AAAA,EAC7B;AAAA,EACA,OAAO;AAAA;AAGR,eAAe,iBAAiB,CAAC,OAAgB;AAAA,EAChD,IAAI,SAAwB;AAAA,EAC5B,IAAI,YAAY;AAAA,EAChB,IAAI,WAAW;AAAA,EACf,IAAI,SAA0B;AAAA,EAE9B,SAAS,IAAI,EAAG,IAAI,MAAK,QAAQ,KAAK;AAAA,IACrC,MAAM,MAAM,MAAK;AAAA,IACjB,IAAI,QAAQ,cAAc;AAAA,MACzB,YAAY;AAAA,IACb,EAAO,SAAI,QAAQ,iBAAiB,MAAK,IAAI,IAAI;AAAA,MAChD,WAAW,OAAO,SAAS,MAAK,EAAE,IAAK,EAAE;AAAA,IAC1C,EAAO,SAAI,QAAQ,cAAc,MAAK,IAAI,IAAI;AAAA,MAC7C,SAAS,MAAK,EAAE;AAAA,IACjB,EAAO,SAAI,QAAQ,gBAAgB,CAAC,IAAI,WAAW,GAAG,GAAG;AAAA,MACxD,SAAS;AAAA,IACV;AAAA,EACD;AAAA,EAEA,IAAI,CAAC,QAAQ;AAAA,IACZ,QAAQ,MAAM,8BAA8B;AAAA,IAC5C,QAAQ,MAAM,4CAA4C;AAAA,IAC1D,QAAQ,KAAK,CAAC;AAAA,EACf;AAAA,EAEA,MAAM,IAAI,WAAW,eAAe,KAAI,CAAC;AAAA,EAEzC,IAAI;AAAA,IACH,QAAQ,MAAM,GAAG,EAAE,mEAAkE,EAAE,OAAO;AAAA,IAC9F,QAAQ,MAAM,GAAG,EAAE,mEAAmE,EAAE,OAAO;AAAA,IAC/F,QAAQ,MAAM,EAAE;AAAA,IAEhB,OAAO,MAAM,QAAQ,MAAM,QAAQ,IAAI;AAAA,MACtC,eAAe,QAAQ,IAAI,cAAgB,EAAE,WAAW,cAAc,SAAS,CAAC;AAAA,MAChF,QAAQ,QAAQ,EAAE,YAAY,EAAE,CAAC,EAAE,MAAM,MAAM,IAAI;AAAA,IACpD,CAAC;AAAA,IAED,IAAI,WAAW,QAAQ;AAAA,MACtB,QAAQ,IAAI,KAAK,UAAU,EAAE,aAAa,MAAM,QAAQ,KAAK,GAAG,MAAM,CAAC,CAAC;AAAA,MACxE;AAAA,IACD;AAAA,IAEA,QAAQ,IAAI,GAAG,EAAE,OAAO,EAAE,UAAU,SAAS,EAAE,OAAO;AAAA,IACtD,IAAI,KAAK,KAAK,aAAa;AAAA,MAC1B,QAAQ,IAAI,GAAG,EAAE,OAAO,KAAK,KAAK,cAAc,EAAE,OAAO;AAAA,IAC1D;AAAA,IACA,QAAQ,IAAI;AAAA,IAEZ,QAAQ,IAAI,GAAG,EAAE,YAAY,EAAE,OAAO;AAAA,IACtC,QAAQ,IAAI,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,OAAO,KAAK,MAAM,eAAe,EAAE,OAAO;AAAA,IAC1F,QAAQ,IAAI,KAAK,EAAE,aAAa,EAAE,YAAY,KAAK,YAAY,GAAG,EAAE,WAAW,EAAE,UAAU,GAAG,EAAE,QAAQ,EAAE,SAAS;AAAA,IACnH,QAAQ,IAAI;AAAA,IAEZ,IAAI,MAAM;AAAA,MACT,QAAQ,IAAI,GAAG,EAAE,gCAAgC,EAAE,OAAO;AAAA,MAC1D,QAAQ,IAAI,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,OAAO,KAAK,MAAM,mBAAmB,EAAE,OAAO;AAAA,MACjG,QAAQ,IAAI,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,OAAO,KAAK,MAAM,oBAAoB,EAAE,OAAO;AAAA,MAElG,IAAI,KAAK,UAAU,SAAS,GAAG;AAAA,QAC9B,QAAQ,IAAI;AAAA,EAAK,EAAE,4BAA4B,EAAE,OAAO;AAAA,QACxD,WAAW,MAAM,KAAK,UAAU,MAAM,GAAG,CAAC,GAAG;AAAA,UAC5C,MAAM,QAAQ,GAAG,KAAK,GAAI,IAAI,OAAK,GAAG,EAAE,QAAQ,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE,QAAO,EAAE,QAAQ;AAAA,UAC3F,QAAQ,IAAI,KAAK,SAAS,EAAE,OAAO,GAAG,YAAW,EAAE,OAAO;AAAA,QAC3D;AAAA,MACD;AAAA,MAEA,IAAI,KAAK,YAAY,SAAS,GAAG;AAAA,QAChC,QAAQ,IAAI;AAAA,EAAK,EAAE,OAAO,EAAE,wCAA6B,EAAE,OAAO;AAAA,QAClE,WAAW,KAAK,KAAK,YAAY,MAAM,GAAG,CAAC,GAAG;AAAA,UAC7C,QAAQ,IAAI,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAU,EAAE,aAAa;AAAA,UAC/D,QAAQ,IAAI,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO;AAAA,QAChD;AAAA,MACD;AAAA,IACD;AAAA,IAEA,QAAQ,IAAI;AAAA,IACZ,QAAQ,IAAI,GAAG,EAAE,yDAAyD,EAAE,OAAO;AAAA,IACnF,QAAQ,IAAI,GAAG,EAAE,+BAA+B,EAAE,OAAO;AAAA,IACzD,QAAQ,IAAI;AAAA,IACX,OAAO,KAAU;AAAA,IAClB,QAAQ,MAAM,GAAG,EAAE,aAAa,IAAI,UAAU,EAAE,OAAO;AAAA,IACvD,QAAQ,KAAK,CAAC;AAAA;AAAA;",
|
|
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.
|
|
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
|
|
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
|
-
#
|
|
123
|
-
|
|
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
|
-
#
|
|
126
|
-
man "
|
|
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
|
|
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;
|