argsbarg 6.1.10 → 6.2.2

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 (136) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/README.md +49 -49
  3. package/docs/README.md +5 -4
  4. package/docs/ai-skills.md +36 -23
  5. package/docs/bundled-docs.md +1 -1
  6. package/docs/cli-program.md +19 -20
  7. package/docs/config-schema.md +3 -3
  8. package/docs/configure.md +12 -16
  9. package/docs/developing.md +9 -9
  10. package/docs/mcp.md +21 -57
  11. package/docs/output-schema.md +3 -3
  12. package/examples/formats.ts +5 -6
  13. package/examples/full-example/AGENTS.md +75 -0
  14. package/examples/full-example/CLAUDE.md +1 -0
  15. package/examples/full-example/README.md +7 -69
  16. package/examples/full-example/docs/README.md +1 -1
  17. package/examples/full-example/docs/cli-schema.json +1 -1659
  18. package/examples/full-example/docs/cli.md +2 -1538
  19. package/examples/full-example/docs/http.md +0 -7
  20. package/examples/full-example/docs/mcp.md +23 -59
  21. package/examples/full-example/docs/openapi.json +2 -782
  22. package/examples/full-example/docs/skill.md +18 -14
  23. package/examples/full-example/justfile +5 -17
  24. package/examples/full-example/scripts/create-identity.ts +2 -1
  25. package/examples/full-example/src/commands/status/command.test.ts +2 -2
  26. package/examples/full-example/src/commands/status/command.ts +7 -6
  27. package/examples/full-example/src/program.ts +4 -10
  28. package/examples/full-example-json/AGENTS.md +86 -0
  29. package/examples/full-example-json/CLAUDE.md +1 -0
  30. package/examples/full-example-json/Formula/.gitkeep +0 -0
  31. package/examples/full-example-json/Formula/full-example-json.rb +35 -0
  32. package/examples/full-example-json/README.md +27 -0
  33. package/examples/full-example-json/biome.json +22 -0
  34. package/examples/full-example-json/bun.lock +48 -0
  35. package/examples/full-example-json/docs/README.md +27 -0
  36. package/examples/full-example-json/docs/cli-schema.json +2145 -0
  37. package/examples/full-example-json/docs/cli.md +1990 -0
  38. package/examples/full-example-json/docs/http.md +92 -0
  39. package/examples/full-example-json/docs/mcp.md +116 -0
  40. package/examples/full-example-json/docs/openapi.json +1246 -0
  41. package/examples/full-example-json/docs/skill.md +57 -0
  42. package/examples/full-example-json/justfile +171 -0
  43. package/examples/full-example-json/package.json +22 -0
  44. package/examples/full-example-json/scripts/create-identity.ts +12 -0
  45. package/examples/full-example-json/scripts/dev-formula.ts +97 -0
  46. package/examples/full-example-json/scripts/formula-shared.test.ts +68 -0
  47. package/examples/full-example-json/scripts/formula-shared.ts +170 -0
  48. package/examples/full-example-json/scripts/print-identity.ts +28 -0
  49. package/examples/full-example-json/scripts/release.ts +212 -0
  50. package/examples/full-example-json/src/commands/echo/command.ts +26 -0
  51. package/examples/full-example-json/src/commands/status/command.test.ts +10 -0
  52. package/examples/full-example-json/src/commands/status/command.ts +28 -0
  53. package/examples/full-example-json/src/index.ts +10 -0
  54. package/examples/full-example-json/src/program.ts +33 -0
  55. package/examples/full-example-json/src/types/md.d.ts +4 -0
  56. package/examples/full-example-json/tsconfig.json +17 -0
  57. package/examples/minimal.ts +17 -17
  58. package/examples/nested.ts +10 -10
  59. package/examples/option-required.ts +13 -13
  60. package/examples/servers.ts +10 -10
  61. package/index.d.ts +17 -43
  62. package/package.json +1 -1
  63. package/src/cli-tool/create.test.ts +44 -68
  64. package/src/cli-tool/create.ts +81 -17
  65. package/src/cli-tool/full-example-capabilities.test.ts +33 -18
  66. package/src/cli-tool/post-create.ts +31 -17
  67. package/src/cli-tool/program.ts +16 -7
  68. package/src/cli-tool/prompt.ts +27 -0
  69. package/src/cli-tool/run-create.ts +19 -7
  70. package/src/cli-tool/schemagen/schemagen.test.ts +3 -3
  71. package/src/configure/artifacts/install-validate.test.ts +20 -33
  72. package/src/configure/artifacts/paths.ts +9 -53
  73. package/src/configure/artifacts/status.test.ts +13 -16
  74. package/src/configure/artifacts/status.ts +5 -22
  75. package/src/configure/artifacts/target-base.ts +6 -15
  76. package/src/configure/artifacts/target-effective.ts +16 -54
  77. package/src/configure/artifacts/target-mcp-json.ts +2 -5
  78. package/src/configure/artifacts/target-registry.ts +0 -7
  79. package/src/configure/artifacts/target-scope.ts +7 -17
  80. package/src/configure/artifacts/target-skill.ts +6 -15
  81. package/src/configure/artifacts/target-types.ts +6 -54
  82. package/src/configure/artifacts/targets/agents-mcp.ts +11 -0
  83. package/src/configure/artifacts/targets/configure.ts +1 -5
  84. package/src/configure/artifacts/targets/index.ts +4 -44
  85. package/src/configure/artifacts/targets/skill.ts +12 -0
  86. package/src/configure/artifacts/targets.test.ts +21 -59
  87. package/src/configure/configure.test.ts +35 -46
  88. package/src/configure/index.ts +19 -19
  89. package/src/configure/prompt.ts +2 -12
  90. package/src/core/parse.test.ts +21 -32
  91. package/src/core/types.ts +18 -44
  92. package/src/core/validate.ts +28 -45
  93. package/src/docs/docs.test.ts +4 -4
  94. package/src/docs/mcp-guide.ts +41 -71
  95. package/src/docs/resolve.ts +1 -1
  96. package/src/exports/cli.ts +1 -1
  97. package/src/index.ts +1 -1
  98. package/src/skill/generate.ts +26 -45
  99. package/src/skill/install.ts +18 -38
  100. package/src/skill/naming.ts +3 -27
  101. package/src/test/integration/config.test.ts +3 -3
  102. package/src/test/integration/mcp.test.ts +4 -4
  103. package/{examples/mcp-test.ts → src/test/mcp-integration-fixture.ts} +20 -22
  104. package/src/configure/artifacts/target-mcp-cli.ts +0 -127
  105. package/src/configure/artifacts/targets/chatgpt-mcp.ts +0 -12
  106. package/src/configure/artifacts/targets/claude-code-mcp.ts +0 -15
  107. package/src/configure/artifacts/targets/claude-desktop-mcp.ts +0 -12
  108. package/src/configure/artifacts/targets/claude-skill.ts +0 -16
  109. package/src/configure/artifacts/targets/codex-mcp.ts +0 -25
  110. package/src/configure/artifacts/targets/codex-skill.ts +0 -14
  111. package/src/configure/artifacts/targets/cursor-mcp.ts +0 -15
  112. package/src/configure/artifacts/targets/cursor-skill.ts +0 -16
  113. package/src/configure/artifacts/targets/openclaw-mcp.ts +0 -25
  114. package/src/configure/artifacts/targets/openclaw-skill.ts +0 -17
  115. package/src/configure/artifacts/targets/opencode-mcp.ts +0 -96
  116. package/src/configure/artifacts/targets/opencode-skill.ts +0 -15
  117. /package/examples/{full-example → full-example-json}/src/commands/render-json/__generated__/RenderJsonInputSchema.json +0 -0
  118. /package/examples/{full-example → full-example-json}/src/commands/render-json/__generated__/index.ts +0 -0
  119. /package/examples/{full-example → full-example-json}/src/commands/render-json/command.test.ts +0 -0
  120. /package/examples/{full-example → full-example-json}/src/commands/render-json/command.ts +0 -0
  121. /package/examples/{full-example → full-example-json}/src/commands/render-json/types.ts +0 -0
  122. /package/examples/{full-example → full-example-json}/src/commands/status/__generated__/StatusJsonOutputSchema.json +0 -0
  123. /package/examples/{full-example → full-example-json}/src/commands/status/__generated__/index.ts +0 -0
  124. /package/examples/{full-example → full-example-json}/src/commands/status/types.ts +0 -0
  125. /package/examples/{full-example → full-example-json}/src/commands/workspaces/__generated__/WorkspaceNameInputSchema.json +0 -0
  126. /package/examples/{full-example → full-example-json}/src/commands/workspaces/__generated__/index.ts +0 -0
  127. /package/examples/{full-example → full-example-json}/src/commands/workspaces/command.test.ts +0 -0
  128. /package/examples/{full-example → full-example-json}/src/commands/workspaces/command.ts +0 -0
  129. /package/examples/{full-example → full-example-json}/src/commands/workspaces/types.ts +0 -0
  130. /package/examples/{full-example → full-example-json}/src/db/index.test.ts +0 -0
  131. /package/examples/{full-example → full-example-json}/src/db/index.ts +0 -0
  132. /package/examples/{full-example → full-example-json}/src/db/migrate.test.ts +0 -0
  133. /package/examples/{full-example → full-example-json}/src/db/migrate.ts +0 -0
  134. /package/examples/{full-example → full-example-json}/src/db/migrations/001_workspaces.sql +0 -0
  135. /package/examples/{full-example → full-example-json}/src/db/tables/workspaces.ts +0 -0
  136. /package/examples/{full-example → full-example-json}/src/types/argsbarg.d.ts +0 -0
@@ -2,10 +2,11 @@ import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import type { CliProgram } from "../core/types.ts";
4
4
  import { userHome } from "../paths/host.ts";
5
- import { generateSkillBundle, type SkillTarget } from "./generate.ts";
5
+ import { generateSkillBundle } from "./generate.ts";
6
6
  import { applySkillInstallHints } from "./hint.ts";
7
+ import { skillDirName } from "./naming.ts";
7
8
 
8
- export { skillDirNameForTarget, skillFrontmatterName, skillSlug } from "./naming.ts";
9
+ export { skillDirName } from "./naming.ts";
9
10
 
10
11
  export interface SkillInstallOpts {
11
12
  global?: boolean;
@@ -13,60 +14,39 @@ export interface SkillInstallOpts {
13
14
  dry?: boolean;
14
15
  }
15
16
 
16
- function resolveSkillDir(target: SkillTarget, dirName: string, global: boolean): string {
17
- const home = userHome();
18
- switch (target) {
19
- case "cursor":
20
- return join(global ? home : process.cwd(), ".cursor", "skills", dirName);
21
- case "claude":
22
- return join(global ? home : process.cwd(), ".claude", "skills", dirName);
23
- case "codex":
24
- return join(global ? home : process.cwd(), ".codex", "skills", dirName);
25
- case "opencode":
26
- return join(global ? home : process.cwd(), ".config", "opencode", "skills", dirName);
27
- case "openclaw":
28
- return join(global ? home : process.cwd(), ".openclaw", "skills", dirName);
29
- }
17
+ /** Resolved skill directory for a program (`~/.agents/skills/<key>/` or project `.agents/skills/<key>/`). */
18
+ export function resolveAgentsSkillDir(root: CliProgram, global = true): string {
19
+ const base = global ? userHome() : process.cwd();
20
+ return join(base, ".agents", "skills", skillDirName(root.key));
30
21
  }
31
22
 
32
- /** Writes SKILL.md and reference.md; returns changed file paths. */
33
- export function cliSkillInstall(root: CliProgram, target: SkillTarget, opts: SkillInstallOpts): string[] {
34
- const bundle = generateSkillBundle(root, target);
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);
35
26
  const { skillMd, referenceMd } = applySkillInstallHints(root, bundle.skillMd, bundle.referenceMd);
36
- const dir = resolveSkillDir(target, bundle.dirName, opts.global ?? false);
27
+ const dir = resolveAgentsSkillDir(root, opts.global ?? true);
37
28
  const changed: string[] = [];
38
29
 
39
30
  if (opts.rimraf && existsSync(dir) && !opts.dry) {
40
31
  rmSync(dir, { recursive: true, force: true });
41
32
  }
42
33
 
43
- const skillPath = join(dir, "SKILL.md");
34
+ const skillPath = join(dir, "skill.md");
35
+ const skillCompatPath = join(dir, "SKILL.md");
44
36
  const refPath = join(dir, "reference.md");
45
37
 
46
38
  if (!opts.dry) {
47
39
  mkdirSync(dir, { recursive: true });
48
40
  writeFileSync(skillPath, skillMd, "utf8");
41
+ writeFileSync(skillCompatPath, skillMd, "utf8");
49
42
  writeFileSync(refPath, referenceMd, "utf8");
50
43
  }
51
44
 
52
- changed.push(skillPath, refPath);
45
+ changed.push(skillPath, skillCompatPath, refPath);
53
46
  return changed;
54
47
  }
55
48
 
56
- /** Maps install action kind to skill target. */
57
- export function skillTargetFromActionKind(kind: string): SkillTarget | undefined {
58
- switch (kind) {
59
- case "cursor-skill":
60
- return "cursor";
61
- case "claude-skill":
62
- return "claude";
63
- case "codex-skill":
64
- return "codex";
65
- case "opencode-skill":
66
- return "opencode";
67
- case "openclaw-skill":
68
- return "openclaw";
69
- default:
70
- return undefined;
71
- }
49
+ /** True when the plan action kind installs the agent skill bundle. */
50
+ export function isAgentSkillActionKind(kind: string): boolean {
51
+ return kind === "agent-skill";
72
52
  }
@@ -1,28 +1,4 @@
1
- /** Agent skill install targets. */
2
- export type SkillTarget = "cursor" | "claude" | "codex" | "opencode" | "openclaw";
3
-
4
- import { sanitizeToolSegment } from "../mcp/tools.ts";
5
-
6
- /** Kebab-case skill folder + frontmatter name for agents that require hyphen slugs. */
7
- export function skillSlug(programKey: string): string {
8
- return programKey
9
- .replace(/[^a-zA-Z0-9]+/g, "-")
10
- .replace(/^-+|-+$/g, "")
11
- .toLowerCase();
12
- }
13
-
14
- /** Directory name for a skill target (underscore vs kebab conventions). */
15
- export function skillDirNameForTarget(programKey: string, target: SkillTarget): string {
16
- if (target === "cursor" || target === "claude") {
17
- return sanitizeToolSegment(programKey);
18
- }
19
- return skillSlug(programKey);
20
- }
21
-
22
- /** Frontmatter `name` for SKILL.md by target. */
23
- export function skillFrontmatterName(programKey: string, target: SkillTarget): string {
24
- if (target === "cursor" || target === "claude") {
25
- return sanitizeToolSegment(programKey);
26
- }
27
- return skillSlug(programKey);
1
+ /** Skill directory and frontmatter name from program key (path-safe segment). */
2
+ export function skillDirName(programKey: string): string {
3
+ return programKey.replace(/[/\\\s]/g, "_");
28
4
  }
@@ -55,7 +55,7 @@ test("MCP program.appConfig fails when required config missing", async () => {
55
55
  params: { name: "echo_env", arguments: { name: "ARGS_TEST_SECRET" } },
56
56
  },
57
57
  ],
58
- { script: "examples/mcp-test.ts", env: { ARGS_TEST_SECRET: "" } },
58
+ { script: "src/test/mcp-integration-fixture.ts", env: { ARGS_TEST_SECRET: "" } },
59
59
  );
60
60
  const res = responses.get(13) as { result: { isError: boolean; content: { text: string }[] } };
61
61
  expect(res.result.isError).toBe(true);
@@ -73,7 +73,7 @@ test("MCP program.appConfig succeeds when env present", async () => {
73
73
  params: { name: "echo_env", arguments: { name: "ARGS_TEST_SECRET" } },
74
74
  },
75
75
  ],
76
- { script: "examples/mcp-test.ts", env: { ARGS_TEST_SECRET: "sekrit" } },
76
+ { script: "src/test/mcp-integration-fixture.ts", env: { ARGS_TEST_SECRET: "sekrit" } },
77
77
  );
78
78
  const res = responses.get(14) as {
79
79
  result: {
@@ -105,7 +105,7 @@ test("MCP config file loads and exports vars for tool handlers", async () => {
105
105
  },
106
106
  ],
107
107
  {
108
- script: "examples/mcp-test.ts",
108
+ script: "src/test/mcp-integration-fixture.ts",
109
109
  env: { HOME: dir, ARGS_TEST_SECRET: "present" },
110
110
  },
111
111
  );
@@ -446,7 +446,7 @@ test("minimal.ts mcp without opt-in fails", async () => {
446
446
 
447
447
  test("MCP resources/list includes custom resource", async () => {
448
448
  const responses = await mcpRequest([{ jsonrpc: "2.0", id: 10, method: "resources/list", params: {} }], {
449
- script: "examples/mcp-test.ts",
449
+ script: "src/test/mcp-integration-fixture.ts",
450
450
  });
451
451
  const res = responses.get(10) as { result: { resources: { uri: string }[] } };
452
452
  const uris = res.result.resources.map((r) => r.uri);
@@ -466,7 +466,7 @@ test("MCP resources/read returns docs topic resource body", async () => {
466
466
  params: { uri: "mcp_test://docs/readme" },
467
467
  },
468
468
  ],
469
- { script: "examples/mcp-test.ts" },
469
+ { script: "src/test/mcp-integration-fixture.ts" },
470
470
  );
471
471
  const res = responses.get(13) as { result: { contents: { text: string }[] } };
472
472
  expect(res.result.contents[0]?.text).toBe("# MCP test readme\n");
@@ -475,7 +475,7 @@ test("MCP resources/read returns docs topic resource body", async () => {
475
475
  test("MCP resources/read returns custom resource body", async () => {
476
476
  const responses = await mcpRequest(
477
477
  [{ jsonrpc: "2.0", id: 11, method: "resources/read", params: { uri: "test://hello" } }],
478
- { script: "examples/mcp-test.ts" },
478
+ { script: "src/test/mcp-integration-fixture.ts" },
479
479
  );
480
480
  const res = responses.get(11) as { result: { contents: { text: string }[] } };
481
481
  expect(res.result.contents[0]?.text).toBe("hello resource");
@@ -484,7 +484,7 @@ test("MCP resources/read returns custom resource body", async () => {
484
484
  test("MCP resources/read unknown URI returns error", async () => {
485
485
  const responses = await mcpRequest(
486
486
  [{ jsonrpc: "2.0", id: 12, method: "resources/read", params: { uri: "missing://nope" } }],
487
- { script: "examples/mcp-test.ts" },
487
+ { script: "src/test/mcp-integration-fixture.ts" },
488
488
  );
489
489
  const res = responses.get(12) as { error: { code: number } };
490
490
  expect(res.error.code).toBe(-32602);
@@ -1,14 +1,11 @@
1
1
  #!/usr/bin/env bun
2
2
  /*
3
- MCP test fixture for subprocess integration tests only.
3
+ MCP integration test fixture for subprocess tests (not a public example).
4
4
  */
5
5
 
6
- import { Cli, CliOptionKind, type CliProgram } from "../src/index";
6
+ import { Cli, CliOptionKind, type CliProgram } from "../index.ts";
7
7
 
8
8
  const program = {
9
- key: "mcp-test",
10
- version: "0.0.0-test",
11
- description: "MCP integration test fixture.",
12
9
  appConfig: {
13
10
  entries: {
14
11
  argsTestSecret: {
@@ -17,23 +14,6 @@ const program = {
17
14
  },
18
15
  },
19
16
  },
20
- mcpServer: {
21
- enabled: true,
22
- resources: [
23
- {
24
- uri: "test://hello",
25
- name: "hello",
26
- description: "Test resource.",
27
- mimeType: "text/plain",
28
- load: () => "hello resource",
29
- },
30
- ],
31
- },
32
- docs: {
33
- topics: {
34
- readme: { text: "# MCP test readme\n" },
35
- },
36
- },
37
17
  commands: [
38
18
  {
39
19
  key: "echo-env",
@@ -79,6 +59,24 @@ const program = {
79
59
  },
80
60
  },
81
61
  ],
62
+ description: "MCP integration test fixture.",
63
+ docs: {
64
+ topics: {
65
+ readme: { text: "# MCP test readme\n" },
66
+ },
67
+ },
68
+ key: "mcp-test",
69
+ mcpServer: {
70
+ enabled: true,
71
+ resources: [
72
+ {
73
+ uri: "test://hello",
74
+ name: "hello",
75
+ load: () => "hello resource",
76
+ },
77
+ ],
78
+ },
79
+ version: "0.0.0-test",
82
80
  } satisfies CliProgram;
83
81
 
84
82
  const cli = new Cli(program);
@@ -1,127 +0,0 @@
1
- import type { CliProgram } from "../../core/types.ts";
2
- import { checkCodexMcpConflict, codexMcpHasServer, mergeCodexMcpConfig, removeCodexMcpConfig } from "./mcp-codex.ts";
3
- import { expectedMcpEntry } from "./mcp-config.ts";
4
- import {
5
- checkOpenclawMcpConflict,
6
- mergeOpenclawMcpConfig,
7
- openclawMcpHasServer,
8
- removeOpenclawMcpConfig,
9
- } from "./mcp-openclaw.ts";
10
- import { displayInstallPath, type InstallPaths, userHome } from "./paths.ts";
11
- import { InstallTarget } from "./target-base.ts";
12
- import type {
13
- CliInstallArtifactKey,
14
- DetectedSnapshot,
15
- InstallAction,
16
- InstallActionKind,
17
- InstalledArtifacts,
18
- InstallStatus,
19
- TargetPlanContext,
20
- UninstallAction,
21
- } from "./target-types.ts";
22
-
23
- export interface McpCliHostSpec {
24
- key: CliInstallArtifactKey;
25
- actionKind: InstallActionKind;
26
- label: string;
27
- pairedSkillKey: CliInstallArtifactKey;
28
- configPath: (paths: InstallPaths) => string;
29
- detectedKey: "codexMcp" | "openclawMcp";
30
- statusField: "codexMcp" | "openclawMcp";
31
- isAvailable: (root: CliProgram, paths: InstallPaths) => boolean;
32
- hasServer: (home: string, name: string) => boolean;
33
- installMessage: string;
34
- uninstallMessage: string;
35
- merge: (home: string, name: string, entry: ReturnType<typeof expectedMcpEntry>, dry: boolean, yes: boolean) => string;
36
- remove: (home: string, name: string, dry: boolean) => void;
37
- preflight: (home: string, name: string, entry: ReturnType<typeof expectedMcpEntry>, yes: boolean) => string | null;
38
- }
39
-
40
- /** MCP host registered via an external CLI (codex, openclaw). */
41
- export class McpCliInstallTarget extends InstallTarget {
42
- readonly key: CliInstallArtifactKey;
43
- readonly actionKind: InstallActionKind;
44
- readonly category = "mcp" as const;
45
- readonly pairedKey: CliInstallArtifactKey;
46
-
47
- private readonly spec: McpCliHostSpec;
48
-
49
- constructor(spec: McpCliHostSpec) {
50
- super();
51
- this.spec = spec;
52
- this.key = spec.key;
53
- this.actionKind = spec.actionKind;
54
- this.pairedKey = spec.pairedSkillKey;
55
- }
56
-
57
- isAvailable(root: CliProgram, paths: InstallPaths): boolean {
58
- return this.spec.isAvailable(root, paths);
59
- }
60
-
61
- isDetected(paths: InstallPaths, _root: CliProgram): boolean {
62
- return this.spec.hasServer(userHome(), paths.mcpName);
63
- }
64
-
65
- applyDetected(paths: InstallPaths, root: CliProgram, out: InstalledArtifacts): void {
66
- out[this.spec.detectedKey] = this.isDetected(paths, root);
67
- }
68
-
69
- protected isDetectedFromSnapshot(detected: DetectedSnapshot): boolean {
70
- return detected[this.spec.detectedKey] ?? false;
71
- }
72
-
73
- protected formatStatusLine(paths: InstallPaths, _root: CliProgram): string {
74
- return `${displayInstallPath(this.spec.configPath(paths))} (server "${paths.mcpName}")`;
75
- }
76
-
77
- protected assignStatusLine(status: InstallStatus, line: string): void {
78
- status[this.spec.statusField] = line;
79
- }
80
-
81
- preflight(ctx: TargetPlanContext): string | null {
82
- const entry = expectedMcpEntry(ctx.root);
83
- return this.spec.preflight(userHome(), ctx.paths.mcpName, entry, !!ctx.opts.yes);
84
- }
85
-
86
- protected buildInstallActions(ctx: TargetPlanContext): InstallAction[] {
87
- const entry = expectedMcpEntry(ctx.root);
88
- const configPath = this.spec.configPath(ctx.paths);
89
- return [
90
- {
91
- kind: this.actionKind,
92
- summary: `${this.spec.label}: ${displayInstallPath(configPath)}`,
93
- message: this.spec.installMessage.replace("{name}", ctx.paths.mcpName),
94
- run: () => {
95
- const written = this.spec.merge(userHome(), ctx.paths.mcpName, entry, ctx.dry, !!ctx.opts.yes);
96
- return [written];
97
- },
98
- },
99
- ];
100
- }
101
-
102
- protected buildUninstallActions(ctx: TargetPlanContext): UninstallAction[] {
103
- const configPath = this.spec.configPath(ctx.paths);
104
- return [
105
- {
106
- kind: this.actionKind,
107
- summary: `${this.spec.label}: ${displayInstallPath(configPath)}`,
108
- message: this.spec.uninstallMessage.replace("{name}", ctx.paths.mcpName),
109
- run: () => {
110
- this.spec.remove(userHome(), ctx.paths.mcpName, ctx.dry);
111
- return [configPath];
112
- },
113
- },
114
- ];
115
- }
116
- }
117
-
118
- export {
119
- checkCodexMcpConflict,
120
- checkOpenclawMcpConflict,
121
- codexMcpHasServer,
122
- mergeCodexMcpConfig,
123
- mergeOpenclawMcpConfig,
124
- openclawMcpHasServer,
125
- removeCodexMcpConfig,
126
- removeOpenclawMcpConfig,
127
- };
@@ -1,12 +0,0 @@
1
- import { chatGptDesktopPresent, userHome } from "../paths.ts";
2
- import { McpJsonInstallTarget } from "../target-mcp-json.ts";
3
-
4
- export const chatgptMcpTarget = new McpJsonInstallTarget({
5
- key: "chatgptMcp",
6
- actionKind: "chatgpt-desktop-mcp",
7
- label: "chatgpt desktop mcp",
8
- configPath: (p) => p.chatGptMcpPath,
9
- detectedKey: "chatGptMcp",
10
- statusField: "chatGptMcp",
11
- isAvailable: (_root, paths) => chatGptDesktopPresent(userHome(), paths.chatGptMcpPath),
12
- });
@@ -1,15 +0,0 @@
1
- import { existsSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { userHome } from "../paths.ts";
4
- import { McpJsonInstallTarget } from "../target-mcp-json.ts";
5
-
6
- export const claudeCodeMcpTarget = new McpJsonInstallTarget({
7
- key: "claudeCodeMcp",
8
- actionKind: "claude-mcp",
9
- label: "claude code mcp",
10
- pairedSkillKey: "claudeSkill",
11
- configPath: (p) => p.claudeMcpPath,
12
- detectedKey: "claudeMcp",
13
- statusField: "claudeMcp",
14
- isAvailable: () => existsSync(join(userHome(), ".claude")),
15
- });
@@ -1,12 +0,0 @@
1
- import { claudeDesktopPresent, userHome } from "../paths.ts";
2
- import { McpJsonInstallTarget } from "../target-mcp-json.ts";
3
-
4
- export const claudeDesktopMcpTarget = new McpJsonInstallTarget({
5
- key: "claudeDesktopMcp",
6
- actionKind: "claude-desktop-mcp",
7
- label: "claude desktop mcp",
8
- configPath: (p) => p.claudeDesktopMcpPath,
9
- detectedKey: "claudeDesktopMcp",
10
- statusField: "claudeDesktopMcp",
11
- isAvailable: (_root, paths) => claudeDesktopPresent(userHome(), paths.claudeDesktopMcpPath),
12
- });
@@ -1,16 +0,0 @@
1
- import { existsSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { userHome } from "../paths.ts";
4
- import { SkillInstallTarget } from "../target-skill.ts";
5
-
6
- export const claudeSkillTarget = new SkillInstallTarget({
7
- key: "claudeSkill",
8
- actionKind: "claude-skill",
9
- label: "Claude Code",
10
- uninstallPrefix: "claude skill",
11
- pairedMcpKey: "claudeCodeMcp",
12
- skillDir: (p) => p.claudeSkillDir,
13
- detectedKey: "claudeSkill",
14
- statusField: "claudeSkill",
15
- isAvailable: () => existsSync(join(userHome(), ".claude")),
16
- });
@@ -1,25 +0,0 @@
1
- import { codexOnPath } from "../mcp-codex.ts";
2
- import {
3
- checkCodexMcpConflict,
4
- codexMcpHasServer,
5
- McpCliInstallTarget,
6
- mergeCodexMcpConfig,
7
- removeCodexMcpConfig,
8
- } from "../target-mcp-cli.ts";
9
-
10
- export const codexMcpTarget = new McpCliInstallTarget({
11
- key: "codexMcp",
12
- actionKind: "codex-mcp",
13
- label: "codex mcp",
14
- pairedSkillKey: "codexSkill",
15
- configPath: (p) => p.codexConfigPath,
16
- detectedKey: "codexMcp",
17
- statusField: "codexMcp",
18
- isAvailable: () => codexOnPath(),
19
- hasServer: codexMcpHasServer,
20
- installMessage: 'Registering MCP server "{name}" via codex mcp add',
21
- uninstallMessage: 'Removing MCP server "{name}" from Codex via codex mcp remove',
22
- merge: mergeCodexMcpConfig,
23
- remove: removeCodexMcpConfig,
24
- preflight: checkCodexMcpConflict,
25
- });
@@ -1,14 +0,0 @@
1
- import { codexOnPath } from "../mcp-codex.ts";
2
- import { SkillInstallTarget } from "../target-skill.ts";
3
-
4
- export const codexSkillTarget = new SkillInstallTarget({
5
- key: "codexSkill",
6
- actionKind: "codex-skill",
7
- label: "Codex",
8
- uninstallPrefix: "codex skill",
9
- pairedMcpKey: "codexMcp",
10
- skillDir: (p) => p.codexSkillDir,
11
- detectedKey: "codexSkill",
12
- statusField: "codexSkill",
13
- isAvailable: () => codexOnPath(),
14
- });
@@ -1,15 +0,0 @@
1
- import { existsSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { userHome } from "../paths.ts";
4
- import { McpJsonInstallTarget } from "../target-mcp-json.ts";
5
-
6
- export const cursorMcpTarget = new McpJsonInstallTarget({
7
- key: "cursorMcp",
8
- actionKind: "cursor-mcp",
9
- label: "cursor mcp",
10
- pairedSkillKey: "cursorSkill",
11
- configPath: (p) => p.cursorMcpPath,
12
- detectedKey: "cursorMcp",
13
- statusField: "cursorMcp",
14
- isAvailable: () => existsSync(join(userHome(), ".cursor")),
15
- });
@@ -1,16 +0,0 @@
1
- import { existsSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { userHome } from "../paths.ts";
4
- import { SkillInstallTarget } from "../target-skill.ts";
5
-
6
- export const cursorSkillTarget = new SkillInstallTarget({
7
- key: "cursorSkill",
8
- actionKind: "cursor-skill",
9
- label: "Cursor",
10
- uninstallPrefix: "cursor skill",
11
- pairedMcpKey: "cursorMcp",
12
- skillDir: (p) => p.cursorSkillDir,
13
- detectedKey: "cursorSkill",
14
- statusField: "cursorSkill",
15
- isAvailable: () => existsSync(join(userHome(), ".cursor")),
16
- });
@@ -1,25 +0,0 @@
1
- import { openclawOnPath } from "../mcp-openclaw.ts";
2
- import {
3
- checkOpenclawMcpConflict,
4
- McpCliInstallTarget,
5
- mergeOpenclawMcpConfig,
6
- openclawMcpHasServer,
7
- removeOpenclawMcpConfig,
8
- } from "../target-mcp-cli.ts";
9
-
10
- export const openclawMcpTarget = new McpCliInstallTarget({
11
- key: "openclawMcp",
12
- actionKind: "openclaw-mcp",
13
- label: "openclaw mcp",
14
- pairedSkillKey: "openclawSkill",
15
- configPath: (p) => p.openclawConfigPath,
16
- detectedKey: "openclawMcp",
17
- statusField: "openclawMcp",
18
- isAvailable: () => openclawOnPath(),
19
- hasServer: openclawMcpHasServer,
20
- installMessage: 'Registering MCP server "{name}" via openclaw mcp add',
21
- uninstallMessage: 'Removing MCP server "{name}" from OpenClaw via openclaw mcp unset',
22
- merge: mergeOpenclawMcpConfig,
23
- remove: removeOpenclawMcpConfig,
24
- preflight: checkOpenclawMcpConflict,
25
- });
@@ -1,17 +0,0 @@
1
- import { existsSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { openclawOnPath } from "../mcp-openclaw.ts";
4
- import { userHome } from "../paths.ts";
5
- import { SkillInstallTarget } from "../target-skill.ts";
6
-
7
- export const openclawSkillTarget = new SkillInstallTarget({
8
- key: "openclawSkill",
9
- actionKind: "openclaw-skill",
10
- label: "OpenClaw",
11
- uninstallPrefix: "openclaw skill",
12
- pairedMcpKey: "openclawMcp",
13
- skillDir: (p) => p.openclawSkillDir,
14
- detectedKey: "openclawSkill",
15
- statusField: "openclawSkill",
16
- isAvailable: () => existsSync(join(userHome(), ".openclaw")) || openclawOnPath(),
17
- });
@@ -1,96 +0,0 @@
1
- import type { CliProgram } from "../../../core/types.ts";
2
- import {
3
- checkOpenCodeMcpConflict,
4
- detectOpenCodeMcpConfigPath,
5
- expectedOpenCodeMcpEntry,
6
- mergeOpenCodeMcpConfig,
7
- opencodePresent,
8
- removeOpenCodeMcpConfig,
9
- } from "../mcp-opencode.ts";
10
- import { displayInstallPath, type InstallPaths, userHome } from "../paths.ts";
11
- import { InstallTarget } from "../target-base.ts";
12
- import type {
13
- DetectedSnapshot,
14
- InstallAction,
15
- InstalledArtifacts,
16
- InstallStatus,
17
- TargetPlanContext,
18
- UninstallAction,
19
- } from "../target-types.ts";
20
-
21
- function resolveConfigPath(paths: InstallPaths, home: string): string {
22
- return detectOpenCodeMcpConfigPath(home, paths.mcpName) ?? paths.opencodeMcpPath;
23
- }
24
-
25
- /** OpenCode MCP (top-level `mcp` key, not `mcpServers`). */
26
- class OpenCodeMcpInstallTarget extends InstallTarget {
27
- readonly key = "opencodeMcp" as const;
28
- readonly actionKind = "opencode-mcp" as const;
29
- readonly category = "mcp" as const;
30
- readonly pairedKey = "opencodeSkill" as const;
31
-
32
- isAvailable(_root: CliProgram, _paths: InstallPaths): boolean {
33
- return opencodePresent(userHome());
34
- }
35
-
36
- isDetected(paths: InstallPaths, _root: CliProgram): boolean {
37
- return detectOpenCodeMcpConfigPath(userHome(), paths.mcpName) !== undefined;
38
- }
39
-
40
- applyDetected(paths: InstallPaths, root: CliProgram, out: InstalledArtifacts): void {
41
- out.opencodeMcp = this.isDetected(paths, root);
42
- }
43
-
44
- protected isDetectedFromSnapshot(detected: DetectedSnapshot): boolean {
45
- return detected.opencodeMcp;
46
- }
47
-
48
- protected formatStatusLine(paths: InstallPaths, _root: CliProgram): string {
49
- const home = userHome();
50
- const path = detectOpenCodeMcpConfigPath(home, paths.mcpName) ?? paths.opencodeMcpPath;
51
- return `${displayInstallPath(path)} (server "${paths.mcpName}")`;
52
- }
53
-
54
- protected assignStatusLine(status: InstallStatus, line: string): void {
55
- status.opencodeMcp = line;
56
- }
57
-
58
- preflight(ctx: TargetPlanContext): string | null {
59
- const entry = expectedOpenCodeMcpEntry(ctx.root);
60
- return checkOpenCodeMcpConflict(ctx.paths.opencodeMcpPath, ctx.paths.mcpName, entry, !!ctx.opts.yes);
61
- }
62
-
63
- protected buildInstallActions(ctx: TargetPlanContext): InstallAction[] {
64
- const entry = expectedOpenCodeMcpEntry(ctx.root);
65
- const configPath = ctx.paths.opencodeMcpPath;
66
- return [
67
- {
68
- kind: this.actionKind,
69
- summary: `opencode mcp: ${displayInstallPath(configPath)}`,
70
- message: `Merging MCP server "${ctx.paths.mcpName}" into ${displayInstallPath(configPath)}`,
71
- run: () => {
72
- mergeOpenCodeMcpConfig(configPath, ctx.paths.mcpName, entry, ctx.dry);
73
- return [configPath];
74
- },
75
- },
76
- ];
77
- }
78
-
79
- protected buildUninstallActions(ctx: TargetPlanContext): UninstallAction[] {
80
- const home = userHome();
81
- const configPath = resolveConfigPath(ctx.paths, home);
82
- return [
83
- {
84
- kind: this.actionKind,
85
- summary: `opencode mcp: ${displayInstallPath(configPath)}`,
86
- message: `Removing MCP server "${ctx.paths.mcpName}" from ${displayInstallPath(configPath)}`,
87
- run: () => {
88
- removeOpenCodeMcpConfig(configPath, ctx.paths.mcpName, ctx.dry);
89
- return [configPath];
90
- },
91
- },
92
- ];
93
- }
94
- }
95
-
96
- export const opencodeMcpTarget = new OpenCodeMcpInstallTarget();