argsbarg 7.0.5 → 7.0.7

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 (49) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/README.md +3 -3
  3. package/docs/README.md +1 -1
  4. package/docs/ai-skills.md +14 -59
  5. package/docs/bundled-docs.md +11 -15
  6. package/docs/cli-program.md +11 -12
  7. package/docs/configure.md +9 -11
  8. package/docs/output-schema.md +0 -1
  9. package/examples/full-example/AGENTS.md +3 -1
  10. package/examples/full-example/docs/README.md +1 -1
  11. package/examples/full-example/docs/http.md +1 -1
  12. package/examples/full-example/docs/mcp.md +1 -1
  13. package/examples/full-example/docs/openapi.json +1 -6
  14. package/examples/full-example/justfile +0 -1
  15. package/examples/full-example/{docs/skill.md → skills/full-example/SKILL.md} +10 -8
  16. package/examples/full-example/src/program.ts +0 -1
  17. package/examples/full-example-json/AGENTS.md +3 -1
  18. package/examples/full-example-json/docs/README.md +1 -1
  19. package/examples/full-example-json/docs/http.md +1 -1
  20. package/examples/full-example-json/docs/mcp.md +5 -5
  21. package/examples/full-example-json/docs/openapi.json +1 -6
  22. package/examples/full-example-json/justfile +0 -1
  23. package/examples/full-example-json/{docs/skill.md → skills/full-example-json/SKILL.md} +15 -13
  24. package/examples/full-example-json/src/program.ts +0 -1
  25. package/index.d.ts +5 -3
  26. package/package.json +1 -1
  27. package/src/builtins/builtins.test.ts +1 -22
  28. package/src/builtins/configure-copy.ts +4 -11
  29. package/src/builtins/presentation.ts +2 -5
  30. package/src/cli-tool/create.test.ts +1 -0
  31. package/src/cli-tool/create.ts +5 -1
  32. package/src/configure/artifacts/status.test.ts +5 -5
  33. package/src/configure/artifacts/target-effective.ts +1 -2
  34. package/src/configure/artifacts/target-skill.ts +9 -15
  35. package/src/configure/artifacts/targets/skill.ts +8 -1
  36. package/src/configure/artifacts/targets.test.ts +5 -5
  37. package/src/configure/configure.test.ts +4 -4
  38. package/src/core/parse.test.ts +1 -93
  39. package/src/core/types.ts +5 -3
  40. package/src/core/validate.ts +4 -2
  41. package/src/docs/builtin.ts +5 -3
  42. package/src/docs/cli-guide.ts +3 -3
  43. package/src/docs/docs.test.ts +3 -45
  44. package/src/docs/resolve.ts +5 -5
  45. package/src/docs/save.ts +52 -15
  46. package/src/help.test.ts +6 -7
  47. package/src/skill/generate.ts +32 -154
  48. package/src/skill/hint.ts +6 -32
  49. package/src/skill/install.ts +10 -31
@@ -76,9 +76,6 @@ test("docs rejects reserved topic keys", () => {
76
76
  docs.topics["cli-schema"] = { text: "nope" };
77
77
  expect(() => cliValidateProgram(root)).toThrow(/reserved/);
78
78
  delete docs.topics["cli-schema"];
79
- docs.topics.skill = { text: "nope" };
80
- expect(() => cliValidateProgram(root)).toThrow(/reserved/);
81
- delete docs.topics.skill;
82
79
  docs.topics.cli = { text: "nope" };
83
80
  expect(() => cliValidateProgram(root)).toThrow(/reserved/);
84
81
  delete docs.topics.cli;
@@ -128,9 +125,6 @@ test("built-in docs work without topics", async () => {
128
125
  const cliRef = await new Cli(root).invoke(["docs", "cli"]);
129
126
  expect(cliRef.exitCode).toBe(0);
130
127
  expect(cliRef.stdout).toContain("CLI API reference");
131
- const skill = await new Cli(root).invoke(["docs", "skill"]);
132
- expect(skill.exitCode).toBe(0);
133
- expect(skill.stdout).toContain("name: myapp");
134
128
  });
135
129
 
136
130
  test("bare docs shows router help", () => {
@@ -253,40 +247,14 @@ test("skipsRequiredAppConfigExit includes docs and config builtins", () => {
253
247
  expect(skipsRequiredAppConfigExit(["run"], caps)).toBe(false);
254
248
  });
255
249
 
256
- test("docs skill prints Cursor SKILL.md", async () => {
257
- const result = await new Cli(docsFixture()).invoke(["docs", "skill"]);
258
- expect(result.exitCode).toBe(0);
259
- expect(result.stdout).toContain("---");
260
- expect(result.stdout).toContain("name: myapp");
261
- expect(result.stdout).toContain("## Commands");
262
- expect(result.stdout).toContain("For full detail, open `reference.md`");
263
- expect(result.stdout).not.toContain("#### Options");
264
- expect(result.stdout).not.toContain("mcp.json");
265
- });
266
-
267
- /** Docs skill help recommends configure. */
268
- test("docs skill help recommends configure", async () => {
269
- const presentation = cliPresentationRoot(docsFixture());
270
- const docsNode = presentation.commands.find((c) => c.key === "docs");
271
- expect(docsNode && "commands" in docsNode).toBe(true);
272
- if (docsNode && "commands" in docsNode) {
273
- const skill = docsNode.commands.find((c) => c.key === "skill");
274
- expect(skill?.description).toContain("reference agent SKILL");
275
- expect(skill?.description).toContain("configure");
276
- expect(skill?.notes).toBeUndefined();
277
- expect(docsNode.notes).toContain("--save");
278
- expect(docsNode.notes).not.toContain("install --skill");
279
- }
280
- });
281
-
282
- test("presentation includes docs cli-schema and skill", () => {
250
+ test("presentation includes docs cli-schema and cli without skill", () => {
283
251
  const presentation = cliPresentationRoot(docsFixture());
284
252
  const docsNode = presentation.commands.find((c) => c.key === "docs");
285
253
  expect(docsNode && "commands" in docsNode).toBe(true);
286
254
  if (docsNode && "commands" in docsNode) {
287
255
  expect(docsNode.commands.some((c) => c.key === "cli-schema")).toBe(true);
288
256
  expect(docsNode.commands.some((c) => c.key === "cli")).toBe(true);
289
- expect(docsNode.commands.some((c) => c.key === "skill")).toBe(true);
257
+ expect(docsNode.commands.some((c) => c.key === "skill")).toBe(false);
290
258
  }
291
259
  });
292
260
 
@@ -296,7 +264,7 @@ test("completions offer docs subcommands", () => {
296
264
  expect(bash).toContain("readme) echo");
297
265
  expect(bash).toContain("cli-schema) echo");
298
266
  expect(bash).toContain("cli) echo");
299
- expect(bash).toContain("skill) echo");
267
+ expect(bash).not.toContain("skill) echo");
300
268
  });
301
269
 
302
270
  test("generateMcpGuide includes schema URI and .agents install", () => {
@@ -329,16 +297,6 @@ test("docs cli --save prepends generated hint", async () => {
329
297
  expect(text).toContain("CLI API reference");
330
298
  });
331
299
 
332
- test("docs skill --save keeps frontmatter first", async () => {
333
- const result = await new Cli(docsFixture()).invoke(["docs", "skill", "--save"]);
334
- expect(result.exitCode).toBe(0);
335
- const text = readFileSync(join(workDir, "docs/skill.md"), "utf8");
336
- expect(text.startsWith("---\n")).toBe(true);
337
- expect(text).toContain("name: myapp");
338
- const hint = "<!-- Generated by myapp docs skill --save; do not edit. -->";
339
- expect(text.indexOf(hint)).toBeGreaterThan(text.indexOf("---\n", 4));
340
- });
341
-
342
300
  test("docs cli-schema --save writes JSON file", async () => {
343
301
  const result = await new Cli(docsFixture()).invoke(["docs", "cli-schema", "--save"]);
344
302
  expect(result.exitCode).toBe(0);
@@ -1,13 +1,16 @@
1
+ /*
2
+ This module resolves and prints bundled documentation topics for the `docs` built-in.
3
+ */
4
+
1
5
  import { cliSchemaJson } from "../core/schema.ts";
2
6
  import type { CliDocsConfig, CliProgram } from "../core/types.ts";
3
7
  import { openApiJson } from "../http/openapi.ts";
4
- import { generateSkillBundle } from "../skill/generate.ts";
5
8
  import { generateCliGuide } from "./cli-guide.ts";
6
9
  import { generateHttpGuide } from "./http-guide.ts";
7
10
  import { generateMcpGuide } from "./mcp-guide.ts";
8
11
 
9
12
  /** Built-in docs subcommand keys not allowed in `docs.topics`. */
10
- export const DOCS_BUILTIN_TOPIC_KEYS = ["http", "mcp", "all", "cli-schema", "cli", "skill", "openapi"] as const;
13
+ export const DOCS_BUILTIN_TOPIC_KEYS = ["http", "mcp", "all", "cli-schema", "cli", "openapi"] as const;
11
14
 
12
15
  export type DocsBuiltinTopicKey = (typeof DOCS_BUILTIN_TOPIC_KEYS)[number];
13
16
 
@@ -98,9 +101,6 @@ export function docsTopicContent(program: CliProgram, topic: string): string {
98
101
  if (topic === "cli") {
99
102
  return generateCliGuide(program);
100
103
  }
101
- if (topic === "skill") {
102
- return `${generateSkillBundle(program).skillMd}\n`;
103
- }
104
104
  const text = docsTopicText(program, topic);
105
105
  return text.endsWith("\n") ? text : `${text}\n`;
106
106
  }
package/src/docs/save.ts CHANGED
@@ -1,5 +1,10 @@
1
+ /*
2
+ This module persists bundled documentation topics to disk when `--save` is passed.
3
+ It writes documentation under `./docs/`.
4
+ */
5
+
1
6
  import { mkdirSync, writeFileSync } from "node:fs";
2
- import { join } from "node:path";
7
+ import { dirname, join } from "node:path";
3
8
  import type { CliProgram } from "../core/types.ts";
4
9
  import { generatedFileHtmlComment, insertGeneratedHint } from "../skill/hint.ts";
5
10
  import { docsTopicContent } from "./resolve.ts";
@@ -8,34 +13,57 @@ import { docsTopicContent } from "./resolve.ts";
8
13
  export const DOCS_SAVE_DIR = "docs";
9
14
 
10
15
  /** Builtin docs topics generated by argsbarg (not consumer `docs.topics`). */
11
- export const DOCS_GENERATED_SAVE_TOPICS = ["mcp", "cli", "skill", "http"] as const;
16
+ export const DOCS_GENERATED_SAVE_TOPICS = ["mcp", "cli", "http"] as const;
12
17
 
13
18
  /** Whether `--save` should prepend a generated-file hint (argsbarg writers only). */
14
- export function docsTopicIsGeneratedByArgsbarg(topic: string): boolean {
19
+ export function docsTopicIsGeneratedByArgsbarg(
20
+ /** Topic name. */
21
+ topic: string,
22
+ ): boolean {
15
23
  return (DOCS_GENERATED_SAVE_TOPICS as readonly string[]).includes(topic);
16
24
  }
17
25
 
18
26
  /** HTML comment for generated markdown saved with `--save`. */
19
- export function docsSaveGeneratedHint(program: CliProgram, topic: string): string {
27
+ export function docsSaveGeneratedHint(
28
+ /** Program definition. */
29
+ program: CliProgram,
30
+ /** Topic name. */
31
+ topic: string,
32
+ ): string {
20
33
  return generatedFileHtmlComment(`${program.key} docs ${topic} --save`);
21
34
  }
22
35
 
23
- /** Inserts save hint without breaking YAML frontmatter (`docs skill`). */
24
- export function applySaveGeneratedHint(program: CliProgram, topic: string, content: string): string {
36
+ /** Inserts save hint into markdown content. */
37
+ export function applySaveGeneratedHint(
38
+ /** Program definition. */
39
+ program: CliProgram,
40
+ /** Topic name. */
41
+ topic: string,
42
+ /** Markdown text. */
43
+ content: string,
44
+ ): string {
25
45
  if (!docsTopicIsGeneratedByArgsbarg(topic)) {
26
46
  return content;
27
47
  }
28
48
  const hint = docsSaveGeneratedHint(program, topic);
29
- return insertGeneratedHint(content, hint, topic === "skill" ? { afterFrontmatter: true } : undefined);
49
+ return insertGeneratedHint(content, hint);
30
50
  }
31
51
 
32
52
  /** File body for `--save` (hint on argsbarg-generated markdown only). */
33
- export function docsTopicContentForSave(program: CliProgram, topic: string): string {
53
+ export function docsTopicContentForSave(
54
+ /** Program definition. */
55
+ program: CliProgram,
56
+ /** Topic name. */
57
+ topic: string,
58
+ ): string {
34
59
  return applySaveGeneratedHint(program, topic, docsTopicContent(program, topic));
35
60
  }
36
61
 
37
62
  /** Filename for a saved docs topic. */
38
- export function docsSaveFilename(topic: string): string {
63
+ export function docsSaveFilename(
64
+ /** Topic name. */
65
+ topic: string,
66
+ ): string {
39
67
  if (topic === "cli-schema") {
40
68
  return "cli-schema.json";
41
69
  }
@@ -46,17 +74,26 @@ export function docsSaveFilename(topic: string): string {
46
74
  }
47
75
 
48
76
  /** Relative path under cwd for a saved docs topic. */
49
- export function docsSaveRelativePath(topic: string): string {
77
+ export function docsSaveRelativePath(
78
+ /** Topic identifier. */
79
+ topic: string,
80
+ /** Program root for resolving app-specific paths. */
81
+ _program?: CliProgram,
82
+ ): string {
50
83
  return join(DOCS_SAVE_DIR, docsSaveFilename(topic));
51
84
  }
52
85
 
53
86
  /** Writes one docs topic under `./docs/`; returns relative path written. */
54
- export function saveDocsTopic(program: CliProgram, topic: string): string {
55
- const dir = join(process.cwd(), DOCS_SAVE_DIR);
56
- mkdirSync(dir, { recursive: true });
57
-
58
- const rel = docsSaveRelativePath(topic);
87
+ export function saveDocsTopic(
88
+ /** Program definition root. */
89
+ program: CliProgram,
90
+ /** Topic identifier to save. */
91
+ topic: string,
92
+ ): string {
93
+ const rel = docsSaveRelativePath(topic, program);
59
94
  const abs = join(process.cwd(), rel);
95
+ mkdirSync(dirname(abs), { recursive: true });
96
+
60
97
  writeFileSync(abs, docsTopicContentForSave(program, topic), "utf8");
61
98
  return rel;
62
99
  }
package/src/help.test.ts CHANGED
@@ -64,7 +64,7 @@ describe("cliResolveNotes", () => {
64
64
  });
65
65
 
66
66
  describe("cliHelpRender", () => {
67
- test("docs help lists schema, cli, and skill subcommands", () => {
67
+ test("docs help lists schema and cli subcommands", () => {
68
68
  const root = testProgram({
69
69
  key: "app",
70
70
  version: "1.0.0",
@@ -85,8 +85,7 @@ describe("cliHelpRender", () => {
85
85
  expect(help).toContain("Print the full CLI command tree as JSON.");
86
86
  expect(help).toContain("cli");
87
87
  expect(help).toContain("markdown");
88
- expect(help).toContain("skill");
89
- expect(help).toContain("reference agent SKILL");
88
+ expect(help).not.toContain("skill");
90
89
  });
91
90
 
92
91
  test("root help omits legacy --schema flag", () => {
@@ -106,7 +105,7 @@ describe("cliHelpRender", () => {
106
105
  expect(help).not.toContain("--schema");
107
106
  });
108
107
 
109
- test("root help shows agent docs hint when docs enabled", () => {
108
+ test("root help omits agent docs hint when docs enabled", () => {
110
109
  const root = testProgram({
111
110
  key: "myapp",
112
111
  version: "1.0.0",
@@ -117,7 +116,7 @@ describe("cliHelpRender", () => {
117
116
  commands: [{ key: "run", description: "Run.", handler: () => {} }],
118
117
  });
119
118
  const help = cliHelpRender(cliPresentationRoot(root), [], false);
120
- expect(help).toContain("For AI agents: `myapp docs skill`.");
119
+ expect(help).not.toContain("docs skill");
121
120
  expect(help).not.toContain("install --skill");
122
121
  });
123
122
 
@@ -134,7 +133,7 @@ describe("cliHelpRender", () => {
134
133
  expect(help).not.toContain("docs skill");
135
134
  });
136
135
 
137
- test("root help includes program notes and agent hint", () => {
136
+ test("root help includes program notes", () => {
138
137
  const root = testProgram({
139
138
  key: "myapp",
140
139
  version: "1.0.0",
@@ -147,6 +146,6 @@ describe("cliHelpRender", () => {
147
146
  });
148
147
  const help = cliHelpRender(cliPresentationRoot(root), [], false);
149
148
  expect(help).toContain("See `myapp docs readme` for the user guide.");
150
- expect(help).toContain("myapp docs skill");
149
+ expect(help).not.toContain("docs skill");
151
150
  });
152
151
  });
@@ -1,29 +1,22 @@
1
1
  /*
2
- This module generates Agent Skills content (SKILL.md + reference.md) from a CLI schema.
2
+ This module generates the MCP routing skill (SKILL.md) for Claude Code plugin zips.
3
3
  */
4
4
 
5
5
  import { defaultConfigEntryTitle } from "../config/entry.ts";
6
- import { CliOptionKind, type CliProgram } from "../core/types.ts";
7
- import { generateCliGuide } from "../docs/cli-guide.ts";
6
+ import type { CliProgram } from "../core/types.ts";
8
7
  import {
9
8
  collectMcpTools,
10
9
  leafWireOptions,
11
- type McpToolDef,
12
10
  mcpServerId,
13
11
  resolveMcpSchemaUri,
14
12
  sanitizeToolSegment,
15
13
  } from "../mcp/tools.ts";
16
- import { skillDirName } from "./naming.ts";
17
-
18
- export interface SkillBundle {
19
- dirName: string;
20
- skillMd: string;
21
- referenceMd: string;
22
- }
23
14
 
24
15
  /** MCP routing skill for Claude Code plugin zips (SKILL.md only). */
25
16
  export interface PluginSkillBundle {
17
+ /** Target directory name under `skills/`. */
26
18
  dirName: string;
19
+ /** Generated plugin SKILL.md content. */
27
20
  skillMd: string;
28
21
  }
29
22
 
@@ -43,168 +36,63 @@ function pluginSkillDescription(root: CliProgram): string {
43
36
  return truncate(desc, 1024);
44
37
  }
45
38
 
46
- /** Builds third-person skill description for YAML frontmatter. */
47
- function skillDescription(root: CliProgram): string {
48
- const tools = collectMcpTools(root);
49
- const paths = tools.map((t) => (t.path.length > 0 ? t.path.join(" ") : root.key));
50
- const sample = paths.slice(0, 5).join(", ");
51
- const more = paths.length > 5 ? `, and ${paths.length - 5} more` : "";
52
- const desc = `Operates the ${root.key} CLI (${sample}${more}). Use when the user mentions ${root.key}${paths.length > 0 ? `, ${paths.slice(0, 3).join(", ")}` : ""}, or related tasks.`;
53
- return truncate(desc, 1024);
54
- }
55
-
56
- /** CLI path with required single-slot positionals for the compact catalog. */
57
- function commandCatalogPath(root: CliProgram, tool: McpToolDef): string {
58
- const base = tool.path.length > 0 ? `${root.key} ${tool.path.join(" ")}` : root.key;
59
- const slots = (tool.leaf.positionals ?? [])
60
- .filter((p) => (p.argMin ?? 1) > 0 && (p.argMax ?? 1) === 1)
61
- .map((p) => `<${p.name}>`);
62
- if (slots.length === 0) {
63
- return base;
64
- }
65
- return `${base} ${slots.join(" ")}`;
66
- }
67
-
68
- /** Formats one command line for the SKILL.md index (details live in reference.md). */
69
- function formatCommandEntry(root: CliProgram, tool: McpToolDef): string {
70
- const cliPath = commandCatalogPath(root, tool);
71
- let line = `- **\`${cliPath}\`** — ${tool.leaf.description}`;
72
- const opts = leafWireOptions(tool.leaf);
73
- const flags = opts.filter((o) => o.kind === CliOptionKind.Presence).map((o) => `--${o.name}`);
74
- if (flags.length > 0) {
75
- line += ` (flags: ${flags.join(", ")})`;
76
- }
77
- const enums = opts.filter((o) => o.kind === CliOptionKind.Enum && o.choices?.length);
78
- for (const e of enums) {
79
- line += ` (\`--${e.name}\`: ${e.choices?.join(" | ")})`;
80
- }
81
- const varargs = (tool.leaf.positionals ?? []).filter((p) => (p.argMax ?? 1) === 0);
82
- if (varargs.length > 0) {
83
- line += ` (varargs: ${varargs.map((p) => p.name).join(", ")})`;
84
- }
85
- return line;
86
- }
87
-
39
+ /** Builds configuration section lines for YAML and markdown. */
88
40
  function buildConfigurationSection(root: CliProgram): string[] {
89
- const schema = root.appConfig?.entries;
90
- if (!schema || Object.keys(schema).length === 0) {
41
+ if (!root.appConfig || Object.keys(root.appConfig.entries).length === 0) {
91
42
  return [];
92
43
  }
93
- const lines = ["## Configuration", ""];
94
- for (const [key, entry] of Object.entries(schema)) {
95
- const label = entry.title ?? defaultConfigEntryTitle(key);
96
- const envNote = entry.env ? ` (env: \`${entry.env}\`)` : "";
97
- lines.push(`- **${label}** (\`${key}\`${envNote}) — ${entry.description}`);
44
+ const entries = root.appConfig.entries;
45
+ const lines: string[] = ["## Configuration", ""];
46
+ for (const name of Object.keys(entries).sort()) {
47
+ const entry = entries[name];
48
+ if (!entry) continue;
49
+ const title = defaultConfigEntryTitle(name);
50
+ const envStr = entry.env ? ` (env: \`${entry.env}\`)` : "";
51
+ const desc = entry.description ? ` — ${entry.description}` : "";
52
+ lines.push(`- **${name}** (\`${title}\`${envStr})${desc}`);
98
53
  }
99
54
  lines.push("");
100
55
  return lines;
101
56
  }
102
57
 
103
- /** Builds SKILL.md body for the agent skill bundle. */
104
- function buildSkillMd(root: CliProgram, dirName: string): string {
105
- const name = dirName;
106
- const description = skillDescription(root);
107
- const tools = collectMcpTools(root);
108
-
58
+ /** Builds SKILL.md for Claude Code plugin zips (MCP routing only). */
59
+ function buildPluginSkillMd(root: CliProgram, dirName: string): string {
109
60
  const lines: string[] = [
110
61
  "---",
111
- `id: ${dirName}`,
112
- `name: ${name}`,
113
- `description: ${description}`,
114
- "enabled: true",
62
+ `name: ${dirName}`,
63
+ `description: ${pluginSkillDescription(root)}`,
115
64
  "---",
116
65
  "",
117
66
  `# ${root.key}`,
118
67
  "",
119
68
  root.description,
120
69
  "",
121
- "## Execution",
70
+ "## MCP Tools",
122
71
  "",
123
- "Invoke via shell:",
72
+ `Server id: \`${mcpServerId(root)}\``,
124
73
  "",
125
- "```bash",
126
- `${root.key} <subcommand> [options] [args]`,
127
- "```",
74
+ "Prefer using MCP tools over terminal commands when available.",
128
75
  "",
129
- "## Commands",
76
+ `- Run \`tools/list\` against \`${mcpServerId(root)}\` to discover tools.`,
77
+ `- Read schema resource \`${resolveMcpSchemaUri(root)}\` for types.`,
130
78
  "",
131
79
  ];
132
80
 
133
- if (tools.length === 0) {
134
- lines.push("(No leaf commands in schema.)", "");
135
- } else {
81
+ const tools = collectMcpTools(root);
82
+ if (tools.length > 0) {
83
+ lines.push("### Available tools", "");
136
84
  for (const tool of tools) {
137
- lines.push(formatCommandEntry(root, tool));
85
+ const toolName = sanitizeToolSegment(tool.path.join("_"));
86
+ const desc = tool.leaf.description;
87
+ const wire = leafWireOptions(tool.leaf);
88
+ const flags = wire.length > 0 ? ` (flags: ${wire.map((o) => `--${o.name}`).join(", ")})` : "";
89
+ lines.push(`- \`${toolName}\` — ${desc}${flags}`);
138
90
  }
139
91
  lines.push("");
140
92
  }
141
93
 
142
94
  lines.push(...buildConfigurationSection(root));
143
95
 
144
- lines.push(
145
- "## Pitfalls",
146
- "",
147
- "- Pass `--` before arguments that look like flags.",
148
- "",
149
- "## Reference",
150
- "",
151
- `For full detail, open \`reference.md\` in this skill directory (same as \`${root.key} docs cli\`).`,
152
- "",
153
- "## Install location",
154
- "",
155
- "Install follows the https://dotagentsprotocol.com:",
156
- "",
157
- `- Auto-install: \`${root.key} configure install\` when \`skill.enabled\` → \`~/.agents/skills/${dirName}/\``,
158
- `- Cursor and most coding agents read \`~/.agents/skills/\` natively`,
159
- "",
160
- "**Claude Code (manual):** symlink or copy into Claude's skill directory:",
161
- "",
162
- "```bash",
163
- "mkdir -p ~/.claude/skills",
164
- `ln -sf ~/.agents/skills/${dirName} ~/.claude/skills/${dirName}`,
165
- "```",
166
- "",
167
- `Project override (optional): \`.agents/skills/${dirName}/\``,
168
- "",
169
- );
170
-
171
- return lines.join("\n");
172
- }
173
-
174
- /** Builds reference.md with the compact `docs cli` markdown guide. */
175
- function buildReferenceMd(root: CliProgram): string {
176
- return generateCliGuide(root, { compact: true });
177
- }
178
-
179
- /** Builds MCP routing SKILL.md for Claude Code plugin zips. */
180
- function buildPluginSkillMd(root: CliProgram, dirName: string): string {
181
- const name = sanitizeToolSegment(root.key);
182
- const description = pluginSkillDescription(root);
183
- const serverId = mcpServerId(root);
184
- const schemaUri = resolveMcpSchemaUri(root);
185
-
186
- const lines: string[] = [
187
- "---",
188
- `name: ${name}`,
189
- `description: ${description}`,
190
- "---",
191
- "",
192
- `# ${root.key}`,
193
- "",
194
- root.description,
195
- "",
196
- "## Execution",
197
- "",
198
- "This plugin bundles an MCP server. Use MCP tools to fulfill requests.",
199
- "",
200
- `- Server id: \`${serverId}\` (configured in plugin \`.mcp.json\`)`,
201
- "- Tool names and argument shapes come from MCP `tools/list`",
202
- `- Full schema: \`${schemaUri}\` (same as \`${root.key} docs cli-schema\`)`,
203
- "",
204
- ];
205
-
206
- lines.push(...buildConfigurationSection(root));
207
-
208
96
  lines.push(
209
97
  "## Claude Code plugin",
210
98
  "",
@@ -223,13 +111,3 @@ export function generatePluginSkillBundle(root: CliProgram): PluginSkillBundle {
223
111
  skillMd: buildPluginSkillMd(root, dirName),
224
112
  };
225
113
  }
226
-
227
- /** Generates SKILL.md and reference.md for agent skill install. */
228
- export function generateSkillBundle(root: CliProgram): SkillBundle {
229
- const dirName = skillDirName(root.key);
230
- return {
231
- dirName,
232
- skillMd: buildSkillMd(root, dirName),
233
- referenceMd: buildReferenceMd(root),
234
- };
235
- }
package/src/skill/hint.ts CHANGED
@@ -1,6 +1,11 @@
1
+ /*
2
+ This module provides HTML comment hints embedded in generated documentation
3
+ and plugin artifacts to mark them as machine-generated.
4
+ */
5
+
1
6
  import type { CliProgram } from "../core/types.ts";
2
7
 
3
- /** YAML frontmatter block at the start of SKILL.md. */
8
+ /** YAML frontmatter block at the start of markdown files. */
4
9
  export const MARKDOWN_FRONTMATTER_RE = /^---\r?\n[\s\S]*?\r?\n---\r?\n/;
5
10
 
6
11
  /** HTML comment marking argsbarg-generated markdown. */
@@ -19,42 +24,11 @@ export function insertGeneratedHint(content: string, hint: string, options?: { a
19
24
  return `${hint}${content}`;
20
25
  }
21
26
 
22
- /** Hint for `configure` skill output files. */
23
- export function skillInstallHint(program: CliProgram): string {
24
- return generatedFileHtmlComment(`${program.key} configure`);
25
- }
26
-
27
- /** Applies install hints to SKILL.md (after frontmatter) and reference.md. */
28
- export function applySkillInstallHints(
29
- program: CliProgram,
30
- skillMd: string,
31
- referenceMd: string,
32
- ): { skillMd: string; referenceMd: string } {
33
- const hint = skillInstallHint(program);
34
- return {
35
- skillMd: insertGeneratedHint(skillMd, hint, { afterFrontmatter: true }),
36
- referenceMd: insertGeneratedHint(referenceMd, hint),
37
- };
38
- }
39
-
40
27
  /** Hint for `mcp bundle` plugin skill output. */
41
28
  export function skillBundleHint(program: CliProgram): string {
42
29
  return generatedFileHtmlComment(`${program.key} mcp bundle`);
43
30
  }
44
31
 
45
- /** Applies bundle hints to SKILL.md (after frontmatter) and reference.md. */
46
- export function applySkillBundleHints(
47
- program: CliProgram,
48
- skillMd: string,
49
- referenceMd: string,
50
- ): { skillMd: string; referenceMd: string } {
51
- const hint = skillBundleHint(program);
52
- return {
53
- skillMd: insertGeneratedHint(skillMd, hint, { afterFrontmatter: true }),
54
- referenceMd: insertGeneratedHint(referenceMd, hint),
55
- };
56
- }
57
-
58
32
  /** Applies bundle hint to plugin SKILL.md (after frontmatter). */
59
33
  export function applyPluginSkillHint(program: CliProgram, skillMd: string): string {
60
34
  return insertGeneratedHint(skillMd, skillBundleHint(program), { afterFrontmatter: true });
@@ -1,16 +1,22 @@
1
- import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
1
+ /*
2
+ This module provides paths and helpers for agent skill directories (~/.agents/skills/<key>/).
3
+ Skill generation is removed; skills are authored directly in repositories under skills/<app>/SKILL.md.
4
+ */
5
+
2
6
  import { join } from "node:path";
3
7
  import type { CliProgram } from "../core/types.ts";
4
- import { displayHomePath, userHome } from "../paths/host.ts";
5
- import { generateSkillBundle } from "./generate.ts";
6
- import { applySkillInstallHints } from "./hint.ts";
8
+ import { userHome } from "../paths/host.ts";
7
9
  import { skillDirName } from "./naming.ts";
8
10
 
9
11
  export { skillDirName } from "./naming.ts";
10
12
 
13
+ /** Options for agent skill installation. */
11
14
  export interface SkillInstallOpts {
15
+ /** When true, installs to user home ~/.agents/skills/<key>/; otherwise project .agents/skills/<key>/. */
12
16
  global?: boolean;
17
+ /** When true, removes existing directory before installing. */
13
18
  rimraf?: boolean;
19
+ /** When true, computes file paths without writing to disk. */
14
20
  dry?: boolean;
15
21
  }
16
22
 
@@ -20,33 +26,6 @@ export function resolveAgentsSkillDir(root: CliProgram, global = true): string {
20
26
  return join(base, ".agents", "skills", skillDirName(root.key));
21
27
  }
22
28
 
23
- /** Writes skill.md, SKILL.md (compatibility copy), and reference.md; returns changed file paths. */
24
- export function cliSkillInstall(root: CliProgram, opts: SkillInstallOpts): string[] {
25
- const bundle = generateSkillBundle(root);
26
- const { skillMd, referenceMd } = applySkillInstallHints(root, bundle.skillMd, bundle.referenceMd);
27
- const dir = resolveAgentsSkillDir(root, opts.global ?? true);
28
- const changed: string[] = [];
29
-
30
- if (opts.rimraf && existsSync(dir) && !opts.dry) {
31
- rmSync(dir, { recursive: true, force: true });
32
- }
33
-
34
- const skillPath = join(dir, "skill.md");
35
- const skillCompatPath = join(dir, "SKILL.md");
36
- const refPath = join(dir, "reference.md");
37
-
38
- if (!opts.dry) {
39
- mkdirSync(dir, { recursive: true });
40
- writeFileSync(skillPath, skillMd, "utf8");
41
- writeFileSync(skillCompatPath, skillMd, "utf8");
42
- writeFileSync(refPath, referenceMd, "utf8");
43
- process.stdout.write(`Installed skill to ${displayHomePath(dir)}/\n`);
44
- }
45
-
46
- changed.push(skillPath, skillCompatPath, refPath);
47
- return changed;
48
- }
49
-
50
29
  /** True when the plan action kind installs the agent skill bundle. */
51
30
  export function isAgentSkillActionKind(kind: string): boolean {
52
31
  return kind === "agent-skill";