argsbarg 3.3.13 → 3.3.14

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/CHANGELOG.md CHANGED
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [3.3.14] - 2026-06-21
11
+
12
+ ### Changed
13
+
14
+ - **Generated notes** — deduplicated agent, docs, MCP, and completion help; each topic owns its guidance in one place.
15
+
10
16
  ## [3.3.13] - 2026-06-21
11
17
 
12
18
  ### Changed
@@ -329,7 +335,8 @@ const cli = { ... } satisfies CliProgram; // or : CliProgram
329
335
  - Migrate schemas: rename every `children` property to **`commands`**; move positional definitions to **`CliPositional`** objects on `positionals` and strip `positional` / `argMin` / `argMax` from flag definitions under `options` (flags only carry `name`, `description`, `kind`, and optional `shortName`).
330
336
  - Imports: use `CliPositional` where needed; replace `CliOptionDef` with `CliOption` or `CliPositional` as appropriate.
331
337
 
332
- [Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v3.3.13...HEAD
338
+ [Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v3.3.14...HEAD
339
+ [3.3.14]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.3.14
333
340
  [3.3.13]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.3.13
334
341
  [3.3.12]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.3.12
335
342
  [3.3.11]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.3.11
@@ -35,7 +35,7 @@ myapp docs readme --save # write ./docs/readme.md
35
35
  myapp docs schema --save # write ./docs/schema.json
36
36
  ```
37
37
 
38
- When `docs` is enabled, top-level `myapp --help` includes a Notes line: `Agents: run \`myapp docs skill\` to learn how to use this app`.
38
+ When `docs` is enabled, top-level `myapp --help` points agents at `myapp docs skill`. The `docs skill` subcommand description recommends `install --skill` for a persisted bundle.
39
39
 
40
40
  ## Configuration
41
41
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "argsbarg",
3
- "version": "3.3.13",
3
+ "version": "3.3.14",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "bun": ">=1.3"
@@ -57,9 +57,14 @@ describe("builtins help copy", () => {
57
57
  });
58
58
 
59
59
  test("mcp builtin description is user-facing", () => {
60
- const mcp = cliBuiltinMcpCommand();
60
+ const withDocs: CliProgram = {
61
+ ...fixture,
62
+ docs: { enabled: true, topics: { readme: { text: "# r\n" } } },
63
+ };
64
+ const mcp = cliBuiltinMcpCommand(withDocs);
61
65
  expect(mcp.description).toContain("MCP server");
62
- expect(mcp.notes).toContain('["mcp"]');
66
+ expect(mcp.notes).toContain("install --mcp --yes");
67
+ expect(mcp.notes).toContain("docs mcp");
63
68
  });
64
69
  });
65
70
 
@@ -87,7 +92,8 @@ describe("presentation root", () => {
87
92
  docs: { enabled: true, topics: { readme: { text: "# r\n" } } },
88
93
  };
89
94
  const root = cliPresentationRoot(withDocs);
90
- expect(root.notes).toContain("Agents: run `myapp docs skill` to learn how to use this app");
95
+ expect(root.notes).toContain("For AI agents: `myapp docs skill`.");
96
+ expect(root.notes).not.toContain("install --skill");
91
97
  });
92
98
  });
93
99
 
@@ -1,10 +1,13 @@
1
- import { type CliLeaf, type CliNode, type CliRouter } from "../types.ts";
1
+ import { resolveCapabilities } from "../capabilities.ts";
2
+ import { type CliLeaf, type CliProgram, type CliRouter } from "../types.ts";
2
3
 
3
4
  /**
4
5
  * Builds the static `completion` / `bash` / `zsh` / `fish` command subtree (merged into the program root at runtime).
5
6
  */
6
- export function cliBuiltinCompletionGroup(appName: string): CliRouter {
7
- return {
7
+ export function cliBuiltinCompletionGroup(program: CliProgram): CliRouter {
8
+ const appName = program.key;
9
+ const caps = resolveCapabilities(program);
10
+ const router: CliRouter = {
8
11
  key: "completion",
9
12
  description: "Generate the autocompletion script for shells.",
10
13
  commands: [
@@ -12,15 +15,10 @@ export function cliBuiltinCompletionGroup(appName: string): CliRouter {
12
15
  key: "bash",
13
16
  description: "Print a bash tab-completion script.",
14
17
  notes:
15
- "Output is the whole script.\n" +
16
- "Pipe it to a file, or feed it straight into your shell.\n\n" +
17
- "To keep it across restarts, save it and source that file from ~/.bashrc.\n\n" +
18
- "For example:\n\n" +
19
- `echo 'eval \"$(${appName} completion bash)\"' >> ~/.bashrc\n` +
20
- `\nor\n` +
18
+ "Manual install:\n\n" +
21
19
  ` ${appName} completion bash > ~/.bash_completion.d/${appName}\n` +
22
20
  ` echo 'source ~/.bash_completion.d/${appName}' >> ~/.bashrc\n\n` +
23
- "To try it only in this session (nothing written to disk):\n" +
21
+ "Try this session only:\n\n" +
24
22
  ` source <(${appName} completion bash)`,
25
23
  handler: () => {},
26
24
  },
@@ -28,23 +26,26 @@ export function cliBuiltinCompletionGroup(appName: string): CliRouter {
28
26
  key: "zsh",
29
27
  description: "Print a zsh tab-completion script.",
30
28
  notes:
31
- "Output is the whole script.\n\n" +
32
- `fpath setup: ${appName} completion zsh > ~/.zsh/completions/_${appName}\n\n` +
33
- `source setup: echo 'eval \"$(${appName} completion zsh)\"' >> ~/.zshrc\n\n` +
34
- "To try it only in this session (nothing written to disk):\n" +
35
- ` eval \"$(${appName} completion zsh)\"`,
29
+ "Manual install:\n\n" +
30
+ ` ${appName} completion zsh > ~/.zsh/completions/_${appName}\n\n` +
31
+ "Ensure ~/.zsh/completions is on your fpath, then restart zsh.\n\n" +
32
+ "Try this session only:\n\n" +
33
+ ` eval "$(${appName} completion zsh)"`,
36
34
  handler: () => {},
37
35
  },
38
36
  {
39
37
  key: "fish",
40
38
  description: "Print a fish tab-completion script.",
41
39
  notes:
42
- "Output is the whole script.\n\n" +
43
- "Install:\n" +
40
+ "Manual install:\n\n" +
44
41
  ` ${appName} completion fish > ~/.config/fish/completions/${appName}.fish\n\n` +
45
42
  "Fish loads completions from that directory automatically.",
46
43
  handler: () => {},
47
44
  },
48
45
  ],
49
46
  };
47
+ if (caps.install) {
48
+ router.notes = `Install for all shells:\n\n ${appName} install --completions --yes`;
49
+ }
50
+ return router;
50
51
  }
@@ -110,7 +110,7 @@ export function builtinInterceptRoot(
110
110
  parseRoot: {
111
111
  key: program.key,
112
112
  description: program.description,
113
- commands: [completionGroup(program.key)],
113
+ commands: [completionGroup(program)],
114
114
  },
115
115
  isLeafCompletionIntercept: true,
116
116
  };
@@ -132,7 +132,7 @@ export function builtinInterceptRoot(
132
132
  parseRoot: {
133
133
  key: program.key,
134
134
  description: program.description,
135
- commands: [cliBuiltinMcpCommand()],
135
+ commands: [cliBuiltinMcpCommand(program)],
136
136
  },
137
137
  isLeafCompletionIntercept: false,
138
138
  };
@@ -45,7 +45,7 @@ function exportBuiltinNode(cmd: {
45
45
  export function exportPresentationBuiltins(program: CliProgram, caps?: CliCapabilities): CliSchemaExport[] {
46
46
  const resolved = caps ?? resolveCapabilities(program);
47
47
  const builtins: CliSchemaExport[] = [
48
- exportBuiltinNode(cliBuiltinCompletionGroup(program.key)),
48
+ exportBuiltinNode(cliBuiltinCompletionGroup(program)),
49
49
  exportBuiltinNode(cliBuiltinVersionCommand()),
50
50
  ];
51
51
  if (resolved.install) {
@@ -56,7 +56,7 @@ export function exportPresentationBuiltins(program: CliProgram, caps?: CliCapabi
56
56
  builtins.push(exportBuiltinNode(docsGroup));
57
57
  }
58
58
  if (resolved.mcp) {
59
- builtins.push(exportBuiltinNode(cliBuiltinMcpCommand()));
59
+ builtins.push(exportBuiltinNode(cliBuiltinMcpCommand(program)));
60
60
  }
61
61
  return builtins;
62
62
  }
@@ -117,7 +117,8 @@ export function cliBuiltinInstallCommand(root: CliProgram): CliLeaf {
117
117
  "Remove everything installed with --all:",
118
118
  ` ${app} install --uninstall --all --yes`,
119
119
  "",
120
- "Use --dry to preview changes, --json for machine-readable output.",
120
+ "Use --dry to preview changes without writing files.",
121
+ "Use --json for machine-readable output.",
121
122
  );
122
123
  return {
123
124
  key: "install",
@@ -1,13 +1,27 @@
1
- import { type CliLeaf } from "../types.ts";
1
+ import { resolveCapabilities } from "../capabilities.ts";
2
+ import { docsEnabled } from "../docs/resolve.ts";
3
+ import { type CliLeaf, type CliProgram } from "../types.ts";
2
4
 
3
5
  /** Presence options for the top-level `mcp` built-in (leaf). */
4
- export function cliBuiltinMcpCommand(): CliLeaf {
6
+ export function cliBuiltinMcpCommand(program: CliProgram): CliLeaf {
7
+ const caps = resolveCapabilities(program);
8
+ const lines = [
9
+ "Stdio MCP server. Add to Cursor or Claude:",
10
+ "",
11
+ " command: {argsbarg:program}",
12
+ " args: mcp",
13
+ "",
14
+ ];
15
+ if (caps.install) {
16
+ lines.push("Or:", "", " {argsbarg:program} install --mcp --yes", "");
17
+ }
18
+ if (docsEnabled(program)) {
19
+ lines.push("Full setup guide: {argsbarg:program} docs mcp");
20
+ }
5
21
  return {
6
22
  key: "mcp",
7
23
  description: "Run as an MCP server over stdio for AI agents.",
8
- notes:
9
- "Configure MCP clients with `command` set to this program name and `args` set to `[\"mcp\"]`.\n\n" +
10
- "See docs/mcp.md for setup details.",
24
+ notes: lines.join("\n"),
11
25
  handler: () => {},
12
26
  };
13
27
  }
@@ -11,7 +11,7 @@ import { cliBuiltinDocsGroupIfEnabled } from "../docs/builtin.ts";
11
11
  /** Built-in command nodes injected for help, schema, and completions. */
12
12
  export function presentationBuiltins(program: CliProgram, caps: CliCapabilities): CliNode[] {
13
13
  const builtins: CliNode[] = [
14
- cliBuiltinCompletionGroup(program.key),
14
+ cliBuiltinCompletionGroup(program),
15
15
  cliBuiltinVersionCommand(),
16
16
  ];
17
17
  if (caps.install) {
@@ -22,7 +22,7 @@ export function presentationBuiltins(program: CliProgram, caps: CliCapabilities)
22
22
  builtins.push(docsGroup);
23
23
  }
24
24
  if (caps.mcp) {
25
- builtins.push(cliBuiltinMcpCommand());
25
+ builtins.push(cliBuiltinMcpCommand(program));
26
26
  }
27
27
  return builtins;
28
28
  }
@@ -64,8 +64,7 @@ export function presentationRootNotes(program: CliProgram, caps: CliCapabilities
64
64
  parts.push(program.notes!.trim());
65
65
  }
66
66
  if (caps.docs) {
67
- const cmd = `${program.key} docs skill`;
68
- parts.push(`Agents: run \`${cmd}\` to learn how to use this app`);
67
+ parts.push(`For AI agents: \`${program.key} docs skill\`.`);
69
68
  }
70
69
  if (parts.length === 0) {
71
70
  return undefined;
@@ -36,6 +36,11 @@ function docsLeaf(program: CliProgram, key: string, description: string): CliLea
36
36
  };
37
37
  }
38
38
 
39
+ /** Help notes for the `docs` router. */
40
+ function docsRouterNotes(): string {
41
+ return "Topics print to stdout. Add --save to write files under ./docs/.";
42
+ }
43
+
39
44
  /** Built-in `docs` router with bundled topic subcommands. */
40
45
  export function cliBuiltinDocsGroup(program: CliProgram): CliRouter {
41
46
  const docs = program.docs!;
@@ -54,26 +59,14 @@ export function cliBuiltinDocsGroup(program: CliProgram): CliRouter {
54
59
 
55
60
  leaves.push(
56
61
  docsLeaf(program, "schema", "Print the full command tree as JSON."),
57
- docsLeaf(program, "api", "Print the command tree as markdown."),
58
- {
59
- key: "skill",
60
- description: "Print generated SKILL.md (compact command index).",
61
- notes: [
62
- "Prefer `{argsbarg:program} install --skill --yes` for agents: it persists an optimized skill bundle",
63
- "(`SKILL.md` index + `reference.md` full API) to your skill directory.",
64
- "`docs skill` prints the index only; use `docs api` or installed `reference.md` for full detail.",
65
- ].join(" "),
66
- options: [DOCS_SAVE_OPTION],
67
- mcpTool: { enabled: false },
68
- handler: (ctx) => {
69
- runDocsTopic(program, "skill", ctx);
70
- },
71
- },
62
+ docsLeaf(program, "api", "Print the full command reference as markdown."),
63
+ docsLeaf(program, "skill", "Print a reference agent SKILL, use `install --skill` for optimized."),
72
64
  );
73
65
 
74
66
  return {
75
67
  key: "docs",
76
68
  description: docs.description ?? DOCS_ROUTER_DESCRIPTION,
69
+ notes: docsRouterNotes(),
77
70
  options: [DOCS_SAVE_OPTION],
78
71
  fallbackCommand: docsEffectiveDefaultTopic(docs),
79
72
  fallbackMode: CliFallbackMode.MissingOnly,
@@ -153,7 +153,7 @@ test("docs skill prints Cursor SKILL.md", async () => {
153
153
  expect(result.stdout).toContain("---");
154
154
  expect(result.stdout).toContain("name: myapp");
155
155
  expect(result.stdout).toContain("## Commands");
156
- expect(result.stdout).toContain("read `reference.md`");
156
+ expect(result.stdout).toContain("For full detail, open `reference.md`");
157
157
  expect(result.stdout).not.toContain("#### Options");
158
158
  expect(result.stdout).not.toContain("mcp.json");
159
159
  });
@@ -164,9 +164,11 @@ test("docs skill help recommends install --skill", async () => {
164
164
  expect(docsNode && "commands" in docsNode).toBe(true);
165
165
  if (docsNode && "commands" in docsNode) {
166
166
  const skill = docsNode.commands.find((c) => c.key === "skill");
167
- expect(skill?.description).toContain("compact command index");
168
- expect(skill?.notes).toContain("install --skill --yes");
169
- expect(skill?.notes).toContain("reference.md");
167
+ expect(skill?.description).toContain("reference agent SKILL");
168
+ expect(skill?.description).toContain("install --skill");
169
+ expect(skill?.notes).toBeUndefined();
170
+ expect(docsNode.notes).toContain("--save");
171
+ expect(docsNode.notes).not.toContain("install --skill");
170
172
  }
171
173
  });
172
174
 
package/src/index.test.ts CHANGED
@@ -496,7 +496,7 @@ test("leaf completion help prints correctly", async () => {
496
496
  const out = stdout.toString();
497
497
  expect(exitCode).toBe(0);
498
498
  expect(out).toContain("Show help for this command.");
499
- expect(out).toContain("Output is the whole script.");
499
+ expect(out).toContain("Manual install:");
500
500
  expect(stderr.toString()).toBe("");
501
501
  });
502
502
 
@@ -658,7 +658,7 @@ test("docs help lists schema, api, and skill subcommands", () => {
658
658
  expect(help).toContain("api");
659
659
  expect(help).toContain("markdown");
660
660
  expect(help).toContain("skill");
661
- expect(help).toContain("SKILL.md");
661
+ expect(help).toContain("reference agent SKILL");
662
662
  });
663
663
 
664
664
  test("root help omits legacy --schema flag", () => {
@@ -690,7 +690,8 @@ test("root help shows agent docs hint when docs enabled", () => {
690
690
  commands: [{ key: "run", description: "Run.", handler: () => {} }],
691
691
  });
692
692
  const help = cliHelpRender(cliPresentationRoot(root), [], false);
693
- expect(help).toContain("Agents: run `myapp docs skill` to learn how to use this app");
693
+ expect(help).toContain("For AI agents: `myapp docs skill`.");
694
+ expect(help).not.toContain("install --skill");
694
695
  });
695
696
 
696
697
  test("root help omits agent hint when docs disabled", () => {
@@ -1815,7 +1816,7 @@ test("generateSkillBundle includes frontmatter and compact command index", () =>
1815
1816
  expect(bundle.skillMd).toContain("## Commands");
1816
1817
  expect(bundle.skillMd).toContain("`nested.ts stat owner lookup <path>`");
1817
1818
  expect(bundle.skillMd).toContain("Invoke via shell:");
1818
- expect(bundle.skillMd).toContain("read `reference.md`");
1819
+ expect(bundle.skillMd).toContain("For full detail, open `reference.md`");
1819
1820
  expect(bundle.skillMd).not.toContain("#### Options");
1820
1821
  expect(bundle.skillMd).not.toContain("CLI API reference");
1821
1822
  expect(bundle.skillMd).not.toContain("mcp.json");
@@ -107,14 +107,12 @@ function buildSkillMd(root: CliProgram, target: SkillTarget, dirName: string): s
107
107
  lines.push(
108
108
  "## Pitfalls",
109
109
  "",
110
- "- Use `--` before tokens that look like flags when they are positional arguments.",
111
- "- Required environment variables are listed per command above (`requires env`) and in `reference.md`.",
110
+ "- Pass `--` before arguments that look like flags.",
111
+ "- Commands marked `[requires env: ...]` need those variables set in the shell.",
112
112
  "",
113
113
  "## Reference",
114
114
  "",
115
- "This file is a command index. For full option tables, positionals, notes, and built-ins,",
116
- `read \`reference.md\` in this skill directory (same content as \`${root.key} docs api\`).`,
117
- "Search for the command path you need before invoking.",
115
+ `For full detail, open \`reference.md\` in this skill directory (same as \`${root.key} docs api\`).`,
118
116
  "",
119
117
  );
120
118