argsbarg 6.1.1 → 6.1.3

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 (229) hide show
  1. package/CHANGELOG.md +72 -1
  2. package/README.md +17 -19
  3. package/bin/argsbarg +10 -0
  4. package/docs/README.md +4 -3
  5. package/docs/ai-skills.md +4 -2
  6. package/docs/bundled-docs.md +50 -25
  7. package/docs/cli-program.md +76 -10
  8. package/docs/config-schema.md +10 -11
  9. package/docs/configure.md +2 -0
  10. package/docs/decisions.md +40 -0
  11. package/docs/developing.md +43 -5
  12. package/docs/http-server.md +171 -0
  13. package/docs/json-schema-subset.md +51 -0
  14. package/docs/mcp.md +4 -2
  15. package/docs/output-schema.md +55 -62
  16. package/examples/formats.ts +6 -6
  17. package/examples/full-example/Formula/full-example.rb +35 -0
  18. package/examples/full-example/README.md +20 -21
  19. package/examples/full-example/docs/README.md +1 -1
  20. package/examples/full-example/docs/cli-schema.json +1790 -98
  21. package/examples/full-example/docs/cli.md +1990 -0
  22. package/examples/full-example/docs/http.md +28 -29
  23. package/examples/full-example/docs/mcp.md +8 -22
  24. package/examples/full-example/docs/openapi.json +783 -50
  25. package/examples/full-example/docs/skill.md +10 -10
  26. package/examples/full-example/justfile +11 -1
  27. package/examples/full-example/src/commands/render-json/__generated__/RenderJsonInputSchema.json +15 -0
  28. package/examples/full-example/src/commands/render-json/__generated__/index.ts +5 -0
  29. package/examples/full-example/src/commands/render-json/command.test.ts +46 -0
  30. package/examples/full-example/src/commands/render-json/command.ts +30 -0
  31. package/examples/full-example/src/commands/render-json/types.ts +9 -0
  32. package/examples/full-example/src/commands/status/__generated__/StatusJsonOutputSchema.json +15 -0
  33. package/examples/full-example/src/commands/status/__generated__/index.ts +2 -2
  34. package/examples/full-example/src/commands/status/command.ts +5 -13
  35. package/examples/full-example/src/commands/status/types.ts +1 -14
  36. package/examples/full-example/src/commands/workspaces/__generated__/WorkspaceNameInputSchema.json +15 -0
  37. package/examples/full-example/src/commands/workspaces/__generated__/index.ts +5 -0
  38. package/examples/full-example/src/commands/workspaces/command.test.ts +58 -0
  39. package/examples/full-example/src/commands/workspaces/command.ts +94 -0
  40. package/examples/full-example/src/commands/workspaces/types.ts +6 -0
  41. package/examples/full-example/src/db/index.test.ts +86 -0
  42. package/examples/full-example/src/db/index.ts +101 -0
  43. package/examples/full-example/src/db/migrate.test.ts +35 -0
  44. package/examples/full-example/src/db/migrate.ts +69 -0
  45. package/examples/full-example/src/db/migrations/001_workspaces.sql +6 -0
  46. package/examples/full-example/src/db/tables/workspaces.ts +66 -0
  47. package/examples/full-example/src/program.ts +11 -36
  48. package/examples/full-example/src/types/argsbarg.d.ts +11 -0
  49. package/examples/full-example/src/types/md.d.ts +4 -0
  50. package/examples/full-example/tsconfig.json +5 -2
  51. package/examples/mcp-test.ts +1 -2
  52. package/examples/minimal.ts +1 -7
  53. package/examples/nested.ts +1 -2
  54. package/examples/option-required.ts +1 -1
  55. package/examples/servers.ts +4 -5
  56. package/index.d.ts +440 -136
  57. package/package.json +19 -2
  58. package/src/builtins/builtins.test.ts +7 -7
  59. package/src/builtins/completion-bash.ts +1 -1
  60. package/src/builtins/completion-fish.ts +1 -1
  61. package/src/builtins/completion-group.ts +4 -4
  62. package/src/builtins/completion-simulate-shared.ts +9 -0
  63. package/src/builtins/completion-zsh.ts +1 -1
  64. package/src/builtins/config.test.ts +3 -3
  65. package/src/builtins/config.ts +9 -9
  66. package/src/builtins/configure-copy.ts +2 -2
  67. package/src/builtins/configure.ts +4 -4
  68. package/src/builtins/dispatch.ts +19 -18
  69. package/src/builtins/export.ts +7 -5
  70. package/src/builtins/http.ts +68 -0
  71. package/src/builtins/mcp.ts +28 -4
  72. package/src/builtins/presentation.ts +6 -6
  73. package/src/builtins/registry.ts +6 -6
  74. package/src/builtins/scopes.ts +2 -2
  75. package/src/builtins/version.ts +1 -1
  76. package/src/cli-tool/full-example-capabilities.test.ts +10 -15
  77. package/src/cli-tool/main.ts +1 -1
  78. package/src/cli-tool/program.ts +3 -2
  79. package/src/cli-tool/prompt.ts +1 -1
  80. package/src/cli-tool/run-schemagen.ts +1 -3
  81. package/src/cli-tool/schemagen/cleanup.ts +6 -7
  82. package/src/cli-tool/schemagen/discover-schema-roots.ts +66 -120
  83. package/src/cli-tool/schemagen/index.ts +2 -2
  84. package/src/cli-tool/schemagen/names.ts +8 -13
  85. package/src/cli-tool/schemagen/run.ts +21 -28
  86. package/src/cli-tool/schemagen/schemagen.test.ts +136 -46
  87. package/src/config/bindings.test.ts +1 -1
  88. package/src/config/bindings.ts +1 -1
  89. package/src/config/bootstrap.test.ts +1 -1
  90. package/src/config/bootstrap.ts +36 -4
  91. package/src/config/context.test.ts +1 -1
  92. package/src/config/context.ts +1 -1
  93. package/src/config/entry.ts +1 -1
  94. package/src/config/file.test.ts +1 -1
  95. package/src/config/file.ts +3 -3
  96. package/src/config/manifest.ts +1 -1
  97. package/src/config/resolve.test.ts +1 -1
  98. package/src/config/resolve.ts +1 -1
  99. package/src/config/schema.ts +1 -1
  100. package/src/config/validate.ts +1 -1
  101. package/src/{install → configure/artifacts}/binary-placement.test.ts +1 -1
  102. package/src/{install → configure/artifacts}/binary-placement.ts +1 -1
  103. package/src/{install → configure/artifacts}/gh-release-update.ts +1 -1
  104. package/src/{install → configure/artifacts}/install-validate.test.ts +3 -3
  105. package/src/{install → configure/artifacts}/mcp-config.ts +1 -1
  106. package/src/{install → configure/artifacts}/mcp-opencode.test.ts +1 -1
  107. package/src/{install → configure/artifacts}/mcp-opencode.ts +1 -1
  108. package/src/{install → configure/artifacts}/paths.ts +5 -5
  109. package/src/configure/artifacts/plan.ts +24 -0
  110. package/src/{install → configure/artifacts}/status.test.ts +1 -1
  111. package/src/{install → configure/artifacts}/status.ts +2 -2
  112. package/src/{install → configure/artifacts}/target-base.ts +1 -1
  113. package/src/{install → configure/artifacts}/target-detect.ts +1 -1
  114. package/src/{install → configure/artifacts}/target-effective.ts +3 -9
  115. package/src/{install → configure/artifacts}/target-mcp-cli.ts +1 -1
  116. package/src/{install → configure/artifacts}/target-mcp-json.ts +1 -1
  117. package/src/{install → configure/artifacts}/target-plan-build.ts +2 -2
  118. package/src/{install → configure/artifacts}/target-registry.ts +2 -2
  119. package/src/{install → configure/artifacts}/target-scope.ts +3 -3
  120. package/src/{install → configure/artifacts}/target-skill.ts +1 -1
  121. package/src/{install → configure/artifacts}/target-types.ts +2 -2
  122. package/src/{install → configure/artifacts}/targets/app.ts +5 -5
  123. package/src/{install → configure/artifacts}/targets/chatgpt-mcp.ts +2 -2
  124. package/src/{install → configure/artifacts}/targets/claude-code-mcp.ts +2 -2
  125. package/src/{install → configure/artifacts}/targets/claude-desktop-mcp.ts +2 -2
  126. package/src/{install → configure/artifacts}/targets/claude-skill.ts +2 -2
  127. package/src/{install → configure/artifacts}/targets/codex-mcp.ts +2 -2
  128. package/src/{install → configure/artifacts}/targets/codex-skill.ts +2 -2
  129. package/src/{install → configure/artifacts}/targets/configure.ts +5 -5
  130. package/src/{install → configure/artifacts}/targets/cursor-mcp.ts +2 -2
  131. package/src/{install → configure/artifacts}/targets/cursor-skill.ts +2 -2
  132. package/src/{install → configure/artifacts}/targets/index.ts +1 -1
  133. package/src/{install → configure/artifacts}/targets/openclaw-mcp.ts +2 -2
  134. package/src/{install → configure/artifacts}/targets/openclaw-skill.ts +3 -3
  135. package/src/{install → configure/artifacts}/targets/opencode-mcp.ts +5 -5
  136. package/src/{install → configure/artifacts}/targets/opencode-skill.ts +3 -3
  137. package/src/{install → configure/artifacts}/targets.test.ts +1 -1
  138. package/src/{install → configure/artifacts}/uninstall.ts +1 -1
  139. package/src/configure/configure.test.ts +11 -11
  140. package/src/configure/index.ts +14 -14
  141. package/src/configure/prompt.ts +2 -2
  142. package/src/{context.ts → core/context.ts} +26 -20
  143. package/src/core/json-leaf.test.ts +156 -0
  144. package/src/{leaf-inputs.test.ts → core/leaf-inputs.test.ts} +7 -7
  145. package/src/{leaf-inputs.ts → core/leaf-inputs.ts} +76 -16
  146. package/src/{parse.test.ts → core/parse.test.ts} +97 -109
  147. package/src/{parse.ts → core/parse.ts} +173 -25
  148. package/src/{schema.ts → core/schema.ts} +25 -13
  149. package/src/{types.ts → core/types.ts} +238 -35
  150. package/src/{validate.ts → core/validate.ts} +51 -29
  151. package/src/docs/builtin.ts +8 -19
  152. package/src/docs/{api-guide.test.ts → cli-guide.test.ts} +21 -21
  153. package/src/docs/{api-guide.ts → cli-guide.ts} +45 -16
  154. package/src/docs/docs.test.ts +76 -41
  155. package/src/docs/http-guide.ts +37 -34
  156. package/src/docs/mcp-guide.ts +12 -14
  157. package/src/docs/mcp-resources.test.ts +2 -3
  158. package/src/docs/mcp-resources.ts +6 -11
  159. package/src/docs/resolve.ts +22 -30
  160. package/src/docs/save.ts +3 -3
  161. package/src/exports/cli.ts +47 -0
  162. package/src/exports/headless.ts +13 -0
  163. package/src/exports/http.ts +6 -0
  164. package/src/exports/mcp.ts +6 -0
  165. package/src/{headless.test.ts → headless/routing.test.ts} +3 -3
  166. package/src/{headless.ts → headless/routing.ts} +3 -3
  167. package/src/headless/tool-call.ts +114 -46
  168. package/src/help.test.ts +152 -0
  169. package/src/help.ts +54 -18
  170. package/src/hooks/builtin.ts +20 -0
  171. package/src/hooks/run.ts +142 -0
  172. package/src/http/openapi.ts +182 -0
  173. package/src/http/readiness.ts +78 -0
  174. package/src/{api → http}/result.ts +16 -5
  175. package/src/http/routes.ts +329 -0
  176. package/src/http/server.ts +225 -0
  177. package/src/index.ts +38 -25
  178. package/src/log/ecs.test.ts +43 -0
  179. package/src/log/ecs.ts +59 -0
  180. package/src/log/emitter.ts +166 -0
  181. package/src/mcp/bundle.ts +2 -2
  182. package/src/mcp/claude.test.ts +1 -1
  183. package/src/mcp/claude.ts +4 -4
  184. package/src/{hidden-mcpb.test.ts → mcp/hidden-mcpb.test.ts} +10 -9
  185. package/src/mcp/result.ts +2 -2
  186. package/src/mcp/server.ts +54 -6
  187. package/src/mcp/tools.ts +18 -20
  188. package/src/{capabilities.ts → runtime/capabilities.ts} +11 -11
  189. package/src/{cli-errors.ts → runtime/cli-errors.ts} +4 -4
  190. package/src/{cli.ts → runtime/cli.ts} +160 -50
  191. package/src/runtime/exposure.ts +102 -0
  192. package/src/{invoke.test.ts → runtime/invoke.test.ts} +31 -7
  193. package/src/server/context.ts +25 -0
  194. package/src/server/overrides.ts +112 -0
  195. package/src/skill/generate.ts +8 -8
  196. package/src/skill/hint.ts +1 -1
  197. package/src/skill/install.ts +2 -2
  198. package/src/skill/naming.ts +1 -1
  199. package/src/{test-fixtures.ts → test/fixtures.ts} +3 -2
  200. package/src/{config.integration.test.ts → test/integration/config.test.ts} +8 -8
  201. package/src/{api.integration.test.ts → test/integration/http.test.ts} +170 -67
  202. package/src/{mcp.integration.test.ts → test/integration/mcp.test.ts} +11 -57
  203. package/docs/api-server.md +0 -141
  204. package/examples/full-example/docs/api.md +0 -511
  205. package/examples/full-example/src/commands/status/__generated__/outputSchema.json +0 -28
  206. package/examples/full-example/src/config/__generated__/configSchema.json +0 -40
  207. package/examples/full-example/src/config/__generated__/index.ts +0 -5
  208. package/examples/full-example/src/config/types.ts +0 -24
  209. package/src/api/openapi.ts +0 -117
  210. package/src/api/server.ts +0 -120
  211. package/src/builtins/api.ts +0 -38
  212. package/src/hidden.ts +0 -30
  213. package/src/install/plan.ts +0 -53
  214. /package/src/{install → configure/artifacts}/detect-installed.ts +0 -0
  215. /package/src/{install → configure/artifacts}/gh-release-update.test.ts +0 -0
  216. /package/src/{install → configure/artifacts}/mcp-codex.test.ts +0 -0
  217. /package/src/{install → configure/artifacts}/mcp-codex.ts +0 -0
  218. /package/src/{install → configure/artifacts}/mcp-openclaw.test.ts +0 -0
  219. /package/src/{install → configure/artifacts}/mcp-openclaw.ts +0 -0
  220. /package/src/{install → configure/artifacts}/normalize-uninstall.ts +0 -0
  221. /package/src/{install → configure/artifacts}/normalize.ts +0 -0
  222. /package/src/{install → configure/artifacts}/opts.ts +0 -0
  223. /package/src/{install → configure/artifacts}/shell.ts +0 -0
  224. /package/src/{formats.test.ts → core/formats.test.ts} +0 -0
  225. /package/src/{formats.ts → core/formats.ts} +0 -0
  226. /package/src/{respond.ts → core/respond.ts} +0 -0
  227. /package/src/{types.test.ts → core/types.test.ts} +0 -0
  228. /package/src/{api → http}/schema-deref.test.ts +0 -0
  229. /package/src/{api → http}/schema-deref.ts +0 -0
@@ -1,5 +1,5 @@
1
- import { resolveCapabilities } from "../capabilities.ts";
2
- import type { CliProgram } from "../types.ts";
1
+ import type { CliProgram } from "~/core/types.ts";
2
+ import { resolveCapabilities } from "~/runtime/capabilities.ts";
3
3
  import type { InstallPaths } from "./paths.ts";
4
4
  import { mcpCategoryEnabled } from "./target-effective.ts";
5
5
  import { INSTALL_TARGETS, installTargetForKey } from "./target-registry.ts";
@@ -1,9 +1,9 @@
1
1
  import type { InstallTarget } from "./target-base.ts";
2
2
  import type { SkillInstallTarget } from "./target-skill.ts";
3
3
  import type { CliInstallArtifactKey, InstallActionKind } from "./target-types.ts";
4
- import { INSTALL_TARGETS } from "./targets/index.ts";
4
+ import { INSTALL_TARGETS } from "./targets";
5
5
 
6
- export { INSTALL_TARGETS } from "./targets/index.ts";
6
+ export { INSTALL_TARGETS } from "./targets";
7
7
 
8
8
  export const INSTALL_ARTIFACT_KEYS: CliInstallArtifactKey[] = INSTALL_TARGETS.map((t) => t.key);
9
9
 
@@ -1,6 +1,6 @@
1
- import { resolveCapabilities } from "../capabilities.ts";
2
- import { appConfigFileExists } from "../config/file.ts";
3
- import type { CliConfigureTargets, CliProgram } from "../types.ts";
1
+ import { appConfigFileExists } from "~/config/file.ts";
2
+ import type { CliConfigureTargets, CliProgram } from "~/core/types.ts";
3
+ import { resolveCapabilities } from "~/runtime/capabilities.ts";
4
4
  import type { InstallPaths } from "./paths.ts";
5
5
  import {
6
6
  type InstallPlanMode,
@@ -1,5 +1,5 @@
1
1
  import { existsSync } from "node:fs";
2
- import type { CliProgram } from "../types.ts";
2
+ import type { CliProgram } from "~/core/types.ts";
3
3
  import { displayInstallPath, type InstallPaths } from "./paths.ts";
4
4
  import { InstallTarget } from "./target-base.ts";
5
5
  import type {
@@ -1,7 +1,7 @@
1
- import type { CliProgram } from "../types.ts";
1
+ import type { CliProgram } from "~/core/types.ts";
2
2
  import type { InstallPaths } from "./paths.ts";
3
3
 
4
- export type { InstallTargetSpec, ResolvedInstallTarget } from "../types.ts";
4
+ export type { InstallTargetSpec, ResolvedInstallTarget } from "~/core/types.ts";
5
5
 
6
6
  export type InstallPlanMode = "install-all" | "install-scoped" | "uninstall-all" | "uninstall-scoped" | "refresh";
7
7
 
@@ -1,7 +1,6 @@
1
- import type { CliProgram } from "../../types.ts";
2
- import { isExternallyManagedBinary } from "../binary-placement.ts";
3
- import type { InstallPaths } from "../paths.ts";
4
- import { InstallTarget } from "../target-base.ts";
1
+ import { isExternallyManagedBinary } from "~/configure/artifacts/binary-placement.ts";
2
+ import type { InstallPaths } from "~/configure/artifacts/paths.ts";
3
+ import { InstallTarget } from "~/configure/artifacts/target-base.ts";
5
4
  import type {
6
5
  DetectedSnapshot,
7
6
  InstallAction,
@@ -9,7 +8,8 @@ import type {
9
8
  InstallStatus,
10
9
  TargetPlanContext,
11
10
  UninstallAction,
12
- } from "../target-types.ts";
11
+ } from "~/configure/artifacts/target-types.ts";
12
+ import type { CliProgram } from "~/core/types.ts";
13
13
 
14
14
  /** Reports app install location (Homebrew PATH or legacy ~/.local/bin). No self-install actions. */
15
15
  class AppInstallTarget extends InstallTarget {
@@ -1,5 +1,5 @@
1
- import { chatGptDesktopPresent, userHome } from "../paths.ts";
2
- import { McpJsonInstallTarget } from "../target-mcp-json.ts";
1
+ import { chatGptDesktopPresent, userHome } from "~/configure/artifacts/paths.ts";
2
+ import { McpJsonInstallTarget } from "~/configure/artifacts/target-mcp-json.ts";
3
3
 
4
4
  export const chatgptMcpTarget = new McpJsonInstallTarget({
5
5
  key: "chatgptMcp",
@@ -1,7 +1,7 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { join } from "node:path";
3
- import { userHome } from "../paths.ts";
4
- import { McpJsonInstallTarget } from "../target-mcp-json.ts";
3
+ import { userHome } from "~/configure/artifacts/paths.ts";
4
+ import { McpJsonInstallTarget } from "~/configure/artifacts/target-mcp-json.ts";
5
5
 
6
6
  export const claudeCodeMcpTarget = new McpJsonInstallTarget({
7
7
  key: "claudeCodeMcp",
@@ -1,5 +1,5 @@
1
- import { claudeDesktopPresent, userHome } from "../paths.ts";
2
- import { McpJsonInstallTarget } from "../target-mcp-json.ts";
1
+ import { claudeDesktopPresent, userHome } from "~/configure/artifacts/paths.ts";
2
+ import { McpJsonInstallTarget } from "~/configure/artifacts/target-mcp-json.ts";
3
3
 
4
4
  export const claudeDesktopMcpTarget = new McpJsonInstallTarget({
5
5
  key: "claudeDesktopMcp",
@@ -1,7 +1,7 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { join } from "node:path";
3
- import { userHome } from "../paths.ts";
4
- import { SkillInstallTarget } from "../target-skill.ts";
3
+ import { userHome } from "~/configure/artifacts/paths.ts";
4
+ import { SkillInstallTarget } from "~/configure/artifacts/target-skill.ts";
5
5
 
6
6
  export const claudeSkillTarget = new SkillInstallTarget({
7
7
  key: "claudeSkill",
@@ -1,11 +1,11 @@
1
- import { codexOnPath } from "../mcp-codex.ts";
1
+ import { codexOnPath } from "~/configure/artifacts/mcp-codex.ts";
2
2
  import {
3
3
  checkCodexMcpConflict,
4
4
  codexMcpHasServer,
5
5
  McpCliInstallTarget,
6
6
  mergeCodexMcpConfig,
7
7
  removeCodexMcpConfig,
8
- } from "../target-mcp-cli.ts";
8
+ } from "~/configure/artifacts/target-mcp-cli.ts";
9
9
 
10
10
  export const codexMcpTarget = new McpCliInstallTarget({
11
11
  key: "codexMcp",
@@ -1,5 +1,5 @@
1
- import { codexOnPath } from "../mcp-codex.ts";
2
- import { SkillInstallTarget } from "../target-skill.ts";
1
+ import { codexOnPath } from "~/configure/artifacts/mcp-codex.ts";
2
+ import { SkillInstallTarget } from "~/configure/artifacts/target-skill.ts";
3
3
 
4
4
  export const codexSkillTarget = new SkillInstallTarget({
5
5
  key: "codexSkill",
@@ -1,7 +1,6 @@
1
- import { appConfigInstalled, displayAppConfigPath, uninstallAppConfig } from "../../config/file.ts";
2
- import type { CliProgram, InstallAgentIntegration } from "../../types.ts";
3
- import type { InstallPaths } from "../paths.ts";
4
- import { InstallTarget } from "../target-base.ts";
1
+ import { appConfigInstalled, displayAppConfigPath, uninstallAppConfig } from "~/config/file.ts";
2
+ import type { InstallPaths } from "~/configure/artifacts/paths.ts";
3
+ import { InstallTarget } from "~/configure/artifacts/target-base.ts";
5
4
  import type {
6
5
  DetectedSnapshot,
7
6
  InstallAction,
@@ -9,7 +8,8 @@ import type {
9
8
  InstallStatus,
10
9
  TargetPlanContext,
11
10
  UninstallAction,
12
- } from "../target-types.ts";
11
+ } from "~/configure/artifacts/target-types.ts";
12
+ import type { CliProgram, InstallAgentIntegration } from "~/core/types.ts";
13
13
 
14
14
  /** App config file (interactive configure / wizard). */
15
15
  class ConfigureInstallTarget extends InstallTarget {
@@ -1,7 +1,7 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { join } from "node:path";
3
- import { userHome } from "../paths.ts";
4
- import { McpJsonInstallTarget } from "../target-mcp-json.ts";
3
+ import { userHome } from "~/configure/artifacts/paths.ts";
4
+ import { McpJsonInstallTarget } from "~/configure/artifacts/target-mcp-json.ts";
5
5
 
6
6
  export const cursorMcpTarget = new McpJsonInstallTarget({
7
7
  key: "cursorMcp",
@@ -1,7 +1,7 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { join } from "node:path";
3
- import { userHome } from "../paths.ts";
4
- import { SkillInstallTarget } from "../target-skill.ts";
3
+ import { userHome } from "~/configure/artifacts/paths.ts";
4
+ import { SkillInstallTarget } from "~/configure/artifacts/target-skill.ts";
5
5
 
6
6
  export const cursorSkillTarget = new SkillInstallTarget({
7
7
  key: "cursorSkill",
@@ -1,4 +1,4 @@
1
- import type { InstallTarget } from "../target-base.ts";
1
+ import type { InstallTarget } from "~/configure/artifacts/target-base.ts";
2
2
  import { appTarget } from "./app.ts";
3
3
  import { chatgptMcpTarget } from "./chatgpt-mcp.ts";
4
4
  import { claudeCodeMcpTarget } from "./claude-code-mcp.ts";
@@ -1,11 +1,11 @@
1
- import { openclawOnPath } from "../mcp-openclaw.ts";
1
+ import { openclawOnPath } from "~/configure/artifacts/mcp-openclaw.ts";
2
2
  import {
3
3
  checkOpenclawMcpConflict,
4
4
  McpCliInstallTarget,
5
5
  mergeOpenclawMcpConfig,
6
6
  openclawMcpHasServer,
7
7
  removeOpenclawMcpConfig,
8
- } from "../target-mcp-cli.ts";
8
+ } from "~/configure/artifacts/target-mcp-cli.ts";
9
9
 
10
10
  export const openclawMcpTarget = new McpCliInstallTarget({
11
11
  key: "openclawMcp",
@@ -1,8 +1,8 @@
1
1
  import { existsSync } from "node:fs";
2
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";
3
+ import { openclawOnPath } from "~/configure/artifacts/mcp-openclaw.ts";
4
+ import { userHome } from "~/configure/artifacts/paths.ts";
5
+ import { SkillInstallTarget } from "~/configure/artifacts/target-skill.ts";
6
6
 
7
7
  export const openclawSkillTarget = new SkillInstallTarget({
8
8
  key: "openclawSkill",
@@ -1,4 +1,3 @@
1
- import type { CliProgram } from "../../types.ts";
2
1
  import {
3
2
  checkOpenCodeMcpConflict,
4
3
  detectOpenCodeMcpConfigPath,
@@ -6,9 +5,9 @@ import {
6
5
  mergeOpenCodeMcpConfig,
7
6
  opencodePresent,
8
7
  removeOpenCodeMcpConfig,
9
- } from "../mcp-opencode.ts";
10
- import { displayInstallPath, type InstallPaths, userHome } from "../paths.ts";
11
- import { InstallTarget } from "../target-base.ts";
8
+ } from "~/configure/artifacts/mcp-opencode.ts";
9
+ import { displayInstallPath, type InstallPaths, userHome } from "~/configure/artifacts/paths.ts";
10
+ import { InstallTarget } from "~/configure/artifacts/target-base.ts";
12
11
  import type {
13
12
  DetectedSnapshot,
14
13
  InstallAction,
@@ -16,7 +15,8 @@ import type {
16
15
  InstallStatus,
17
16
  TargetPlanContext,
18
17
  UninstallAction,
19
- } from "../target-types.ts";
18
+ } from "~/configure/artifacts/target-types.ts";
19
+ import type { CliProgram } from "~/core/types.ts";
20
20
 
21
21
  function resolveConfigPath(paths: InstallPaths, home: string): string {
22
22
  return detectOpenCodeMcpConfigPath(home, paths.mcpName) ?? paths.opencodeMcpPath;
@@ -1,6 +1,6 @@
1
- import { opencodePresent } from "../mcp-opencode.ts";
2
- import { userHome } from "../paths.ts";
3
- import { SkillInstallTarget } from "../target-skill.ts";
1
+ import { opencodePresent } from "~/configure/artifacts/mcp-opencode.ts";
2
+ import { userHome } from "~/configure/artifacts/paths.ts";
3
+ import { SkillInstallTarget } from "~/configure/artifacts/target-skill.ts";
4
4
 
5
5
  export const opencodeSkillTarget = new SkillInstallTarget({
6
6
  key: "opencodeSkill",
@@ -3,7 +3,7 @@ Tests for install/targets module behavior.
3
3
  */
4
4
 
5
5
  import { describe, expect, test } from "bun:test";
6
- import type { CliProgram } from "../types.ts";
6
+ import type { CliProgram } from "~/core/types.ts";
7
7
  import { normalizeInstallRawOpts } from "./normalize.ts";
8
8
  import { normalizeUninstallRawOpts } from "./normalize-uninstall.ts";
9
9
  import { resolveAgentIntegration, resolveEffectiveInstallTargets } from "./target-effective.ts";
@@ -1,5 +1,5 @@
1
1
  import { existsSync, rmSync } from "node:fs";
2
- import type { CliProgram } from "../types.ts";
2
+ import type { CliProgram } from "~/core/types.ts";
3
3
  import type { InstallPaths } from "./paths.ts";
4
4
  import { buildUninstallPlanFromTargets } from "./target-plan-build.ts";
5
5
  import { skillTargetForUninstallSummary } from "./target-registry.ts";
@@ -6,22 +6,22 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
6
6
  import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
7
7
  import { tmpdir } from "node:os";
8
8
  import { join } from "node:path";
9
- import { appConfigFileExists } from "../config/file.ts";
9
+ import { appConfigFileExists } from "~/config/file.ts";
10
10
  import {
11
11
  appConfigHasEntries,
12
12
  formatConfigureMutationSummary,
13
13
  parseConfigureOpts,
14
14
  validateConfigureOpts,
15
- } from "../configure/index.ts";
16
- import { Cli } from "../index.ts";
17
- import { detectInstalledArtifacts } from "../install/detect-installed.ts";
18
- import { parseInstallOpts } from "../install/opts.ts";
19
- import { resolveClaudeDesktopMcpPath, resolveInstallPaths } from "../install/paths.ts";
20
- import { buildInstallPlan, buildUpdatePlan } from "../install/plan.ts";
21
- import { installTargetForKey } from "../install/target-registry.ts";
22
- import { buildDetectedSnapshot, buildTargetPlanContext } from "../install/target-scope.ts";
23
- import { buildUninstallPlan } from "../install/uninstall.ts";
24
- import type { CliProgram } from "../types.ts";
15
+ } from "~/configure";
16
+ import type { CliProgram } from "~/core/types.ts";
17
+ import { Cli } from "~/index";
18
+ import { detectInstalledArtifacts } from "./artifacts/detect-installed.ts";
19
+ import { parseInstallOpts } from "./artifacts/opts.ts";
20
+ import { resolveClaudeDesktopMcpPath, resolveInstallPaths } from "./artifacts/paths.ts";
21
+ import { buildInstallPlan, buildUpdatePlan } from "./artifacts/plan.ts";
22
+ import { installTargetForKey } from "./artifacts/target-registry.ts";
23
+ import { buildDetectedSnapshot, buildTargetPlanContext } from "./artifacts/target-scope.ts";
24
+ import { buildUninstallPlan } from "./artifacts/uninstall.ts";
25
25
 
26
26
  const fixture: CliProgram = {
27
27
  key: "testapp",
@@ -2,22 +2,24 @@
2
2
  Interactive and automated `configure` command orchestration (agent artifacts and app config).
3
3
  */
4
4
 
5
- import { resolveCapabilities } from "../capabilities.ts";
6
- import { displayAppConfigPath, runConfigure } from "../config/bootstrap.ts";
7
- import { ensureAppConfigFile } from "../config/file.ts";
8
- import { resolveInstallPaths } from "../install/paths.ts";
9
- import { buildInstallPlan, buildUpdatePlan } from "../install/plan.ts";
5
+ import { displayAppConfigPath, runConfigure } from "~/config/bootstrap.ts";
6
+ import { ensureAppConfigFile } from "~/config/file.ts";
7
+ import type { CliProgram } from "~/core/types.ts";
8
+ import { resolveCapabilities } from "~/runtime/capabilities.ts";
9
+ import { cliSkillInstall, skillTargetFromActionKind } from "~/skill/install.ts";
10
+ import { resolveInstallPaths } from "./artifacts/paths.ts";
11
+ import { buildInstallPlan, buildUpdatePlan } from "./artifacts/plan.ts";
10
12
  import {
11
13
  installErr,
12
14
  installInfo,
13
15
  installOut,
14
16
  printInstallStatus,
15
17
  writeInteractiveInstallIntro,
16
- } from "../install/status.ts";
17
- import { resolveEffectiveInstallTargets } from "../install/target-effective.ts";
18
- import { runTargetPreflight } from "../install/target-plan-build.ts";
19
- import { INSTALL_TARGETS, installTargetForKey } from "../install/target-registry.ts";
20
- import { buildDetectedSnapshot, buildTargetPlanContext } from "../install/target-scope.ts";
18
+ } from "./artifacts/status.ts";
19
+ import { resolveEffectiveInstallTargets } from "./artifacts/target-effective.ts";
20
+ import { runTargetPreflight } from "./artifacts/target-plan-build.ts";
21
+ import { INSTALL_TARGETS, installTargetForKey } from "./artifacts/target-registry.ts";
22
+ import { buildDetectedSnapshot, buildTargetPlanContext } from "./artifacts/target-scope.ts";
21
23
  import type {
22
24
  CliInstallArtifactKey,
23
25
  InstallAction,
@@ -25,10 +27,8 @@ import type {
25
27
  InstallOpts,
26
28
  TargetPlanContext,
27
29
  UninstallAction,
28
- } from "../install/target-types.ts";
29
- import { buildUninstallPlan, skillDirFromUninstallSummary, uninstallSkillDir } from "../install/uninstall.ts";
30
- import { cliSkillInstall, skillTargetFromActionKind } from "../skill/install.ts";
31
- import type { CliProgram } from "../types.ts";
30
+ } from "./artifacts/target-types.ts";
31
+ import { buildUninstallPlan, skillDirFromUninstallSummary, uninstallSkillDir } from "./artifacts/uninstall.ts";
32
32
  import { artifactPromptLabel, promptTargetAction } from "./prompt.ts";
33
33
 
34
34
  /** True when interactive `configure` should auto-run the app config wizard. */
@@ -2,8 +2,8 @@
2
2
  TTY prompts for per-target install, skip, or uninstall during interactive `configure`.
3
3
  */
4
4
 
5
- import type { CliInstallArtifactKey } from "../install/target-types.ts";
6
- import { readPromptLine } from "../prompt.ts";
5
+ import { readPromptLine } from "~/prompt.ts";
6
+ import type { CliInstallArtifactKey } from "./artifacts/target-types.ts";
7
7
 
8
8
  /** Human-readable labels for each install artifact key in interactive prompts. */
9
9
  const LABELS: Record<CliInstallArtifactKey, string> = {
@@ -7,14 +7,22 @@ It keeps handlers small with a typed read API for flags, strings, numbers, and c
7
7
  parsed values.
8
8
  */
9
9
 
10
- import type { AnyAppConfigSnapshot } from "./config/context.ts";
11
- import { EmptyAppConfigSnapshot } from "./config/context.ts";
10
+ import type { AnyAppConfigSnapshot } from "~/config/context.ts";
11
+ import { EmptyAppConfigSnapshot } from "~/config/context.ts";
12
+ import { strictParseDouble } from "~/utils.ts";
12
13
  import { parseCommaList, parseDate, parseDateTime, parseDurationMs } from "./formats.ts";
13
14
  import { loadLeafInputs, readJsonOptionValue } from "./leaf-inputs.ts";
14
15
  import { normalizeRespondOptions, writeRespondBodyToStdout } from "./respond.ts";
15
- import type { CliInvocation, CliLeaf, CliNode, CliProgram, CliRespondOptions } from "./types.ts";
16
+ import type {
17
+ CliInvocation,
18
+ CliLeaf,
19
+ CliLocals,
20
+ CliNode,
21
+ CliProgram,
22
+ CliRespondOptions,
23
+ ServerRuntime,
24
+ } from "./types.ts";
16
25
  import { isCliLeaf, isCliRouter } from "./types.ts";
17
- import { strictParseDouble } from "./utils.ts";
18
26
 
19
27
  /** Coerced leaf inputs keyed by option and positional names. */
20
28
  export type CliLeafInputs = Record<string, boolean | number | string | string[] | unknown | undefined>;
@@ -25,15 +33,21 @@ export type CliLeafInputs = Record<string, boolean | number | string | string[]
25
33
  export class CliContext {
26
34
  readonly appName: string;
27
35
  readonly commandPath: string[];
28
- readonly args: string[];
36
+ args: string[];
29
37
  readonly program: CliProgram;
30
- readonly opts: Record<string, string>;
38
+ opts: Record<string, string>;
31
39
  readonly invocation: CliInvocation;
32
40
  readonly appConfig: AnyAppConfigSnapshot;
33
41
  /** Original flat tool arguments for API/MCP invocations (when provided). */
34
42
  readonly toolArgs?: Record<string, unknown>;
43
+ /** Path parameter values from `:param` router descent. */
44
+ readonly pathParams: Record<string, string>;
35
45
  /** Pipable Json option values read from stdin before the handler (CLI only). */
36
46
  readonly preloadedJson: Record<string, unknown>;
47
+ /** Per-invocation bag; `beforeInvoke` may write. */
48
+ readonly locals: CliLocals;
49
+ /** Shared server state for HTTP/MCP invocations. */
50
+ runtime?: ServerRuntime;
37
51
 
38
52
  private response?: CliRespondOptions;
39
53
  private leafInputsCache?: CliLeafInputs;
@@ -49,6 +63,9 @@ export class CliContext {
49
63
  appConfig: AnyAppConfigSnapshot = new EmptyAppConfigSnapshot(program),
50
64
  toolArgs?: Record<string, unknown>,
51
65
  preloadedJson: Record<string, unknown> = {},
66
+ pathParams: Record<string, string> = {},
67
+ locals: CliLocals = {} as CliLocals,
68
+ runtime?: ServerRuntime,
52
69
  ) {
53
70
  this.appName = appName;
54
71
  this.commandPath = commandPath;
@@ -59,6 +76,9 @@ export class CliContext {
59
76
  this.appConfig = appConfig;
60
77
  this.toolArgs = toolArgs;
61
78
  this.preloadedJson = preloadedJson;
79
+ this.pathParams = pathParams;
80
+ this.locals = locals;
81
+ this.runtime = runtime;
62
82
  }
63
83
 
64
84
  /**
@@ -173,20 +193,6 @@ export class CliContext {
173
193
  return this.inputs as T;
174
194
  }
175
195
 
176
- /**
177
- * @deprecated Use {@link inputs} or {@link inputsAs}.
178
- */
179
- readLeafInputs(): CliLeafInputs {
180
- return this.inputs;
181
- }
182
-
183
- /**
184
- * @deprecated Use sync {@link readLeafInputs} — stdin is preloaded before the handler runs.
185
- */
186
- readLeafInputsAsync(): Promise<CliLeafInputs> {
187
- return Promise.resolve(this.readLeafInputs());
188
- }
189
-
190
196
  private _leafNode(): CliLeaf | undefined {
191
197
  let node: CliNode = this.program;
192
198
  for (const seg of this.commandPath) {
@@ -0,0 +1,156 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { Cli } from "~/index";
3
+ import { ParseKind, parse } from "./parse.ts";
4
+ import { CliOptionKind, type CliProgram, CliSchemaValidationError } from "./types.ts";
5
+ import { cliValidateProgram } from "./validate.ts";
6
+
7
+ const bodySchema = {
8
+ type: "object",
9
+ properties: {
10
+ format: { type: "string", enum: ["pdf", "html"] },
11
+ invoice: {
12
+ type: "object",
13
+ properties: { id: { type: "string" } },
14
+ required: ["id"],
15
+ additionalProperties: false,
16
+ },
17
+ },
18
+ required: ["format", "invoice"],
19
+ additionalProperties: false,
20
+ } as const;
21
+
22
+ function jsonLeafProgram() {
23
+ return {
24
+ key: "json-leaf-test",
25
+ version: "1.0.0",
26
+ description: "json leaf tests",
27
+ commands: [
28
+ {
29
+ key: "render",
30
+ description: "Render from JSON body",
31
+ kind: "json",
32
+ inputSchema: bodySchema,
33
+ handler: (ctx) => ctx.inputsAs<{ format: string; invoice: { id: string } }>(),
34
+ },
35
+ ],
36
+ } satisfies CliProgram;
37
+ }
38
+
39
+ describe("kind: json leaf", () => {
40
+ test("validate requires inputSchema and forbids options/positionals", () => {
41
+ expect(() =>
42
+ cliValidateProgram({
43
+ key: "bad",
44
+ version: "1",
45
+ description: "bad",
46
+ commands: [{ key: "x", description: "x", kind: "json", handler: () => {} }],
47
+ }),
48
+ ).toThrow(CliSchemaValidationError);
49
+
50
+ expect(() =>
51
+ cliValidateProgram({
52
+ key: "bad",
53
+ version: "1",
54
+ description: "bad",
55
+ commands: [
56
+ {
57
+ key: "x",
58
+ description: "x",
59
+ kind: "json",
60
+ inputSchema: bodySchema,
61
+ options: [{ name: "f", description: "f", kind: CliOptionKind.String }],
62
+ handler: () => {},
63
+ },
64
+ ],
65
+ }),
66
+ ).toThrow(CliSchemaValidationError);
67
+
68
+ expect(() =>
69
+ cliValidateProgram({
70
+ key: "bad",
71
+ version: "1",
72
+ description: "bad",
73
+ commands: [
74
+ {
75
+ key: "x",
76
+ description: "x",
77
+ kind: "json",
78
+ inputSchema: bodySchema,
79
+ positionals: [{ name: "file", description: "file", kind: CliOptionKind.String }],
80
+ handler: () => {},
81
+ },
82
+ ],
83
+ }),
84
+ ).toThrow(CliSchemaValidationError);
85
+ });
86
+
87
+ test("parse rejects CLI flags on json leaf", () => {
88
+ const root = jsonLeafProgram();
89
+ const pr = parse(root, ["render", "--format", "pdf"]);
90
+ expect(pr.kind).toBe(ParseKind.Error);
91
+ expect(pr.errorMsg).toContain("JSON commands do not accept options");
92
+ });
93
+
94
+ test("parse accepts JSON positional", () => {
95
+ const root = jsonLeafProgram();
96
+ const pr = parse(root, ["render", '{"format":"pdf","invoice":{"id":"1"}}']);
97
+ expect(pr.kind).toBe(ParseKind.Ok);
98
+ expect(pr.args).toEqual(['{"format":"pdf","invoice":{"id":"1"}}']);
99
+ });
100
+
101
+ test("invoke reads body from toolArgs", async () => {
102
+ const cli = new Cli(jsonLeafProgram());
103
+ const result = await cli.invoke(["render"], {
104
+ invocation: "http",
105
+ toolArgs: { format: "pdf", invoice: { id: "INV-1" } },
106
+ });
107
+ expect(result.kind).toBe("ok");
108
+ expect(result.response?.body).toEqual({ format: "pdf", invoice: { id: "INV-1" } });
109
+ });
110
+
111
+ test("invoke reads body from JSON positional argv", async () => {
112
+ const cli = new Cli(jsonLeafProgram());
113
+ const result = await cli.invoke(["render", '{"format":"html","invoice":{"id":"2"}}'], {
114
+ invocation: "mcp",
115
+ });
116
+ expect(result.kind).toBe("ok");
117
+ expect(result.response?.body).toEqual({ format: "html", invoice: { id: "2" } });
118
+ });
119
+
120
+ test("invoke errors when body missing", async () => {
121
+ const cli = new Cli(jsonLeafProgram());
122
+ const result = await cli.invoke(["render"], { invocation: "http" });
123
+ expect(result.kind).toBe("error");
124
+ expect(result.errorMsg).toContain("Missing JSON input");
125
+ });
126
+
127
+ test("invoke validates inputSchema before handler", async () => {
128
+ let called = false;
129
+ const base = jsonLeafProgram();
130
+ const program = {
131
+ ...base,
132
+ commands: [
133
+ {
134
+ ...base.commands[0],
135
+ handler: () => {
136
+ called = true;
137
+ },
138
+ },
139
+ ],
140
+ } satisfies CliProgram;
141
+ const cli = new Cli(program);
142
+ const result = await cli.invoke(["render"], {
143
+ invocation: "http",
144
+ toolArgs: { format: "pdf", invoice: { id: 123 } },
145
+ });
146
+ expect(result.kind).toBe("error");
147
+ expect(called).toBe(false);
148
+ });
149
+
150
+ test("non-object JSON body returns error", async () => {
151
+ const cli = new Cli(jsonLeafProgram());
152
+ const result = await cli.invoke(["render", '"not-an-object"'], { invocation: "cli" });
153
+ expect(result.kind).toBe("error");
154
+ expect(result.errorMsg).toContain("JSON input must be a JSON object");
155
+ });
156
+ });