argsbarg 7.0.6 → 7.0.8

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 (42) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/README.md +4 -4
  3. package/docs/README.md +1 -1
  4. package/docs/ai-skills.md +14 -62
  5. package/docs/bundled-docs.md +9 -13
  6. package/docs/cli-program.md +10 -11
  7. package/docs/configure.md +9 -11
  8. package/docs/output-schema.md +1 -1
  9. package/examples/full-example/AGENTS.md +3 -3
  10. package/examples/full-example/docs/README.md +1 -1
  11. package/examples/full-example/justfile +0 -1
  12. package/examples/full-example/skills/full-example/SKILL.md +0 -2
  13. package/examples/full-example/src/program.ts +0 -1
  14. package/examples/full-example-json/AGENTS.md +3 -3
  15. package/examples/full-example-json/docs/README.md +1 -1
  16. package/examples/full-example-json/justfile +0 -1
  17. package/examples/full-example-json/skills/full-example-json/SKILL.md +0 -2
  18. package/examples/full-example-json/src/program.ts +0 -1
  19. package/index.d.ts +5 -3
  20. package/package.json +1 -1
  21. package/src/builtins/builtins.test.ts +1 -22
  22. package/src/builtins/configure-copy.ts +4 -11
  23. package/src/builtins/presentation.ts +2 -5
  24. package/src/configure/artifacts/status.test.ts +5 -5
  25. package/src/configure/artifacts/target-effective.ts +1 -2
  26. package/src/configure/artifacts/target-skill.ts +9 -15
  27. package/src/configure/artifacts/targets/skill.ts +8 -1
  28. package/src/configure/artifacts/targets.test.ts +5 -5
  29. package/src/configure/configure.test.ts +4 -4
  30. package/src/core/parse.test.ts +1 -112
  31. package/src/core/types.ts +5 -3
  32. package/src/core/validate.ts +4 -2
  33. package/src/docs/builtin.ts +5 -3
  34. package/src/docs/cli-guide.ts +3 -3
  35. package/src/docs/docs.test.ts +3 -47
  36. package/src/docs/resolve.ts +5 -5
  37. package/src/docs/save.ts +9 -20
  38. package/src/help.test.ts +250 -8
  39. package/src/help.ts +397 -46
  40. package/src/skill/generate.ts +30 -156
  41. package/src/skill/hint.ts +2 -15
  42. package/src/skill/install.ts +3 -35
@@ -5,7 +5,6 @@ Tests for builtins/builtins module behavior.
5
5
  import { describe, expect, test } from "bun:test";
6
6
  import { ParseKind, parse, postParseValidate } from "../core/parse.ts";
7
7
  import type { CliProgram } from "../core/types.ts";
8
- import { cliBuiltinDocsGroup } from "../docs/builtin.ts";
9
8
  import { resolveCapabilities } from "../runtime/capabilities.ts";
10
9
  import { completionBashScript, completionFishScript, completionZshScript } from ".";
11
10
  import { cliBuiltinConfigureCommand } from "./configure.ts";
@@ -41,7 +40,6 @@ const noMcp: CliProgram = {
41
40
  describe("builtins help copy", () => {
42
41
  test("configure command includes capability-aware description", () => {
43
42
  const configure = cliBuiltinConfigureCommand(fixture);
44
- expect(configure.description).toContain("agent skills");
45
43
  expect(configure.description).toContain("MCP config");
46
44
  expect(configure.notes).toContain("brew upgrade");
47
45
  const commandKeys = configure.commands.map((c) => c.key);
@@ -55,7 +53,7 @@ describe("builtins help copy", () => {
55
53
 
56
54
  test("configure copy omits MCP when mcpServer unset", () => {
57
55
  const caps = resolveCapabilities(noMcp);
58
- expect(configureCommandDescription(noMcp, caps)).toBe("Set up agent skills for this app (binary via Homebrew).");
56
+ expect(configureCommandDescription(noMcp, caps)).toBe("Set up agent artifacts for this app (binary via Homebrew).");
59
57
  expect(configureCommandDescription(noMcp, caps)).not.toContain("MCP");
60
58
  const configure = cliBuiltinConfigureCommand(noMcp);
61
59
  expect(configure.description).not.toContain("MCP");
@@ -172,22 +170,3 @@ describe("schema export builtins", () => {
172
170
  expect(builtins.map((b) => b.key)).not.toContain("completion");
173
171
  });
174
172
  });
175
-
176
- /** Tests for docs skill topic copy. */
177
- describe("docs skill topic copy", () => {
178
- test("mentions configure when configure is enabled", () => {
179
- const withDocs: CliProgram = {
180
- ...noMcp,
181
- docs: { topics: { readme: { text: "# r\n" } } },
182
- };
183
- const skill = cliBuiltinDocsGroup(withDocs).commands.find((c) => c.key === "skill");
184
- expect(skill?.description).toContain("configure");
185
-
186
- const configureOff: CliProgram = {
187
- ...withDocs,
188
- configure: { enabled: false },
189
- };
190
- const skillOff = cliBuiltinDocsGroup(configureOff).commands.find((c) => c.key === "skill");
191
- expect(skillOff?.description).not.toContain("configure");
192
- });
193
- });
@@ -1,19 +1,19 @@
1
- /** Capability-aware labels for configure builtin and docs copy. */
1
+ /*
2
+ This module provides capability-aware labels for the configure built-in and docs copy.
3
+ */
2
4
 
3
5
  import type { CliProgram } from "../core/types.ts";
4
6
  import type { CliCapabilities } from "../runtime/capabilities.ts";
5
7
 
6
- type Kind = "skills" | "mcp" | "config";
8
+ type Kind = "mcp" | "config";
7
9
 
8
10
  const LABEL: Record<Kind, { prose: string; short: string }> = {
9
- skills: { prose: "agent skills", short: "skills" },
10
11
  mcp: { prose: "MCP config", short: "MCP" },
11
12
  config: { prose: "app config", short: "config" },
12
13
  };
13
14
 
14
15
  function enabledKinds(program: CliProgram, caps: CliCapabilities): Kind[] {
15
16
  const kinds: Kind[] = [];
16
- if (program.skill?.enabled) kinds.push("skills");
17
17
  if (caps.mcp && program.mcpServer?.enabled) kinds.push("mcp");
18
18
  if (program.appConfig && Object.keys(program.appConfig.entries).length > 0) kinds.push("config");
19
19
  return kinds;
@@ -39,13 +39,6 @@ export function configureCommandDescription(program: CliProgram, caps: CliCapabi
39
39
  return `Set up ${prose(program, caps)} for this app (binary via Homebrew).`;
40
40
  }
41
41
 
42
- export function docsSkillTopicDescription(_program: CliProgram, caps: CliCapabilities): string {
43
- if (caps.configure) {
44
- return "Print a reference agent SKILL; run `configure install` to install an optimized copy.";
45
- }
46
- return "Print a reference agent SKILL for AI agents.";
47
- }
48
-
49
42
  export function configureCommandNotes(program: CliProgram, _caps: CliCapabilities): string {
50
43
  const app = program.key;
51
44
  const lines = [
@@ -77,15 +77,12 @@ export function cliPresentationRoot(program: CliProgram): CliRouter {
77
77
  };
78
78
  }
79
79
 
80
- /** Root help notes: consumer `program.notes` plus agent discovery when `docs` is enabled. */
81
- export function presentationRootNotes(program: CliProgram, caps: CliCapabilities): string | undefined {
80
+ /** Root help notes from consumer `program.notes`. */
81
+ export function presentationRootNotes(program: CliProgram, _caps: CliCapabilities): string | undefined {
82
82
  const parts: string[] = [];
83
83
  if ((program.notes ?? "").trim().length > 0) {
84
84
  parts.push((program.notes ?? "").trim());
85
85
  }
86
- if (caps.docs) {
87
- parts.push(`For AI agents: \`${program.key} docs skill\`.`);
88
- }
89
86
  if (parts.length === 0) {
90
87
  return undefined;
91
88
  }
@@ -43,7 +43,7 @@ describe("resolveInstallTargetPreview", () => {
43
43
  expect(preview.skill).toEqual([]);
44
44
  });
45
45
 
46
- test("skill app includes skill in all scope when enabled", () => {
46
+ test("skill app does not include skill in all scope (skill gen removed)", () => {
47
47
  const program: CliProgram = {
48
48
  key: "cliapp",
49
49
  version: "1",
@@ -53,8 +53,8 @@ describe("resolveInstallTargetPreview", () => {
53
53
  };
54
54
  const paths = resolveInstallPaths(program);
55
55
  const preview = resolveInstallTargetPreview(program, paths);
56
- expect(preview.all).toEqual(["skill"]);
57
- expect(preview.skill).toEqual(["skill"]);
56
+ expect(preview.all).toEqual([]);
57
+ expect(preview.skill).toEqual([]);
58
58
  expect(preview.mcp).toEqual([]);
59
59
  });
60
60
  });
@@ -81,8 +81,8 @@ describe("printInstallStatus json", () => {
81
81
  const parsed = JSON.parse(chunks.join("")) as {
82
82
  effective: { all: string[]; mcp: string[]; skill: string[] };
83
83
  };
84
- expect(parsed.effective.all).toEqual(["skill", "agentsMcp"]);
85
- expect(parsed.effective.skill).toEqual(["skill"]);
84
+ expect(parsed.effective.all).toEqual(["agentsMcp"]);
85
+ expect(parsed.effective.skill).toEqual([]);
86
86
  expect(parsed.effective.mcp).toEqual(["agentsMcp"]);
87
87
  } finally {
88
88
  process.stdout.write = orig;
@@ -32,8 +32,7 @@ function artifactDefaults(
32
32
  program?: Pick<CliProgram, "mcpServer" | "skill">,
33
33
  ): { enabled: boolean; includedInAll: boolean } {
34
34
  if (key === "skill") {
35
- const on = program?.skill?.enabled === true;
36
- return { enabled: on, includedInAll: on };
35
+ return { enabled: false, includedInAll: false };
37
36
  }
38
37
  if (key === "agentsMcp") {
39
38
  const on = program?.mcpServer?.enabled === true;
@@ -1,6 +1,11 @@
1
+ /*
2
+ Agent shell skill directory install (~/.agents/skills/<key>/).
3
+ Skill generation is removed; skills are authored directly in repositories under skills/<app>/SKILL.md.
4
+ Uninstall cleans up legacy/stale skill directories if present.
5
+ */
6
+
1
7
  import { existsSync } from "node:fs";
2
8
  import type { CliProgram } from "../../core/types.ts";
3
- import { cliSkillInstall } from "../../skill/install.ts";
4
9
  import { displayInstallPath, type InstallPaths } from "./paths.ts";
5
10
  import { InstallTarget } from "./target-base.ts";
6
11
  import type {
@@ -15,6 +20,7 @@ import type {
15
20
  } from "./target-types.ts";
16
21
  import { uninstallSkillDir } from "./uninstall.ts";
17
22
 
23
+ /** Specification for an agent skill install target. */
18
24
  export interface SkillHostSpec {
19
25
  key: CliInstallArtifactKey;
20
26
  actionKind: InstallActionKind;
@@ -71,20 +77,8 @@ export class SkillInstallTarget extends InstallTarget {
71
77
  return this.spec.skillDir(paths);
72
78
  }
73
79
 
74
- protected buildInstallActions(ctx: TargetPlanContext): InstallAction[] {
75
- const dir = this.spec.skillDir(ctx.paths);
76
- const displayDir = `${displayInstallPath(dir)}/`;
77
- return [
78
- {
79
- kind: this.actionKind,
80
- summary: `${this.spec.label.toLowerCase()}: ${displayDir}`,
81
- message: `Installing ${this.spec.label.toLowerCase()} to ${displayDir}`,
82
- run: () => {
83
- cliSkillInstall(ctx.root, { global: true, rimraf: true, dry: ctx.dry });
84
- return [];
85
- },
86
- },
87
- ];
80
+ protected buildInstallActions(_ctx: TargetPlanContext): InstallAction[] {
81
+ return [];
88
82
  }
89
83
 
90
84
  protected buildUninstallActions(ctx: TargetPlanContext): UninstallAction[] {
@@ -1,5 +1,12 @@
1
+ /*
2
+ Install target definition for agent skill cleanup and status.
3
+ Skill generation is removed; skills are authored directly in repositories under skills/<app>/SKILL.md.
4
+ */
5
+
6
+ import { existsSync } from "node:fs";
1
7
  import { SkillInstallTarget } from "../target-skill.ts";
2
8
 
9
+ /** Registered install target for agent skill directory cleanup and detection. */
3
10
  export const skillTarget = new SkillInstallTarget({
4
11
  key: "skill",
5
12
  actionKind: "agent-skill",
@@ -8,5 +15,5 @@ export const skillTarget = new SkillInstallTarget({
8
15
  skillDir: (p) => p.agentsSkillDir,
9
16
  detectedKey: "skill",
10
17
  statusField: "skill",
11
- isAvailable: (root) => root.skill?.enabled === true,
18
+ isAvailable: (_root, p) => existsSync(p.agentsSkillDir),
12
19
  });
@@ -42,10 +42,10 @@ describe("resolveEffectiveInstallTargets", () => {
42
42
  expect(t.agentsMcp.includedInAll).toBe(false);
43
43
  });
44
44
 
45
- test("skill enabled via program.skill", () => {
45
+ test("skill disabled even when program.skill is set (skill gen removed)", () => {
46
46
  const t = resolveEffectiveInstallTargets(undefined, { skill: { enabled: true } });
47
- expect(t.skill.enabled).toBe(true);
48
- expect(t.skill.includedInAll).toBe(true);
47
+ expect(t.skill.enabled).toBe(false);
48
+ expect(t.skill.includedInAll).toBe(false);
49
49
  });
50
50
 
51
51
  test("agentsMcp in --all when mcpServer enabled", () => {
@@ -69,7 +69,7 @@ describe("resolveEffectiveInstallTargets", () => {
69
69
  expect(isArtifactInScope("agentsMcp", scope, effective, "install-scoped", program)).toBe(true);
70
70
  });
71
71
 
72
- test("scoped --skill includes skill when program.skill.enabled", () => {
72
+ test("scoped --skill omits skill because skill generation is removed", () => {
73
73
  const program: CliProgram = {
74
74
  key: "app",
75
75
  version: "1",
@@ -79,6 +79,6 @@ describe("resolveEffectiveInstallTargets", () => {
79
79
  };
80
80
  const effective = resolveEffectiveInstallTargets(program.configure, program);
81
81
  const scope = { skill: true };
82
- expect(isArtifactInScope("skill", scope, effective, "install-scoped", program)).toBe(true);
82
+ expect(isArtifactInScope("skill", scope, effective, "install-scoped", program)).toBe(false);
83
83
  });
84
84
  });
@@ -88,19 +88,19 @@ describe("detect installed", () => {
88
88
 
89
89
  /** Tests for install plan. */
90
90
  describe("install plan", () => {
91
- test("buildUpdatePlan greenfield includes skill when enabled", () => {
91
+ test("buildUpdatePlan greenfield omits skill because skill generation is removed", () => {
92
92
  const paths = resolveInstallPaths(fixture);
93
93
  const plan = buildUpdatePlan(fixture, paths, parseInstallOpts({ reinstall: "1", yes: "1" }));
94
94
  expect(plan.length).toBeGreaterThan(0);
95
- expect(plan.some((a) => a.kind === "agent-skill")).toBe(true);
95
+ expect(plan.some((a) => a.kind === "agent-skill")).toBe(false);
96
96
  expect(plan.some((a) => a.kind === "app")).toBe(false);
97
97
  });
98
98
 
99
- test("buildInstallPlan --all omits app self-install", () => {
99
+ test("buildInstallPlan --all omits app self-install and skill", () => {
100
100
  const paths = resolveInstallPaths(fixture);
101
101
  const plan = buildInstallPlan(fixture, paths, parseInstallOpts({ all: "1" }));
102
102
  expect(plan.some((a) => a.kind === "app")).toBe(false);
103
- expect(plan.some((a) => a.kind === "agent-skill")).toBe(true);
103
+ expect(plan.some((a) => a.kind === "agent-skill")).toBe(false);
104
104
  expect(plan.some((a) => a.kind === "agents-mcp")).toBe(true);
105
105
  });
106
106
 
@@ -3,9 +3,6 @@ Domain-specific regression tests (split from index.test.ts).
3
3
  */
4
4
 
5
5
  import { expect, test } from "bun:test";
6
- import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
7
- import { tmpdir } from "node:os";
8
- import { join } from "node:path";
9
6
  import { $ } from "bun";
10
7
  import { completionBashScript, completionZshScript } from "../builtins/index.ts";
11
8
  import { cliPresentationRoot } from "../builtins/presentation.ts";
@@ -13,8 +10,7 @@ import { cliHelpRender } from "../help.ts";
13
10
  import { Cli, CliFallbackMode, CliOptionKind, type CliProgram } from "../index.ts";
14
11
  import { applyShellEnv } from "../mcp/env.ts";
15
12
  import { allMcpResources, collectMcpTools, mcpToolCallToArgv, resolveMcpSchemaUri } from "../mcp/tools.ts";
16
- import { generatePluginSkillBundle, generateSkillBundle } from "../skill/generate.ts";
17
- import { cliSkillInstall } from "../skill/install.ts";
13
+ import { generatePluginSkillBundle } from "../skill/generate.ts";
18
14
  import {
19
15
  enumMcpFixture,
20
16
  nestedDocsFallbackFixture,
@@ -1352,31 +1348,6 @@ test("configure.prefix is rejected", () => {
1352
1348
  expect(() => cliValidateProgram(root)).toThrow(/configure\.prefix removed/);
1353
1349
  });
1354
1350
 
1355
- /** Tests that generateSkillBundle includes frontmatter and intent-based router. */
1356
- test("generateSkillBundle includes frontmatter and intent-based router", () => {
1357
- const bundle = generateSkillBundle(nestedMcpFixture);
1358
- expect(bundle.dirName).toBe("nested.ts");
1359
- expect(bundle.skillMd).toMatch(/^---\nid: nested\.ts\nname: nested\.ts\n/);
1360
- expect(bundle.skillMd).toContain("enabled: true");
1361
- expect(bundle.skillMd).toContain("dotagentsprotocol.com");
1362
- expect(bundle.skillMd).toContain("~/.claude/skills/nested.ts");
1363
- expect(bundle.skillMd).toContain("Options & Help Discovery");
1364
- expect(bundle.skillMd).toContain("Run `nested.ts <subcommand> --help`");
1365
- expect(bundle.skillMd).toContain("## Commands");
1366
- expect(bundle.skillMd).toContain("`nested.ts stat owner lookup <path>`");
1367
- expect(bundle.skillMd).toContain("Invoke via shell:");
1368
- expect(bundle.skillMd).toContain("Workflow & Pitfalls");
1369
- expect(bundle.skillMd).toContain("~/.agents/skills/nested.ts/");
1370
- expect(bundle.skillMd).not.toContain("reference.md");
1371
- expect(bundle.skillMd).not.toContain("#### Options");
1372
- expect(bundle.skillMd).not.toContain("CLI API reference");
1373
- expect(bundle.skillMd).not.toContain("mcp.json");
1374
- expect(bundle.skillMd).not.toContain("Prefer MCP");
1375
- expect(bundle.skillMd).not.toContain("tools/call");
1376
- expect(bundle.skillMd).not.toContain("Generated by");
1377
- expect((bundle as unknown as Record<string, unknown>).referenceMd).toBeUndefined();
1378
- });
1379
-
1380
1351
  /** Tests that generatePluginSkillBundle is MCP routing stub without shell catalog. */
1381
1352
  test("generatePluginSkillBundle is MCP routing stub without shell catalog", () => {
1382
1353
  const bundle = generatePluginSkillBundle(nestedMcpFixture);
@@ -1391,85 +1362,3 @@ test("generatePluginSkillBundle is MCP routing stub without shell catalog", () =
1391
1362
  expect(bundle.skillMd).not.toContain("`nested.ts stat owner lookup <path>`");
1392
1363
  expect(bundle.skillMd).not.toContain("## Commands");
1393
1364
  });
1394
-
1395
- /** CliSkillInstall writes project agent skill files. */
1396
- test("cliSkillInstall writes project agent skill files", () => {
1397
- const cwd = mkdtempSync(join(tmpdir(), "argsbarg-skill-"));
1398
- const prev = process.cwd();
1399
- process.chdir(cwd);
1400
- try {
1401
- const files = cliSkillInstall(nestedMcpFixture, { global: false, rimraf: true });
1402
- expect(files.some((f) => f.includes(".agents/skills/nested.ts/"))).toBe(true);
1403
- const skillDir = join(cwd, ".agents", "skills", "nested.ts");
1404
- expect(existsSync(join(skillDir, "SKILL.md"))).toBe(true);
1405
- expect(existsSync(join(skillDir, "skill.md"))).toBe(true);
1406
- expect(existsSync(join(skillDir, "reference.md"))).toBe(false);
1407
- expect(readFileSync(join(skillDir, "SKILL.md"), "utf8")).toContain("## Commands");
1408
- expect(readFileSync(join(skillDir, "SKILL.md"), "utf8")).toContain("Options & Help Discovery");
1409
- const skillText = readFileSync(join(skillDir, "SKILL.md"), "utf8");
1410
- expect(skillText.startsWith("---\n")).toBe(true);
1411
- const hint = "<!-- Generated by nested.ts configure; do not edit. -->";
1412
- expect(skillText.indexOf(hint)).toBeGreaterThan(skillText.indexOf("---\n", 4));
1413
- } finally {
1414
- process.chdir(prev);
1415
- rmSync(cwd, { recursive: true, force: true });
1416
- }
1417
- });
1418
-
1419
- /** CliSkillInstall removes legacy reference.md if present. */
1420
- test("cliSkillInstall removes legacy reference.md if present", () => {
1421
- const cwd = mkdtempSync(join(tmpdir(), "argsbarg-skill-legacy-"));
1422
- const prev = process.cwd();
1423
- process.chdir(cwd);
1424
- try {
1425
- const skillDir = join(cwd, ".agents", "skills", "nested.ts");
1426
- mkdirSync(skillDir, { recursive: true });
1427
- writeFileSync(join(skillDir, "reference.md"), "legacy reference content", "utf8");
1428
- expect(existsSync(join(skillDir, "reference.md"))).toBe(true);
1429
-
1430
- cliSkillInstall(nestedMcpFixture, { global: false, rimraf: false });
1431
- expect(existsSync(join(skillDir, "SKILL.md"))).toBe(true);
1432
- expect(existsSync(join(skillDir, "reference.md"))).toBe(false);
1433
- } finally {
1434
- process.chdir(prev);
1435
- rmSync(cwd, { recursive: true, force: true });
1436
- }
1437
- });
1438
-
1439
- /** CliSkillInstall global uses TEST_USER_HOME agents skills directory. */
1440
- test("cliSkillInstall global uses TEST_USER_HOME agents skills directory", () => {
1441
- const home = mkdtempSync(join(tmpdir(), "argsbarg-home-"));
1442
- const prevTestHome = process.env.TEST_USER_HOME;
1443
- process.env.TEST_USER_HOME = home;
1444
- try {
1445
- const files = cliSkillInstall(nestedMcpFixture, { global: true, rimraf: true });
1446
- expect(files.some((f) => f.includes(join(home, ".agents", "skills", "nested.ts")))).toBe(true);
1447
- expect(existsSync(join(home, ".agents", "skills", "nested.ts", "SKILL.md"))).toBe(true);
1448
- } finally {
1449
- if (prevTestHome === undefined) {
1450
- delete process.env.TEST_USER_HOME;
1451
- } else {
1452
- process.env.TEST_USER_HOME = prevTestHome;
1453
- }
1454
- rmSync(home, { recursive: true, force: true });
1455
- }
1456
- });
1457
-
1458
- /** CliSkillInstall rimraf overwrites existing directory. */
1459
- test("cliSkillInstall rimraf overwrites existing directory", () => {
1460
- const cwd = mkdtempSync(join(tmpdir(), "argsbarg-skill-dup-"));
1461
- const prev = process.cwd();
1462
- process.chdir(cwd);
1463
- try {
1464
- cliSkillInstall(nestedMcpFixture, { global: false, rimraf: true });
1465
- writeFileSync(join(cwd, ".agents", "skills", "nested.ts", "SKILL.md"), "stale", "utf8");
1466
- const files = cliSkillInstall(nestedMcpFixture, { global: false, rimraf: true });
1467
- expect(files.length).toBeGreaterThan(0);
1468
- expect(readFileSync(join(cwd, ".agents", "skills", "nested.ts", "SKILL.md"), "utf8")).toContain(
1469
- "stat owner lookup",
1470
- );
1471
- } finally {
1472
- process.chdir(prev);
1473
- rmSync(cwd, { recursive: true, force: true });
1474
- }
1475
- });
package/src/core/types.ts CHANGED
@@ -404,9 +404,11 @@ export interface CliCompletionConfig {
404
404
  enabled?: boolean;
405
405
  }
406
406
 
407
- /** Opt-in agent skill install to `~/.agents/skills/<key>/` (default: disabled). */
407
+ /**
408
+ * @deprecated Skill generation was removed; skills are authored directly in repositories under `skills/<app>/SKILL.md`.
409
+ */
408
410
  export interface CliSkillConfig {
409
- /** When `true`, install the agent skill via `configure install`. Default false when omitted. */
411
+ /** @deprecated Skill generation was removed; this property has no effect. */
410
412
  enabled?: boolean;
411
413
  }
412
414
 
@@ -678,7 +680,7 @@ export type CliProgram = CliNode & {
678
680
  mcpServer?: CliMcpServerConfig;
679
681
  /** Optional readiness probe for HTTP/MCP `GET /health/readiness` only. */
680
682
  readiness?: (ctx: ReadinessContext) => boolean | Promise<boolean>;
681
- /** Opt-in agent skill (`~/.agents/skills/<key>/`). Default disabled when omitted. */
683
+ /** @deprecated Skill generation was removed; skills are authored directly in repositories under `skills/<app>/SKILL.md`. */
682
684
  skill?: CliSkillConfig;
683
685
  /** Program version (printed by the `version` built-in and MCP serverInfo). */
684
686
  version: string;
@@ -105,7 +105,9 @@ function validateConfigureConfig(program: CliProgram): void {
105
105
  }
106
106
 
107
107
  if ("agentIntegration" in configure) {
108
- throw new CliSchemaValidationError("configure.agentIntegration removed; use program.skill.enabled for skills");
108
+ throw new CliSchemaValidationError(
109
+ "configure.agentIntegration removed; skills are authored under skills/<app>/SKILL.md",
110
+ );
109
111
  }
110
112
 
111
113
  if (!configure.targets) return;
@@ -119,7 +121,7 @@ function validateConfigureConfig(program: CliProgram): void {
119
121
  for (const key of legacySkillKeys) {
120
122
  if (key in targets) {
121
123
  throw new CliSchemaValidationError(
122
- `configure.targets.${key} removed; use program.skill.enabled for agent skill install`,
124
+ `configure.targets.${key} removed; skills are authored under skills/<app>/SKILL.md`,
123
125
  );
124
126
  }
125
127
  }
@@ -1,6 +1,9 @@
1
- import { docsSkillTopicDescription } from "../builtins/configure-copy.ts";
1
+ /*
2
+ This module builds the built-in `docs` command group router.
3
+ It registers bundled documentation topics (CLI guide, schema, MCP, HTTP) as subcommands.
4
+ */
5
+
2
6
  import { type CliLeaf, type CliOption, CliOptionKind, type CliProgram, type CliRouter } from "../core/types.ts";
3
- import { resolveCapabilities } from "../runtime/capabilities.ts";
4
7
  import {
5
8
  DOCS_ROUTER_DESCRIPTION,
6
9
  docsEnabled,
@@ -74,7 +77,6 @@ export function cliBuiltinDocsGroup(program: CliProgram): CliRouter {
74
77
  leaves.push(
75
78
  docsLeaf(program, "cli-schema", "Print the full CLI command tree as JSON."),
76
79
  docsLeaf(program, "cli", "Print the full command reference as markdown."),
77
- docsLeaf(program, "skill", docsSkillTopicDescription(program, resolveCapabilities(program))),
78
80
  );
79
81
 
80
82
  return {
@@ -6,7 +6,7 @@ import { cliPositionalLabel, cliResolveNotes } from "../help.ts";
6
6
 
7
7
  /** Options for {@link generateCliGuideBody} and {@link generateCliGuide}. */
8
8
  export interface CliGuideBodyOptions {
9
- /** Omit embedded outputSchema JSON; point to `docs cli-schema` instead (skill reference). */
9
+ /** Omit embedded outputSchema JSON; point to `docs cli-schema` instead. */
10
10
  compact?: boolean;
11
11
  }
12
12
 
@@ -72,7 +72,7 @@ function formatNotesBlockquote(notes: string, appKey: string): string {
72
72
  .join("\n");
73
73
  }
74
74
 
75
- /** Markdown section for leaf outputSchema (docs cli / skill reference). */
75
+ /** Markdown section for leaf outputSchema (docs cli). */
76
76
  function formatOutputSchemaSection(schema: Record<string, unknown>): string[] {
77
77
  return [
78
78
  "#### Output",
@@ -173,7 +173,7 @@ function renderCommandNode(
173
173
  }
174
174
  }
175
175
 
176
- /** Command-tree markdown shared by `docs cli` and generated agent skills (no API doc header). */
176
+ /** Command-tree markdown for `docs cli` (no API doc header). */
177
177
  export function generateCliGuideBody(program: CliProgram, opts: CliGuideBodyOptions = {}): string {
178
178
  const schema = cliSchemaExport(program);
179
179
  const lines: string[] = [];
@@ -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,41 +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("--help");
263
- expect(result.stdout).not.toContain("reference.md");
264
- expect(result.stdout).not.toContain("#### Options");
265
- expect(result.stdout).not.toContain("mcp.json");
266
- });
267
-
268
- /** Docs skill help recommends configure. */
269
- test("docs skill help recommends configure", async () => {
270
- const presentation = cliPresentationRoot(docsFixture());
271
- const docsNode = presentation.commands.find((c) => c.key === "docs");
272
- expect(docsNode && "commands" in docsNode).toBe(true);
273
- if (docsNode && "commands" in docsNode) {
274
- const skill = docsNode.commands.find((c) => c.key === "skill");
275
- expect(skill?.description).toContain("reference agent SKILL");
276
- expect(skill?.description).toContain("configure");
277
- expect(skill?.notes).toBeUndefined();
278
- expect(docsNode.notes).toContain("--save");
279
- expect(docsNode.notes).not.toContain("install --skill");
280
- }
281
- });
282
-
283
- test("presentation includes docs cli-schema and skill", () => {
250
+ test("presentation includes docs cli-schema and cli without skill", () => {
284
251
  const presentation = cliPresentationRoot(docsFixture());
285
252
  const docsNode = presentation.commands.find((c) => c.key === "docs");
286
253
  expect(docsNode && "commands" in docsNode).toBe(true);
287
254
  if (docsNode && "commands" in docsNode) {
288
255
  expect(docsNode.commands.some((c) => c.key === "cli-schema")).toBe(true);
289
256
  expect(docsNode.commands.some((c) => c.key === "cli")).toBe(true);
290
- expect(docsNode.commands.some((c) => c.key === "skill")).toBe(true);
257
+ expect(docsNode.commands.some((c) => c.key === "skill")).toBe(false);
291
258
  }
292
259
  });
293
260
 
@@ -297,7 +264,7 @@ test("completions offer docs subcommands", () => {
297
264
  expect(bash).toContain("readme) echo");
298
265
  expect(bash).toContain("cli-schema) echo");
299
266
  expect(bash).toContain("cli) echo");
300
- expect(bash).toContain("skill) echo");
267
+ expect(bash).not.toContain("skill) echo");
301
268
  });
302
269
 
303
270
  test("generateMcpGuide includes schema URI and .agents install", () => {
@@ -330,17 +297,6 @@ test("docs cli --save prepends generated hint", async () => {
330
297
  expect(text).toContain("CLI API reference");
331
298
  });
332
299
 
333
- test("docs skill --save writes skills/<app>/SKILL.md and keeps frontmatter first", async () => {
334
- const result = await new Cli(docsFixture()).invoke(["docs", "skill", "--save"]);
335
- expect(result.exitCode).toBe(0);
336
- expect(result.stdout.trim()).toBe("skills/myapp/SKILL.md");
337
- const text = readFileSync(join(workDir, "skills/myapp/SKILL.md"), "utf8");
338
- expect(text.startsWith("---\n")).toBe(true);
339
- expect(text).toContain("name: myapp");
340
- const hint = "<!-- Generated by myapp docs skill --save; do not edit. -->";
341
- expect(text.indexOf(hint)).toBeGreaterThan(text.indexOf("---\n", 4));
342
- });
343
-
344
300
  test("docs cli-schema --save writes JSON file", async () => {
345
301
  const result = await new Cli(docsFixture()).invoke(["docs", "cli-schema", "--save"]);
346
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
  }