argsbarg 3.4.2 → 3.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/CHANGELOG.md +31 -1
  2. package/README.md +24 -8
  3. package/biome.json +29 -6
  4. package/bun.lock +22 -0
  5. package/docs/cli-program.md +75 -1
  6. package/docs/install.md +1 -1
  7. package/docs/mcp.md +45 -1
  8. package/docs/templates/cursor/rules/cli-program.mdc +15 -21
  9. package/index.d.ts +95 -50
  10. package/justfile +24 -6
  11. package/package.json +4 -2
  12. package/scripts/release.ts +26 -9
  13. package/src/builtins/builtins.test.ts +9 -4
  14. package/src/builtins/completion-bash.ts +74 -50
  15. package/src/builtins/completion-fish.ts +3 -8
  16. package/src/builtins/completion-group.ts +1 -1
  17. package/src/builtins/completion-zsh.ts +80 -42
  18. package/src/builtins/dispatch.ts +20 -16
  19. package/src/builtins/export.ts +19 -10
  20. package/src/builtins/index.ts +9 -4
  21. package/src/builtins/install.ts +10 -10
  22. package/src/builtins/mcp.ts +1 -1
  23. package/src/builtins/presentation.ts +8 -8
  24. package/src/builtins/scopes.ts +1 -1
  25. package/src/builtins/version.ts +1 -1
  26. package/src/completion.ts +4 -4
  27. package/src/context.ts +91 -15
  28. package/src/docs/api-guide.test.ts +2 -2
  29. package/src/docs/api-guide.ts +19 -5
  30. package/src/docs/builtin.ts +27 -8
  31. package/src/docs/docs.test.ts +18 -11
  32. package/src/docs/mcp-guide.ts +108 -25
  33. package/src/docs/resolve.ts +10 -3
  34. package/src/docs/save.ts +11 -3
  35. package/src/formats.test.ts +35 -0
  36. package/src/formats.ts +135 -0
  37. package/src/headless.test.ts +8 -16
  38. package/src/help.ts +73 -43
  39. package/src/hidden-mcpb.test.ts +7 -6
  40. package/src/hidden.ts +2 -2
  41. package/src/index.test.ts +120 -96
  42. package/src/index.ts +36 -24
  43. package/src/install/binary.ts +12 -5
  44. package/src/install/completions.ts +7 -3
  45. package/src/install/detect-installed.ts +29 -4
  46. package/src/install/gh-release-update.ts +31 -23
  47. package/src/install/index.ts +69 -19
  48. package/src/install/install.test.ts +31 -8
  49. package/src/install/mcp-codex.test.ts +57 -0
  50. package/src/install/mcp-codex.ts +125 -0
  51. package/src/install/mcp-config.ts +12 -5
  52. package/src/install/mcp-opencode.test.ts +98 -0
  53. package/src/install/mcp-opencode.ts +149 -0
  54. package/src/install/paths.ts +29 -3
  55. package/src/install/plan.ts +73 -6
  56. package/src/install/shell.ts +1 -4
  57. package/src/install/status.ts +12 -6
  58. package/src/install/uninstall.ts +38 -4
  59. package/src/install/update.test.ts +2 -2
  60. package/src/install/update.ts +3 -1
  61. package/src/invoke.ts +12 -9
  62. package/src/mcp/bundle.ts +36 -8
  63. package/src/mcp/env.ts +7 -13
  64. package/src/mcp/server.ts +12 -6
  65. package/src/mcp/tools.ts +83 -18
  66. package/src/mcp.ts +3 -3
  67. package/src/parse.ts +129 -27
  68. package/src/runtime.ts +22 -12
  69. package/src/schema.ts +11 -5
  70. package/src/skill/generate.ts +4 -4
  71. package/src/skill/install.ts +6 -2
  72. package/src/types.ts +24 -0
  73. package/src/validate.ts +75 -16
@@ -1,4 +1,4 @@
1
- import { CliNode, CliRouter, CliOptionKind } from "../types.ts";
1
+ import { CliOptionKind, type CliRouter } from "../types.ts";
2
2
  import { collectScopes, type ScopeRec } from "./scopes.ts";
3
3
  import {
4
4
  escShellSingleQuoted,
@@ -11,22 +11,41 @@ import {
11
11
  function emitScopeArraysZsh(ident: string, scopes: ScopeRec[]): string {
12
12
  let out = "";
13
13
  for (const [i, sc] of scopes.entries()) {
14
- out += "typeset -g A_" + ident + "_" + i + "_opts\n";
15
- out += "A_" + ident + "_" + i + "_opts=(";
16
- out += "'" + escShellSingleQuoted(kHelpLong) + ":" + escShellSingleQuoted("Show help for this command.") + "' '" + escShellSingleQuoted(kHelpShort) + ":" + escShellSingleQuoted("Show help for this command.") + "'";
14
+ out += `typeset -g A_${ident}_${i}_opts\n`;
15
+ out += `A_${ident}_${i}_opts=(`;
16
+ out +=
17
+ "'" +
18
+ escShellSingleQuoted(kHelpLong) +
19
+ ":" +
20
+ escShellSingleQuoted("Show help for this command.") +
21
+ "' '" +
22
+ escShellSingleQuoted(kHelpShort) +
23
+ ":" +
24
+ escShellSingleQuoted("Show help for this command.") +
25
+ "'";
17
26
  for (const o of sc.opts) {
18
- out += " '" + escShellSingleQuoted("--" + o.name) + ":" + escShellSingleQuoted(o.description) + "'";
27
+ out +=
28
+ " '" +
29
+ escShellSingleQuoted(`--${o.name}`) +
30
+ ":" +
31
+ escShellSingleQuoted(o.description) +
32
+ "'";
19
33
  if (o.shortName) {
20
- out += " '" + escShellSingleQuoted("-" + o.shortName) + ":" + escShellSingleQuoted(o.description) + "'";
34
+ out +=
35
+ " '" +
36
+ escShellSingleQuoted(`-${o.shortName}`) +
37
+ ":" +
38
+ escShellSingleQuoted(o.description) +
39
+ "'";
21
40
  }
22
41
  }
23
42
  out += ")\n";
24
- out += "typeset -g A_" + ident + "_" + i + "_leaf=" + (sc.kids.length === 0 ? "1" : "0") + "\n";
25
- out += "typeset -g A_" + ident + "_" + i + "_pos=" + (sc.wantsFiles ? "1" : "0") + "\n";
43
+ out += `typeset -g A_${ident}_${i}_leaf=${sc.kids.length === 0 ? "1" : "0"}\n`;
44
+ out += `typeset -g A_${ident}_${i}_pos=${sc.wantsFiles ? "1" : "0"}\n`;
26
45
  if (sc.kids.length > 0) {
27
- out += "typeset -g A_" + ident + "_" + i + "_cmds=(";
46
+ out += `typeset -g A_${ident}_${i}_cmds=(`;
28
47
  for (const ch of sc.kids) {
29
- out += " '" + escShellSingleQuoted(ch.key) + ":" + escShellSingleQuoted(ch.description) + "'";
48
+ out += ` '${escShellSingleQuoted(ch.key)}:${escShellSingleQuoted(ch.description)}'`;
30
49
  }
31
50
  out += ")\n";
32
51
  }
@@ -36,19 +55,24 @@ function emitScopeArraysZsh(ident: string, scopes: ScopeRec[]): string {
36
55
 
37
56
  function emitConsumeLongZsh(ident: string, scopes: ScopeRec[]): string {
38
57
  let o = "_${ident}_nac_consume_long() {\n".replace("${ident}", ident);
39
- o += " local sid=\"$1\" w=\"$2\" nw=\"$3\"\n";
58
+ o += ' local sid="$1" w="$2" nw="$3"\n';
40
59
  o += " case $sid in\n";
41
60
  for (const [i, sc] of scopes.entries()) {
42
- o += " " + i + ")\n";
61
+ o += ` ${i})\n`;
43
62
  o += " case $w in\n";
44
- o += " " + kHelpLong + "|${kHelpLong}=*|${kHelpShort}) echo 1 ;;\n".replace(/\$\{kHelpLong\}/g, kHelpLong).replace(/\$\{kHelpShort\}/g, kHelpShort);
63
+ o +=
64
+ " " +
65
+ kHelpLong +
66
+ "|${kHelpLong}=*|${kHelpShort}) echo 1 ;;\n"
67
+ .replace(/\$\{kHelpLong\}/g, kHelpLong)
68
+ .replace(/\$\{kHelpShort\}/g, kHelpShort);
45
69
  for (const op of sc.opts) {
46
- const base = "--" + op.name;
70
+ const base = `--${op.name}`;
47
71
  if (op.kind === "presence") {
48
- o += " " + base + "|${base}=*) echo 1 ;;\n".replace(/\$\{base\}/g, base);
72
+ o += ` ${base}${"|${base}=*) echo 1 ;;\n".replace(/\$\{base\}/g, base)}`;
49
73
  } else {
50
- o += " " + base + "=*) echo 1 ;;\n";
51
- o += " " + base + ") echo 2 ;;\n";
74
+ o += ` ${base}=*) echo 1 ;;\n`;
75
+ o += ` ${base}) echo 2 ;;\n`;
52
76
  }
53
77
  }
54
78
  o += " *) echo 0 ;;\n";
@@ -63,10 +87,10 @@ function emitConsumeLongZsh(ident: string, scopes: ScopeRec[]): string {
63
87
 
64
88
  function emitConsumeShortZsh(ident: string, scopes: ScopeRec[]): string {
65
89
  let o = "_${ident}_nac_consume_short() {\n".replace("${ident}", ident);
66
- o += " local sid=\"$1\" w=\"$2\"\n";
90
+ o += ' local sid="$1" w="$2"\n';
67
91
  o += " case $sid in\n";
68
92
  for (const [i, sc] of scopes.entries()) {
69
- o += " " + i + ")\n";
93
+ o += ` ${i})\n`;
70
94
  o += " local rest=${w#-}\n";
71
95
  o += " local ch\n";
72
96
  o += " local saw=0\n";
@@ -78,16 +102,16 @@ function emitConsumeShortZsh(ident: string, scopes: ScopeRec[]): string {
78
102
  for (const op of sc.opts) {
79
103
  if (!op.shortName) continue;
80
104
  if (op.kind === "presence") {
81
- boolChars += op.shortName + "|";
105
+ boolChars += `${op.shortName}|`;
82
106
  } else {
83
- o += " " + op.shortName + ")\n";
107
+ o += ` ${op.shortName})\n`;
84
108
  o += " if [[ $saw -ne 0 || -n $rest ]]; then echo 0; return; fi\n";
85
109
  o += " echo 2; return ;;\n";
86
110
  }
87
111
  }
88
112
  if (boolChars.length > 0) {
89
113
  boolChars = boolChars.slice(0, -1);
90
- o += " " + boolChars + ") ;;\n";
114
+ o += ` ${boolChars}) ;;\n`;
91
115
  }
92
116
  o += " *) echo 0; return ;;\n";
93
117
  o += " esac\n";
@@ -102,18 +126,22 @@ function emitConsumeShortZsh(ident: string, scopes: ScopeRec[]): string {
102
126
  return o;
103
127
  }
104
128
 
105
- function emitMatchChildZsh(ident: string, scopes: ScopeRec[], pathIndex: Record<string, number>): string {
129
+ function emitMatchChildZsh(
130
+ ident: string,
131
+ scopes: ScopeRec[],
132
+ pathIndex: Record<string, number>,
133
+ ): string {
106
134
  let o = "_${ident}_nac_match_child() {\n".replace("${ident}", ident);
107
- o += " local sid=\"$1\" w=\"$2\"\n";
135
+ o += ' local sid="$1" w="$2"\n';
108
136
  o += " case $sid in\n";
109
137
  for (const [sid, sc] of scopes.entries()) {
110
138
  if (sc.kids.length === 0) continue;
111
- o += " " + sid + ")\n";
139
+ o += ` ${sid})\n`;
112
140
  o += " case $w in\n";
113
141
  for (const ch of sc.kids) {
114
- const childPath = sc.path === "" ? ch.key : sc.path + "/" + ch.key;
142
+ const childPath = sc.path === "" ? ch.key : `${sc.path}/${ch.key}`;
115
143
  const cid = pathIndex[childPath] ?? 0;
116
- o += " " + ch.key + ") echo " + cid + "; return 0 ;;\n";
144
+ o += ` ${ch.key}) echo ${cid}; return 0 ;;\n`;
117
145
  }
118
146
  o += " esac\n";
119
147
  o += " ;;\n";
@@ -129,11 +157,14 @@ function emitSimulateZsh(ident: string): string {
129
157
  o += " local i=2 sid=0 w steps next\n";
130
158
  o += " while (( i < CURRENT )); do\n";
131
159
  o += " w=$words[i]\n";
132
- o += " if [[ $w == " + kHelpShort + " || $w == " + kHelpLong + " ]]; then\n";
160
+ o += ` if [[ $w == ${kHelpShort} || $w == ${kHelpLong} ]]; then\n`;
133
161
  o += " ((i++)); continue\n";
134
162
  o += " fi\n";
135
163
  o += " if [[ $w == --* ]]; then\n";
136
- o += " steps=$(_${ident}_nac_consume_long \"$sid\" \"$w\" \"${words[i+1]}\")\n".replace("${ident}", ident);
164
+ o += ' steps=$(_${ident}_nac_consume_long "$sid" "$w" "${words[i+1]}")\n'.replace(
165
+ "${ident}",
166
+ ident,
167
+ );
137
168
  o += " case $steps in\n";
138
169
  o += " 0) break ;;\n";
139
170
  o += " 1) ((i++)) ;;\n";
@@ -143,7 +174,7 @@ function emitSimulateZsh(ident: string): string {
143
174
  o += " continue\n";
144
175
  o += " fi\n";
145
176
  o += " if [[ $w == -* ]]; then\n";
146
- o += " steps=$(_${ident}_nac_consume_short \"$sid\" \"$w\")\n".replace("${ident}", ident);
177
+ o += ' steps=$(_${ident}_nac_consume_short "$sid" "$w")\n'.replace("${ident}", ident);
147
178
  o += " case $steps in\n";
148
179
  o += " 0) break ;;\n";
149
180
  o += " 1) ((i++)) ;;\n";
@@ -152,7 +183,7 @@ function emitSimulateZsh(ident: string): string {
152
183
  o += " esac\n";
153
184
  o += " continue\n";
154
185
  o += " fi\n";
155
- o += " next=$(_${ident}_nac_match_child \"$sid\" \"$w\") || break\n".replace("${ident}", ident);
186
+ o += ' next=$(_${ident}_nac_match_child "$sid" "$w") || break\n'.replace("${ident}", ident);
156
187
  o += " sid=$next\n";
157
188
  o += " ((i++))\n";
158
189
  o += " done\n";
@@ -166,13 +197,15 @@ function emitEnumReplyZsh(ident: string, scopes: ScopeRec[]): string {
166
197
  o += " local sid=$1 prev=$2\n";
167
198
  o += " case $sid in\n";
168
199
  for (const [i, sc] of scopes.entries()) {
169
- const enumOpts = sc.opts.filter((op) => op.kind === CliOptionKind.Enum && (op.choices?.length ?? 0) > 0);
200
+ const enumOpts = sc.opts.filter(
201
+ (op) => op.kind === CliOptionKind.Enum && (op.choices?.length ?? 0) > 0,
202
+ );
170
203
  if (enumOpts.length === 0) continue;
171
- o += " " + i + ")\n";
204
+ o += ` ${i})\n`;
172
205
  o += " case $prev in\n";
173
206
  for (const op of enumOpts) {
174
207
  const vals = (op.choices ?? []).map((c) => escShellSingleQuoted(c)).join(" ");
175
- o += " --" + op.name + ") _values " + vals + "; return 0 ;;\n";
208
+ o += ` --${op.name}) _values ${vals}; return 0 ;;\n`;
176
209
  }
177
210
  o += " esac\n";
178
211
  o += " ;;\n";
@@ -186,24 +219,27 @@ function emitEnumReplyZsh(ident: string, scopes: ScopeRec[]): string {
186
219
  function emitMainBodyZsh(schema: CliRouter, ident: string): string {
187
220
  const main = mainName(schema.key);
188
221
  let o = "_${main}() {\n".replace("${main}", main);
189
- o += " local curcontext=\"$curcontext\" ret=1\n";
222
+ o += ' local curcontext="$curcontext" ret=1\n';
190
223
  o += " _${ident}_nac_simulate\n".replace("${ident}", ident);
191
224
  o += " local sid=$REPLY_SID\n";
192
- o += " if _${ident}_nac_enum_reply \"$sid\" \"$words[CURRENT-1]\"; then return 0; fi\n".replace("${ident}", ident);
225
+ o += ' if _${ident}_nac_enum_reply "$sid" "$words[CURRENT-1]"; then return 0; fi\n'.replace(
226
+ "${ident}",
227
+ ident,
228
+ );
193
229
  o += " if [[ $PREFIX == -* ]]; then\n";
194
230
  o += " local -a optsarr\n";
195
- o += " local oname=\"A_${ident}_${sid}_opts\"\n".replace("${ident}", ident);
231
+ o += ' local oname="A_${ident}_${sid}_opts"\n'.replace("${ident}", ident);
196
232
  o += " optsarr=(${(@P)oname})\n";
197
233
  o += " _describe -t options 'option' optsarr && ret=0\n";
198
234
  o += " else\n";
199
- o += " local lname=\"A_${ident}_${sid}_leaf\"\n".replace("${ident}", ident);
235
+ o += ' local lname="A_${ident}_${sid}_leaf"\n'.replace("${ident}", ident);
200
236
  o += " if [[ ${(P)lname} -eq 0 ]]; then\n";
201
237
  o += " local -a cmdsarr\n";
202
- o += " local cname=\"A_${ident}_${sid}_cmds\"\n".replace("${ident}", ident);
238
+ o += ' local cname="A_${ident}_${sid}_cmds"\n'.replace("${ident}", ident);
203
239
  o += " cmdsarr=(${(@P)cname})\n";
204
240
  o += " _describe -t commands 'command' cmdsarr && ret=0\n";
205
241
  o += " else\n";
206
- o += " local pname=\"A_${ident}_${sid}_pos\"\n".replace("${ident}", ident);
242
+ o += ' local pname="A_${ident}_${sid}_pos"\n'.replace("${ident}", ident);
207
243
  o += " if [[ ${(P)pname} -eq 1 ]]; then\n";
208
244
  o += " _files && ret=0\n";
209
245
  o += " fi\n";
@@ -211,7 +247,9 @@ function emitMainBodyZsh(schema: CliRouter, ident: string): string {
211
247
  o += " fi\n";
212
248
  o += " return ret\n";
213
249
  o += "}\n\n";
214
- o += "compdef _${main} ${schema.key}\n".replace("${main}", main).replace("${schema.key}", schema.key);
250
+ o += "compdef _${main} ${schema.key}\n"
251
+ .replace("${main}", main)
252
+ .replace("${schema.key}", schema.key);
215
253
  return o;
216
254
  }
217
255
 
@@ -224,7 +262,7 @@ export function completionZshScript(schema: CliRouter): string {
224
262
  pathIndex[s.path] = i;
225
263
  }
226
264
 
227
- let out = "#compdef " + schema.key + "\n\n";
265
+ let out = `#compdef ${schema.key}\n\n`;
228
266
  out += emitScopeArraysZsh(ident, scopes);
229
267
  out += emitConsumeLongZsh(ident, scopes);
230
268
  out += emitConsumeShortZsh(ident, scopes);
@@ -1,20 +1,20 @@
1
1
  import { resolveCapabilities } from "../capabilities.ts";
2
+ import { cliBuiltinDocsGroupIfEnabled } from "../docs/builtin.ts";
3
+ import { cliInstall } from "../install/index.ts";
4
+ import { runMcpBundle } from "../mcp/bundle.ts";
5
+ import { cliMcpServeStdio } from "../mcp.ts";
6
+ import type { ParseResult } from "../parse.ts";
7
+ import { ParseKind } from "../parse.ts";
2
8
  import type { CliNode, CliProgram, CliRouter } from "../types.ts";
3
- import { isCliLeaf, isCliRouter } from "../types.ts";
9
+ import { isCliLeaf } from "../types.ts";
4
10
  import { completionBashScript } from "./completion-bash.ts";
5
11
  import { completionFishScript } from "./completion-fish.ts";
12
+ import { cliBuiltinCompletionGroup as completionGroup } from "./completion-group.ts";
6
13
  import { completionZshScript } from "./completion-zsh.ts";
7
14
  import { cliBuiltinInstallCommand } from "./install.ts";
8
15
  import { cliBuiltinMcpCommand } from "./mcp.ts";
9
- import { cliBuiltinVersionCommand } from "./version.ts";
10
- import { cliBuiltinCompletionGroup as completionGroup } from "./completion-group.ts";
11
16
  import { cliPresentationRoot } from "./presentation.ts";
12
- import { runMcpBundle } from "../mcp/bundle.ts";
13
- import { cliBuiltinDocsGroupIfEnabled } from "../docs/builtin.ts";
14
- import { cliMcpServeStdio } from "../mcp.ts";
15
- import { cliInstall } from "../install/index.ts";
16
- import type { ParseResult } from "../parse.ts";
17
- import { ParseKind } from "../parse.ts";
17
+ import { cliBuiltinVersionCommand } from "./version.ts";
18
18
 
19
19
  export interface DispatchBuiltinOpts {
20
20
  isLeafCompletionIntercept: boolean;
@@ -61,16 +61,18 @@ export async function dispatchBuiltin(
61
61
 
62
62
  if (pr.path[0] === "version") {
63
63
  if (pr.path.length !== 1) {
64
- process.stderr.write("Unknown subcommand: version " + pr.path.slice(1).join(" ") + "\n");
64
+ process.stderr.write(`Unknown subcommand: version ${pr.path.slice(1).join(" ")}\n`);
65
65
  process.exit(1);
66
66
  }
67
- process.stdout.write(program.version + "\n");
67
+ process.stdout.write(`${program.version}\n`);
68
68
  process.exit(0);
69
69
  }
70
70
 
71
71
  if (pr.path[0] === "mcp") {
72
72
  if (!caps.mcp) {
73
- process.stderr.write("MCP is not enabled. Set mcpServer: { enabled: true } on the program root.\n");
73
+ process.stderr.write(
74
+ "MCP is not enabled. Set mcpServer: { enabled: true } on the program root.\n",
75
+ );
74
76
  process.exit(1);
75
77
  }
76
78
  const sub = pr.path[1];
@@ -82,22 +84,24 @@ export async function dispatchBuiltin(
82
84
  try {
83
85
  runMcpBundle(program);
84
86
  } catch (err) {
85
- process.stderr.write(err instanceof Error ? err.message + "\n" : "mcp bundle failed.\n");
87
+ process.stderr.write(err instanceof Error ? `${err.message}\n` : "mcp bundle failed.\n");
86
88
  process.exit(1);
87
89
  }
88
90
  process.exit(0);
89
91
  }
90
- process.stderr.write("Unknown subcommand: mcp " + pr.path.slice(1).join(" ") + "\n");
92
+ process.stderr.write(`Unknown subcommand: mcp ${pr.path.slice(1).join(" ")}\n`);
91
93
  process.exit(1);
92
94
  }
93
95
 
94
96
  if (pr.path[0] === "install") {
95
97
  if (!caps.install) {
96
- process.stderr.write("install is disabled. Remove install.enabled: false from the program root.\n");
98
+ process.stderr.write(
99
+ "install is disabled. Remove install.enabled: false from the program root.\n",
100
+ );
97
101
  process.exit(1);
98
102
  }
99
103
  if (pr.path.length !== 1) {
100
- process.stderr.write("Unknown subcommand: install " + pr.path.slice(1).join(" ") + "\n");
104
+ process.stderr.write(`Unknown subcommand: install ${pr.path.slice(1).join(" ")}\n`);
101
105
  process.exit(1);
102
106
  }
103
107
  await cliInstall(program, pr.opts);
@@ -1,12 +1,12 @@
1
1
  import { type CliCapabilities, resolveCapabilities } from "../capabilities.ts";
2
+ import { cliBuiltinDocsGroupIfEnabled } from "../docs/builtin.ts";
3
+ import { visibleOptions } from "../hidden.ts";
2
4
  import type { CliFallbackMode, CliNode, CliOption, CliPositional, CliProgram } from "../types.ts";
3
5
  import { isCliRouter } from "../types.ts";
4
- import { visibleOptions } from "../hidden.ts";
5
6
  import { cliBuiltinCompletionGroup } from "./completion-group.ts";
6
7
  import { cliBuiltinInstallCommand } from "./install.ts";
7
8
  import { cliBuiltinMcpCommand } from "./mcp.ts";
8
9
  import { cliBuiltinVersionCommand } from "./version.ts";
9
- import { cliBuiltinDocsGroupIfEnabled } from "../docs/builtin.ts";
10
10
 
11
11
  /** JSON-safe command node (no handlers). */
12
12
  export interface CliSchemaExport {
@@ -55,22 +55,31 @@ function exportBuiltinNode(cmd: CliNode): CliSchemaExport | null {
55
55
  return out;
56
56
  }
57
57
 
58
+ function pushExportedBuiltin(builtins: CliSchemaExport[], cmd: CliNode): void {
59
+ const node = exportBuiltinNode(cmd);
60
+ if (node) {
61
+ builtins.push(node);
62
+ }
63
+ }
64
+
58
65
  /** Built-in subtrees matching help visibility for `--schema` export. */
59
- export function exportPresentationBuiltins(program: CliProgram, caps?: CliCapabilities): CliSchemaExport[] {
66
+ export function exportPresentationBuiltins(
67
+ program: CliProgram,
68
+ caps?: CliCapabilities,
69
+ ): CliSchemaExport[] {
60
70
  const resolved = caps ?? resolveCapabilities(program);
61
- const builtins: CliSchemaExport[] = [
62
- exportBuiltinNode(cliBuiltinCompletionGroup(program))!,
63
- exportBuiltinNode(cliBuiltinVersionCommand())!,
64
- ];
71
+ const builtins: CliSchemaExport[] = [];
72
+ pushExportedBuiltin(builtins, cliBuiltinCompletionGroup(program));
73
+ pushExportedBuiltin(builtins, cliBuiltinVersionCommand());
65
74
  if (resolved.install) {
66
- builtins.push(exportBuiltinNode(cliBuiltinInstallCommand(program))!);
75
+ pushExportedBuiltin(builtins, cliBuiltinInstallCommand(program));
67
76
  }
68
77
  const docsGroup = cliBuiltinDocsGroupIfEnabled(program);
69
78
  if (docsGroup) {
70
- builtins.push(exportBuiltinNode(docsGroup)!);
79
+ pushExportedBuiltin(builtins, docsGroup);
71
80
  }
72
81
  if (resolved.mcp) {
73
- builtins.push(exportBuiltinNode(cliBuiltinMcpCommand(program))!);
82
+ pushExportedBuiltin(builtins, cliBuiltinMcpCommand(program));
74
83
  }
75
84
  return builtins;
76
85
  }
@@ -1,10 +1,15 @@
1
1
  export { completionBashScript } from "./completion-bash.ts";
2
- export { completionZshScript } from "./completion-zsh.ts";
3
2
  export { completionFishScript } from "./completion-fish.ts";
4
3
  export { cliBuiltinCompletionGroup } from "./completion-group.ts";
4
+ export { completionZshScript } from "./completion-zsh.ts";
5
+ export { builtinInterceptRoot, dispatchBuiltin } from "./dispatch.ts";
6
+ export { type CliSchemaExport, exportPresentationBuiltins } from "./export.ts";
5
7
  export { cliBuiltinInstallCommand, installBuiltinOptions } from "./install.ts";
6
8
  export { cliBuiltinMcpCommand } from "./mcp.ts";
7
- export { cliParseRoot, cliPresentationRoot, parseBuiltins, presentationBuiltins } from "./presentation.ts";
8
- export { exportPresentationBuiltins, type CliSchemaExport } from "./export.ts";
9
- export { dispatchBuiltin, builtinInterceptRoot } from "./dispatch.ts";
9
+ export {
10
+ cliParseRoot,
11
+ cliPresentationRoot,
12
+ parseBuiltins,
13
+ presentationBuiltins,
14
+ } from "./presentation.ts";
10
15
  export { collectScopes, type ScopeRec } from "./scopes.ts";
@@ -1,5 +1,5 @@
1
1
  import { resolveCapabilities } from "../capabilities.ts";
2
- import { CliProgram, CliOption, CliOptionKind, type CliLeaf } from "../types.ts";
2
+ import { type CliLeaf, type CliOption, CliOptionKind, type CliProgram } from "../types.ts";
3
3
 
4
4
  /** Install command options (dynamic: `--mcp` only when MCP is enabled). */
5
5
  export function installBuiltinOptions(root: CliProgram): CliOption[] {
@@ -42,12 +42,14 @@ export function installBuiltinOptions(root: CliProgram): CliOption[] {
42
42
  },
43
43
  {
44
44
  name: "uninstall",
45
- description: "Remove installed artifacts (use --all or scoped flags; skips targets not on disk).",
45
+ description:
46
+ "Remove installed artifacts (use --all or scoped flags; skips targets not on disk).",
46
47
  kind: CliOptionKind.Presence,
47
48
  },
48
49
  {
49
50
  name: "prefix",
50
- description: "Install directory for the binary (default ~/.local/bin; overrides INSTALL_PREFIX).",
51
+ description:
52
+ "Install directory for the binary (default ~/.local/bin; overrides INSTALL_PREFIX).",
51
53
  kind: CliOptionKind.String,
52
54
  },
53
55
  {
@@ -67,7 +69,8 @@ export function installBuiltinOptions(root: CliProgram): CliOption[] {
67
69
  },
68
70
  {
69
71
  name: "quiet",
70
- description: "Suppress informational output (requires --yes, --json, --reinstall, or --update).",
72
+ description:
73
+ "Suppress informational output (requires --yes, --json, --reinstall, or --update).",
71
74
  kind: CliOptionKind.Presence,
72
75
  },
73
76
  ];
@@ -103,11 +106,7 @@ export function cliBuiltinInstallCommand(root: CliProgram): CliLeaf {
103
106
  ` ${app} install --reinstall`,
104
107
  ];
105
108
  if (resolveCapabilities(root).update) {
106
- notesLines.push(
107
- "",
108
- "Upgrade to latest release:",
109
- ` ${app} install --update`,
110
- );
109
+ notesLines.push("", "Upgrade to latest release:", ` ${app} install --update`);
111
110
  }
112
111
  notesLines.push(
113
112
  "",
@@ -122,7 +121,8 @@ export function cliBuiltinInstallCommand(root: CliProgram): CliLeaf {
122
121
  );
123
122
  return {
124
123
  key: "install",
125
- description: "Install the binary, shell completions, agent skills, and MCP config to your user environment.",
124
+ description:
125
+ "Install the binary, shell completions, agent skills, and MCP config to your user environment.",
126
126
  notes: notesLines.join("\n"),
127
127
  options: installBuiltinOptions(root),
128
128
  handler: () => {},
@@ -1,6 +1,6 @@
1
1
  import { resolveCapabilities } from "../capabilities.ts";
2
2
  import { docsEnabled } from "../docs/resolve.ts";
3
- import { type CliLeaf, type CliProgram, type CliRouter, CliFallbackMode } from "../types.ts";
3
+ import { CliFallbackMode, type CliLeaf, type CliProgram, type CliRouter } from "../types.ts";
4
4
 
5
5
  /** Built-in `mcp` router: bare `myapp mcp` runs stdio (via hidden `serve` fallback); `mcp bundle` packs `.mcpb`. */
6
6
  export function cliBuiltinMcpCommand(program: CliProgram): CliRouter {
@@ -1,20 +1,17 @@
1
1
  import type { CliCapabilities } from "../capabilities.ts";
2
2
  import { resolveCapabilities } from "../capabilities.ts";
3
+ import { cliBuiltinDocsGroupIfEnabled } from "../docs/builtin.ts";
3
4
  import { presentationNode, visibleOptions } from "../hidden.ts";
4
5
  import type { CliLeaf, CliNode, CliProgram, CliRouter } from "../types.ts";
5
- import { isCliLeaf, isCliRouter } from "../types.ts";
6
+ import { isCliLeaf } from "../types.ts";
6
7
  import { cliBuiltinCompletionGroup } from "./completion-group.ts";
7
8
  import { cliBuiltinInstallCommand } from "./install.ts";
8
9
  import { cliBuiltinMcpCommand } from "./mcp.ts";
9
10
  import { cliBuiltinVersionCommand } from "./version.ts";
10
- import { cliBuiltinDocsGroupIfEnabled } from "../docs/builtin.ts";
11
11
 
12
12
  /** All built-in command nodes for argv parsing (includes hidden builtins). */
13
13
  export function parseBuiltins(program: CliProgram, caps: CliCapabilities): CliNode[] {
14
- const builtins: CliNode[] = [
15
- cliBuiltinCompletionGroup(program),
16
- cliBuiltinVersionCommand(),
17
- ];
14
+ const builtins: CliNode[] = [cliBuiltinCompletionGroup(program), cliBuiltinVersionCommand()];
18
15
  if (caps.install) {
19
16
  builtins.push(cliBuiltinInstallCommand(program));
20
17
  }
@@ -98,10 +95,13 @@ export function cliPresentationRoot(program: CliProgram): CliRouter {
98
95
  }
99
96
 
100
97
  /** Root help notes: consumer `program.notes` plus agent discovery when `docs` is enabled. */
101
- export function presentationRootNotes(program: CliProgram, caps: CliCapabilities): string | undefined {
98
+ export function presentationRootNotes(
99
+ program: CliProgram,
100
+ caps: CliCapabilities,
101
+ ): string | undefined {
102
102
  const parts: string[] = [];
103
103
  if ((program.notes ?? "").trim().length > 0) {
104
- parts.push(program.notes!.trim());
104
+ parts.push((program.notes ?? "").trim());
105
105
  }
106
106
  if (caps.docs) {
107
107
  parts.push(`For AI agents: \`${program.key} docs skill\`.`);
@@ -25,7 +25,7 @@ function walkScopes(cmdPath: string, cmd: CliNode, acc: ScopeRec[]): void {
25
25
  wantsFiles: hasPositionalArguments(cmd),
26
26
  });
27
27
  for (const ch of kids) {
28
- const nextPath = cmdPath === "" ? ch.key : cmdPath + "/" + ch.key;
28
+ const nextPath = cmdPath === "" ? ch.key : `${cmdPath}/${ch.key}`;
29
29
  walkScopes(nextPath, ch, acc);
30
30
  }
31
31
  }
@@ -1,4 +1,4 @@
1
- import { type CliLeaf } from "../types.ts";
1
+ import type { CliLeaf } from "../types.ts";
2
2
 
3
3
  /** Top-level `version` built-in (leaf). */
4
4
  export function cliBuiltinVersionCommand(): CliLeaf {
package/src/completion.ts CHANGED
@@ -3,11 +3,11 @@ Re-export shim — completion emitters and built-in trees live in ./builtins/.
3
3
  */
4
4
 
5
5
  export {
6
- completionBashScript,
7
- completionZshScript,
8
- completionFishScript,
9
- cliPresentationRoot,
10
6
  cliBuiltinCompletionGroup,
11
7
  cliBuiltinInstallCommand,
12
8
  cliBuiltinMcpCommand,
9
+ cliPresentationRoot,
10
+ completionBashScript,
11
+ completionFishScript,
12
+ completionZshScript,
13
13
  } from "./builtins/index.ts";