argsbarg 3.3.9 → 3.3.11
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 +16 -1
- package/docs/bundled-docs.md +2 -0
- package/docs/install.md +2 -2
- package/package.json +1 -1
- package/plan.md +2 -2
- package/src/builtins/builtins.test.ts +28 -0
- package/src/builtins/install.ts +2 -2
- package/src/builtins/presentation.ts +20 -1
- package/src/docs/api-guide.test.ts +14 -0
- package/src/help.ts +17 -5
- package/src/index.test.ts +44 -0
- package/src/install/update.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [3.3.11] - 2026-06-21
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Root help agent hint** — when `docs` is enabled, top-level `-h` includes a Notes line: `Agents: run \`myapp docs skill\` to learn how to use this app`. Root help also renders `program.notes`.
|
|
15
|
+
|
|
16
|
+
## [3.3.10] - 2026-06-21
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- **`install` help copy** — `--update` and `--quiet` option descriptions match behavior; `install --update` error message clarified.
|
|
21
|
+
- **`docs/install.md`** — quick-start and `--yes` flag docs aligned with install notes.
|
|
22
|
+
|
|
10
23
|
## [3.3.9] - 2026-06-21
|
|
11
24
|
|
|
12
25
|
### Changed
|
|
@@ -304,7 +317,9 @@ const cli = { ... } satisfies CliProgram; // or : CliProgram
|
|
|
304
317
|
- 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`).
|
|
305
318
|
- Imports: use `CliPositional` where needed; replace `CliOptionDef` with `CliOption` or `CliPositional` as appropriate.
|
|
306
319
|
|
|
307
|
-
[Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v3.3.
|
|
320
|
+
[Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v3.3.11...HEAD
|
|
321
|
+
[3.3.11]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.3.11
|
|
322
|
+
[3.3.10]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.3.10
|
|
308
323
|
[3.3.9]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.3.9
|
|
309
324
|
[3.3.8]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.3.8
|
|
310
325
|
[3.3.7]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.3.7
|
package/docs/bundled-docs.md
CHANGED
|
@@ -35,6 +35,8 @@ 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`.
|
|
39
|
+
|
|
38
40
|
## Configuration
|
|
39
41
|
|
|
40
42
|
| Field | Default | Purpose |
|
package/docs/install.md
CHANGED
|
@@ -11,7 +11,7 @@ myapp install --all --yes
|
|
|
11
11
|
# Refresh after upgrading (re-copy running binary + refresh installed artifacts)
|
|
12
12
|
myapp install --reinstall
|
|
13
13
|
|
|
14
|
-
#
|
|
14
|
+
# Upgrade to latest release (when install.updateGetLatest is configured)
|
|
15
15
|
myapp install --update
|
|
16
16
|
|
|
17
17
|
# See what is installed
|
|
@@ -99,7 +99,7 @@ Environment:
|
|
|
99
99
|
|
|
100
100
|
| Flag | Description |
|
|
101
101
|
| --- | --- |
|
|
102
|
-
| `--yes` | Skip confirmation (required for non-TTY unless `--json
|
|
102
|
+
| `--yes` | Skip confirmation (required for non-TTY unless `--json`, `--reinstall`, or `--update`) |
|
|
103
103
|
| `--dry` | Preview changes; per-step messages on stderr with `[dry run]` |
|
|
104
104
|
| `--json` | Machine-readable output on stdout (implies `--yes`) |
|
|
105
105
|
| `--quiet` | Suppress summaries and per-step messages (requires `--yes`) |
|
package/package.json
CHANGED
package/plan.md
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## Current Status
|
|
4
4
|
|
|
5
|
-
**Overall**: Core CLI, MCP, install, docs, and update
|
|
5
|
+
**Overall**: Core CLI, MCP, install, docs, and `install --update` are complete. Public API is stable at **3.x**.
|
|
6
6
|
|
|
7
7
|
### Shipped
|
|
8
8
|
|
|
9
9
|
- Schema-driven parsing, help, completions, subcommand routing, fallback commands
|
|
10
10
|
- MCP server (`mcpServer: { enabled: true }`), `ctx.invocation`, `cliInvoke`
|
|
11
|
-
- `install`
|
|
11
|
+
- `install` built-in (`install --update` when `updateGetLatest` is set), agent skills, bundled `docs` (topics, schema, api, skill, mcp)
|
|
12
12
|
- Headless helpers and `ghReleaseUpdateGetLatest` for GitHub release consumers
|
|
13
13
|
|
|
14
14
|
### Consumers
|
|
@@ -37,6 +37,25 @@ describe("builtins help copy", () => {
|
|
|
37
37
|
expect(names).not.toContain("mcp");
|
|
38
38
|
});
|
|
39
39
|
|
|
40
|
+
test("install omits --update when updateGetLatest unset", () => {
|
|
41
|
+
const install = cliBuiltinInstallCommand(fixture);
|
|
42
|
+
expect(installBuiltinOptions(fixture).map((o) => o.name)).not.toContain("update");
|
|
43
|
+
expect(install.notes).not.toContain("Upgrade to latest release");
|
|
44
|
+
expect(install.notes).toContain("Refresh after upgrading");
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test("install notes include upgrade section when updateGetLatest is set", () => {
|
|
48
|
+
const withUpdate: CliProgram = {
|
|
49
|
+
...fixture,
|
|
50
|
+
install: { updateGetLatest: async () => ({ path: process.execPath }) },
|
|
51
|
+
};
|
|
52
|
+
const install = cliBuiltinInstallCommand(withUpdate);
|
|
53
|
+
const notes = install.notes ?? "";
|
|
54
|
+
expect(installBuiltinOptions(withUpdate).map((o) => o.name)).toContain("update");
|
|
55
|
+
expect(notes).toContain("Upgrade to latest release");
|
|
56
|
+
expect(notes.indexOf("install --reinstall")).toBeLessThan(notes.indexOf("install --update"));
|
|
57
|
+
});
|
|
58
|
+
|
|
40
59
|
test("mcp builtin description is user-facing", () => {
|
|
41
60
|
const mcp = cliBuiltinMcpCommand();
|
|
42
61
|
expect(mcp.description).toContain("MCP server");
|
|
@@ -61,6 +80,15 @@ describe("presentation root", () => {
|
|
|
61
80
|
const root = cliPresentationRoot(fixture);
|
|
62
81
|
expect(root.commands?.map((c) => c.key)).toContain("version");
|
|
63
82
|
});
|
|
83
|
+
|
|
84
|
+
test("root notes include agent hint when docs enabled", () => {
|
|
85
|
+
const withDocs: CliProgram = {
|
|
86
|
+
...fixture,
|
|
87
|
+
docs: { enabled: true, topics: { readme: { text: "# r\n" } } },
|
|
88
|
+
};
|
|
89
|
+
const root = cliPresentationRoot(withDocs);
|
|
90
|
+
expect(root.notes).toContain("Agents: run `myapp docs skill` to learn how to use this app");
|
|
91
|
+
});
|
|
64
92
|
});
|
|
65
93
|
|
|
66
94
|
describe("completion emitters", () => {
|
package/src/builtins/install.ts
CHANGED
|
@@ -67,7 +67,7 @@ export function installBuiltinOptions(root: CliProgram): CliOption[] {
|
|
|
67
67
|
},
|
|
68
68
|
{
|
|
69
69
|
name: "quiet",
|
|
70
|
-
description: "Suppress informational output (requires --yes).",
|
|
70
|
+
description: "Suppress informational output (requires --yes, --json, --reinstall, or --update).",
|
|
71
71
|
kind: CliOptionKind.Presence,
|
|
72
72
|
},
|
|
73
73
|
];
|
|
@@ -84,7 +84,7 @@ export function installBuiltinOptions(root: CliProgram): CliOption[] {
|
|
|
84
84
|
const statusIdx = opts.findIndex((o) => o.name === "status");
|
|
85
85
|
opts.splice(statusIdx, 0, {
|
|
86
86
|
name: "update",
|
|
87
|
-
description: "Download
|
|
87
|
+
description: "Download the latest release and reinstall installed artifacts.",
|
|
88
88
|
kind: CliOptionKind.Presence,
|
|
89
89
|
});
|
|
90
90
|
}
|
|
@@ -34,11 +34,13 @@ export function presentationBuiltins(program: CliProgram, caps: CliCapabilities)
|
|
|
34
34
|
export function cliPresentationRoot(program: CliProgram): CliRouter {
|
|
35
35
|
const caps = resolveCapabilities(program);
|
|
36
36
|
const builtins = presentationBuiltins(program, caps);
|
|
37
|
+
const notes = presentationRootNotes(program, caps);
|
|
37
38
|
|
|
38
39
|
if (isCliLeaf(program)) {
|
|
39
40
|
return {
|
|
40
41
|
key: program.key,
|
|
41
42
|
description: program.description,
|
|
43
|
+
notes,
|
|
42
44
|
options: program.options,
|
|
43
45
|
commands: builtins,
|
|
44
46
|
};
|
|
@@ -47,7 +49,7 @@ export function cliPresentationRoot(program: CliProgram): CliRouter {
|
|
|
47
49
|
return {
|
|
48
50
|
key: program.key,
|
|
49
51
|
description: program.description,
|
|
50
|
-
notes
|
|
52
|
+
notes,
|
|
51
53
|
options: program.options,
|
|
52
54
|
fallbackCommand: program.fallbackCommand,
|
|
53
55
|
fallbackMode: program.fallbackMode,
|
|
@@ -55,5 +57,22 @@ export function cliPresentationRoot(program: CliProgram): CliRouter {
|
|
|
55
57
|
};
|
|
56
58
|
}
|
|
57
59
|
|
|
60
|
+
/** Root help notes: consumer `program.notes` plus agent discovery when `docs` is enabled. */
|
|
61
|
+
export function presentationRootNotes(program: CliProgram, caps: CliCapabilities): string | undefined {
|
|
62
|
+
const parts: string[] = [];
|
|
63
|
+
if ((program.notes ?? "").trim().length > 0) {
|
|
64
|
+
parts.push(program.notes!.trim());
|
|
65
|
+
}
|
|
66
|
+
if (caps.docs) {
|
|
67
|
+
const cmd = `${program.key} docs skill`;
|
|
68
|
+
parts.push(`Agents: run \`${cmd}\` to learn how to use this app`);
|
|
69
|
+
}
|
|
70
|
+
if (parts.length === 0) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
return parts.join("\n\n");
|
|
74
|
+
}
|
|
75
|
+
|
|
58
76
|
/** Presentation tree may include builtin leaf stubs. */
|
|
59
77
|
export type CliPresentationNode = CliNode | CliLeaf;
|
|
78
|
+
|
|
@@ -64,6 +64,20 @@ test("generateApiGuide resolves program key in install notes", () => {
|
|
|
64
64
|
const md = generateApiGuide(fixture);
|
|
65
65
|
expect(md).not.toContain("{argsbarg:program}");
|
|
66
66
|
expect(md).toContain("myapp install --all --yes");
|
|
67
|
+
expect(md).not.toContain("Upgrade to latest release");
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("generateApiGuide includes upgrade section when updateGetLatest is set", () => {
|
|
71
|
+
const fixture: CliProgram = {
|
|
72
|
+
key: "myapp",
|
|
73
|
+
version: "1.0.0",
|
|
74
|
+
description: "Demo app.",
|
|
75
|
+
install: { updateGetLatest: async () => ({ path: process.execPath }) },
|
|
76
|
+
commands: [{ key: "run", description: "Run.", handler: () => {} }],
|
|
77
|
+
};
|
|
78
|
+
const md = generateApiGuide(fixture);
|
|
79
|
+
expect(md).toContain("Upgrade to latest release");
|
|
80
|
+
expect(md).toContain("myapp install --update");
|
|
67
81
|
});
|
|
68
82
|
|
|
69
83
|
test("generateApiGuide resolves {argsbarg:program} in consumer notes", () => {
|
package/src/help.ts
CHANGED
|
@@ -381,6 +381,21 @@ function rowsForSubcommands(cmds: CliNode[]): HelpRow[] {
|
|
|
381
381
|
|
|
382
382
|
// ── Main Help Render ──────────────────────────────────────────────────────────
|
|
383
383
|
|
|
384
|
+
function appendNotesBox(
|
|
385
|
+
lines: string[],
|
|
386
|
+
notes: string | undefined,
|
|
387
|
+
appKey: string,
|
|
388
|
+
hw: number,
|
|
389
|
+
color: boolean,
|
|
390
|
+
): void {
|
|
391
|
+
if ((notes ?? "").length === 0) {
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
const resolved = cliResolveNotes(notes!, appKey);
|
|
395
|
+
lines.push("");
|
|
396
|
+
lines.push(renderTextBox("Notes", wrapText(resolved, hw - 4), hw, color).join("\n"));
|
|
397
|
+
}
|
|
398
|
+
|
|
384
399
|
/**
|
|
385
400
|
* Renders full help for the app root or a nested command, following `helpPath` from the root key.
|
|
386
401
|
* `useStderr` is reserved for call-site consistency; width and color use stdout TTY.
|
|
@@ -416,6 +431,7 @@ export function cliHelpRender(schema: CliRouter, helpPath: string[], useStderr:
|
|
|
416
431
|
renderTableBox("Commands", rowsForSubcommands(schema.commands ?? []), hw, color).join("\n"),
|
|
417
432
|
);
|
|
418
433
|
}
|
|
434
|
+
appendNotesBox(lines, schema.notes, schema.key, hw, color);
|
|
419
435
|
return lines.join("\n") + "\n\n";
|
|
420
436
|
}
|
|
421
437
|
|
|
@@ -479,11 +495,7 @@ export function cliHelpRender(schema: CliRouter, helpPath: string[], useStderr:
|
|
|
479
495
|
}
|
|
480
496
|
|
|
481
497
|
if ((node.notes ?? "").length > 0) {
|
|
482
|
-
|
|
483
|
-
lines.push("");
|
|
484
|
-
lines.push(
|
|
485
|
-
renderTextBox("Notes", wrapText(resolved, hw - 4), hw, color).join("\n"),
|
|
486
|
-
);
|
|
498
|
+
appendNotesBox(lines, node.notes, schema.key, hw, color);
|
|
487
499
|
}
|
|
488
500
|
|
|
489
501
|
return lines.join("\n") + "\n\n";
|
package/src/index.test.ts
CHANGED
|
@@ -678,6 +678,50 @@ test("root help omits legacy --schema flag", () => {
|
|
|
678
678
|
expect(help).not.toContain("--schema");
|
|
679
679
|
});
|
|
680
680
|
|
|
681
|
+
test("root help shows agent docs hint when docs enabled", () => {
|
|
682
|
+
const root = testProgram({
|
|
683
|
+
key: "myapp",
|
|
684
|
+
version: "1.0.0",
|
|
685
|
+
description: "demo",
|
|
686
|
+
docs: {
|
|
687
|
+
enabled: true,
|
|
688
|
+
topics: { readme: { text: "# readme\n" } },
|
|
689
|
+
},
|
|
690
|
+
commands: [{ key: "run", description: "Run.", handler: () => {} }],
|
|
691
|
+
});
|
|
692
|
+
const help = cliHelpRender(cliPresentationRoot(root), [], false);
|
|
693
|
+
expect(help).toContain("Agents: run `myapp docs skill` to learn how to use this app");
|
|
694
|
+
});
|
|
695
|
+
|
|
696
|
+
test("root help omits agent hint when docs disabled", () => {
|
|
697
|
+
const root = testProgram({
|
|
698
|
+
key: "myapp",
|
|
699
|
+
version: "1.0.0",
|
|
700
|
+
description: "demo",
|
|
701
|
+
commands: [{ key: "run", description: "Run.", handler: () => {} }],
|
|
702
|
+
});
|
|
703
|
+
const help = cliHelpRender(cliPresentationRoot(root), [], false);
|
|
704
|
+
expect(help).not.toContain("Agents:");
|
|
705
|
+
expect(help).not.toContain("docs skill");
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
test("root help includes program notes and agent hint", () => {
|
|
709
|
+
const root = testProgram({
|
|
710
|
+
key: "myapp",
|
|
711
|
+
version: "1.0.0",
|
|
712
|
+
description: "demo",
|
|
713
|
+
notes: "See `{argsbarg:program} docs readme` for the user guide.",
|
|
714
|
+
docs: {
|
|
715
|
+
enabled: true,
|
|
716
|
+
topics: { readme: { text: "# readme\n" } },
|
|
717
|
+
},
|
|
718
|
+
commands: [{ key: "run", description: "Run.", handler: () => {} }],
|
|
719
|
+
});
|
|
720
|
+
const help = cliHelpRender(cliPresentationRoot(root), [], false);
|
|
721
|
+
expect(help).toContain("See `myapp docs readme` for the user guide.");
|
|
722
|
+
expect(help).toContain("myapp docs skill");
|
|
723
|
+
});
|
|
724
|
+
|
|
681
725
|
const nestedMcpFixture = testProgram({
|
|
682
726
|
key: "nested.ts",
|
|
683
727
|
description: "Nested groups demo.",
|
package/src/install/update.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { installErr } from "./status.ts";
|
|
|
7
7
|
export async function cliUpdate(root: CliProgram): Promise<never> {
|
|
8
8
|
const hook = root.install?.updateGetLatest;
|
|
9
9
|
if (!hook) {
|
|
10
|
-
installErr("update is not configured. Set install.updateGetLatest on the program root.");
|
|
10
|
+
installErr("install --update is not configured. Set install.updateGetLatest on the program root.");
|
|
11
11
|
process.exit(1);
|
|
12
12
|
}
|
|
13
13
|
|