argsbarg 2.1.1 → 3.1.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 CHANGED
@@ -7,6 +7,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [3.1.0] - 2026-06-20
11
+
12
+ ### Added
13
+
14
+ - **`docs` built-in** — opt in with `docs: { enabled: true, topics: { ... } }` on the program root. Bundled markdown topics on stdout (`myapp docs`, `myapp docs readme`, `myapp docs all`). Auto **`docs mcp`** guide when `docs` and `mcpServer` are both enabled. See [docs/bundled-docs.md](docs/bundled-docs.md).
15
+
16
+ ### Changed
17
+
18
+ - **Agent skills** — `SKILL.md` is shell-only (removed MCP setup, `mcp.json`, and `tools/call` content). Use `docs mcp` or MCP tools for agent execution guidance.
19
+
20
+ ## [3.0.0] - 2026-06-20
21
+
22
+ ### Added
23
+
24
+ - **`version` built-in** — `myapp version` prints `CliProgram.version` (always available; reserved command name).
25
+
26
+ ### Changed
27
+
28
+ - **`CliProgram.version`** (required) — single source of truth for the `version` built-in and MCP `serverInfo.version`. Removed `mcpServer.version` and automatic `package.json` lookup.
29
+ - **MCP opt-in** — `mcpServer: { enabled: true }` enables MCP; omit `mcpServer` to disable. Empty `mcpServer: {}` is rejected at validation.
30
+ - **MCP identity from `key`** — removed `mcpServer.name`. MCP `serverInfo.name`, schema URI, and `mcp.json` entry keys use `sanitizeToolSegment(root.key)` (e.g. `nested.ts` → `nested_ts://schema`). Shell `command` stays the raw `key`.
31
+
10
32
  ## [2.1.1] - 2026-06-20
11
33
 
12
34
  ### Changed
@@ -186,7 +208,9 @@ const cli = { ... } satisfies CliProgram; // or : CliProgram
186
208
  - 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`).
187
209
  - Imports: use `CliPositional` where needed; replace `CliOptionDef` with `CliOption` or `CliPositional` as appropriate.
188
210
 
189
- [Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v2.1.1...HEAD
211
+ [Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v3.1.0...HEAD
212
+ [3.1.0]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.1.0
213
+ [3.0.0]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.0.0
190
214
  [2.1.1]: https://github.com/bdombro/bun-argsbarg/releases/tag/v2.1.1
191
215
  [2.1.0]: https://github.com/bdombro/bun-argsbarg/releases/tag/v2.1.0
192
216
  [2.0.1]: https://github.com/bdombro/bun-argsbarg/releases/tag/v2.0.1
package/README.md CHANGED
@@ -16,7 +16,7 @@ Why another CLI parser?
16
16
 
17
17
  *Shell completions* — `completion bash`, `completion zsh`, and `completion fish` built-ins generate installable scripts from your schema so users get tab completion for commands, flags, and positionals without extra tooling.
18
18
 
19
- *Optional MCP server* — set `mcpServer: {}` on the program root to expose leaf commands as MCP tools and the full CLI tree as a schema resource (`myapp mcp` over stdio). See [docs/mcp.md](docs/mcp.md). Compiled binaries can install binary, completions, skills, and MCP config with `myapp install` — see [docs/install.md](docs/install.md).
19
+ *Optional MCP server* — set `mcpServer: { enabled: true }` on the program root to expose leaf commands as MCP tools and the full CLI tree as a schema resource (`myapp mcp` over stdio). See [docs/mcp.md](docs/mcp.md). Compiled binaries can install binary, completions, skills, and MCP config with `myapp install` — see [docs/install.md](docs/install.md).
20
20
 
21
21
  *Bun-optimized* — built from the ground up for Bun and TypeScript, leveraging Bun’s performance and modern JavaScript features without any extra dependencies.
22
22
 
@@ -39,6 +39,7 @@ import { cliRun, type CliProgram, CliOptionKind } from "argsbarg";
39
39
 
40
40
  const cli = {
41
41
  key: "helloapp",
42
+ version: "1.0.0",
42
43
  description: "Tiny demo.",
43
44
  positionals: [
44
45
  {
@@ -96,17 +97,20 @@ Every app gets:
96
97
  - `-h` / `--help` at any routing depth (scoped help).
97
98
  - **`--schema`** at the program root — print the full command tree as JSON (for tooling and agents).
98
99
  - **`completion bash` / `completion zsh` / `completion fish`** — print shell completion scripts to stdout (injected by `cliRun`).
99
- - **`mcp`** — when `mcpServer` is set on the program root, run as an MCP stdio server (`myapp mcp`).
100
+ - **`version`** — print `CliProgram.version` (`myapp version`).
101
+ - **`mcp`** — when `mcpServer.enabled` is `true`, run as an MCP stdio server (`myapp mcp`).
102
+ - **`docs`** — when `docs.enabled` is `true`, print bundled markdown topics (`myapp docs`, `myapp docs readme`, …). See [docs/bundled-docs.md](docs/bundled-docs.md).
100
103
  - **`install`** — install the binary, completions, skills, and MCP config to the user environment (`myapp install --all --yes`). See [docs/install.md](docs/install.md).
101
104
 
102
- Do not declare a top-level command named **`completion`** or **`install`** — they are reserved.
103
- When **`mcpServer`** is set, do not declare a top-level command named **`mcp`** — it is reserved for the MCP built-in.
105
+ Do not declare a top-level command named **`completion`**, **`version`**, or **`install`** — they are reserved.
106
+ When **`mcpServer.enabled`** is `true`, do not declare a top-level command named **`mcp`** — it is reserved for the MCP built-in.
107
+ When **`docs.enabled`** is `true`, do not declare a top-level command named **`docs`** — it is reserved for the docs built-in.
104
108
  Do not declare an option named **`schema`** — it is reserved for `--schema`.
105
109
 
106
110
 
107
111
  ### MCP (AI agents)
108
112
 
109
- Opt in on the program root with `mcpServer: {}` (or `{ name, version, … }`), then run `myapp mcp` for a stdio MCP server. Each leaf command becomes a tool; the CLI tree is available as resource `argsbarg://schema`. Handlers can read `ctx.invocation` and use `cliInvoke` for headless testing.
113
+ 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 --schema`). Handlers can read `ctx.invocation` and use `cliInvoke` for headless testing.
110
114
 
111
115
  See **[docs/mcp.md](docs/mcp.md)** for configuration, env bootstrapping, custom resources, Cursor setup, and protocol details.
112
116
 
@@ -185,7 +189,7 @@ Add `CliPositional` entries to the command’s `positionals` list (separate from
185
189
 
186
190
  ### Capabilities (built-ins)
187
191
 
188
- `completion`, `install`, and `mcp` are not part of your schema — they are injected at runtime from program-level config (`mcpServer`, `install`). Reserved command names follow from that config: `completion` and `install` are always reserved unless `install.enabled: false`; `mcp` is reserved when `mcpServer` is set.
192
+ `completion`, `version`, `install`, and `mcp` are not part of your schema — they are injected at runtime from program-level config (`mcpServer`, `install`). Reserved command names: `completion` and `version` always; `install` unless `install.enabled: false`; `mcp` when `mcpServer.enabled` is `true`.
189
193
 
190
194
 
191
195
 
@@ -226,7 +230,7 @@ The package root (`argsbarg` / `src/index.ts`) exports the types and runtime you
226
230
  | `cliInvoke(root, argv)` | Parse and dispatch without exiting; returns captured stdout/stderr. |
227
231
  | `cliErrWithHelp(ctx, msg)` | Print error + scoped help on stderr, exit 1. |
228
232
 
229
- Reserved identifiers (validated at startup): root commands **`completion`**, **`install`**, and **`mcp`** (only when `mcpServer` is set).
233
+ Reserved identifiers (validated at startup): root commands **`completion`**, **`version`**, **`install`**, **`docs`** (when `docs.enabled` is `true`), and **`mcp`** (when `mcpServer.enabled` is `true`).
230
234
 
231
235
  ---
232
236
 
package/bun.lock ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "lockfileVersion": 1,
3
+ "configVersion": 1,
4
+ "workspaces": {
5
+ "": {
6
+ "name": "argsbarg",
7
+ "devDependencies": {
8
+ "@types/bun": "^1.3.12",
9
+ },
10
+ },
11
+ },
12
+ "packages": {
13
+ "@types/bun": ["@types/bun@1.3.14", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="],
14
+
15
+ "@types/node": ["@types/node@26.0.0", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-vf2YFi1iY9lHGwNJMs01biZFbKJkrZR1T6/MlzjhJLPdntOHLhTrDSnSVcdtvjihi4VQNlrFRIxLsDBlQpAipA=="],
16
+
17
+ "bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="],
18
+
19
+ "undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="],
20
+ }
21
+ }
package/docs/ai-skills.md CHANGED
@@ -31,17 +31,21 @@ For library use, call `cliSkillInstall(root, "cursor" | "claude", { global: true
31
31
 
32
32
  ## Generated content
33
33
 
34
- - **`SKILL.md`** — YAML frontmatter, when-to-use guidance, command catalog, MCP setup hints
34
+ - **`SKILL.md`** — YAML frontmatter, when-to-use guidance, shell command catalog, pitfalls
35
35
  - **`reference.md`** — full `--schema` JSON export
36
36
 
37
- ## MCP vs skills
37
+ Skills describe **shell invocation only** — no MCP setup, `mcp.json`, or `tools/call` guidance. Use **`myapp docs mcp`** (when `docs` and `mcpServer` are enabled) or connect the MCP server for agent execution.
38
+
39
+ ## MCP vs skills vs docs
38
40
 
39
41
  | Mechanism | Role |
40
42
  | --- | --- |
41
43
  | **`myapp mcp`** (requires `mcpServer`) | Runtime tool execution over MCP |
42
- | **`myapp install --skill`** | Static discovery files for agents |
44
+ | **`myapp install --skill`** | Static shell command catalog for agents |
45
+ | **`myapp docs`** (requires `docs`) | Bundled markdown on stdout (`docs mcp` when MCP enabled) |
43
46
 
44
47
  See also:
45
48
 
49
+ - [Bundled docs](bundled-docs.md) — `docs` config and compile-time imports
46
50
  - [MCP server](mcp.md) — `mcpServer` config and `mcp` protocol
47
51
  - [Install](install.md) — binary, completions, skills, and MCP config
@@ -0,0 +1,77 @@
1
+ # Bundled documentation (`docs`)
2
+
3
+ ArgsBarg can expose bundled markdown topics as the built-in `docs` command group. Opt in on the program root with `docs: { enabled: true, topics: { ... } }`.
4
+
5
+ ## Quick start
6
+
7
+ ```typescript
8
+ import readmeText from "../README.md" with { type: "text" };
9
+ import archText from "../docs/architecture.md" with { type: "text" };
10
+
11
+ const cli = {
12
+ key: "myapp",
13
+ version: "1.0.0",
14
+ description: "My app.",
15
+ docs: {
16
+ enabled: true,
17
+ topics: {
18
+ readme: { text: readmeText },
19
+ architecture: { text: archText, description: "Contributor architecture notes." },
20
+ },
21
+ },
22
+ commands: [/* ... */],
23
+ } satisfies CliProgram;
24
+ ```
25
+
26
+ ```bash
27
+ myapp docs # first topic (readme) via fallback
28
+ myapp docs readme
29
+ myapp docs architecture
30
+ myapp docs all # all user topics; includes auto mcp when MCP enabled
31
+ myapp docs mcp # auto-generated when mcpServer.enabled
32
+ ```
33
+
34
+ ## Configuration
35
+
36
+ | Field | Default | Purpose |
37
+ | --- | --- | --- |
38
+ | `enabled` | *(required)* | Must be `true` when `docs` is set |
39
+ | `description` | `"Print bundled CLI documentation."` | Router help for `myapp docs` |
40
+ | `defaultTopic` | first key in `topics` | `fallbackCommand` for bare `myapp docs` |
41
+ | `topics` | *(required)* | Topic key → `{ text, description? }` |
42
+
43
+ Reserved topic keys in `topics`: **`mcp`**, **`all`** (supplied by the built-in).
44
+
45
+ When `description` is omitted on a topic, ArgsBarg generates leaf help (`readme` → "Print README (user guide).").
46
+
47
+ ## Compile-time bundling
48
+
49
+ Topic `text` must be **bundled markdown strings**. Use Bun text imports in the consumer module graph:
50
+
51
+ ```typescript
52
+ import readmeText from "../README.md" with { type: "text" };
53
+ ```
54
+
55
+ Bun embeds the file when you `bun build --compile`. ArgsBarg does not read the filesystem at runtime.
56
+
57
+ For several topics, use a barrel file (e.g. `src/docs/topics.ts`) so `index.tsx` stays small.
58
+
59
+ ## MCP guide (`docs mcp`)
60
+
61
+ When both `docs.enabled` and `mcpServer.enabled` are `true`, ArgsBarg injects a **`docs mcp`** topic with an auto-generated guide: tool list, `requiresEnv`, schema resource URI, `install --mcp`, and protocol notes.
62
+
63
+ There is no override API in v1 — customize behavior via `mcpTool.description` on leaf commands.
64
+
65
+ ## MCP tools
66
+
67
+ All `docs` subcommands are hidden from MCP `tools/list` (`mcpTool: { enabled: false }`).
68
+
69
+ ## Skills vs docs vs MCP
70
+
71
+ | Channel | Role |
72
+ | --- | --- |
73
+ | `install --skill` | Shell command catalog + `--schema` JSON (no MCP setup) |
74
+ | `docs` | Bundled markdown on stdout |
75
+ | `mcp` | Callable tools + schema resource |
76
+
77
+ Do not declare a top-level command named **`docs`** when `docs.enabled` is `true` — it is reserved.
package/docs/install.md CHANGED
@@ -30,7 +30,7 @@ myapp install --uninstall --yes
30
30
  | Claude skill | `--skill` | `~/.claude/skills/<dir>/` when `~/.claude` exists |
31
31
  | MCP config | `--mcp` | `~/.cursor/mcp.json` and `~/.claude.json` when MCP is enabled |
32
32
 
33
- `--all` expands to `--bin`, `--completions`, `--skill`, and `--mcp` (when `mcpServer` is set).
33
+ `--all` expands to `--bin`, `--completions`, `--skill`, and `--mcp` (when `mcpServer.enabled` is `true`).
34
34
 
35
35
  Shells not on PATH are skipped silently (no warnings).
36
36
 
@@ -64,7 +64,7 @@ Environment:
64
64
 
65
65
  ## MCP merge behavior
66
66
 
67
- When `--mcp` runs, entries are merged into `mcpServers[<name>]` with:
67
+ When `--mcp` runs, entries are merged into `mcpServers[<sanitized-key>]` with:
68
68
 
69
69
  ```json
70
70
  { "command": "<root.key>", "args": ["mcp"] }
package/docs/mcp.md CHANGED
@@ -9,15 +9,18 @@ MCP is **opt-in**. Apps that do not set `mcpServer` on the program root behave e
9
9
  1. Add `mcpServer` to your program root:
10
10
 
11
11
  ```typescript
12
+ import pkg from "../package.json" with { type: "json" };
13
+
12
14
  const cli = {
13
15
  key: "myapp",
16
+ version: pkg.version,
14
17
  description: "My app.",
15
- mcpServer: { name: "myapp", version: "1.0.0" },
18
+ mcpServer: { enabled: true },
16
19
  commands: [/* ... */],
17
20
  } satisfies CliProgram;
18
21
  ```
19
22
 
20
- `mcpServer: {}` is enough to enable the server. Optional fields override defaults (see [Configuration](#configuration)).
23
+ `mcpServer: { enabled: true }` opts in. Omit `mcpServer` entirely to disable MCP. Empty `mcpServer: {}` is rejected at validation.
21
24
 
22
25
  2. Run the MCP server:
23
26
 
@@ -66,26 +69,27 @@ Set `mcpServer` on the **program root only** (the `CliProgram` passed to `cliRun
66
69
 
67
70
  | Field | Default | Purpose |
68
71
  | --- | --- | --- |
69
- | `name` | root `key` | `serverInfo.name` in the `initialize` response |
70
- | `version` | `package.json` `version` in cwd, else `"0.0.0"` | `serverInfo.version` |
71
- | `schemaResourceUri` | `"argsbarg://schema"` | URI for the schema resource |
72
+ | `enabled` | *(required)* | Must be `true` when `mcpServer` is set |
73
+ | `schemaResourceUri` | `<sanitized root key>://schema` | URI for the built-in schema resource |
72
74
  | `shellEnv` | off | Capture login-shell `env` at startup (`true` uses `$SHELL`, or pass a shell path) |
73
75
  | `envFile` | off | Load a `.env` file after `shellEnv` (`~` supported); warns on stderr if missing |
74
- | `resources` | `[]` | Custom `CliMcpResource` entries for `resources/list` and `resources/read` |
76
+ | `resources` | `[]` | Custom `CliMcpResource` entries (additive; schema resource is always included) |
77
+
78
+ MCP `serverInfo.name` and the default schema URI use the sanitized program `key` (non-alphanumeric characters become `_`). Program `version` comes from `CliProgram.version` (also used by the `version` built-in).
75
79
 
76
- Example with all fields:
80
+ Example with optional fields:
77
81
 
78
82
  ```typescript
79
83
  mcpServer: {
80
- name: "nested-demo",
81
- version: "1.0.0",
82
- schemaResourceUri: "argsbarg://schema",
84
+ enabled: true,
85
+ shellEnv: true,
86
+ envFile: "~/.config/myapp/mcp.env",
83
87
  }
84
88
  ```
85
89
 
86
90
  ## Tools
87
91
 
88
- Every **user-defined leaf command** in your schema becomes one MCP tool. Built-ins (`completion`, `ai`) are not exposed as tools.
92
+ Every **user-defined leaf command** in your schema becomes one MCP tool. Built-ins (`completion`, `version`, `install`, `mcp`) are not exposed as tools.
89
93
 
90
94
  ### Tool names
91
95
 
@@ -172,11 +176,11 @@ Help and `--schema` are not available through tool calls; use the schema resourc
172
176
 
173
177
  ## Schema and custom resources
174
178
 
175
- The built-in resource `argsbarg://schema` (or `schemaResourceUri`) exposes your full CLI tree as JSON — the same output as `myapp --schema`.
179
+ 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 --schema`. Override with `schemaResourceUri` if needed.
176
180
 
177
181
  | Property | Value |
178
182
  | --- | --- |
179
- | Default URI | `argsbarg://schema` |
183
+ | Default URI | `<sanitized root key>://schema` |
180
184
  | MIME type | `application/json` |
181
185
  | Contents | `cliSchemaJson(root)` — handlers omitted, built-ins excluded |
182
186
 
@@ -184,6 +188,7 @@ Add custom resources on the program root:
184
188
 
185
189
  ```typescript
186
190
  mcpServer: {
191
+ enabled: true,
187
192
  resources: [
188
193
  {
189
194
  uri: "myapp://config",
@@ -9,10 +9,10 @@ const envFilePath = process.env.ARGS_TEST_ENV_FILE;
9
9
 
10
10
  const cli = {
11
11
  key: "mcp-test",
12
+ version: "0.0.0-test",
12
13
  description: "MCP integration test fixture.",
13
14
  mcpServer: {
14
- name: "mcp-test",
15
- version: "0.0.0-test",
15
+ enabled: true,
16
16
  ...(envFilePath ? { envFile: envFilePath } : {}),
17
17
  resources: [
18
18
  {
@@ -7,10 +7,12 @@ readers can copy the pattern into their own scripts quickly.
7
7
  It demonstrates the minimal Bun integration path.
8
8
  */
9
9
 
10
+ import pkg from "../package.json" with { type: "json" };
10
11
  import { cliRun, CliProgram, CliOptionKind } from "../src/index.ts";
11
12
 
12
13
  const cli = {
13
14
  key: "minimal.ts",
15
+ version: pkg.version,
14
16
  description: "Tiny demo.",
15
17
  positionals: [
16
18
  {
@@ -7,12 +7,20 @@ and fallback commands fit together in one schema.
7
7
  It demonstrates how the schema scales beyond one command.
8
8
  */
9
9
 
10
+ import pkg from "../package.json" with { type: "json" };
10
11
  import { cliRun, CliProgram, CliOptionKind, CliFallbackMode } from "../src/index.ts";
11
12
 
12
13
  const cli = {
13
14
  key: "nested.ts",
15
+ version: pkg.version,
14
16
  description: "Nested groups demo.",
15
- mcpServer: { name: "nested-demo", version: "1.0.0" },
17
+ mcpServer: { enabled: true },
18
+ docs: {
19
+ enabled: true,
20
+ topics: {
21
+ readme: { text: "# nested.ts\n\nNested groups demo.\n" },
22
+ },
23
+ },
16
24
  commands: [
17
25
  {
18
26
  key: "stat",
@@ -7,10 +7,12 @@ readers can copy the pattern into their own scripts quickly.
7
7
  It demonstrates the minimal Bun integration path.
8
8
  */
9
9
 
10
+ import pkg from "../package.json" with { type: "json" };
10
11
  import { cliRun, CliProgram, CliOptionKind, CliFallbackMode, isInteractiveTty } from "../src/index.ts";
11
12
 
12
13
  const cli = {
13
14
  key: "option-required.ts",
15
+ version: pkg.version,
14
16
  description: "Demo of a required option.",
15
17
  options: [
16
18
  {
package/index.d.ts CHANGED
@@ -106,13 +106,12 @@ export interface CliPositional {
106
106
  }
107
107
  /**
108
108
  * Enables `myapp mcp` and MCP stdio server metadata (program root only).
109
+ * Must include `enabled: true`; omit `mcpServer` entirely to disable MCP.
109
110
  */
110
111
  export interface CliMcpServerConfig {
111
- /** `initialize` serverInfo.name (default: root `key`). */
112
- name?: string;
113
- /** `initialize` serverInfo.version (default: see resolveMcpVersion). */
114
- version?: string;
115
- /** Resource URI for schema export (default: `"argsbarg://schema"`). */
112
+ /** When `true`, enables the `mcp` built-in and MCP stdio server. */
113
+ enabled: boolean;
114
+ /** Resource URI for schema export (default: `<sanitized root key>://schema`). */
116
115
  schemaResourceUri?: string;
117
116
  /**
118
117
  * Capture the user's login shell environment at MCP server start and merge it
@@ -127,7 +126,7 @@ export interface CliMcpServerConfig {
127
126
  */
128
127
  envFile?: string;
129
128
  /**
130
- * Custom MCP resources exposed alongside the built-in argsbarg://schema resource.
129
+ * Custom MCP resources exposed alongside the built-in schema resource.
131
130
  * URIs must be unique and must not equal schemaResourceUri.
132
131
  */
133
132
  resources?: CliMcpResource[];
@@ -174,6 +173,32 @@ export interface CliInstallConfig {
174
173
  /** Default bin directory (default: `~/.local/bin`). Overridden by `INSTALL_PREFIX` env and `--prefix`. */
175
174
  prefix?: string;
176
175
  }
176
+ /**
177
+ * One bundled documentation topic for the `docs` built-in (program root only).
178
+ */
179
+ export interface CliDocsTopic {
180
+ /** Bundled markdown (use compile-time text imports in the consumer). */
181
+ text: string;
182
+ /** Leaf help text for `myapp docs <key> -h`. Auto-generated from key when omitted. */
183
+ description?: string;
184
+ }
185
+ /**
186
+ * Enables `myapp docs` and bundled markdown topics (program root only).
187
+ * Must include `enabled: true`; omit `docs` entirely to disable.
188
+ */
189
+ export interface CliDocsConfig {
190
+ /** When `true`, enables the `docs` built-in command group. */
191
+ enabled: boolean;
192
+ /** Router description for `myapp docs` (default: "Print bundled CLI documentation."). */
193
+ description?: string;
194
+ /**
195
+ * Subcommand for bare `myapp docs` (maps to router `fallbackCommand`).
196
+ * When omitted, uses the first key in `topics` (insertion order).
197
+ */
198
+ defaultTopic?: string;
199
+ /** Topic key → bundled markdown. Reserved keys: `mcp`, `all` (supplied by the built-in). */
200
+ topics: Record<string, CliDocsTopic>;
201
+ }
177
202
  /**
178
203
  * Base properties shared by all nodes in the user command tree.
179
204
  */
@@ -218,10 +243,14 @@ export type CliNode = CliLeaf | CliRouter;
218
243
  * May be a leaf or router, plus optional program-level MCP and install config.
219
244
  */
220
245
  export type CliProgram = CliNode & {
221
- /** When set, enables the `mcp` built-in subcommand. */
246
+ /** Program version (printed by the `version` built-in and MCP serverInfo). */
247
+ version: string;
248
+ /** When set with `enabled: true`, enables the `mcp` built-in subcommand. */
222
249
  mcpServer?: CliMcpServerConfig;
223
250
  /** Opt-out and defaults for `install`. */
224
251
  install?: CliInstallConfig;
252
+ /** When set with `enabled: true`, enables the `docs` built-in command group. */
253
+ docs?: CliDocsConfig;
225
254
  };
226
255
  /**
227
256
  * Handler closure type for leaf commands.
package/package.json CHANGED
@@ -1,7 +1,10 @@
1
1
  {
2
2
  "name": "argsbarg",
3
- "version": "2.1.1",
3
+ "version": "3.1.0",
4
4
  "type": "module",
5
+ "engines": {
6
+ "bun": ">=1.3"
7
+ },
5
8
  "scripts": {
6
9
  "//just": "echo this app uses justfile for development tasks"
7
10
  },
@@ -8,8 +8,9 @@ import { CliProgram } from "../types.ts";
8
8
 
9
9
  const fixture: CliProgram = {
10
10
  key: "myapp",
11
+ version: "0.0.0",
11
12
  description: "Demo app.",
12
- mcpServer: { name: "myapp" },
13
+ mcpServer: { enabled: true },
13
14
  commands: [
14
15
  {
15
16
  key: "hello",
@@ -31,7 +32,7 @@ describe("builtins help copy", () => {
31
32
  });
32
33
 
33
34
  test("install omits --mcp option when mcpServer unset", () => {
34
- const noMcp: CliProgram = { key: "x", description: "x", handler: () => {} };
35
+ const noMcp: CliProgram = { key: "x", version: "0.0.0", description: "x", handler: () => {} };
35
36
  const names = installBuiltinOptions(noMcp).map((o) => o.name);
36
37
  expect(names).not.toContain("mcp");
37
38
  });
@@ -56,6 +57,10 @@ describe("presentation root", () => {
56
57
  const root = cliPresentationRoot(disabled);
57
58
  expect(root.commands?.map((c) => c.key)).not.toContain("install");
58
59
  });
60
+ test("includes version builtin", () => {
61
+ const root = cliPresentationRoot(fixture);
62
+ expect(root.commands?.map((c) => c.key)).toContain("version");
63
+ });
59
64
  });
60
65
 
61
66
  describe("completion emitters", () => {
@@ -75,7 +80,7 @@ describe("completion emitters", () => {
75
80
  });
76
81
 
77
82
  test("zsh script registers compdef", () => {
78
- const schema = cliPresentationRoot({ key: "zapp", description: "z", handler: () => {} });
83
+ const schema = cliPresentationRoot({ key: "zapp", version: "0.0.0", description: "z", handler: () => {} });
79
84
  const zsh = completionZshScript(schema);
80
85
  expect(zsh).toContain("#compdef zapp");
81
86
  expect(zsh).toContain("compdef _zapp zapp");
@@ -6,8 +6,10 @@ import { completionFishScript } from "./completion-fish.ts";
6
6
  import { completionZshScript } from "./completion-zsh.ts";
7
7
  import { cliBuiltinInstallCommand } from "./install.ts";
8
8
  import { cliBuiltinMcpCommand } from "./mcp.ts";
9
+ import { cliBuiltinVersionCommand } from "./version.ts";
9
10
  import { cliBuiltinCompletionGroup as completionGroup } from "./completion-group.ts";
10
11
  import { cliPresentationRoot } from "./presentation.ts";
12
+ import { cliBuiltinDocsGroupIfEnabled } from "../docs/builtin.ts";
11
13
  import { cliMcpServeStdio } from "../mcp.ts";
12
14
  import { cliInstall } from "../install/index.ts";
13
15
  import type { ParseResult } from "../parse.ts";
@@ -56,9 +58,18 @@ export async function dispatchBuiltin(
56
58
  return;
57
59
  }
58
60
 
61
+ if (pr.path[0] === "version") {
62
+ if (pr.path.length !== 1) {
63
+ process.stderr.write("Unknown subcommand: version " + pr.path.slice(1).join(" ") + "\n");
64
+ process.exit(1);
65
+ }
66
+ process.stdout.write(program.version + "\n");
67
+ process.exit(0);
68
+ }
69
+
59
70
  if (pr.path[0] === "mcp") {
60
71
  if (!caps.mcp) {
61
- process.stderr.write("MCP is not enabled. Set mcpServer on the program root.\n");
72
+ process.stderr.write("MCP is not enabled. Set mcpServer: { enabled: true } on the program root.\n");
62
73
  process.exit(1);
63
74
  }
64
75
  if (pr.path.length !== 1) {
@@ -127,5 +138,28 @@ export function builtinInterceptRoot(
127
138
  };
128
139
  }
129
140
 
141
+ if (first === "version") {
142
+ return {
143
+ parseRoot: {
144
+ key: program.key,
145
+ description: program.description,
146
+ commands: [cliBuiltinVersionCommand()],
147
+ },
148
+ isLeafCompletionIntercept: false,
149
+ };
150
+ }
151
+
152
+ const docsGroup = cliBuiltinDocsGroupIfEnabled(program);
153
+ if (first === "docs" && docsGroup) {
154
+ return {
155
+ parseRoot: {
156
+ key: program.key,
157
+ description: program.description,
158
+ commands: [docsGroup],
159
+ },
160
+ isLeafCompletionIntercept: false,
161
+ };
162
+ }
163
+
130
164
  return { parseRoot: program, isLeafCompletionIntercept: false };
131
165
  }
@@ -3,6 +3,8 @@ import type { CliFallbackMode, CliOption, CliPositional, CliProgram } from "../t
3
3
  import { cliBuiltinCompletionGroup } from "./completion-group.ts";
4
4
  import { cliBuiltinInstallCommand } from "./install.ts";
5
5
  import { cliBuiltinMcpCommand } from "./mcp.ts";
6
+ import { cliBuiltinVersionCommand } from "./version.ts";
7
+ import { cliBuiltinDocsGroupIfEnabled } from "../docs/builtin.ts";
6
8
 
7
9
  /** JSON-safe command node (no handlers). */
8
10
  export interface CliSchemaExport {
@@ -42,10 +44,17 @@ function exportBuiltinNode(cmd: {
42
44
  /** Built-in subtrees matching help visibility for `--schema` export. */
43
45
  export function exportPresentationBuiltins(program: CliProgram, caps?: CliCapabilities): CliSchemaExport[] {
44
46
  const resolved = caps ?? resolveCapabilities(program);
45
- const builtins: CliSchemaExport[] = [exportBuiltinNode(cliBuiltinCompletionGroup(program.key))];
47
+ const builtins: CliSchemaExport[] = [
48
+ exportBuiltinNode(cliBuiltinCompletionGroup(program.key)),
49
+ exportBuiltinNode(cliBuiltinVersionCommand()),
50
+ ];
46
51
  if (resolved.install) {
47
52
  builtins.push(exportBuiltinNode(cliBuiltinInstallCommand(program)));
48
53
  }
54
+ const docsGroup = cliBuiltinDocsGroupIfEnabled(program);
55
+ if (docsGroup) {
56
+ builtins.push(exportBuiltinNode(docsGroup));
57
+ }
49
58
  if (resolved.mcp) {
50
59
  builtins.push(exportBuiltinNode(cliBuiltinMcpCommand()));
51
60
  }
@@ -1,3 +1,4 @@
1
+ import { resolveCapabilities } from "../capabilities.ts";
1
2
  import { CliProgram, CliOption, CliOptionKind, type CliLeaf } from "../types.ts";
2
3
 
3
4
  /** Install command options (dynamic: `--mcp` only when MCP is enabled). */
@@ -66,7 +67,7 @@ export function installBuiltinOptions(root: CliProgram): CliOption[] {
66
67
  },
67
68
  ];
68
69
 
69
- if (root.mcpServer !== undefined) {
70
+ if (resolveCapabilities(root).mcp) {
70
71
  opts.splice(4, 0, {
71
72
  name: "mcp",
72
73
  description: "Add or update MCP server entries in Cursor and Claude config files.",
@@ -5,13 +5,22 @@ import { isCliLeaf, isCliRouter } from "../types.ts";
5
5
  import { cliBuiltinCompletionGroup } from "./completion-group.ts";
6
6
  import { cliBuiltinInstallCommand } from "./install.ts";
7
7
  import { cliBuiltinMcpCommand } from "./mcp.ts";
8
+ import { cliBuiltinVersionCommand } from "./version.ts";
9
+ import { cliBuiltinDocsGroupIfEnabled } from "../docs/builtin.ts";
8
10
 
9
11
  /** Built-in command nodes injected for help, schema, and completions. */
10
12
  export function presentationBuiltins(program: CliProgram, caps: CliCapabilities): CliNode[] {
11
- const builtins: CliNode[] = [cliBuiltinCompletionGroup(program.key)];
13
+ const builtins: CliNode[] = [
14
+ cliBuiltinCompletionGroup(program.key),
15
+ cliBuiltinVersionCommand(),
16
+ ];
12
17
  if (caps.install) {
13
18
  builtins.push(cliBuiltinInstallCommand(program));
14
19
  }
20
+ const docsGroup = cliBuiltinDocsGroupIfEnabled(program);
21
+ if (docsGroup) {
22
+ builtins.push(docsGroup);
23
+ }
15
24
  if (caps.mcp) {
16
25
  builtins.push(cliBuiltinMcpCommand());
17
26
  }
@@ -0,0 +1,10 @@
1
+ import { type CliLeaf } from "../types.ts";
2
+
3
+ /** Top-level `version` built-in (leaf). */
4
+ export function cliBuiltinVersionCommand(): CliLeaf {
5
+ return {
6
+ key: "version",
7
+ description: "Print the program version.",
8
+ handler: () => {},
9
+ };
10
+ }