argsbarg 5.1.16 → 6.0.0
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.
- package/CHANGELOG.md +32 -1
- package/README.md +32 -24
- package/docs/README.md +2 -1
- package/docs/api-server.md +141 -0
- package/docs/bundled-docs.md +24 -10
- package/docs/cli-program.md +17 -2
- package/docs/developing.md +1 -1
- package/docs/mcp.md +5 -5
- package/docs/output-schema.md +3 -3
- package/examples/full-example/README.md +8 -0
- package/examples/full-example/docs/README.md +27 -0
- package/examples/full-example/docs/api.md +511 -0
- package/examples/full-example/docs/cli-schema.json +453 -0
- package/examples/full-example/docs/http.md +81 -0
- package/examples/full-example/docs/mcp.md +159 -0
- package/examples/full-example/docs/openapi.json +222 -0
- package/examples/full-example/docs/skill.md +46 -0
- package/examples/full-example/justfile +6 -2
- package/examples/full-example/scripts/dev-formula.ts +1 -1
- package/examples/full-example/src/commands/echo/command.ts +6 -1
- package/examples/full-example/src/program.ts +3 -0
- package/examples/mcp-test.ts +13 -2
- package/examples/nested.ts +12 -3
- package/examples/servers.ts +72 -0
- package/index.d.ts +66 -7
- package/package.json +1 -1
- package/src/api/openapi.ts +115 -0
- package/src/api/result.ts +89 -0
- package/src/api/server.ts +120 -0
- package/src/api.integration.test.ts +358 -0
- package/src/builtins/api.ts +38 -0
- package/src/builtins/dispatch.ts +26 -0
- package/src/builtins/registry.ts +4 -0
- package/src/capabilities.ts +12 -1
- package/src/cli-tool/full-example-capabilities.test.ts +3 -0
- package/src/cli.ts +60 -8
- package/src/config.integration.test.ts +22 -4
- package/src/context.ts +29 -1
- package/src/docs/api-guide.ts +2 -2
- package/src/docs/builtin.ts +11 -1
- package/src/docs/docs.test.ts +70 -12
- package/src/docs/http-guide.ts +132 -0
- package/src/docs/mcp-guide.ts +3 -3
- package/src/docs/resolve.ts +26 -2
- package/src/docs/save.ts +5 -2
- package/src/headless/tool-call.ts +147 -0
- package/src/headless.test.ts +4 -2
- package/src/headless.ts +10 -5
- package/src/index.ts +5 -0
- package/src/mcp/result.ts +39 -34
- package/src/mcp/server.ts +18 -36
- package/src/mcp/tools.ts +14 -3
- package/src/mcp.integration.test.ts +46 -39
- package/src/parse.test.ts +16 -6
- package/src/respond.ts +48 -0
- package/src/schema.ts +1 -1
- package/src/skill/generate.ts +1 -1
- package/src/types.ts +46 -4
- package/src/validate.ts +7 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,36 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [6.0.0] - 2026-07-22
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`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`.
|
|
15
|
+
- **`ctx.respond()`** — set machine-readable responses for API/MCP; polymorphic CLI stdout printing.
|
|
16
|
+
- **Implicit handler return values** — non-undefined return values become JSON responses for headless invocations.
|
|
17
|
+
- **`apiResponse`** leaf metadata — default HTTP `Content-Type` and `Content-Disposition`.
|
|
18
|
+
- **`generateOpenApi(program)`** — hand-built OpenAPI 3.1 document; served at `GET /openapi.json`.
|
|
19
|
+
- **`GET /openapi-browser`** — Scalar API reference UI (CDN). Replaces `GET /docs`.
|
|
20
|
+
- **`ctx.toolArgs`** — original flat tool JSON for API/MCP handlers with custom `inputSchema`.
|
|
21
|
+
- **Wide-open CORS** — `Access-Control-Allow-Origin: *` on all API responses.
|
|
22
|
+
- **`docs http`** — auto-generated HTTP API guide when `docs` and `apiServer` are both enabled.
|
|
23
|
+
- **`docs openapi`** — print OpenAPI 3.1 JSON (`myapp docs openapi`); save with `--save` to `./docs/openapi.json` when `apiServer` is enabled.
|
|
24
|
+
- **`Cli.invoke(argv, { invocation, toolArgs })`** — optional invocation source (`"mcp"` default, `"api"` for HTTP).
|
|
25
|
+
- **`ctx.invocation === "api"`** — headless helpers treat API like MCP.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- **HTTP success responses** — raw body (JSON/HTML/PDF bytes); no `{ ok, stdout, stderr }` envelope.
|
|
30
|
+
- **MCP/API tool handlers** — must `ctx.respond()` or return a value; stdout is not part of success payloads.
|
|
31
|
+
- **MCP binary** — `Uint8Array` responses encoded as base64 in `structuredContent`.
|
|
32
|
+
- **Removed `POST /tools`** — MCP-shaped invoke endpoint; use `POST /tools/:name` only.
|
|
33
|
+
- **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`).
|
|
34
|
+
- **Removed `GET /docs`** — use **`GET /openapi-browser`** for the Scalar API reference UI.
|
|
35
|
+
- **Removed `GET /schema`** from the HTTP API — use `myapp docs cli-schema`, MCP `://schema`, or `GET /openapi.json` / `docs openapi` instead.
|
|
36
|
+
- **Removed `GET /tools`** from the HTTP API — use `GET /openapi.json` for tool discovery.
|
|
37
|
+
- **Renamed `docs schema` → `docs cli-schema`** — saved file is `./docs/cli-schema.json` (disambiguates CLI tree JSON from OpenAPI and JSON Schema artifacts).
|
|
38
|
+
- **Custom `inputSchema`** on leaves is used for MCP/HTTP tool metadata when set.
|
|
39
|
+
|
|
10
40
|
## [5.1.16] - 2026-07-07
|
|
11
41
|
|
|
12
42
|
|
|
@@ -685,7 +715,8 @@ const cli = { ... } satisfies CliProgram; // or : CliProgram
|
|
|
685
715
|
- 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
716
|
- Imports: use `CliPositional` where needed; replace `CliOptionDef` with `CliOption` or `CliPositional` as appropriate.
|
|
687
717
|
|
|
688
|
-
[Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/
|
|
718
|
+
[Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v6.0.0...HEAD
|
|
719
|
+
[6.0.0]: https://github.com/bdombro/bun-argsbarg/releases/tag/v6.0.0
|
|
689
720
|
[5.1.16]: https://github.com/bdombro/bun-argsbarg/releases/tag/v5.1.16
|
|
690
721
|
[5.1.15]: https://github.com/bdombro/bun-argsbarg/releases/tag/v5.1.15
|
|
691
722
|
[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
|
-
- `
|
|
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).
|
|
@@ -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 `
|
|
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
|
-
|
|
261
|
-
|
|
|
262
|
-
|
|
|
263
|
-
|
|
|
264
|
-
| `
|
|
265
|
-
|
|
|
266
|
-
|
|
|
267
|
-
|
|
|
268
|
-
|
|
|
269
|
-
|
|
|
270
|
-
|
|
|
271
|
-
|
|
|
266
|
+
|
|
267
|
+
| Area | Files / wiring |
|
|
268
|
+
| --------------------- | -------------------------------------------------------------------------------------- |
|
|
269
|
+
| All builtins | `completion`, `version`, `configure`, `docs`, `mcp`, `api`, `configure get`/`set` |
|
|
270
|
+
| `program.appConfig` | `src/types.ts` (`AppConfig`) → `schemas/configSchemas.ts` |
|
|
271
|
+
| `outputSchema` | `src/commands/status/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`),
|
|
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`). Tools with custom `inputSchema` on the leaf are reflected in the document.
|
|
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`.
|
package/docs/bundled-docs.md
CHANGED
|
@@ -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
|
-
##
|
|
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.
|
package/docs/cli-program.md
CHANGED
|
@@ -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
|
|
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
|
|
package/docs/developing.md
CHANGED
|
@@ -28,7 +28,7 @@ Update `CHANGELOG.md` under `[Unreleased]` before releasing.
|
|
|
28
28
|
|
|
29
29
|
## Local consumer apps
|
|
30
30
|
|
|
31
|
-
Sibling repos
|
|
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).
|
package/docs/output-schema.md
CHANGED
|
@@ -19,7 +19,7 @@ export const status = {
|
|
|
19
19
|
|
|
20
20
|
| Where argsbarg uses it | Purpose |
|
|
21
21
|
| --- | --- |
|
|
22
|
-
| `myapp docs schema` | Full command tree JSON export |
|
|
22
|
+
| `myapp docs cli-schema` | Full command tree JSON export |
|
|
23
23
|
| `myapp docs api` | Markdown per-command **Output** section |
|
|
24
24
|
| `myapp docs skill` | `reference.md` for agent skills |
|
|
25
25
|
| MCP `tools/list` | Optional `outputSchema` on each tool |
|
|
@@ -79,7 +79,7 @@ flowchart LR
|
|
|
79
79
|
| Artifacts | Commit `src/schemas/generated/*.json` **and** auto-generated `src/schemas/outputSchemas.ts` |
|
|
80
80
|
| tsconfig | `"resolveJsonModule": true` |
|
|
81
81
|
| CI | `just check`: `schemagen` → `git diff --exit-code src/schemas/generated/ src/schemas/outputSchemas.ts` → typecheck |
|
|
82
|
-
| Docgen | `docgen` depends on `schemagen` so saved `./docs/api.md` and `./docs/schema.json` are fresh |
|
|
82
|
+
| Docgen | `docgen` depends on `schemagen` so saved `./docs/api.md` and `./docs/cli-schema.json` are fresh |
|
|
83
83
|
|
|
84
84
|
Copy these scripts into each consumer repo (they are intentionally duplicated, not published):
|
|
85
85
|
|
|
@@ -199,5 +199,5 @@ Add a bullet under your app’s `**… conventions:**` block in `.cursor/rules/c
|
|
|
199
199
|
|
|
200
200
|
- [cli-program.md](cli-program.md) — structured stdout, headless JSON, `read*Flags`
|
|
201
201
|
- [mcp.md](mcp.md) — `tools/list`, `structuredContent`
|
|
202
|
-
- [bundled-docs.md](bundled-docs.md) — `docs api` / `docs schema` docgen
|
|
202
|
+
- [bundled-docs.md](bundled-docs.md) — `docs api` / `docs cli-schema` docgen
|
|
203
203
|
- [docs/README.md](README.md) — documentation map
|
|
@@ -69,6 +69,14 @@ Undo a local dev install: `just uninstall` (formula + agent artifacts; app confi
|
|
|
69
69
|
|
|
70
70
|
Discovery walks `src/**/types.ts` only.
|
|
71
71
|
|
|
72
|
+
## Consumer docs
|
|
73
|
+
|
|
74
|
+
Regenerate committed reference docs under `docs/` (see [docs/README.md](docs/README.md)):
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
just docgen
|
|
78
|
+
```
|
|
79
|
+
|
|
72
80
|
## Environment
|
|
73
81
|
|
|
74
82
|
Optional overrides for `program.appConfig` (the configure wizard is the usual path):
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# full-example documentation
|
|
2
|
+
|
|
3
|
+
Reference template for argsbarg consumer docgen. Every builtin is enabled in `src/program.ts`.
|
|
4
|
+
|
|
5
|
+
| If you are… | Read |
|
|
6
|
+
| --- | --- |
|
|
7
|
+
| **Using the CLI** | [../README.md](../README.md) |
|
|
8
|
+
| **Authoring argsbarg schema** | `node_modules/argsbarg/docs/cli-program.md` — see `.cursor/rules/cli-program.mdc` |
|
|
9
|
+
| **HTTP API / curl** | [http.md](http.md) — generated; or run `full-example docs http` |
|
|
10
|
+
| **MCP tools** | [mcp.md](mcp.md) — generated; or run `full-example docs mcp` |
|
|
11
|
+
| **Full command tree (markdown)** | [api.md](api.md) — generated |
|
|
12
|
+
| **Full command tree (JSON)** | [cli-schema.json](cli-schema.json) — generated |
|
|
13
|
+
| **OpenAPI 3.1** | [openapi.json](openapi.json) — generated |
|
|
14
|
+
| **Agent skill index** | [skill.md](skill.md) — generated |
|
|
15
|
+
|
|
16
|
+
## Framework docs vs this directory
|
|
17
|
+
|
|
18
|
+
| Layer | Contents |
|
|
19
|
+
| --- | --- |
|
|
20
|
+
| **Argsbarg framework** | How to author `CliProgram`, MCP, HTTP API | `node_modules/argsbarg/docs/` |
|
|
21
|
+
| **This `docs/` folder** | *full-example* command tree and guides | `just docgen` |
|
|
22
|
+
|
|
23
|
+
Do not hand-edit generated files. Refresh with:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
just docgen
|
|
27
|
+
```
|