argsbarg 6.1.2 → 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.
- package/CHANGELOG.md +65 -1
- package/README.md +17 -19
- package/bin/argsbarg +10 -0
- package/docs/README.md +4 -3
- package/docs/ai-skills.md +4 -2
- package/docs/bundled-docs.md +50 -25
- package/docs/cli-program.md +52 -10
- package/docs/config-schema.md +10 -11
- package/docs/configure.md +2 -0
- package/docs/decisions.md +40 -0
- package/docs/developing.md +43 -5
- package/docs/http-server.md +171 -0
- package/docs/json-schema-subset.md +51 -0
- package/docs/mcp.md +4 -2
- package/docs/output-schema.md +55 -62
- package/examples/formats.ts +6 -6
- package/examples/full-example/Formula/full-example.rb +35 -0
- package/examples/full-example/README.md +20 -21
- package/examples/full-example/docs/README.md +1 -1
- package/examples/full-example/docs/cli-schema.json +1790 -98
- package/examples/full-example/docs/cli.md +1990 -0
- package/examples/full-example/docs/http.md +28 -29
- package/examples/full-example/docs/mcp.md +8 -22
- package/examples/full-example/docs/openapi.json +783 -50
- package/examples/full-example/docs/skill.md +10 -10
- package/examples/full-example/justfile +11 -1
- package/examples/full-example/src/commands/render-json/__generated__/RenderJsonInputSchema.json +15 -0
- package/examples/full-example/src/commands/render-json/__generated__/index.ts +5 -0
- package/examples/full-example/src/commands/render-json/command.test.ts +46 -0
- package/examples/full-example/src/commands/render-json/command.ts +30 -0
- package/examples/full-example/src/commands/render-json/types.ts +9 -0
- package/examples/full-example/src/commands/status/__generated__/StatusJsonOutputSchema.json +15 -0
- package/examples/full-example/src/commands/status/__generated__/index.ts +2 -2
- package/examples/full-example/src/commands/status/command.ts +5 -13
- package/examples/full-example/src/commands/status/types.ts +1 -14
- package/examples/full-example/src/commands/workspaces/__generated__/WorkspaceNameInputSchema.json +15 -0
- package/examples/full-example/src/commands/workspaces/__generated__/index.ts +5 -0
- package/examples/full-example/src/commands/workspaces/command.test.ts +58 -0
- package/examples/full-example/src/commands/workspaces/command.ts +94 -0
- package/examples/full-example/src/commands/workspaces/types.ts +6 -0
- package/examples/full-example/src/db/index.test.ts +86 -0
- package/examples/full-example/src/db/index.ts +101 -0
- package/examples/full-example/src/db/migrate.test.ts +35 -0
- package/examples/full-example/src/db/migrate.ts +69 -0
- package/examples/full-example/src/db/migrations/001_workspaces.sql +6 -0
- package/examples/full-example/src/db/tables/workspaces.ts +66 -0
- package/examples/full-example/src/program.ts +11 -36
- package/examples/full-example/src/types/argsbarg.d.ts +11 -0
- package/examples/full-example/src/types/md.d.ts +4 -0
- package/examples/full-example/tsconfig.json +5 -2
- package/examples/mcp-test.ts +1 -2
- package/examples/minimal.ts +1 -7
- package/examples/nested.ts +1 -2
- package/examples/option-required.ts +1 -1
- package/examples/servers.ts +4 -5
- package/index.d.ts +431 -136
- package/package.json +19 -2
- package/src/builtins/builtins.test.ts +7 -7
- package/src/builtins/completion-bash.ts +1 -1
- package/src/builtins/completion-fish.ts +1 -1
- package/src/builtins/completion-group.ts +4 -4
- package/src/builtins/completion-simulate-shared.ts +9 -0
- package/src/builtins/completion-zsh.ts +1 -1
- package/src/builtins/config.test.ts +3 -3
- package/src/builtins/config.ts +9 -9
- package/src/builtins/configure-copy.ts +2 -2
- package/src/builtins/configure.ts +4 -4
- package/src/builtins/dispatch.ts +19 -18
- package/src/builtins/export.ts +7 -5
- package/src/builtins/http.ts +68 -0
- package/src/builtins/mcp.ts +28 -4
- package/src/builtins/presentation.ts +6 -6
- package/src/builtins/registry.ts +6 -6
- package/src/builtins/scopes.ts +2 -2
- package/src/builtins/version.ts +1 -1
- package/src/cli-tool/full-example-capabilities.test.ts +10 -15
- package/src/cli-tool/main.ts +1 -1
- package/src/cli-tool/program.ts +3 -2
- package/src/cli-tool/prompt.ts +1 -1
- package/src/cli-tool/run-schemagen.ts +1 -3
- package/src/cli-tool/schemagen/cleanup.ts +6 -7
- package/src/cli-tool/schemagen/discover-schema-roots.ts +66 -120
- package/src/cli-tool/schemagen/index.ts +2 -2
- package/src/cli-tool/schemagen/names.ts +8 -13
- package/src/cli-tool/schemagen/run.ts +21 -28
- package/src/cli-tool/schemagen/schemagen.test.ts +136 -46
- package/src/config/bindings.test.ts +1 -1
- package/src/config/bindings.ts +1 -1
- package/src/config/bootstrap.test.ts +1 -1
- package/src/config/bootstrap.ts +36 -4
- package/src/config/context.test.ts +1 -1
- package/src/config/context.ts +1 -1
- package/src/config/entry.ts +1 -1
- package/src/config/file.test.ts +1 -1
- package/src/config/file.ts +3 -3
- package/src/config/manifest.ts +1 -1
- package/src/config/resolve.test.ts +1 -1
- package/src/config/resolve.ts +1 -1
- package/src/config/schema.ts +1 -1
- package/src/config/validate.ts +1 -1
- package/src/{install → configure/artifacts}/binary-placement.test.ts +1 -1
- package/src/{install → configure/artifacts}/binary-placement.ts +1 -1
- package/src/{install → configure/artifacts}/gh-release-update.ts +1 -1
- package/src/{install → configure/artifacts}/install-validate.test.ts +3 -3
- package/src/{install → configure/artifacts}/mcp-config.ts +1 -1
- package/src/{install → configure/artifacts}/mcp-opencode.test.ts +1 -1
- package/src/{install → configure/artifacts}/mcp-opencode.ts +1 -1
- package/src/{install → configure/artifacts}/paths.ts +5 -5
- package/src/configure/artifacts/plan.ts +24 -0
- package/src/{install → configure/artifacts}/status.test.ts +1 -1
- package/src/{install → configure/artifacts}/status.ts +2 -2
- package/src/{install → configure/artifacts}/target-base.ts +1 -1
- package/src/{install → configure/artifacts}/target-detect.ts +1 -1
- package/src/{install → configure/artifacts}/target-effective.ts +3 -9
- package/src/{install → configure/artifacts}/target-mcp-cli.ts +1 -1
- package/src/{install → configure/artifacts}/target-mcp-json.ts +1 -1
- package/src/{install → configure/artifacts}/target-plan-build.ts +2 -2
- package/src/{install → configure/artifacts}/target-registry.ts +2 -2
- package/src/{install → configure/artifacts}/target-scope.ts +3 -3
- package/src/{install → configure/artifacts}/target-skill.ts +1 -1
- package/src/{install → configure/artifacts}/target-types.ts +2 -2
- package/src/{install → configure/artifacts}/targets/app.ts +5 -5
- package/src/{install → configure/artifacts}/targets/chatgpt-mcp.ts +2 -2
- package/src/{install → configure/artifacts}/targets/claude-code-mcp.ts +2 -2
- package/src/{install → configure/artifacts}/targets/claude-desktop-mcp.ts +2 -2
- package/src/{install → configure/artifacts}/targets/claude-skill.ts +2 -2
- package/src/{install → configure/artifacts}/targets/codex-mcp.ts +2 -2
- package/src/{install → configure/artifacts}/targets/codex-skill.ts +2 -2
- package/src/{install → configure/artifacts}/targets/configure.ts +5 -5
- package/src/{install → configure/artifacts}/targets/cursor-mcp.ts +2 -2
- package/src/{install → configure/artifacts}/targets/cursor-skill.ts +2 -2
- package/src/{install → configure/artifacts}/targets/index.ts +1 -1
- package/src/{install → configure/artifacts}/targets/openclaw-mcp.ts +2 -2
- package/src/{install → configure/artifacts}/targets/openclaw-skill.ts +3 -3
- package/src/{install → configure/artifacts}/targets/opencode-mcp.ts +5 -5
- package/src/{install → configure/artifacts}/targets/opencode-skill.ts +3 -3
- package/src/{install → configure/artifacts}/targets.test.ts +1 -1
- package/src/{install → configure/artifacts}/uninstall.ts +1 -1
- package/src/configure/configure.test.ts +11 -11
- package/src/configure/index.ts +14 -14
- package/src/configure/prompt.ts +2 -2
- package/src/{context.ts → core/context.ts} +26 -20
- package/src/{json-leaf.test.ts → core/json-leaf.test.ts} +4 -4
- package/src/{leaf-inputs.test.ts → core/leaf-inputs.test.ts} +7 -7
- package/src/{leaf-inputs.ts → core/leaf-inputs.ts} +16 -12
- package/src/{parse.test.ts → core/parse.test.ts} +97 -109
- package/src/{parse.ts → core/parse.ts} +129 -31
- package/src/{schema.ts → core/schema.ts} +25 -13
- package/src/{types.ts → core/types.ts} +225 -35
- package/src/{validate.ts → core/validate.ts} +39 -29
- package/src/docs/builtin.ts +8 -19
- package/src/docs/{api-guide.test.ts → cli-guide.test.ts} +21 -21
- package/src/docs/{api-guide.ts → cli-guide.ts} +45 -16
- package/src/docs/docs.test.ts +76 -41
- package/src/docs/http-guide.ts +37 -34
- package/src/docs/mcp-guide.ts +12 -14
- package/src/docs/mcp-resources.test.ts +2 -3
- package/src/docs/mcp-resources.ts +6 -11
- package/src/docs/resolve.ts +22 -30
- package/src/docs/save.ts +3 -3
- package/src/exports/cli.ts +47 -0
- package/src/exports/headless.ts +13 -0
- package/src/exports/http.ts +6 -0
- package/src/exports/mcp.ts +6 -0
- package/src/{headless.test.ts → headless/routing.test.ts} +3 -3
- package/src/{headless.ts → headless/routing.ts} +3 -3
- package/src/headless/tool-call.ts +114 -46
- package/src/help.test.ts +152 -0
- package/src/help.ts +3 -3
- package/src/hooks/builtin.ts +20 -0
- package/src/hooks/run.ts +142 -0
- package/src/http/openapi.ts +182 -0
- package/src/http/readiness.ts +78 -0
- package/src/{api → http}/result.ts +16 -5
- package/src/http/routes.ts +329 -0
- package/src/http/server.ts +225 -0
- package/src/index.ts +36 -25
- package/src/log/ecs.test.ts +43 -0
- package/src/log/ecs.ts +59 -0
- package/src/log/emitter.ts +166 -0
- package/src/mcp/bundle.ts +2 -2
- package/src/mcp/claude.test.ts +1 -1
- package/src/mcp/claude.ts +4 -4
- package/src/{hidden-mcpb.test.ts → mcp/hidden-mcpb.test.ts} +10 -9
- package/src/mcp/result.ts +2 -2
- package/src/mcp/server.ts +54 -6
- package/src/mcp/tools.ts +9 -20
- package/src/{capabilities.ts → runtime/capabilities.ts} +11 -11
- package/src/{cli-errors.ts → runtime/cli-errors.ts} +4 -4
- package/src/{cli.ts → runtime/cli.ts} +159 -49
- package/src/runtime/exposure.ts +102 -0
- package/src/{invoke.test.ts → runtime/invoke.test.ts} +31 -7
- package/src/server/context.ts +25 -0
- package/src/server/overrides.ts +112 -0
- package/src/skill/generate.ts +8 -8
- package/src/skill/hint.ts +1 -1
- package/src/skill/install.ts +2 -2
- package/src/skill/naming.ts +1 -1
- package/src/{test-fixtures.ts → test/fixtures.ts} +3 -2
- package/src/{config.integration.test.ts → test/integration/config.test.ts} +8 -8
- package/src/{api.integration.test.ts → test/integration/http.test.ts} +170 -67
- package/src/{mcp.integration.test.ts → test/integration/mcp.test.ts} +11 -57
- package/docs/api-server.md +0 -141
- package/examples/full-example/docs/api.md +0 -511
- package/examples/full-example/src/commands/status/__generated__/outputSchema.json +0 -28
- package/examples/full-example/src/config/__generated__/configSchema.json +0 -40
- package/examples/full-example/src/config/__generated__/index.ts +0 -5
- package/examples/full-example/src/config/types.ts +0 -24
- package/src/api/openapi.ts +0 -117
- package/src/api/server.ts +0 -120
- package/src/builtins/api.ts +0 -38
- package/src/hidden.ts +0 -30
- package/src/install/plan.ts +0 -53
- /package/src/{install → configure/artifacts}/detect-installed.ts +0 -0
- /package/src/{install → configure/artifacts}/gh-release-update.test.ts +0 -0
- /package/src/{install → configure/artifacts}/mcp-codex.test.ts +0 -0
- /package/src/{install → configure/artifacts}/mcp-codex.ts +0 -0
- /package/src/{install → configure/artifacts}/mcp-openclaw.test.ts +0 -0
- /package/src/{install → configure/artifacts}/mcp-openclaw.ts +0 -0
- /package/src/{install → configure/artifacts}/normalize-uninstall.ts +0 -0
- /package/src/{install → configure/artifacts}/normalize.ts +0 -0
- /package/src/{install → configure/artifacts}/opts.ts +0 -0
- /package/src/{install → configure/artifacts}/shell.ts +0 -0
- /package/src/{formats.test.ts → core/formats.test.ts} +0 -0
- /package/src/{formats.ts → core/formats.ts} +0 -0
- /package/src/{respond.ts → core/respond.ts} +0 -0
- /package/src/{types.test.ts → core/types.test.ts} +0 -0
- /package/src/{api → http}/schema-deref.test.ts +0 -0
- /package/src/{api → http}/schema-deref.ts +0 -0
package/docs/configure.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Configure command
|
|
2
2
|
|
|
3
|
+
> This feature is experimental.
|
|
4
|
+
|
|
3
5
|
The `configure` built-in manages **agent artifacts** (skills, MCP config, app config). The **binary and shell completions** ship via Homebrew — see [distribution-homebrew.md](distribution-homebrew.md).
|
|
4
6
|
|
|
5
7
|
Opt out with `configure: { enabled: false }` on the program root.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Decisions
|
|
2
|
+
|
|
3
|
+
This doc tracks big architectural decisions so that we can avoid re-hashing the same decisions over and over.
|
|
4
|
+
|
|
5
|
+
## HTTP REST vs flat `/tools/:name`
|
|
6
|
+
|
|
7
|
+
Decision: **nested `/api/...` REST** (7.0)
|
|
8
|
+
|
|
9
|
+
### Context
|
|
10
|
+
|
|
11
|
+
- v6 exposed tools as `POST /tools/:flat-name` with hyphen-joined paths
|
|
12
|
+
- Nested resources (e.g. `workspaces/{id}`) and verb-specific methods need a route model aligned with the CLI tree
|
|
13
|
+
|
|
14
|
+
### Rationale
|
|
15
|
+
|
|
16
|
+
1. Command tree already encodes hierarchy — REST paths mirror `http.segment ?? key` plus `:param` routers
|
|
17
|
+
2. Verb leaves (`get`, `post`, …) map to HTTP methods without duplicating path segments
|
|
18
|
+
3. OpenAPI paths match real URLs clients call; query/body binding matches MCP flat args
|
|
19
|
+
4. Hard break on `/tools/*` is acceptable pre-7.0-ship
|
|
20
|
+
|
|
21
|
+
## Validation: JSON-SCHEMA vs Zod, etc
|
|
22
|
+
|
|
23
|
+
Decision: JSON-SCHEMA
|
|
24
|
+
|
|
25
|
+
### Context
|
|
26
|
+
- JSON-SCHEMA is an open standard to capture a schema in json
|
|
27
|
+
- Zod is the leading Typescript schema management library
|
|
28
|
+
- Others are similar or less good than Zod
|
|
29
|
+
|
|
30
|
+
### Rational
|
|
31
|
+
Zod may actually cause more complexity and little/no gain for consumers.
|
|
32
|
+
|
|
33
|
+
Yes Zod implements some features we do custom for JSON-SCHEMA, but is opinionated, less flexible, and would actually explode complexity in some situations. Zod could be a win for consumers if they require substantial, complex validation -- but then that may not convert well to json-schema anyways and json-schema generation is a big win.
|
|
34
|
+
|
|
35
|
+
1. Argsbarg does a lot of schema patching/manipulation to create different schemas per target (cli-schema.json, MCP contract, openapi.json). This would be harder with Zod
|
|
36
|
+
2. Consumers can already use zod if they want by using Zod's to-json-schema features to convert when passing to Argsbarg. So we aren't actually alienating / thwarting consumers from using Zod anyways.
|
|
37
|
+
3. For uses like API pass-through, proxy, dynamic schemas, Zod may actually explode complexity for consumers.
|
|
38
|
+
4. Our TS->json-schema approach is actually easier and better in many cases
|
|
39
|
+
- Just write plain typescript, done.
|
|
40
|
+
- Better intellisense -- substantially less abstraction/inference, much better control
|
package/docs/developing.md
CHANGED
|
@@ -32,14 +32,28 @@ Sibling consumer repos (machine-specific paths in the root `justfile` `consumer_
|
|
|
32
32
|
|
|
33
33
|
| Recipe | When | Effect |
|
|
34
34
|
| --- | --- | --- |
|
|
35
|
-
| `just consumers-dev` | Before publish; hacking on argsbarg locally | `bun add argsbarg@file:<relative>`; refresh `.cursor/rules/cli-program.mdc` from template (keeps app-specific suffix) |
|
|
36
|
-
| `just consumers-sync` | After release | Sets `"argsbarg": "^<this package.json version>"`, `bun install`, merge **
|
|
35
|
+
| `just consumers-dev` | Before publish; hacking on argsbarg locally | `bun add argsbarg@file:<relative>`; refresh `.cursor/rules/cli-program.mdc` and `code.mdc` from template (keeps app-specific suffix) |
|
|
36
|
+
| `just consumers-sync` | After release | Sets `"argsbarg": "^<this package.json version>"`, `bun install`, merge **cli-program** + **code** Cursor rules, `just build`, `just docgen`, `just install-local` (Homebrew dev formula + agent artifacts; `just install` is an alias) |
|
|
37
|
+
| `just consumers-schemagen` | After `@sg` type changes in consumers | Runs `argsbarg schemagen` in each `consumer_apps` path (fails if missing) |
|
|
37
38
|
|
|
38
39
|
`consumers-sync` reads the version from **this repo’s** `package.json` — not npm. Run it **after** `just release` so consumers pin a version that exists on the registry.
|
|
39
40
|
|
|
40
|
-
**Argsbarg authoring
|
|
41
|
+
**Argsbarg authoring rules** — `scripts/merge-cli-program-rule.ts` and `scripts/merge-code-rule.ts` copy templates from `examples/full-example/.cursor/rules/` into each consumer, preserving any existing `**… conventions:**` footer block.
|
|
41
42
|
|
|
42
|
-
**Recommended in each consumer:** replace
|
|
43
|
+
**Recommended in each consumer:** replace template placeholders with `**<app> conventions:**` bullets. Commit those files; merges refresh the shared top, not your footer.
|
|
44
|
+
|
|
45
|
+
## Upgrading consumer apps to 7.0
|
|
46
|
+
|
|
47
|
+
Breaking changes (no backward compat). See [CHANGELOG.md](../CHANGELOG.md) `[Unreleased]`.
|
|
48
|
+
|
|
49
|
+
1. **Schemagen:** replace `export type configType|inputType|outputType` with `/** @sg */` immediately above `export interface` / `export type` (no blank line).
|
|
50
|
+
2. **Imports:** `configSchema` → `{AppConfig}Schema` (type name + `Schema`); same for leaf `inputSchema` / `outputSchema` imports (`StatusJsonOutputSchema`, etc.).
|
|
51
|
+
3. **Run** `argsbarg schemagen` (or `just schemagen`) after every type change.
|
|
52
|
+
4. **HTTP:** use `/api/...` REST routes only (`POST /tools/*` removed).
|
|
53
|
+
5. **Hooks:** remove manual `ctx.locals.requestId` in `beforeInvoke` — framework seeds it.
|
|
54
|
+
6. **Exports:** stop importing `loadLeafInputs` / `CliHttpResponseConfig` from `argsbarg` (use `ctx.inputs`, leaf `http.successContentType`).
|
|
55
|
+
7. **Cursor rules:** `just consumers-dev` merges `cli-program.mdc` + `code.mdc` (includes **Abstractions** needless-extraction rule).
|
|
56
|
+
8. **Verify:** `just test` and `just docgen` in each consumer repo.
|
|
43
57
|
|
|
44
58
|
**Consumer app skill** — `just install-local` in each consumer (part of `consumers-sync`) runs Homebrew dev install then `myapp configure --sync --yes`, which updates `~/.cursor/skills/<app>/` from that app’s schema — not the argsbarg framework rule.
|
|
45
59
|
|
|
@@ -60,7 +74,31 @@ just full-example-schemagen
|
|
|
60
74
|
just test
|
|
61
75
|
```
|
|
62
76
|
|
|
63
|
-
See [
|
|
77
|
+
See [docs/README.md](README.md) for the full documentation map.
|
|
78
|
+
|
|
79
|
+
## Advanced imports
|
|
80
|
+
|
|
81
|
+
Subpath exports (root barrel still re-exports everything):
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import { Cli, type CliProgram } from "argsbarg/cli";
|
|
85
|
+
import { generateOpenApi, httpServeHttp } from "argsbarg/http";
|
|
86
|
+
import { packMcpBundle } from "argsbarg/mcp"; // @experimental
|
|
87
|
+
import { shouldRunHeadless } from "argsbarg/headless";
|
|
88
|
+
import { runSchemagen } from "argsbarg/schemagen";
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Module boundaries
|
|
92
|
+
|
|
93
|
+
| Layer | Role |
|
|
94
|
+
| --- | --- |
|
|
95
|
+
| `schema.ts`, `parse.ts`, `context.ts` | Transport-agnostic CLI core |
|
|
96
|
+
| `http/` | HTTP tool server (`httpServer` capability) |
|
|
97
|
+
| `mcp/` | MCP stdio server and bundle (`mcpServer` capability) |
|
|
98
|
+
| `configure/artifacts/` | Agent artifact sync (`configure` capability) |
|
|
99
|
+
| `docs/` | Built-in documentation generators |
|
|
100
|
+
|
|
101
|
+
Capabilities are declared on `CliProgram`; builtins wire them in [`src/builtins/`](../src/builtins/).
|
|
64
102
|
|
|
65
103
|
## Docs
|
|
66
104
|
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# HTTP API server
|
|
2
|
+
|
|
3
|
+
ArgsBarg can expose your CLI as an HTTP REST server. Each **leaf command** becomes a route under `/api/...` — nested command paths, HTTP verbs, and `:param` routers are reflected in the URL. 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 `httpServer` on the program root behave exactly as before.
|
|
6
|
+
|
|
7
|
+
## Quick start
|
|
8
|
+
|
|
9
|
+
1. Add `httpServer` 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
|
+
httpServer: { enabled: true },
|
|
19
|
+
commands: [/* ... */],
|
|
20
|
+
} satisfies CliProgram;
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`httpServer: { enabled: true }` opts in. Omit `httpServer` entirely to disable HTTP. Empty `httpServer: {}` is rejected at validation.
|
|
24
|
+
|
|
25
|
+
2. Run the HTTP server:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
myapp http
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The process listens until interrupted. Startup prints the listen URL to stderr.
|
|
32
|
+
|
|
33
|
+
Optional flags on `myapp http` (and `myapp http serve`): `--host`, `--port`, `--trust-proxy`, `--obscure-errors`, `--log-format`, `--log-file`, `--no-access-log`, `--dev`.
|
|
34
|
+
|
|
35
|
+
## Configuration
|
|
36
|
+
|
|
37
|
+
Set `httpServer` on the **program root only**. Validation rejects `httpServer` on nested nodes.
|
|
38
|
+
|
|
39
|
+
| Field | Default | Purpose |
|
|
40
|
+
| --- | --- | --- |
|
|
41
|
+
| `enabled` | *(required)* | Must be `true` when `httpServer` is set |
|
|
42
|
+
| `host` | `127.0.0.1` | Listen address |
|
|
43
|
+
| `port` | `3000` | Listen port |
|
|
44
|
+
| `trustProxy` | `false` | Honor `X-Forwarded-For` in hooks and access logs |
|
|
45
|
+
| `errors.errorSchema` | `{ error: string }` | OpenAPI + default error body shape |
|
|
46
|
+
| `errors.obscureUnexpected` | `false` | Client sees generic message on 500; ECS logs real stack |
|
|
47
|
+
| `hooks` | — | Observe-only wire hooks (`onRequest`, `onResponse`, `onError`) |
|
|
48
|
+
|
|
49
|
+
`httpServer` and `mcpServer` are independent — enable either or both.
|
|
50
|
+
|
|
51
|
+
Program-level `program.log` controls ECS JSON vs human text on stderr (and optional file tee). See [docs/decisions.md](decisions.md).
|
|
52
|
+
|
|
53
|
+
## REST routes
|
|
54
|
+
|
|
55
|
+
Routes are derived from the command tree:
|
|
56
|
+
|
|
57
|
+
| CLI path | HTTP | Notes |
|
|
58
|
+
| --- | --- | --- |
|
|
59
|
+
| `workspaces get` | `GET /api/workspaces` | Verb leaf (`get`) omitted from URL |
|
|
60
|
+
| `workspaces post` | `POST /api/workspaces` | Default POST success **201** |
|
|
61
|
+
| `workspaces :id get` | `GET /api/workspaces/{id}` | `:id` param router |
|
|
62
|
+
| `stat owner lookup` | `POST /api/stat/owner/lookup` | Default method POST when key is not a verb |
|
|
63
|
+
|
|
64
|
+
Method precedence: `leaf.http.method` → verb key (`get`/`post`/…) → **POST**.
|
|
65
|
+
|
|
66
|
+
Query string binds to options (values starting with `{` or `[` are JSON-parsed). Body on POST/PUT/PATCH binds to options, positionals, and `inputSchema` fields.
|
|
67
|
+
|
|
68
|
+
Per-surface exposure: `http.enabled: false` removes a leaf from the route table; `http.hidden: true` keeps it callable but omits it from OpenAPI.
|
|
69
|
+
|
|
70
|
+
## Endpoints
|
|
71
|
+
|
|
72
|
+
| Method | Path | Purpose |
|
|
73
|
+
| --- | --- | --- |
|
|
74
|
+
| `GET` | `/health` or `/health/live` | Liveness — 200 when server is listening |
|
|
75
|
+
| `GET` | `/health/ready` | Readiness — config + optional `program.readiness` |
|
|
76
|
+
| `GET` | `/openapi.json` | OpenAPI 3.1 REST paths |
|
|
77
|
+
| `GET` | `/openapi-browser` | Interactive Scalar API reference (CDN) |
|
|
78
|
+
| `*` | `/api/...` | Invoke user commands (method per route) |
|
|
79
|
+
| `OPTIONS` | `*` | CORS preflight (`GET, POST, PUT, PATCH, DELETE`) |
|
|
80
|
+
|
|
81
|
+
`POST /tools/*` was removed in 7.0 — use `/api/*` only.
|
|
82
|
+
|
|
83
|
+
## Examples
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
curl -s http://127.0.0.1:3000/health
|
|
87
|
+
curl -s http://127.0.0.1:3000/health/ready
|
|
88
|
+
curl -s http://127.0.0.1:3000/openapi.json
|
|
89
|
+
open http://127.0.0.1:3000/openapi-browser
|
|
90
|
+
curl -s http://127.0.0.1:3000/api/workspaces
|
|
91
|
+
curl -s -X POST http://127.0.0.1:3000/api/workspaces \
|
|
92
|
+
-H 'content-type: application/json' \
|
|
93
|
+
-d '{"name":"qa2"}'
|
|
94
|
+
curl -s http://127.0.0.1:3000/api/workspaces/{id}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Discover paths and request shapes from `openapi.json` or `myapp docs openapi`.
|
|
98
|
+
|
|
99
|
+
## Handler responses (`ctx.respond()`)
|
|
100
|
+
|
|
101
|
+
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.
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
handler: (ctx) => {
|
|
105
|
+
if (ctx.hasFlag("json")) {
|
|
106
|
+
return { user: "alice", path: "/tmp" };
|
|
107
|
+
}
|
|
108
|
+
ctx.respond({
|
|
109
|
+
body: pdfBytes,
|
|
110
|
+
contentType: "application/pdf",
|
|
111
|
+
headers: { "Content-Disposition": 'inline; filename="invoice.pdf"' },
|
|
112
|
+
});
|
|
113
|
+
},
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**CLI mode:** `ctx.respond()` prints to stdout. Handlers may still use `console.log` for human-only CLI output.
|
|
117
|
+
|
|
118
|
+
### Leaf HTTP metadata
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
http?: {
|
|
122
|
+
method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
123
|
+
segment?: string; // URL segment override
|
|
124
|
+
successStatus?: number;
|
|
125
|
+
successContentType?: string; // OpenAPI + default Content-Type
|
|
126
|
+
contentDisposition?: string;
|
|
127
|
+
};
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Responses
|
|
131
|
+
|
|
132
|
+
**Success:** status from `ctx.respond({ status })` → `http.successStatus` → method default (GET 200, POST 201, DELETE 204 without body).
|
|
133
|
+
|
|
134
|
+
| Body type | HTTP `Content-Type` |
|
|
135
|
+
| --- | --- |
|
|
136
|
+
| object / array | `application/json` |
|
|
137
|
+
| string | handler `contentType` or `text/plain` |
|
|
138
|
+
| `Uint8Array` | e.g. `application/pdf` (set explicitly) |
|
|
139
|
+
|
|
140
|
+
**Errors:** JSON `{ "error": "..." }` by default (override with `httpServer.errors.errorSchema`).
|
|
141
|
+
|
|
142
|
+
| Situation | Status |
|
|
143
|
+
| --- | --- |
|
|
144
|
+
| Validation / help | 400 |
|
|
145
|
+
| Unknown route | 404 |
|
|
146
|
+
| Thrown handler / missing `ctx.respond()` | 500 |
|
|
147
|
+
| Missing required config | 503 |
|
|
148
|
+
|
|
149
|
+
Tool invocations are **not** gated on `/health/ready`; readiness is for orchestrators only.
|
|
150
|
+
|
|
151
|
+
## Hooks and runtime
|
|
152
|
+
|
|
153
|
+
`program.hooks` (`beforeInvoke`, `afterInvoke`, `formatError`, `onError`) run for user commands on CLI, HTTP, and MCP — **not** for builtins.
|
|
154
|
+
|
|
155
|
+
- `ctx.locals` — per-request bag (fresh each invoke); framework sets `requestId` before `beforeInvoke` (HTTP/MCP wire id when present, else a new UUID)
|
|
156
|
+
- `ctx.runtime` — shared `ServerRuntime.state` on HTTP/MCP server sessions
|
|
157
|
+
- `ctx.pathParams` — values from `:param` routers
|
|
158
|
+
|
|
159
|
+
Error order: `formatError` → `onError` → ECS log → client response.
|
|
160
|
+
|
|
161
|
+
## CORS
|
|
162
|
+
|
|
163
|
+
All responses include wide-open CORS headers (`Access-Control-Allow-Origin: *`). Not configurable in v1.
|
|
164
|
+
|
|
165
|
+
## OpenAPI
|
|
166
|
+
|
|
167
|
+
Call `generateOpenApi(program)` from `argsbarg/http`, fetch `GET /openapi.json`, or run `myapp docs openapi --save`. Nested `$ref` in input/output schemas are dereferenced in the spec.
|
|
168
|
+
|
|
169
|
+
## Complex tool inputs
|
|
170
|
+
|
|
171
|
+
Set `inputSchema` on the leaf and read coerced values with `ctx.inputs` / `ctx.inputsAs<T>()`. HTTP query, body, and path params merge into inputs before validation.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# JSON Schema subset
|
|
2
|
+
|
|
3
|
+
Argsbarg validates `program.appConfig`, leaf `inputSchema`, and related documents with a **custom Draft-07 subset** in [`src/config/validate.ts`](../src/config/validate.ts). There is no runtime dependency on a full JSON Schema validator.
|
|
4
|
+
|
|
5
|
+
Use this page when authoring schemas for config files, `inputSchema` on leaves, or `@sg` schemagen output.
|
|
6
|
+
|
|
7
|
+
## Supported constructs
|
|
8
|
+
|
|
9
|
+
| Feature | Notes |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| `type` | `object`, `array`, `string`, `integer`, `number`, `boolean`, `null` |
|
|
12
|
+
| `properties` / `required` | Object keys; `additionalProperties: false` enforced when set |
|
|
13
|
+
| `items` | Homogeneous arrays; comma-separated CLI strings coerced when `items` is a primitive |
|
|
14
|
+
| `enum` / `const` | Exact value checks |
|
|
15
|
+
| `anyOf` / `oneOf` | First matching branch wins; errors surface when none match |
|
|
16
|
+
| `$ref` | **Local only** — `#/definitions/Name` resolved within the same root document |
|
|
17
|
+
| `definitions` | Companion to local `$ref` |
|
|
18
|
+
| `format` | `date`, `date-time`, `duration`, `comma-list` (and related string coercions) |
|
|
19
|
+
| `minimum` / `maximum` | Numbers and integers |
|
|
20
|
+
| `minLength` / `maxLength` | Strings |
|
|
21
|
+
| `pattern` | String regex (ECMAScript) |
|
|
22
|
+
|
|
23
|
+
## Partial validation
|
|
24
|
+
|
|
25
|
+
`validateConfigDocumentPartial` validates **present keys only** — root `required` is skipped. Used for `configure set` partial writes and bootstrap flows.
|
|
26
|
+
|
|
27
|
+
Leaf `inputSchema` validation uses full validation (including `required`) before the handler runs.
|
|
28
|
+
|
|
29
|
+
## Not supported (today)
|
|
30
|
+
|
|
31
|
+
- Remote `$ref` (`http://…`, other files)
|
|
32
|
+
- `allOf`, conditional (`if`/`then`/`else`), `not`
|
|
33
|
+
- Unevaluated / dynamic references
|
|
34
|
+
- `default` application at validation time (defaults come from CLI option `default` or config bindings)
|
|
35
|
+
|
|
36
|
+
If schemagen emits an unsupported keyword, simplify the TypeScript type or post-process the generated JSON Schema.
|
|
37
|
+
|
|
38
|
+
## Where validation runs
|
|
39
|
+
|
|
40
|
+
| Surface | Validator | When |
|
|
41
|
+
| --- | --- | --- |
|
|
42
|
+
| App config file | `validateConfigDocument` / `Partial` | `configure set`, config load |
|
|
43
|
+
| Leaf `inputSchema` | Same engine via leaf-inputs | Before handler (MCP/HTTP/CLI merged inputs) |
|
|
44
|
+
| `outputSchema` | Structural checks at program validate time | Startup / `cliValidateProgram` |
|
|
45
|
+
|
|
46
|
+
## Related docs
|
|
47
|
+
|
|
48
|
+
- [cli-program.md](cli-program.md) — `inputSchema`, JSON leaves, `ctx.inputs` / `ctx.inputsAs`
|
|
49
|
+
- [config-schema.md](config-schema.md) — `program.appConfig` and schemagen pipeline
|
|
50
|
+
|
|
51
|
+
Implementation: [`src/config/validate.ts`](../src/config/validate.ts), [`src/core/leaf-inputs.ts`](../src/core/leaf-inputs.ts).
|
package/docs/mcp.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# MCP server
|
|
2
2
|
|
|
3
|
+
> This feature is experimental.
|
|
4
|
+
|
|
3
5
|
ArgsBarg can expose your CLI to AI agents through the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/). Each **leaf command** becomes an MCP tool; the full command tree is available as a schema resource. The server speaks JSON-RPC over stdio — one JSON object per line on stdin and stdout.
|
|
4
6
|
|
|
5
7
|
MCP is **opt-in**. Apps that do not set `mcpServer` on the program root behave exactly as before.
|
|
@@ -246,7 +248,7 @@ The built-in schema resource (default URI `<sanitized-key>://schema`, e.g. `nest
|
|
|
246
248
|
|
|
247
249
|
### Auto docs topic resources
|
|
248
250
|
|
|
249
|
-
When
|
|
251
|
+
When docs is enabled (default) and **`mcpServer.enabled`** is true, each user key in **`docs.topics`** is also exposed as an MCP resource:
|
|
250
252
|
|
|
251
253
|
| Property | Value |
|
|
252
254
|
| --- | --- |
|
|
@@ -419,7 +421,7 @@ Bare **`myapp mcp`** still runs the stdio MCP server (unchanged for `configure`
|
|
|
419
421
|
|
|
420
422
|
## Hidden commands and options
|
|
421
423
|
|
|
422
|
-
Set **`hidden: true`** on a command or option to omit it from help listings, `docs cli-schema` / `docs
|
|
424
|
+
Set **`hidden: true`** on a command or option to omit it from help listings, `docs cli-schema` / `docs cli`, shell completions, and MCP `tools/list` / tool `inputSchema`. Hidden commands remain invocable; **`myapp hidden-cmd -h`** still works.
|
|
423
425
|
|
|
424
426
|
## Reserved names
|
|
425
427
|
|
package/docs/output-schema.md
CHANGED
|
@@ -7,12 +7,12 @@ How to describe JSON stdout on leaf commands — and the **argsbarg schemagen**
|
|
|
7
7
|
On **leaf commands**, set `outputSchema` to a JSON Schema object when the handler emits JSON (typically with `--json`, always for JSON-only commands, or on the MCP headless path).
|
|
8
8
|
|
|
9
9
|
```typescript
|
|
10
|
-
import {
|
|
10
|
+
import { StatusJsonOutputSchema } from "./__generated__";
|
|
11
11
|
|
|
12
12
|
export const status = {
|
|
13
13
|
key: "status",
|
|
14
14
|
description: "Show environment status.",
|
|
15
|
-
outputSchema,
|
|
15
|
+
outputSchema: StatusJsonOutputSchema,
|
|
16
16
|
handler: async (ctx) => { /* writes JSON to stdout */ },
|
|
17
17
|
} satisfies CliLeaf;
|
|
18
18
|
```
|
|
@@ -20,14 +20,14 @@ export const status = {
|
|
|
20
20
|
| Where argsbarg uses it | Purpose |
|
|
21
21
|
| --- | --- |
|
|
22
22
|
| `myapp docs cli-schema` | Full command tree JSON export |
|
|
23
|
-
| `myapp docs
|
|
23
|
+
| `myapp docs cli` | 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 |
|
|
26
26
|
| HTTP `GET /openapi.json` | Response schema per tool |
|
|
27
27
|
|
|
28
28
|
**Not validated at runtime** — argsbarg does not parse or reject handler stdout against the schema today. The schema is documentation and MCP/HTTP metadata.
|
|
29
29
|
|
|
30
|
-
**Set on the leaf only** — not under `mcpTool
|
|
30
|
+
**Set on the leaf only** — not under `mcpTool`.
|
|
31
31
|
|
|
32
32
|
**Draft version** — argsbarg accepts any JSON Schema object (`type`, `properties`, `definitions`, etc.). Generators may emit draft-07 or draft 2020-12; docgen embeds the object as-is.
|
|
33
33
|
|
|
@@ -38,7 +38,7 @@ See [cli-program.md — Structured stdout](cli-program.md#structured-stdout) for
|
|
|
38
38
|
| Approach | When |
|
|
39
39
|
| --- | --- |
|
|
40
40
|
| **Inline object** on the leaf | One-off commands, spikes, very small shapes |
|
|
41
|
-
| **Codegen from TypeScript** | Multiple commands share a shape, nested objects, or you want rich `description` fields in `docs
|
|
41
|
+
| **Codegen from TypeScript** | Multiple commands share a shape, nested objects, or you want rich `description` fields in `docs cli` / skills |
|
|
42
42
|
|
|
43
43
|
Production CLIs with several JSON commands tend to use **codegen** so types, handlers, and schemas stay aligned.
|
|
44
44
|
|
|
@@ -50,137 +50,129 @@ Reference implementations: **sqsp-qa-manager-poc**, **sqsp-workspaces**, **sqsp-
|
|
|
50
50
|
|
|
51
51
|
```mermaid
|
|
52
52
|
flowchart LR
|
|
53
|
-
subgraph
|
|
54
|
-
|
|
55
|
-
Output["export type outputType = StatusJsonOutput"]
|
|
56
|
-
Input["export type inputType = ToolInput (optional)"]
|
|
53
|
+
subgraph src [src/**/*.ts]
|
|
54
|
+
Sg["/** @sg */ export interface TypeName"]
|
|
57
55
|
end
|
|
58
56
|
subgraph gen [argsbarg schemagen]
|
|
59
|
-
|
|
57
|
+
Walk["walk src/ minus tests and __generated__"]
|
|
60
58
|
Gen["ts-json-schema-generator"]
|
|
61
59
|
end
|
|
62
60
|
subgraph artifacts [Gitignored __generated__]
|
|
63
|
-
Json["
|
|
61
|
+
Json["TypeNameSchema.json"]
|
|
64
62
|
Index["index.ts re-exports"]
|
|
65
63
|
end
|
|
66
64
|
subgraph runtime [Runtime]
|
|
67
|
-
Leaves["import {
|
|
65
|
+
Leaves["import { TypeNameSchema } from ./__generated__"]
|
|
68
66
|
Docgen["just docgen"]
|
|
69
67
|
end
|
|
70
|
-
|
|
68
|
+
src --> Walk --> Gen --> Json
|
|
71
69
|
Gen --> Index --> Leaves --> Docgen
|
|
72
70
|
```
|
|
73
71
|
|
|
74
72
|
| Piece | Convention |
|
|
75
73
|
| --- | --- |
|
|
76
74
|
| Generator | [`ts-json-schema-generator`](https://github.com/vega/ts-json-schema-generator) (bundled as an argsbarg dependency) |
|
|
77
|
-
| Discovery | Walk `src
|
|
78
|
-
| Artifacts | `
|
|
75
|
+
| Discovery | Walk `src/**/*.ts` (exclude `*.test.ts`, `__generated__/`); find `/** @sg */` JSDoc immediately followed by `export interface` or `export type` |
|
|
76
|
+
| Artifacts | One `__generated__/` per source directory; `{TypeName}Schema.json` + `export const {TypeName}Schema` in `index.ts` |
|
|
79
77
|
| Invocation | `just schemagen` — justfile exports `node_modules/.bin` on `PATH` for local `argsbarg` |
|
|
80
78
|
| tsconfig | `"resolveJsonModule": true` |
|
|
81
79
|
| CI | `just check`: `schemagen` → typecheck (no git diff on generated files) |
|
|
82
|
-
| Cleanup | Schemagen removes orphan `__generated__/` dirs and stale JSON when roots
|
|
83
|
-
| Docgen | `docgen` depends on `schemagen` so saved `./docs/
|
|
80
|
+
| Cleanup | Schemagen removes orphan `__generated__/` dirs and stale JSON when roots are removed |
|
|
81
|
+
| Docgen | `docgen` depends on `schemagen` so saved `./docs/cli.md` and `./docs/cli-schema.json` are fresh |
|
|
84
82
|
|
|
85
83
|
### Declaring a schema root
|
|
86
84
|
|
|
87
|
-
|
|
85
|
+
Mark any exported interface or type with `/** @sg */` on the line immediately above the declaration (no blank line):
|
|
88
86
|
|
|
89
87
|
```typescript
|
|
90
88
|
// src/commands/status/types.ts
|
|
91
|
-
/**
|
|
89
|
+
/** @sg */
|
|
92
90
|
export interface StatusJsonOutput {
|
|
93
|
-
|
|
91
|
+
version: string;
|
|
94
92
|
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Handlers import types from the same module; leaves import schemas from `./__generated__`:
|
|
95
96
|
|
|
96
|
-
|
|
97
|
-
|
|
97
|
+
```typescript
|
|
98
|
+
import { StatusJsonOutputSchema } from "./__generated__";
|
|
98
99
|
```
|
|
99
100
|
|
|
100
|
-
|
|
101
|
+
Shared shapes in one directory share one `__generated__/index.ts`:
|
|
101
102
|
|
|
102
103
|
```typescript
|
|
103
|
-
// src/ui/runHeadless/types.ts
|
|
104
|
+
// src/ui/runHeadless/types.ts
|
|
105
|
+
/** @sg */
|
|
104
106
|
export interface HeadlessOpResult {
|
|
105
107
|
command: string;
|
|
106
108
|
exitCode: number;
|
|
107
109
|
tasks: HeadlessTaskResult[];
|
|
108
110
|
}
|
|
109
|
-
|
|
110
|
-
export type outputType = HeadlessOpResult;
|
|
111
111
|
```
|
|
112
112
|
|
|
113
113
|
```typescript
|
|
114
|
-
// src/commands/render-invoice/types.ts
|
|
114
|
+
// src/commands/render-invoice/types.ts
|
|
115
|
+
/** @sg */
|
|
115
116
|
export interface RenderInvoiceInput {
|
|
116
117
|
format: "pdf" | "html";
|
|
117
118
|
invoice: InvoiceData;
|
|
118
119
|
}
|
|
119
120
|
|
|
121
|
+
/** @sg */
|
|
120
122
|
export interface RenderInvoiceOutput {
|
|
121
123
|
bytes: number;
|
|
122
124
|
}
|
|
123
|
-
|
|
124
|
-
export type inputType = RenderInvoiceInput;
|
|
125
|
-
export type outputType = RenderInvoiceOutput;
|
|
126
125
|
```
|
|
127
126
|
|
|
128
|
-
|
|
129
|
-
| --- | --- |
|
|
130
|
-
| `export type configType = AppConfig` | `program.appConfig.jsonSchema` (one per repo, typically `src/config/types.ts`) |
|
|
131
|
-
| `export type outputType = …` | `leaf.outputSchema` |
|
|
132
|
-
| `export type inputType = …` | `leaf.inputSchema` (only when the tool body is not flat CLI flags) |
|
|
127
|
+
Wire on the leaf or `program.appConfig`:
|
|
133
128
|
|
|
134
|
-
|
|
129
|
+
| Generated export | Typical use |
|
|
130
|
+
| --- | --- |
|
|
131
|
+
| `AppConfigSchema` | `program.appConfig.jsonSchema` (optional — `src/config/types.ts`) |
|
|
132
|
+
| `StatusJsonOutputSchema` | `leaf.outputSchema` |
|
|
133
|
+
| `RenderInvoiceInputSchema` | `leaf.inputSchema` |
|
|
135
134
|
|
|
136
|
-
For nested MCP/HTTP bodies, add a `kind: Json` option (same name as the
|
|
135
|
+
For nested MCP/HTTP bodies, add a `kind: Json` option (same name as the schema property) and use `ctx.jsonOpt(...)`, `ctx.inputs`, or `ctx.inputsAs<T>()` — see [cli-program.md](cli-program.md#json-options-and-piped-stdin).
|
|
137
136
|
|
|
138
137
|
When you do **not** set `inputSchema`, argsbarg builds tool input from CLI `options` + `positionals`.
|
|
139
138
|
|
|
140
139
|
### Generated artifacts
|
|
141
140
|
|
|
142
|
-
Schemagen writes under `__generated__/` beside
|
|
141
|
+
Schemagen writes under `__generated__/` beside the `@sg` source files in each directory:
|
|
143
142
|
|
|
144
|
-
|
|
|
143
|
+
| Type name | Generated file | Exported const |
|
|
145
144
|
| --- | --- | --- |
|
|
146
|
-
|
|
|
147
|
-
|
|
|
148
|
-
| input | `inputSchema.json` | `inputSchema` |
|
|
145
|
+
| `StatusJsonOutput` | `StatusJsonOutputSchema.json` | `StatusJsonOutputSchema` |
|
|
146
|
+
| `RenderInvoiceInput` | `RenderInvoiceInputSchema.json` | `RenderInvoiceInputSchema` |
|
|
149
147
|
|
|
150
148
|
Wire on the leaf:
|
|
151
149
|
|
|
152
150
|
```typescript
|
|
153
|
-
import {
|
|
151
|
+
import { StatusJsonOutputSchema } from "./__generated__";
|
|
154
152
|
|
|
155
153
|
export const statusCommand = {
|
|
156
|
-
outputSchema,
|
|
154
|
+
outputSchema: StatusJsonOutputSchema,
|
|
157
155
|
// …
|
|
158
156
|
} satisfies CliLeaf;
|
|
159
157
|
```
|
|
160
158
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
```typescript
|
|
164
|
-
import { outputSchema } from "../../../ui/runHeadless/__generated__/index.ts";
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
App config:
|
|
159
|
+
App config (when used):
|
|
168
160
|
|
|
169
161
|
```typescript
|
|
170
|
-
import {
|
|
162
|
+
import { AppConfigSchema } from "./config/__generated__";
|
|
171
163
|
|
|
172
|
-
appConfig: { jsonSchema:
|
|
164
|
+
appConfig: { jsonSchema: AppConfigSchema, entries: { … } },
|
|
173
165
|
```
|
|
174
166
|
|
|
175
167
|
## Schema-facing types
|
|
176
168
|
|
|
177
|
-
**Goal:** generated schemas match what handlers actually print, with descriptions agents can read in `docs
|
|
169
|
+
**Goal:** generated schemas match what handlers actually print, with descriptions agents can read in `docs cli`.
|
|
178
170
|
|
|
179
|
-
1. **Schema roots** — `export interface`
|
|
171
|
+
1. **Schema roots** — `/** @sg */` immediately above `export interface` or `export type`, with per-field JSDoc.
|
|
180
172
|
2. **Per property** — `/** … */` on every field that should appear in JSON Schema `properties` (including nested named types).
|
|
181
173
|
3. **Unions / enums** — document the alias; generator emits `enum` / `anyOf` with type-level description.
|
|
182
174
|
4. **Formats** — property JSDoc can include `@format date-time` for ISO timestamps; add a smoke test that the generated property has `format: "date-time"`.
|
|
183
|
-
5. **Do not hand-edit** `__generated__/` — change types/JSDoc in
|
|
175
|
+
5. **Do not hand-edit** `__generated__/` — change types/JSDoc in source files, run `just schemagen`.
|
|
184
176
|
|
|
185
177
|
### Narrowing when runtime ≠ stdout
|
|
186
178
|
|
|
@@ -193,7 +185,8 @@ export interface TranslationReadinessResult {
|
|
|
193
185
|
evaluatedAt: string;
|
|
194
186
|
}
|
|
195
187
|
|
|
196
|
-
|
|
188
|
+
/** @sg */
|
|
189
|
+
export interface TranslationReadinessResult {
|
|
197
190
|
```
|
|
198
191
|
|
|
199
192
|
Patterns:
|
|
@@ -213,15 +206,15 @@ Per consumer repo (optional):
|
|
|
213
206
|
|
|
214
207
|
## Contributor workflow
|
|
215
208
|
|
|
216
|
-
1. Add or edit
|
|
209
|
+
1. Add or edit `/** @sg */` roots in `src/**/*.ts` with per-field JSDoc.
|
|
217
210
|
2. `just schemagen` — refresh `src/**/__generated__/`.
|
|
218
|
-
3. Import `{
|
|
219
|
-
4. `just docgen` / `myapp docs
|
|
211
|
+
3. Import `{ TypeNameSchema }` from the relevant `./__generated__` barrel.
|
|
212
|
+
4. `just docgen` / `myapp docs cli --save` — refresh consumer docs.
|
|
220
213
|
5. Document which commands use which roots in **your** `docs/architecture.md` (argsbarg does not maintain per-app tables).
|
|
221
214
|
|
|
222
215
|
Add a bullet under your app’s `**… conventions:**` block in `.cursor/rules/cli-program.mdc` pointing at `node_modules/argsbarg/docs/output-schema.md`.
|
|
223
216
|
|
|
224
|
-
**Reference implementation:** [`examples/full-example/`](../examples/full-example/) in this repo — `types
|
|
217
|
+
**Reference implementation:** [`examples/full-example/`](../examples/full-example/) in this repo — `@sg` on command types, `__generated__/`, and `status` leaf with `StatusJsonOutputSchema`.
|
|
225
218
|
|
|
226
219
|
## Out of scope
|
|
227
220
|
|
|
@@ -233,5 +226,5 @@ Add a bullet under your app’s `**… conventions:**` block in `.cursor/rules/c
|
|
|
233
226
|
- [config-schema.md](config-schema.md) — `configType` / `program.appConfig`
|
|
234
227
|
- [cli-program.md](cli-program.md) — structured stdout, headless JSON, `read*Flags`
|
|
235
228
|
- [mcp.md](mcp.md) — `tools/list`, `structuredContent`
|
|
236
|
-
- [bundled-docs.md](bundled-docs.md) — `docs
|
|
229
|
+
- [bundled-docs.md](bundled-docs.md) — `docs cli` / `docs cli-schema` docgen
|
|
237
230
|
- [docs/README.md](README.md) — documentation map
|