argsbarg 5.1.16 → 6.0.1

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 (73) hide show
  1. package/CHANGELOG.md +46 -1
  2. package/README.md +33 -25
  3. package/docs/README.md +2 -1
  4. package/docs/api-server.md +141 -0
  5. package/docs/bundled-docs.md +24 -10
  6. package/docs/cli-program.md +17 -2
  7. package/docs/config-schema.md +18 -8
  8. package/docs/developing.md +1 -1
  9. package/docs/mcp.md +5 -5
  10. package/docs/output-schema.md +78 -47
  11. package/examples/full-example/README.md +15 -6
  12. package/examples/full-example/docs/README.md +27 -0
  13. package/examples/full-example/docs/api.md +511 -0
  14. package/examples/full-example/docs/cli-schema.json +453 -0
  15. package/examples/full-example/docs/http.md +81 -0
  16. package/examples/full-example/docs/mcp.md +159 -0
  17. package/examples/full-example/docs/openapi.json +222 -0
  18. package/examples/full-example/docs/skill.md +46 -0
  19. package/examples/full-example/justfile +6 -2
  20. package/examples/full-example/schemas/generated/app-config.json +1 -1
  21. package/examples/full-example/schemas/generated/status.json +1 -1
  22. package/examples/full-example/scripts/dev-formula.ts +1 -1
  23. package/examples/full-example/scripts/schemagen/discover-schema-roots.test.ts +3 -3
  24. package/examples/full-example/scripts/schemagen/discover-schema-roots.ts +90 -35
  25. package/examples/full-example/scripts/schemagen/naming.ts +17 -0
  26. package/examples/full-example/scripts/schemagen.ts +14 -3
  27. package/examples/full-example/src/commands/echo/command.ts +6 -1
  28. package/examples/full-example/src/commands/status/schema-types.ts +14 -0
  29. package/examples/full-example/src/commands/status/types.ts +1 -11
  30. package/examples/full-example/src/{types.ts → config/schema-types.ts} +3 -2
  31. package/examples/full-example/src/program.ts +3 -0
  32. package/examples/mcp-test.ts +13 -2
  33. package/examples/nested.ts +12 -3
  34. package/examples/servers.ts +72 -0
  35. package/index.d.ts +66 -7
  36. package/package.json +17 -17
  37. package/src/api/openapi.ts +117 -0
  38. package/src/api/result.ts +111 -0
  39. package/src/api/schema-deref.test.ts +99 -0
  40. package/src/api/schema-deref.ts +76 -0
  41. package/src/api/server.ts +120 -0
  42. package/src/api.integration.test.ts +441 -0
  43. package/src/builtins/api.ts +38 -0
  44. package/src/builtins/dispatch.ts +26 -0
  45. package/src/builtins/registry.ts +4 -0
  46. package/src/capabilities.ts +12 -1
  47. package/src/cli-errors.ts +3 -0
  48. package/src/cli-tool/full-example-capabilities.test.ts +3 -0
  49. package/src/cli.ts +60 -8
  50. package/src/config.integration.test.ts +22 -4
  51. package/src/context.ts +29 -1
  52. package/src/docs/api-guide.ts +2 -2
  53. package/src/docs/builtin.ts +11 -1
  54. package/src/docs/docs.test.ts +70 -12
  55. package/src/docs/http-guide.ts +132 -0
  56. package/src/docs/mcp-guide.ts +3 -3
  57. package/src/docs/mcp-resources.ts +5 -2
  58. package/src/docs/resolve.ts +26 -2
  59. package/src/docs/save.ts +5 -2
  60. package/src/headless/tool-call.ts +157 -0
  61. package/src/headless.test.ts +4 -2
  62. package/src/headless.ts +10 -5
  63. package/src/index.ts +5 -0
  64. package/src/mcp/result.ts +39 -34
  65. package/src/mcp/server.ts +18 -36
  66. package/src/mcp/tools.ts +14 -3
  67. package/src/mcp.integration.test.ts +46 -39
  68. package/src/parse.test.ts +16 -6
  69. package/src/respond.ts +48 -0
  70. package/src/schema.ts +1 -1
  71. package/src/skill/generate.ts +1 -1
  72. package/src/types.ts +46 -4
  73. package/src/validate.ts +7 -0
package/CHANGELOG.md CHANGED
@@ -7,6 +7,49 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [6.0.1] - 2026-07-22
11
+
12
+ ### Added
13
+
14
+ - **OpenAPI schema dereferencing** — inline internal `$ref` pointers when building OpenAPI documents so API reference UIs show nested request shapes.
15
+
16
+ ### Changed
17
+
18
+ - **Schemagen discovery contract** — `examples/full-example` and docs now use `src/**/schema-types.ts` with `export type configType` / `outputType` / `inputType` instead of JSDoc markers (`Config schema`, `JSON payload`, `Tool input`) on `types.ts`.
19
+ - **HTTP tool errors** — return a plain `{ "error": "..." }` JSON body without ANSI color codes or appended CLI help text.
20
+ - **`cliErrWithHelp`** — on `api` / `mcp` invocations, throws a plain error instead of printing contextual help.
21
+ - **`GET /openapi-browser`** — Scalar config preserves schema property order from the OpenAPI document (`orderSchemaPropertiesBy: "preserve"`).
22
+
23
+ ## [6.0.0] - 2026-07-22
24
+
25
+ ### Added
26
+
27
+ - **`apiServer`** — opt-in HTTP tool server (`myapp api`). Exposes leaf commands over `GET /health`, `GET /openapi.json`, `GET /openapi-browser`, and `POST /tools/:name`. Defaults to `127.0.0.1:3000`. Independent of `mcpServer`.
28
+ - **`ctx.respond()`** — set machine-readable responses for API/MCP; polymorphic CLI stdout printing.
29
+ - **Implicit handler return values** — non-undefined return values become JSON responses for headless invocations.
30
+ - **`apiResponse`** leaf metadata — default HTTP `Content-Type` and `Content-Disposition`.
31
+ - **`generateOpenApi(program)`** — hand-built OpenAPI 3.1 document; served at `GET /openapi.json`.
32
+ - **`GET /openapi-browser`** — Scalar API reference UI (CDN). Replaces `GET /docs`.
33
+ - **`ctx.toolArgs`** — original flat tool JSON for API/MCP handlers with custom `inputSchema`.
34
+ - **Wide-open CORS** — `Access-Control-Allow-Origin: *` on all API responses.
35
+ - **`docs http`** — auto-generated HTTP API guide when `docs` and `apiServer` are both enabled.
36
+ - **`docs openapi`** — print OpenAPI 3.1 JSON (`myapp docs openapi`); save with `--save` to `./docs/openapi.json` when `apiServer` is enabled.
37
+ - **`Cli.invoke(argv, { invocation, toolArgs })`** — optional invocation source (`"mcp"` default, `"api"` for HTTP).
38
+ - **`ctx.invocation === "api"`** — headless helpers treat API like MCP.
39
+
40
+ ### Changed
41
+
42
+ - **HTTP success responses** — raw body (JSON/HTML/PDF bytes); no `{ ok, stdout, stderr }` envelope.
43
+ - **MCP/API tool handlers** — must `ctx.respond()` or return a value; stdout is not part of success payloads.
44
+ - **MCP binary** — `Uint8Array` responses encoded as base64 in `structuredContent`.
45
+ - **Removed `POST /tools`** — MCP-shaped invoke endpoint; use `POST /tools/:name` only.
46
+ - **HTTP API tool names** — hyphen-joined command paths (e.g. `render-invoice`, `stat-owner-lookup`); MCP keeps underscore-sanitized names (`render_invoice`, `stat_owner_lookup`).
47
+ - **Removed `GET /docs`** — use **`GET /openapi-browser`** for the Scalar API reference UI.
48
+ - **Removed `GET /schema`** from the HTTP API — use `myapp docs cli-schema`, MCP `://schema`, or `GET /openapi.json` / `docs openapi` instead.
49
+ - **Removed `GET /tools`** from the HTTP API — use `GET /openapi.json` for tool discovery.
50
+ - **Renamed `docs schema` → `docs cli-schema`** — saved file is `./docs/cli-schema.json` (disambiguates CLI tree JSON from OpenAPI and JSON Schema artifacts).
51
+ - **Custom `inputSchema`** on leaves is used for MCP/HTTP tool metadata when set.
52
+
10
53
  ## [5.1.16] - 2026-07-07
11
54
 
12
55
 
@@ -685,7 +728,9 @@ const cli = { ... } satisfies CliProgram; // or : CliProgram
685
728
  - Migrate schemas: rename every `children` property to **`commands`**; move positional definitions to **`CliPositional`** objects on `positionals` and strip `positional` / `argMin` / `argMax` from flag definitions under `options` (flags only carry `name`, `description`, `kind`, and optional `shortName`).
686
729
  - Imports: use `CliPositional` where needed; replace `CliOptionDef` with `CliOption` or `CliPositional` as appropriate.
687
730
 
688
- [Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v5.1.16...HEAD
731
+ [Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v6.0.1...HEAD
732
+ [6.0.1]: https://github.com/bdombro/bun-argsbarg/releases/tag/v6.0.1
733
+ [6.0.0]: https://github.com/bdombro/bun-argsbarg/releases/tag/v6.0.0
689
734
  [5.1.16]: https://github.com/bdombro/bun-argsbarg/releases/tag/v5.1.16
690
735
  [5.1.15]: https://github.com/bdombro/bun-argsbarg/releases/tag/v5.1.15
691
736
  [5.1.14]: https://github.com/bdombro/bun-argsbarg/releases/tag/v5.1.14
package/README.md CHANGED
@@ -1,13 +1,11 @@
1
1
  Logo
2
2
 
3
-
4
-
5
3
  [GitHub](https://github.com/bdombro/bun-argsbarg)
6
4
  [License: MIT](LICENSE)
7
5
  [npm version](https://www.npmjs.com/package/argsbarg)
8
6
  [Bun](https://bun.sh)
9
7
 
10
- Build beautiful, well-behaved CLI+MCP apps with Bun — **no third-party runtime dependencies**.
8
+ Build beautiful, well-behaved CLI+MCP+HTTP apps with Bun — **no third-party runtime dependencies**.
11
9
 
12
10
  Why another CLI parser?
13
11
 
@@ -97,19 +95,27 @@ Every app gets:
97
95
  - `completion bash` **/** `completion zsh` **/** `completion fish` — print shell completion scripts to stdout (injected by `Cli.run()`).
98
96
  - `version` — print `CliProgram.version` (`myapp version`).
99
97
  - `mcp` — when `mcpServer.enabled` is `true`, run as an MCP stdio server (`myapp mcp`).
100
- - `docs` — when `docs.enabled` is `true`, print bundled markdown topics, schema JSON, API markdown, and generated skill content (`myapp docs`, `myapp docs readme`, `myapp docs schema`, `myapp docs api`, `myapp docs skill`, …). See [docs/bundled-docs.md](docs/bundled-docs.md).
98
+ - `api` — when `apiServer.enabled` is `true`, run as an HTTP tool server (`myapp api`).
99
+ - `docs` — when `docs.enabled` is `true`, print bundled markdown topics, schema JSON, API markdown, and generated skill content (`myapp docs`, `myapp docs readme`, `myapp docs cli-schema`, `myapp docs api`, `myapp docs skill`, …). See [docs/bundled-docs.md](docs/bundled-docs.md).
101
100
  - `configure` — manage agent skills, MCP config, and app config (`myapp configure --sync --yes` after Homebrew install). See [docs/configure.md](docs/configure.md).
102
101
 
103
102
  Do not declare a top-level command named `completion`, `version`, or `configure` — they are reserved.
104
103
  When `mcpServer.enabled` is `true`, do not declare a top-level command named `mcp` — it is reserved for the MCP built-in.
104
+ When `apiServer.enabled` is `true`, do not declare a top-level command named `api` — it is reserved for the HTTP API built-in.
105
105
  When `docs.enabled` is `true`, do not declare a top-level command named `docs` — it is reserved for the docs built-in.
106
106
 
107
107
  ### MCP (AI agents)
108
108
 
109
- Opt in on the program root with `mcpServer: { enabled: true }`, then run `myapp mcp` for a stdio MCP server. Each leaf command becomes a tool; the CLI tree is available as resource `<sanitized-key>://schema` (same as `myapp docs schema`). Handlers can read `ctx.invocation`; use `cli.invoke(argv)` for headless testing.
109
+ Opt in on the program root with `mcpServer: { enabled: true }`, then run `myapp mcp` for a stdio MCP server. Each leaf command becomes a tool; the CLI tree is available as resource `<sanitized-key>://schema` (same as `myapp docs cli-schema`). Handlers can read `ctx.invocation`; use `cli.invoke(argv)` for headless testing.
110
110
 
111
111
  See **[docs/mcp.md](docs/mcp.md)** for configuration, env bootstrapping, custom resources, Cursor setup, and protocol details. See **[docs/cli-program.md](docs/cli-program.md)** for schema authoring (consumer apps: run `bunx argsbarg create` or refresh with `bun scripts/merge-cli-program-rule.ts .` from the argsbarg package).
112
112
 
113
+ ### HTTP API
114
+
115
+ Opt in on the program root with `apiServer: { enabled: true }`, then run `myapp api` for an HTTP tool server (default `http://127.0.0.1:3000`). Same tool exposure as MCP: `POST /tools/:name` (hyphen-joined command paths). Discover tools via `GET /openapi.json`.
116
+
117
+ See **[docs/api-server.md](docs/api-server.md)** for endpoints, curl examples, and response shapes.
118
+
113
119
  ### Configure CLI
114
120
 
115
121
  Ship via **Homebrew** (tap-from-repo). The formula installs the binary and shell completions; `post_install` runs agent artifact refresh. Private taps require `gh auth login` — see [docs/distribution-homebrew.md](docs/distribution-homebrew.md#end-user-install).
@@ -161,7 +167,7 @@ Add app-specific conventions in a second rule if needed. Copy the rule from the
161
167
 
162
168
  1. Build a **program root** with `satisfies CliProgram` (or `: CliProgram`): `key` is the app name, `commands` are top-level subcommands, `options` are global flags. A router root must not set `handler` or declare `positionals` (validated at startup). A leaf root may set `handler` and `positionals` directly. Use `fallbackCommand` / `fallbackMode` on any **routing node** for default subcommand routing (not root-only).
163
169
  2. Call `await new Cli(program).run()` — validates, parses argv, renders help or errors, invokes the leaf handler, and `process.exit`s with status **0** on success, **1** on implicit help or error (explicit `--help` → **0**).
164
- 3. From a handler, `cliErrWithHelp(ctx, "message")` prints a red error line plus contextual help on stderr and exits **1**.
170
+ 3. From a handler, `cliErrWithHelp(ctx, "message")` prints a red error line plus contextual help on stderr and exits **1** (CLI only; API/MCP invocations throw a plain `Error`).
165
171
 
166
172
 
167
173
 
@@ -211,18 +217,18 @@ Add `CliPositional` entries to the command’s `positionals` list (separate from
211
217
 
212
218
  ### Capabilities (built-ins)
213
219
 
214
- `completion`, `version`, `install`, and `mcp` are not part of your schema — they are injected at runtime from program-level config (`mcpServer`, `install`, `docs`). Reserved command names: `completion` and `version` always; `install` unless `install.enabled: false`; `mcp` when `mcpServer.enabled` is `true`; `docs` when `docs.enabled` is `true`.
220
+ `completion`, `version`, `install`, `mcp`, and `api` are not part of your schema — they are injected at runtime from program-level config (`mcpServer`, `apiServer`, `install`, `docs`). Reserved command names: `completion` and `version` always; `install` unless `install.enabled: false`; `mcp` when `mcpServer.enabled` is `true`; `api` when `apiServer.enabled` is `true`; `docs` when `docs.enabled` is `true`.
215
221
 
216
222
  ## Examples
217
223
 
218
224
  Check the `examples/` directory for full working scripts:
219
225
 
220
226
 
221
- | Example | File | Shows |
222
- | --------------------- | ------------------------ | ---------------------------------------------------------------------------------------- |
223
- | `ArgsBargMinimal` | `examples/minimal.ts` | String + presence flags, `MissingOrUnknown` fallback. |
224
- | `ArgsBargNested` | `examples/nested.ts` | Nested command tree, positional tails, async handlers. |
225
- | `ArgsBargFormats` | `examples/formats.ts` | `CliValueFormat`, `default`, `readLeafInputs()`. |
227
+ | Example | File | Shows |
228
+ | --------------------- | ------------------------ | ------------------------------------------------------------------------------------------------- |
229
+ | `ArgsBargMinimal` | `examples/minimal.ts` | String + presence flags, `MissingOrUnknown` fallback. |
230
+ | `ArgsBargNested` | `examples/nested.ts` | Nested command tree, positional tails, async handlers. |
231
+ | `ArgsBargFormats` | `examples/formats.ts` | `CliValueFormat`, `default`, `readLeafInputs()`. |
226
232
  | `ArgsBargFullExample` | `examples/full-example/` | **Copy template:** all builtins, schemagen, Homebrew justfile, `outputSchema`, `from "argsbarg"`. |
227
233
 
228
234
 
@@ -257,18 +263,20 @@ To refresh the Cursor rule in an existing consumer: `bun scripts/merge-cli-progr
257
263
 
258
264
  ### What the full-example template includes
259
265
 
260
- | Area | Files / wiring |
261
- | --- | --- |
262
- | All builtins | `completion`, `version`, `configure`, `docs`, `mcp`, `configure get`/`set` |
263
- | `program.appConfig` | `src/types.ts` (`AppConfig`) → `schemas/configSchemas.ts` |
264
- | `outputSchema` | `src/commands/status/types.ts` → `schemas/outputSchemas.ts` |
265
- | Schemagen | `scripts/schemagen.ts` + `scripts/schemagen/discover-schema-roots.ts` |
266
- | Command layout | `src/commands/<name>/command.ts`; registration in `src/program.ts` |
267
- | MCP doc topics | `docs.topics` auto-exposed as `<key>://docs/<topic>` resources when docs + MCP enabled |
268
- | Package import | `from "argsbarg"` (not relative to argsbarg `src/`) |
269
- | Homebrew distribution | `scripts/formula-shared.ts`, `scripts/dev-formula.ts`, `Formula/`, `justfile` |
270
- | Dev tooling | Biome (`just format` / `just lint`), TypeScript, colocated tests |
271
- | Cursor rules | `.cursor/rules/cli-program.mdc`, `.cursor/rules/code.mdc` |
266
+
267
+ | Area | Files / wiring |
268
+ | --------------------- | -------------------------------------------------------------------------------------- |
269
+ | All builtins | `completion`, `version`, `configure`, `docs`, `mcp`, `api`, `configure get`/`set` |
270
+ | `program.appConfig` | `src/config/schema-types.ts` (`AppConfig`) → `schemas/configSchemas.ts` |
271
+ | `outputSchema` | `src/commands/status/schema-types.ts` → `schemas/outputSchemas.ts` |
272
+ | Schemagen | `scripts/schemagen.ts` + `scripts/schemagen/discover-schema-roots.ts` |
273
+ | Command layout | `src/commands/<name>/command.ts`; registration in `src/program.ts` |
274
+ | MCP doc topics | `docs.topics` auto-exposed as `<key>://docs/<topic>` resources when docs + MCP enabled |
275
+ | Package import | `from "argsbarg"` (not relative to argsbarg `src/`) |
276
+ | Homebrew distribution | `scripts/formula-shared.ts`, `scripts/dev-formula.ts`, `Formula/`, `justfile` |
277
+ | Dev tooling | Biome (`just format` / `just lint`), TypeScript, colocated tests |
278
+ | Cursor rules | `.cursor/rules/cli-program.mdc`, `.cursor/rules/code.mdc` |
279
+
272
280
 
273
281
  When changing builtins or the template, run `just check-full-example` from the argsbarg repo root.
274
282
 
@@ -310,7 +318,7 @@ The package root (`argsbarg` / `src/index.ts`) exports the types and runtime you
310
318
  | `parseDurationMs`, `parseCommaList`, `parseDate`, `parseDateTime` | Optional format parsers for use outside handlers. |
311
319
 
312
320
 
313
- Reserved identifiers (validated at startup): root commands `completion`, `version`, `install`, `docs` (when `docs.enabled` is `true`), and `mcp` (when `mcpServer.enabled` is `true`).
321
+ Reserved identifiers (validated at startup): root commands `completion`, `version`, `install`, `docs` (when `docs.enabled` is `true`), `mcp` (when `mcpServer.enabled` is `true`), and `api` (when `apiServer.enabled` is `true`).
314
322
 
315
323
  ---
316
324
 
package/docs/README.md CHANGED
@@ -9,6 +9,7 @@ Start here to pick the right guide.
9
9
  | **JSON stdout / `outputSchema`** | [output-schema.md](output-schema.md) — codegen pipeline, JSDoc, narrowing |
10
10
  | **App config / `program.appConfig`** | [config-schema.md](config-schema.md) — flat JSON file, `ctx.appConfig`, codegen |
11
11
  | **Exposing MCP tools** | [mcp.md](mcp.md) — stdio server, `inputSchema`, varargs, `configure --sync` |
12
+ | **HTTP tool server** | [api-server.md](api-server.md) — `myapp api`, endpoints, curl examples |
12
13
  | **Shipping configure / agent artifacts** | [configure.md](configure.md) — Homebrew + `myapp configure --sync` |
13
14
  | **Homebrew tap-from-repo distribution** | [distribution-homebrew.md](distribution-homebrew.md) — formula pattern, `argsbarg create` |
14
15
  | **Bundling `myapp docs` topics** | [bundled-docs.md](bundled-docs.md) — consumer docgen vs framework docs |
@@ -31,7 +32,7 @@ Examples are included in the npm tarball (`package.json` `files`). After `bun ad
31
32
  | Source | What it is | Where it lives |
32
33
  | --- | --- | --- |
33
34
  | **Framework docs** | How argsbarg works; authoring conventions | This directory — shipped in `node_modules/argsbarg/docs/` after `bun add argsbarg` |
34
- | **Consumer docgen** | *Your* command tree, API, MCP guide for *your* app | `myapp docs api`, `docs schema`, `docs mcp` — written to `./docs/` with `--save` |
35
+ | **Consumer docgen** | *Your* command tree, API, MCP guide for *your* app | `myapp docs api`, `docs cli-schema`, `docs mcp` — written to `./docs/` with `--save` |
35
36
  | **Cursor rule** | Thin tripwire telling agents to read framework docs | `node_modules/argsbarg/examples/full-example/.cursor/rules/cli-program.mdc` — included by `create`; refresh with `merge-cli-program-rule.ts` |
36
37
 
37
38
  Agents do **not** load `node_modules/argsbarg/docs/` unless your repo references them (Cursor rule, `AGENTS.md`, or an `alwaysApply` project rule). Generated `./docs/api.md` in a consumer repo describes **your** CLI, not argsbarg itself.
@@ -0,0 +1,141 @@
1
+ # HTTP API server
2
+
3
+ ArgsBarg can expose your CLI as an HTTP tool server. Each **leaf command** becomes a callable tool — the same exposure model as MCP. The server uses Bun's built-in HTTP stack and binds to **localhost by default**.
4
+
5
+ The HTTP API is **opt-in**. Apps that do not set `apiServer` on the program root behave exactly as before.
6
+
7
+ ## Quick start
8
+
9
+ 1. Add `apiServer` to your program root:
10
+
11
+ ```typescript
12
+ import pkg from "../package.json" with { type: "json" };
13
+
14
+ const cli = {
15
+ key: "myapp",
16
+ version: pkg.version,
17
+ description: "My app.",
18
+ apiServer: { enabled: true },
19
+ commands: [/* ... */],
20
+ } satisfies CliProgram;
21
+ ```
22
+
23
+ `apiServer: { enabled: true }` opts in. Omit `apiServer` entirely to disable HTTP. Empty `apiServer: {}` is rejected at validation.
24
+
25
+ 2. Run the HTTP server:
26
+
27
+ ```bash
28
+ myapp api
29
+ ```
30
+
31
+ The process listens until interrupted. Startup prints the listen URL to stderr.
32
+
33
+ ## Configuration
34
+
35
+ Set `apiServer` on the **program root only**. Validation rejects `apiServer` on nested nodes.
36
+
37
+ | Field | Default | Purpose |
38
+ | --- | --- | --- |
39
+ | `enabled` | *(required)* | Must be `true` when `apiServer` is set |
40
+ | `host` | `127.0.0.1` | Listen address |
41
+ | `port` | `3000` | Listen port |
42
+
43
+ `apiServer` and `mcpServer` are independent — enable either or both.
44
+
45
+ ## Tool names
46
+
47
+ HTTP and MCP use different tool identifiers for the same leaf command:
48
+
49
+ | CLI path | HTTP API (`POST /tools/:name`) | MCP (`tools/call`) |
50
+ | --- | --- | --- |
51
+ | `stat owner lookup` | `stat-owner-lookup` | `stat_owner_lookup` |
52
+ | `render-invoice` | `render-invoice` | `render_invoice` |
53
+
54
+ OpenAPI `paths` use the API id (`/tools/render-invoice`, etc.).
55
+
56
+ ## Endpoints
57
+
58
+ | Method | Path | Purpose |
59
+ | --- | --- | --- |
60
+ | `GET` | `/health` | Liveness check |
61
+ | `GET` | `/openapi.json` | OpenAPI 3.1 document (per-tool `POST /tools/{name}` paths) |
62
+ | `GET` | `/openapi-browser` | Interactive Scalar API reference (CDN) |
63
+ | `POST` | `/tools/:name` | Invoke tool; body is a flat JSON args object |
64
+ | `OPTIONS` | `*` | CORS preflight (wide-open `Access-Control-Allow-Origin: *`) |
65
+
66
+ ## Examples
67
+
68
+ ```bash
69
+ curl -s http://127.0.0.1:3000/health
70
+ curl -s http://127.0.0.1:3000/openapi.json
71
+ open http://127.0.0.1:3000/openapi-browser
72
+ curl -s -X POST http://127.0.0.1:3000/tools/{tool-key} \
73
+ -H 'content-type: application/json' \
74
+ -d '{...}'
75
+ ```
76
+
77
+ Replace `{tool-key}` with a path segment from `openapi.json` (`paths` keys are `/tools/{tool-key}`); body keys match that tool's flat JSON args (see `docs cli-schema` or `openapi.json`).
78
+
79
+ ## Handler responses (`ctx.respond()`)
80
+
81
+ API and MCP tool handlers must return machine-readable output via **`ctx.respond()`** or by **returning a value** (implicit JSON). `console.log` is not included in HTTP/MCP success payloads.
82
+
83
+ ```typescript
84
+ handler: (ctx) => {
85
+ if (ctx.hasFlag("json")) {
86
+ return { user: "alice", path: "/tmp" };
87
+ }
88
+ ctx.respond({
89
+ body: pdfBytes,
90
+ contentType: "application/pdf",
91
+ headers: { "Content-Disposition": 'inline; filename="invoice.pdf"' },
92
+ });
93
+ },
94
+ ```
95
+
96
+ **CLI mode:** `ctx.respond()` prints to stdout (JSON pretty-printed, strings as-is, `Uint8Array` as raw bytes). Handlers may still use `console.log` for human-only CLI output.
97
+
98
+ ### Leaf metadata
99
+
100
+ ```typescript
101
+ apiResponse?: {
102
+ contentType?: string; // default application/json
103
+ contentDisposition?: string; // e.g. attachment; filename="invoice.pdf"
104
+ };
105
+ ```
106
+
107
+ Used by OpenAPI and as a default `Content-Type` when the handler does not set one.
108
+
109
+ ## Responses
110
+
111
+ **Success (`200`):** raw body — no `{ ok, stdout }` envelope.
112
+
113
+ | Body type | HTTP `Content-Type` |
114
+ | --- | --- |
115
+ | object / array | `application/json` |
116
+ | string | handler `contentType` or `text/plain` |
117
+ | `Uint8Array` | e.g. `application/pdf` (required on `respond()`) |
118
+
119
+ **Errors:** JSON `{ "error": "...", "exitCode?": number }` with `400` (bad args), `404` (unknown tool), `503` (missing config), or `500` (handler failure).
120
+
121
+ ## MCP binary payloads
122
+
123
+ Binary `ctx.respond()` bodies are encoded in MCP `structuredContent` as:
124
+
125
+ ```json
126
+ { "data": "<base64>", "contentType": "application/pdf", "encoding": "base64" }
127
+ ```
128
+
129
+ String bodies use `{ "content": "...", "contentType": "..." }`. JSON objects are returned as-is in `structuredContent`.
130
+
131
+ ## CORS
132
+
133
+ All responses include wide-open CORS headers (`Access-Control-Allow-Origin: *`). Not configurable in v1.
134
+
135
+ ## OpenAPI
136
+
137
+ Call `generateOpenApi(program)` or `openApiJson(program)` from the package, fetch `GET /openapi.json` from a running server, or run `myapp docs openapi` / `myapp docs openapi --save` (writes `./docs/openapi.json` when `docs.enabled` and `apiServer.enabled`). Nested `inputSchema` / `outputSchema` `$ref` pointers are dereferenced when the OpenAPI document is built so API reference UIs can show nested request shapes.
138
+
139
+ ## Complex tool inputs
140
+
141
+ For nested request bodies (e.g. invoice template data), set `inputSchema` on the leaf and read `ctx.toolArgs` in the handler — it contains the original flat JSON body from `POST /tools/:name`.
@@ -9,9 +9,9 @@ Two documentation layers often coexist in a consumer repo:
9
9
  | Layer | Contents | How agents/humans get it |
10
10
  | --- | --- | --- |
11
11
  | **Argsbarg framework** | How to author `CliProgram`, MCP varargs policy, headless patterns | `node_modules/argsbarg/docs/` — wire via [full-example Cursor rule](../examples/full-example/.cursor/rules/cli-program.mdc) or `AGENTS.md` |
12
- | **Your CLI (docgen)** | Your command tree, options, MCP tool list, install notes | `myapp docs api`, `docs schema`, `docs mcp` — save with `--save` to `./docs/` |
12
+ | **Your CLI (docgen)** | Your command tree, options, MCP tool list, install notes | `myapp docs api`, `docs cli-schema`, `docs mcp` — save with `--save` to `./docs/` |
13
13
 
14
- `docs api` and `docs schema` embed each leaf’s `outputSchema` when set — see [output-schema.md](output-schema.md) for how to generate and wire schemas.
14
+ `docs api` and `docs cli-schema` embed each leaf’s `outputSchema` when set — see [output-schema.md](output-schema.md) for how to generate and wire schemas.
15
15
 
16
16
  Do not confuse them: editing `./docs/api.md` after docgen updates **your** app reference; it does not change argsbarg's framework guides. When MCP behavior changes (e.g. varargs arrays in 3.6+), update consumer `docs/mcp.md` via **`myapp docs mcp --save`** and bump the `argsbarg` dependency.
17
17
 
@@ -42,12 +42,15 @@ const cli = {
42
42
  myapp docs # first topic (readme) via fallback
43
43
  myapp docs readme
44
44
  myapp docs architecture
45
- myapp docs schema # full command tree as JSON
45
+ myapp docs cli-schema # full command tree as JSON
46
46
  myapp docs api # command tree as markdown
47
47
  myapp docs skill # generated Cursor SKILL.md
48
48
  myapp docs mcp # auto-generated when mcpServer.enabled
49
+ myapp docs http # auto-generated when apiServer.enabled
50
+ myapp docs openapi # OpenAPI 3.1 JSON when apiServer.enabled
49
51
  myapp docs readme --save # write ./docs/readme.md
50
- myapp docs schema --save # write ./docs/schema.json
52
+ myapp docs cli-schema --save # write ./docs/cli-schema.json
53
+ myapp docs openapi --save # write ./docs/openapi.json
51
54
  ```
52
55
 
53
56
  When `docs` is enabled, top-level `myapp --help` points agents at `myapp docs skill`. The `docs skill` subcommand description recommends `configure` for a persisted bundle.
@@ -61,7 +64,7 @@ When `docs` is enabled, top-level `myapp --help` points agents at `myapp docs sk
61
64
  | `defaultTopic` | first key in `topics` | `fallbackCommand` for bare `myapp docs` |
62
65
  | `topics` | *(required)* | Topic key → `{ text, description? }` |
63
66
 
64
- Reserved topic keys in `topics`: **`mcp`**, **`all`**, **`schema`**, **`api`**, **`skill`** (reserved — use the matching `docs <name>` subcommand instead).
67
+ Reserved topic keys in `topics`: **`http`**, **`mcp`**, **`all`**, **`schema`**, **`api`**, **`skill`**, **`openapi`** (reserved — use the matching `docs <name>` subcommand instead).
65
68
 
66
69
  When `description` is omitted on a topic, ArgsBarg generates leaf help (`readme` → "Print README (user guide).").
67
70
 
@@ -77,11 +80,11 @@ Bun embeds the file when you `bun build --compile`. ArgsBarg does not read the f
77
80
 
78
81
  Inline topics in your program root when the set is small; use a separate module only if the import map grows enough to clutter `index.tsx`.
79
82
 
80
- ## Schema, API, and skill (`docs schema`, `docs api`, `docs skill`)
83
+ ## CLI schema, API, and skill (`docs cli-schema`, `docs api`, `docs skill`)
81
84
 
82
85
  When `docs.enabled` is `true`:
83
86
 
84
- - **`docs schema`** — same JSON as the former root `--schema` flag (handlers omitted; built-in subtrees included for leaf roots).
87
+ - **`docs cli-schema`** — same JSON as the former root `--schema` flag (handlers omitted; built-in subtrees included for leaf roots).
85
88
  - **`docs api`** — markdown rendering of the same command tree (options, positionals, subcommands, fallback routing).
86
89
  - **`docs skill`** — prints the compact `SKILL.md` index. Prefer `configure --sync --yes` for agents (persists index + full API in `reference.md`).
87
90
 
@@ -91,6 +94,16 @@ When both `docs.enabled` and `mcpServer.enabled` are `true`, ArgsBarg injects a
91
94
 
92
95
  There is no override API in v1 — customize behavior via `mcpTool.description` on leaf commands.
93
96
 
97
+ ## HTTP guide (`docs http`)
98
+
99
+ When both `docs.enabled` and `apiServer.enabled` are `true`, ArgsBarg injects a **`docs http`** topic with curl examples, endpoints, and tool list.
100
+
101
+ Shell invocation tables remain under **`docs api`** (not HTTP).
102
+
103
+ ## OpenAPI (`docs openapi`)
104
+
105
+ When both `docs.enabled` and `apiServer.enabled` are `true`, ArgsBarg injects a **`docs openapi`** topic with the same OpenAPI 3.1 document served at `GET /openapi.json`.
106
+
94
107
  ## MCP tools
95
108
 
96
109
  All `docs` subcommands are hidden from MCP `tools/list` (`mcpTool: { enabled: false }`).
@@ -102,7 +115,7 @@ All `docs` subcommands are hidden from MCP `tools/list` (`mcpTool: { enabled: fa
102
115
  | `configure` (skill targets) | Writes compact `SKILL.md` + full-API `reference.md` to disk |
103
116
  | `docs skill` | Print generated `SKILL.md` to stdout |
104
117
  | `docs api` | Print command tree markdown to stdout |
105
- | `docs schema` | Print command tree JSON to stdout |
118
+ | `docs cli-schema` | Print command tree JSON to stdout |
106
119
  | `docs` | Bundled markdown topics on stdout |
107
120
  | MCP docs topic resources | User `docs.topics` on the MCP wire (`<mcpId>://docs/<topic>`) when docs + MCP enabled |
108
121
  | `mcp` | Callable tools + schema resource |
@@ -116,8 +129,9 @@ Pass **`--save`** on `docs` or any docs subcommand to write files under **`./doc
116
129
  | Command | Output |
117
130
  | --- | --- |
118
131
  | `docs readme --save` | `./docs/readme.md` |
119
- | `docs schema --save` | `./docs/schema.json` |
132
+ | `docs cli-schema --save` | `./docs/cli-schema.json` |
133
+ | `docs openapi --save` | `./docs/openapi.json` |
120
134
  | `docs api --save` | `./docs/api.md` |
121
135
  | `docs skill --save` | `./docs/skill.md` |
122
136
 
123
- Argsbarg-generated markdown (`mcp`, `api`, `skill`) includes a `Generated by … docs … --save` HTML comment (`skill` places it after YAML frontmatter so parsers still work). `schema.json` and argsbarg-generated markdown resolve `{argsbarg:program}` in `notes` to the program key. Consumer-authored topic files are written as-is.
137
+ Argsbarg-generated markdown (`mcp`, `api`, `skill`) includes a `Generated by … docs … --save` HTML comment (`skill` places it after YAML frontmatter so parsers still work). `cli-schema.json`, `openapi.json`, and argsbarg-generated markdown resolve `{argsbarg:program}` in `notes` to the program key. Consumer-authored topic files are written as-is.
@@ -27,6 +27,20 @@ const cli = {
27
27
 
28
28
  No `mcpTool` blocks required. Every leaf becomes an MCP tool; `inputSchema` comes from options and positionals.
29
29
 
30
+ ## HTTP API (optional)
31
+
32
+ ```typescript
33
+ const cli = {
34
+ key: "myapp",
35
+ version: "1.0.0",
36
+ description: "One-line summary of what the CLI does.",
37
+ apiServer: { enabled: true }, // myapp api → http://127.0.0.1:3000
38
+ commands: [/* ... */],
39
+ } satisfies CliProgram;
40
+ ```
41
+
42
+ `apiServer` and `mcpServer` are independent. Tool exposure uses the same rules (`mcpTool.enabled: false` hides from MCP and HTTP). See [api-server.md](api-server.md).
43
+
30
44
  ## Inline schema by default
31
45
 
32
46
  ArgsBarg is **schema-first** — the program tree is the product. **Keep `CliProgram` and leaf fields inline** (`key`, `description`, `options`, `positionals`, `handler`) so a reader sees the full command contract in one place.
@@ -131,7 +145,7 @@ On **leaf commands**, set `outputSchema` to a JSON Schema describing stdout when
131
145
  }
132
146
  ```
133
147
 
134
- Exported in `docs schema`, `docs api`, skill `reference.md`, and MCP `tools/list`. Not validated at runtime yet. Pair with `notes` for prose examples; do not duplicate the full schema in `notes`.
148
+ Exported in `docs cli-schema`, `docs api`, skill `reference.md`, and MCP `tools/list`. Not validated at runtime yet. Pair with `notes` for prose examples; do not duplicate the full schema in `notes`.
135
149
 
136
150
  For a **outputSchema codegen guidelines** (TypeScript types → JSON Schema → `outputSchema` constants), see [output-schema.md](output-schema.md).
137
151
 
@@ -300,10 +314,11 @@ Ink + headless + MCP apps benefit from `read*Flags(ctx)` + `resolve*Input(flags)
300
314
  Simple leaves (read args, print stdout) are already headless — no extra work. **Any handler that might mount Ink, prompt, or open a browser should also implement a scriptable fast path** for:
301
315
 
302
316
  - **MCP** (`ctx.invocation === "mcp"` — always non-interactive)
317
+ - **HTTP API** (`ctx.invocation === "api"` — same headless rules as MCP)
303
318
  - **Non-TTY CLI** (pipes, CI, `myapp cmd --yes` in a script)
304
319
  - **Explicit flags** (`--json`, `--dry-run`)
305
320
 
306
- Use **one headless implementation** for all three; do not fork separate "MCP handlers."
321
+ Use **one headless implementation** for MCP, HTTP API, and scripted CLI; do not fork separate transport handlers.
307
322
 
308
323
  ### When to branch
309
324
 
@@ -142,33 +142,43 @@ Mirror the [output-schema.md](output-schema.md) pattern for config:
142
142
 
143
143
  ```mermaid
144
144
  flowchart LR
145
- subgraph types [Schema-facing TS + JSDoc]
146
- TypesTs["src/**/types.ts"]
147
- Marker["JSDoc contains Config schema"]
145
+ subgraph types [schema-types.ts]
146
+ Marker["export type configType = AppConfig"]
148
147
  end
149
148
  subgraph gen [just schemagen]
150
- Script["scripts/generate-config-schemas.ts"]
149
+ Script["scripts/schemagen.ts"]
151
150
  Gen["ts-json-schema-generator"]
152
151
  end
153
152
  subgraph artifacts [Committed]
154
- Json["src/schemas/generated/app-config.json"]
155
- Bridge["src/schemas/configSchemas.ts"]
153
+ Json["schemas/generated/app-config.json"]
154
+ Bridge["schemas/configSchemas.ts"]
156
155
  end
157
156
  subgraph runtime [Runtime]
158
157
  Program["program.appConfig.jsonSchema"]
159
158
  Validate["argsbarg runtime subset validator"]
160
159
  end
161
- TypesTs --> Marker --> Script --> Gen --> Json
160
+ types --> Script --> Gen --> Json
162
161
  Script --> Bridge --> Program --> Validate
163
162
  ```
164
163
 
165
164
  | Piece | Convention |
166
165
  | --- | --- |
167
166
  | Generator | [`ts-json-schema-generator`](https://github.com/vega/ts-json-schema-generator) |
168
- | Discovery | JSDoc marker **`Config schema`** on the root config interface |
167
+ | Discovery | `export type configType = …` in `src/config/schema-types.ts` (type defined in same file) |
169
168
  | Artifacts | Commit `app-config.json` and `configSchemas.ts` bridge exporting `APP_CONFIG_JSON_SCHEMA` |
170
169
  | Consumer CI | Optional: `ajv` + `ajv-formats` against the same committed JSON (not an argsbarg runtime dep) |
171
170
 
171
+ Example:
172
+
173
+ ```typescript
174
+ // src/config/schema-types.ts
175
+ export interface AppConfig {
176
+ apiToken: string;
177
+ }
178
+
179
+ export type configType = AppConfig;
180
+ ```
181
+
172
182
  ### Supported AppConfig shapes (argsbarg runtime validator)
173
183
 
174
184
  | Supported (v1) | Deferred |
@@ -28,7 +28,7 @@ Update `CHANGELOG.md` under `[Unreleased]` before releasing.
28
28
 
29
29
  ## Local consumer apps
30
30
 
31
- Sibling repos under `../../ss/` (paths are machine-specific; adjust in `justfile` if needed):
31
+ Sibling consumer repos (machine-specific paths in the root `justfile` `consumer_apps` variable, e.g. `~/dev/ss/sqsp-workspaces`):
32
32
 
33
33
  | Recipe | When | Effect |
34
34
  | --- | --- | --- |
package/docs/mcp.md CHANGED
@@ -171,7 +171,7 @@ Each tool’s `description` includes the human CLI path and the leaf’s help te
171
171
 
172
172
  ### Per-leaf visibility
173
173
 
174
- Set `mcpTool: { enabled: false }` on a **leaf command** to hide it from `tools/list` while keeping it in the CLI and in `docs schema` output:
174
+ Set `mcpTool: { enabled: false }` on a **leaf command** to hide it from `tools/list` while keeping it in the CLI and in `docs cli-schema` output:
175
175
 
176
176
  ```typescript
177
177
  {
@@ -232,11 +232,11 @@ On success (`isError: false`):
232
232
 
233
233
  On failure (parse error, validation error, non-zero exit, thrown error), the message is returned as text content with `isError: true`. Handler stderr is included when present.
234
234
 
235
- Help and `docs schema` are not available through tool calls; use the schema resource or run the CLI directly for those.
235
+ Help and `docs cli-schema` are not available through tool calls; use the schema resource or run the CLI directly for those.
236
236
 
237
237
  ## Schema and custom resources
238
238
 
239
- The built-in schema resource (default URI `<sanitized-key>://schema`, e.g. `nested.ts` → `nested_ts://schema`) exposes your full CLI tree as JSON — the same output as `myapp docs schema`. Override with `schemaResourceUri` if needed.
239
+ The built-in schema resource (default URI `<sanitized-key>://schema`, e.g. `nested.ts` → `nested_ts://schema`) exposes your full CLI tree as JSON — the same output as `myapp docs cli-schema`. Override with `schemaResourceUri` if needed.
240
240
 
241
241
  | Property | Value |
242
242
  | --- | --- |
@@ -419,7 +419,7 @@ Bare **`myapp mcp`** still runs the stdio MCP server (unchanged for `configure`
419
419
 
420
420
  ## Hidden commands and options
421
421
 
422
- Set **`hidden: true`** on a command or option to omit it from help listings, `docs schema` / `docs api`, shell completions, and MCP `tools/list` / tool `inputSchema`. Hidden commands remain invocable; **`myapp hidden-cmd -h`** still works.
422
+ Set **`hidden: true`** on a command or option to omit it from help listings, `docs cli-schema` / `docs api`, shell completions, and MCP `tools/list` / tool `inputSchema`. Hidden commands remain invocable; **`myapp hidden-cmd -h`** still works.
423
423
 
424
424
  ## Reserved names
425
425
 
@@ -436,4 +436,4 @@ Running `myapp mcp` without `mcpServer` on the root fails with an error (exit 1)
436
436
  - **User schema only** — tool dispatch uses your program root, not merged presentation builtins.
437
437
  - **Buffered output** — MCP tool results are sent after the handler finishes. Incremental stdout (log tail, progress) is not streamed; a future release may add MCP progress notifications.
438
438
 
439
- For the `docs schema` export used by the resource, see [docs/bundled-docs.md](bundled-docs.md).
439
+ For the `docs cli-schema` export used by the resource, see [docs/bundled-docs.md](bundled-docs.md).