argsbarg 3.3.11 → 3.3.13
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 +15 -1
- package/docs/ai-skills.md +4 -4
- package/docs/bundled-docs.md +2 -2
- package/package.json +1 -1
- package/src/docs/api-guide.test.ts +9 -1
- package/src/docs/api-guide.ts +9 -1
- package/src/docs/builtin.ts +14 -1
- package/src/docs/docs.test.ts +14 -0
- package/src/index.test.ts +11 -5
- package/src/skill/generate.ts +34 -25
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [3.3.13] - 2026-06-21
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- **Agent skills** — `SKILL.md` is a compact command index; `reference.md` holds the full `docs api` guide. `docs skill` notes recommend `install --skill` for the optimized persisted bundle.
|
|
15
|
+
|
|
16
|
+
## [3.3.12] - 2026-06-21
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- **Agent skills** — `SKILL.md` embeds the `docs api` command reference (body only) instead of a separate `## Commands` bullet catalog.
|
|
21
|
+
|
|
10
22
|
## [3.3.11] - 2026-06-21
|
|
11
23
|
|
|
12
24
|
### Added
|
|
@@ -317,7 +329,9 @@ const cli = { ... } satisfies CliProgram; // or : CliProgram
|
|
|
317
329
|
- 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`).
|
|
318
330
|
- Imports: use `CliPositional` where needed; replace `CliOptionDef` with `CliOption` or `CliPositional` as appropriate.
|
|
319
331
|
|
|
320
|
-
[Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v3.3.
|
|
332
|
+
[Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v3.3.13...HEAD
|
|
333
|
+
[3.3.13]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.3.13
|
|
334
|
+
[3.3.12]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.3.12
|
|
321
335
|
[3.3.11]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.3.11
|
|
322
336
|
[3.3.10]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.3.10
|
|
323
337
|
[3.3.9]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.3.9
|
package/docs/ai-skills.md
CHANGED
|
@@ -31,8 +31,8 @@ For library use, call `cliSkillInstall(root, "cursor" | "claude", { global: true
|
|
|
31
31
|
|
|
32
32
|
## Generated content
|
|
33
33
|
|
|
34
|
-
- **`SKILL.md`** — YAML frontmatter,
|
|
35
|
-
- **`reference.md`** — full `docs
|
|
34
|
+
- **`SKILL.md`** — YAML frontmatter, compact command index, pitfalls, and a pointer to `reference.md`
|
|
35
|
+
- **`reference.md`** — full `docs api` markdown reference
|
|
36
36
|
|
|
37
37
|
Installed files include an HTML comment hint (`Generated by myapp install --skill; do not edit.`) after SKILL.md frontmatter and at the top of `reference.md`.
|
|
38
38
|
|
|
@@ -43,10 +43,10 @@ Skills describe **shell invocation only** — no MCP setup, `mcp.json`, or `tool
|
|
|
43
43
|
| Mechanism | Role |
|
|
44
44
|
| --- | --- |
|
|
45
45
|
| **`myapp mcp`** (requires `mcpServer`) | Runtime tool execution over MCP |
|
|
46
|
-
| **`myapp install --skill`** |
|
|
46
|
+
| **`myapp install --skill`** | Persists optimized skill bundle (`SKILL.md` index + `reference.md` full API) |
|
|
47
47
|
| **`myapp docs`** (requires `docs`) | Bundled markdown on stdout (`docs mcp` when MCP enabled) |
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
`SKILL.md` is the routing index; `reference.md` matches `docs api`. Prefer `install --skill` over `docs skill` for agents. See [cli-program.md](cli-program.md).
|
|
50
50
|
|
|
51
51
|
See also:
|
|
52
52
|
|
package/docs/bundled-docs.md
CHANGED
|
@@ -68,7 +68,7 @@ When `docs.enabled` is `true`:
|
|
|
68
68
|
|
|
69
69
|
- **`docs schema`** — same JSON as the former root `--schema` flag (handlers omitted; built-in subtrees included for leaf roots).
|
|
70
70
|
- **`docs api`** — markdown rendering of the same command tree (options, positionals, subcommands, fallback routing).
|
|
71
|
-
- **`docs skill`** — prints
|
|
71
|
+
- **`docs skill`** — prints the compact `SKILL.md` index. Prefer `install --skill --yes` for agents (persists index + full API in `reference.md`).
|
|
72
72
|
|
|
73
73
|
## MCP guide (`docs mcp`)
|
|
74
74
|
|
|
@@ -84,7 +84,7 @@ All `docs` subcommands are hidden from MCP `tools/list` (`mcpTool: { enabled: fa
|
|
|
84
84
|
|
|
85
85
|
| Channel | Role |
|
|
86
86
|
| --- | --- |
|
|
87
|
-
| `install --skill` | Writes
|
|
87
|
+
| `install --skill` | Writes compact `SKILL.md` + full-API `reference.md` to disk |
|
|
88
88
|
| `docs skill` | Print generated `SKILL.md` to stdout |
|
|
89
89
|
| `docs api` | Print command tree markdown to stdout |
|
|
90
90
|
| `docs schema` | Print command tree JSON to stdout |
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { expect, test } from "bun:test";
|
|
2
2
|
import type { CliProgram } from "../types.ts";
|
|
3
3
|
import { CliOptionKind } from "../types.ts";
|
|
4
|
-
import { generateApiGuide } from "./api-guide.ts";
|
|
4
|
+
import { generateApiGuide, generateApiGuideBody } from "./api-guide.ts";
|
|
5
5
|
import { cliSchemaExport } from "../schema.ts";
|
|
6
6
|
|
|
7
7
|
const nestedFixture: CliProgram = {
|
|
@@ -45,6 +45,14 @@ const nestedFixture: CliProgram = {
|
|
|
45
45
|
],
|
|
46
46
|
};
|
|
47
47
|
|
|
48
|
+
test("generateApiGuideBody matches command section of full API guide", () => {
|
|
49
|
+
const body = generateApiGuideBody(nestedFixture);
|
|
50
|
+
const full = generateApiGuide(nestedFixture);
|
|
51
|
+
expect(full).toContain(body.trimEnd());
|
|
52
|
+
expect(body).toContain("## `nested.ts stat`");
|
|
53
|
+
expect(body).not.toContain("CLI API reference");
|
|
54
|
+
});
|
|
55
|
+
|
|
48
56
|
test("generateApiGuide covers the same command keys as cliSchemaExport", () => {
|
|
49
57
|
const md = generateApiGuide(nestedFixture);
|
|
50
58
|
const schema = cliSchemaExport(nestedFixture);
|
package/src/docs/api-guide.ts
CHANGED
|
@@ -117,6 +117,14 @@ function renderCommandNode(
|
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
+
/** Command-tree markdown shared by `docs api` and generated agent skills (no API doc header). */
|
|
121
|
+
export function generateApiGuideBody(program: CliProgram): string {
|
|
122
|
+
const schema = cliSchemaExport(program);
|
|
123
|
+
const lines: string[] = [];
|
|
124
|
+
renderCommandNode(program.key, [], schema, lines);
|
|
125
|
+
return `${lines.join("\n").trimEnd()}\n`;
|
|
126
|
+
}
|
|
127
|
+
|
|
120
128
|
/** Generates markdown API reference from the same export as `docs schema`. */
|
|
121
129
|
export function generateApiGuide(program: CliProgram): string {
|
|
122
130
|
const schema = cliSchemaExport(program);
|
|
@@ -133,6 +141,6 @@ export function generateApiGuide(program: CliProgram): string {
|
|
|
133
141
|
lines.push(formatNotesBlockquote(schema.notes, program.key), "");
|
|
134
142
|
}
|
|
135
143
|
|
|
136
|
-
|
|
144
|
+
lines.push(generateApiGuideBody(program).trimEnd(), "");
|
|
137
145
|
return `${lines.join("\n").trimEnd()}\n`;
|
|
138
146
|
}
|
package/src/docs/builtin.ts
CHANGED
|
@@ -55,7 +55,20 @@ export function cliBuiltinDocsGroup(program: CliProgram): CliRouter {
|
|
|
55
55
|
leaves.push(
|
|
56
56
|
docsLeaf(program, "schema", "Print the full command tree as JSON."),
|
|
57
57
|
docsLeaf(program, "api", "Print the command tree as markdown."),
|
|
58
|
-
|
|
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
|
+
},
|
|
59
72
|
);
|
|
60
73
|
|
|
61
74
|
return {
|
package/src/docs/docs.test.ts
CHANGED
|
@@ -153,9 +153,23 @@ 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`");
|
|
157
|
+
expect(result.stdout).not.toContain("#### Options");
|
|
156
158
|
expect(result.stdout).not.toContain("mcp.json");
|
|
157
159
|
});
|
|
158
160
|
|
|
161
|
+
test("docs skill help recommends install --skill", async () => {
|
|
162
|
+
const presentation = cliPresentationRoot(docsFixture());
|
|
163
|
+
const docsNode = presentation.commands.find((c) => c.key === "docs");
|
|
164
|
+
expect(docsNode && "commands" in docsNode).toBe(true);
|
|
165
|
+
if (docsNode && "commands" in docsNode) {
|
|
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");
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
|
|
159
173
|
test("presentation includes docs schema and skill", () => {
|
|
160
174
|
const presentation = cliPresentationRoot(docsFixture());
|
|
161
175
|
const docsNode = presentation.commands.find((c) => c.key === "docs");
|
package/src/index.test.ts
CHANGED
|
@@ -1808,19 +1808,24 @@ test("install config on non-root node is rejected", () => {
|
|
|
1808
1808
|
expect(() => cliValidateProgram(root)).toThrow(/install is only supported on the program root/);
|
|
1809
1809
|
});
|
|
1810
1810
|
|
|
1811
|
-
test("generateSkillBundle includes frontmatter and command
|
|
1811
|
+
test("generateSkillBundle includes frontmatter and compact command index", () => {
|
|
1812
1812
|
const bundle = generateSkillBundle(nestedMcpFixture, "cursor");
|
|
1813
1813
|
expect(bundle.dirName).toBe("nested_ts");
|
|
1814
1814
|
expect(bundle.skillMd).toMatch(/^---\nname: nested_ts\n/);
|
|
1815
|
-
expect(bundle.skillMd).toContain("
|
|
1815
|
+
expect(bundle.skillMd).toContain("## Commands");
|
|
1816
|
+
expect(bundle.skillMd).toContain("`nested.ts stat owner lookup <path>`");
|
|
1816
1817
|
expect(bundle.skillMd).toContain("Invoke via shell:");
|
|
1818
|
+
expect(bundle.skillMd).toContain("read `reference.md`");
|
|
1819
|
+
expect(bundle.skillMd).not.toContain("#### Options");
|
|
1820
|
+
expect(bundle.skillMd).not.toContain("CLI API reference");
|
|
1817
1821
|
expect(bundle.skillMd).not.toContain("mcp.json");
|
|
1818
1822
|
expect(bundle.skillMd).not.toContain("Prefer MCP");
|
|
1819
1823
|
expect(bundle.skillMd).not.toContain("tools/call");
|
|
1820
1824
|
expect(bundle.skillMd).not.toContain("Generated by");
|
|
1821
|
-
expect(bundle.referenceMd).toContain("
|
|
1825
|
+
expect(bundle.referenceMd).toContain("CLI API reference");
|
|
1826
|
+
expect(bundle.referenceMd).toContain("#### Options");
|
|
1822
1827
|
expect(bundle.referenceMd).not.toContain("Generated by");
|
|
1823
|
-
expect(
|
|
1828
|
+
expect(bundle.referenceMd).not.toContain("```json");
|
|
1824
1829
|
});
|
|
1825
1830
|
|
|
1826
1831
|
test("cliSkillInstall writes project Cursor skill files", () => {
|
|
@@ -1833,7 +1838,8 @@ test("cliSkillInstall writes project Cursor skill files", () => {
|
|
|
1833
1838
|
const skillDir = join(cwd, ".cursor", "skills", "nested_ts");
|
|
1834
1839
|
expect(existsSync(join(skillDir, "SKILL.md"))).toBe(true);
|
|
1835
1840
|
expect(existsSync(join(skillDir, "reference.md"))).toBe(true);
|
|
1836
|
-
expect(readFileSync(join(skillDir, "SKILL.md"), "utf8")).toContain("
|
|
1841
|
+
expect(readFileSync(join(skillDir, "SKILL.md"), "utf8")).toContain("## Commands");
|
|
1842
|
+
expect(readFileSync(join(skillDir, "reference.md"), "utf8")).toContain("CLI API reference");
|
|
1837
1843
|
const skillText = readFileSync(join(skillDir, "SKILL.md"), "utf8");
|
|
1838
1844
|
expect(skillText.startsWith("---\n")).toBe(true);
|
|
1839
1845
|
const hint = "<!-- Generated by nested.ts install --skill; do not edit. -->";
|
package/src/skill/generate.ts
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
This module generates Agent Skills content (SKILL.md + reference.md) from a CLI schema.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import { generateApiGuide } from "../docs/api-guide.ts";
|
|
5
6
|
import { collectOptionDefs } from "../parse.ts";
|
|
6
|
-
import {
|
|
7
|
-
import { collectMcpTools, sanitizeToolSegment } from "../mcp/tools.ts";
|
|
7
|
+
import { collectMcpTools, sanitizeToolSegment, type McpToolDef } from "../mcp/tools.ts";
|
|
8
8
|
import { CliProgram, CliOptionKind } from "../types.ts";
|
|
9
9
|
|
|
10
10
|
export type SkillTarget = "cursor" | "claude";
|
|
@@ -31,10 +31,22 @@ function skillDescription(root: CliProgram): string {
|
|
|
31
31
|
return truncate(desc, 1024);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
/**
|
|
35
|
-
function
|
|
36
|
-
const
|
|
37
|
-
|
|
34
|
+
/** CLI path with required single-slot positionals for the compact catalog. */
|
|
35
|
+
function commandCatalogPath(root: CliProgram, tool: McpToolDef): string {
|
|
36
|
+
const base = tool.path.length > 0 ? `${root.key} ${tool.path.join(" ")}` : root.key;
|
|
37
|
+
const slots = (tool.leaf.positionals ?? [])
|
|
38
|
+
.filter((p) => (p.argMin ?? 1) > 0 && (p.argMax ?? 1) === 1)
|
|
39
|
+
.map((p) => `<${p.name}>`);
|
|
40
|
+
if (slots.length === 0) {
|
|
41
|
+
return base;
|
|
42
|
+
}
|
|
43
|
+
return `${base} ${slots.join(" ")}`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Formats one command line for the SKILL.md index (details live in reference.md). */
|
|
47
|
+
function formatCommandEntry(root: CliProgram, tool: McpToolDef): string {
|
|
48
|
+
const cliPath = commandCatalogPath(root, tool);
|
|
49
|
+
let line = `- **\`${cliPath}\`** — ${tool.leaf.description}`;
|
|
38
50
|
const opts = collectOptionDefs(root, tool.path);
|
|
39
51
|
const flags = opts.filter((o) => o.kind === CliOptionKind.Presence).map((o) => `--${o.name}`);
|
|
40
52
|
if (flags.length > 0) {
|
|
@@ -48,6 +60,10 @@ function formatCommandEntry(root: CliProgram, tool: ReturnType<typeof collectMcp
|
|
|
48
60
|
if (varargs.length > 0) {
|
|
49
61
|
line += ` (varargs: ${varargs.map((p) => p.name).join(", ")})`;
|
|
50
62
|
}
|
|
63
|
+
const env = tool.leaf.mcpTool?.requiresEnv;
|
|
64
|
+
if (env && env.length > 0) {
|
|
65
|
+
line += ` [requires env: ${env.join(", ")}]`;
|
|
66
|
+
}
|
|
51
67
|
return line;
|
|
52
68
|
}
|
|
53
69
|
|
|
@@ -67,18 +83,18 @@ function buildSkillMd(root: CliProgram, target: SkillTarget, dirName: string): s
|
|
|
67
83
|
"",
|
|
68
84
|
root.description,
|
|
69
85
|
"",
|
|
70
|
-
"## When to use",
|
|
71
|
-
"",
|
|
72
|
-
`Use this skill when working with **${root.key}** — shell commands and automation for this application.`,
|
|
73
|
-
"",
|
|
74
86
|
"## Execution",
|
|
75
87
|
"",
|
|
76
88
|
"Invoke via shell:",
|
|
77
89
|
"",
|
|
90
|
+
"```bash",
|
|
91
|
+
`${root.key} <subcommand> [options] [args]`,
|
|
92
|
+
"```",
|
|
93
|
+
"",
|
|
94
|
+
"## Commands",
|
|
95
|
+
"",
|
|
78
96
|
];
|
|
79
97
|
|
|
80
|
-
lines.push("```bash", `${root.key} <subcommand> [options] [args]`, "```", "", "## Commands", "");
|
|
81
|
-
|
|
82
98
|
if (tools.length === 0) {
|
|
83
99
|
lines.push("(No leaf commands in schema.)", "");
|
|
84
100
|
} else {
|
|
@@ -92,11 +108,13 @@ function buildSkillMd(root: CliProgram, target: SkillTarget, dirName: string): s
|
|
|
92
108
|
"## Pitfalls",
|
|
93
109
|
"",
|
|
94
110
|
"- Use `--` before tokens that look like flags when they are positional arguments.",
|
|
95
|
-
"- Required environment variables are listed per command
|
|
111
|
+
"- Required environment variables are listed per command above (`requires env`) and in `reference.md`.",
|
|
96
112
|
"",
|
|
97
113
|
"## Reference",
|
|
98
114
|
"",
|
|
99
|
-
"
|
|
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.",
|
|
100
118
|
"",
|
|
101
119
|
);
|
|
102
120
|
|
|
@@ -125,18 +143,9 @@ function buildSkillMd(root: CliProgram, target: SkillTarget, dirName: string): s
|
|
|
125
143
|
return lines.join("\n");
|
|
126
144
|
}
|
|
127
145
|
|
|
128
|
-
/** Builds reference.md with
|
|
146
|
+
/** Builds reference.md with the full `docs api` markdown guide. */
|
|
129
147
|
function buildReferenceMd(root: CliProgram): string {
|
|
130
|
-
return
|
|
131
|
-
`# ${root.key} — CLI reference`,
|
|
132
|
-
"",
|
|
133
|
-
"Generated from the program `docs schema` export. Handlers and runtime-only nodes are omitted.",
|
|
134
|
-
"",
|
|
135
|
-
"```json",
|
|
136
|
-
cliSchemaJson(root).trimEnd(),
|
|
137
|
-
"```",
|
|
138
|
-
"",
|
|
139
|
-
].join("\n");
|
|
148
|
+
return generateApiGuide(root);
|
|
140
149
|
}
|
|
141
150
|
|
|
142
151
|
/** Generates SKILL.md and reference.md for Cursor or Claude Code. */
|