argsbarg 3.6.2 → 3.6.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 CHANGED
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [3.6.3] - 2026-06-23
11
+
12
+ ### Added
13
+
14
+ - **`docs/README.md`** — documentation map (framework vs consumer docgen).
15
+ - **`docs/developing.md`** — maintainer workflow (`consumer-dev`, `consumers-sync`, npm `files`).
16
+ - **`examples/formats.ts`** — `CliValueFormat`, `default`, and `readLeafInputs()` demo.
17
+
18
+ ### Changed
19
+
20
+ - **`cli-program.md`** — `CliLeafInputs` / `readLeafInputs()` semantics, upgrading to 3.6+, read-once-resolve-once cross-links.
21
+ - **`bundled-docs.md`** — framework docs vs consumer docgen.
22
+ - **`docs/mcp.md`** — varargs JSON array only (fixes stale comma-string guidance).
23
+
10
24
  ## [3.6.2] - 2026-06-23
11
25
 
12
26
  ### Added
@@ -399,7 +413,8 @@ const cli = { ... } satisfies CliProgram; // or : CliProgram
399
413
  - 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`).
400
414
  - Imports: use `CliPositional` where needed; replace `CliOptionDef` with `CliOption` or `CliPositional` as appropriate.
401
415
 
402
- [Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v3.6.2...HEAD
416
+ [Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v3.6.3...HEAD
417
+ [3.6.3]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.6.3
403
418
  [3.6.2]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.6.2
404
419
  [3.6.1]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.6.1
405
420
  [3.6.0]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.6.0
package/README.md CHANGED
@@ -155,7 +155,7 @@ mkdir -p .cursor/rules
155
155
  cp node_modules/argsbarg/docs/templates/cursor/rules/cli-program.mdc .cursor/rules/cli-program.mdc
156
156
  ```
157
157
 
158
- Add app-specific conventions in a second rule if needed. Full guide: **[docs/cli-program.md](docs/cli-program.md)**.
158
+ Add app-specific conventions in a second rule if needed. Documentation map: **[docs/README.md](docs/README.md)**. Authoring guide: **[docs/cli-program.md](docs/cli-program.md)**.
159
159
 
160
160
 
161
161
  ## How it works
@@ -214,6 +214,7 @@ Check the `examples/` directory for full working scripts:
214
214
  | --- | --- | --- |
215
215
  | `ArgsBargMinimal` | `examples/minimal.ts` | String + presence flags, `MissingOrUnknown` fallback. |
216
216
  | `ArgsBargNested` | `examples/nested.ts` | Nested command tree, positional tails, async handlers. |
217
+ | `ArgsBargFormats` | `examples/formats.ts` | `CliValueFormat`, `default`, `readLeafInputs()`. |
217
218
 
218
219
  ```bash
219
220
  export PATH="$PATH:$(pwd)/examples"
@@ -225,6 +226,8 @@ minimal.ts hello --name world
225
226
  eval "$(nested.ts completion zsh)"
226
227
  nested.ts stat owner lookup -u alice ./README.md
227
228
  nested.ts read ./README.md
229
+
230
+ bun ./examples/formats.ts run --tags demo,docs --on 2026-06-22
228
231
  ```
229
232
 
230
233
 
@@ -238,7 +241,8 @@ The package root (`argsbarg` / `src/index.ts`) exports the types and runtime you
238
241
  | `CliProgram`, `CliOption`, `CliPositional`, `CliHandler` | Schema and handler types. |
239
242
  | `CliOptionKind`, `CliValueFormat`, `CliFallbackMode` | Option kinds, value formats (`duration`, `comma-list`, `date`, `date-time`), and root fallback behavior. |
240
243
  | `CliSchemaValidationError` | Thrown when the static command tree violates schema rules. |
241
- | `CliContext` | Handler context (`ctx.flag`, `ctx.stringOpt`, `ctx.durationOpt`, `ctx.readLeafInputs`, `ctx.invocation`, …). |
244
+ | `CliContext` | Handler context (`ctx.hasFlag`, `ctx.stringOpt`, `ctx.durationOpt`, `ctx.readLeafInputs`, `ctx.invocation`, …). |
245
+ | `CliLeafInputs` | Record type returned by `readLeafInputs()` — coerced option/positional values keyed by schema name. |
242
246
  | `cliRun(root, [argv])` | Validate, parse argv, dispatch, exit. |
243
247
  | `cliInvoke(root, argv)` | Parse and dispatch without exiting; returns captured stdout/stderr. |
244
248
  | `cliErrWithHelp(ctx, msg)` | Print error + scoped help on stderr, exit 1. |
package/docs/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # Argsbarg documentation
2
+
3
+ Start here to pick the right guide.
4
+
5
+ | If you are… | Read |
6
+ | --- | --- |
7
+ | **New to argsbarg** | [../README.md](../README.md) — install, minimal usage, public API |
8
+ | **Authoring a `CliProgram`** (humans or agents) | [cli-program.md](cli-program.md) — schema, formats, headless, `read*Flags` |
9
+ | **Exposing MCP tools** | [mcp.md](mcp.md) — stdio server, `inputSchema`, varargs, `install --mcp` |
10
+ | **Shipping install / completions / skills** | [install.md](install.md) — `myapp install`, shell completions |
11
+ | **Bundling `myapp docs` topics** | [bundled-docs.md](bundled-docs.md) — consumer docgen vs framework docs |
12
+ | **Agent skills** | [ai-skills.md](ai-skills.md) — `install --skill`, `docs skill` |
13
+ | **Maintaining the argsbarg repo** | [developing.md](developing.md) — release, consumers, npm `files` |
14
+ | **Cursor / IDE agents in a consumer app** | Copy [templates/cursor/rules/cli-program.mdc](templates/cursor/rules/cli-program.mdc) to `.cursor/rules/` |
15
+
16
+ ## Framework docs vs consumer docgen
17
+
18
+ | Source | What it is | Where it lives |
19
+ | --- | --- | --- |
20
+ | **Framework docs** | How argsbarg works; authoring conventions | This directory — shipped in `node_modules/argsbarg/docs/` after `bun add argsbarg` |
21
+ | **Consumer docgen** | *Your* command tree, API, MCP guide for *your* app | `myapp docs api`, `docs schema`, `docs mcp` — written to `./docs/` with `--save` |
22
+ | **Cursor rule** | Thin tripwire telling agents to read framework docs | `node_modules/argsbarg/docs/templates/cursor/rules/cli-program.mdc` — copy into your repo and append app conventions |
23
+
24
+ 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.
25
+
26
+ ## Examples
27
+
28
+ | Example | Shows |
29
+ | --- | --- |
30
+ | [../examples/minimal.ts](../examples/minimal.ts) | Presence + string flags, fallback routing |
31
+ | [../examples/nested.ts](../examples/nested.ts) | Nested commands, varargs, MCP + `docs` |
32
+ | [../examples/formats.ts](../examples/formats.ts) | `CliValueFormat`, `default`, `readLeafInputs()` |
@@ -2,6 +2,19 @@
2
2
 
3
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
4
 
5
+ ## Framework docs vs your app's docgen
6
+
7
+ Two documentation layers often coexist in a consumer repo:
8
+
9
+ | Layer | Contents | How agents/humans get it |
10
+ | --- | --- | --- |
11
+ | **Argsbarg framework** | How to author `CliProgram`, MCP varargs policy, headless patterns | `node_modules/argsbarg/docs/` — wire via [Cursor rule](templates/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/` |
13
+
14
+ 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.
15
+
16
+ See [docs/README.md](README.md) for the full documentation map.
17
+
5
18
  ## Quick start
6
19
 
7
20
  ```typescript
@@ -2,6 +2,8 @@
2
2
 
3
3
  ArgsBarg turns your schema into help, shell completions, MCP tools, and agent skills. **The same `description` fields you write for humans are the agent contract** for basic apps.
4
4
 
5
+ **Documentation map:** [docs/README.md](README.md) — which guide to read for MCP, install, consumer docgen, and Cursor setup.
6
+
5
7
  ## Minimal app (MCP is free)
6
8
 
7
9
  ```typescript
@@ -193,6 +195,26 @@ const { limit, "skip-readiness": skipReadiness, timeout } = ctx.readLeafInputs()
193
195
  // duration → number (ms); comma-list → string[]; presence → boolean; number → number
194
196
  ```
195
197
 
198
+ **`CliLeafInputs`** — return type of `readLeafInputs()` (exported from `"argsbarg"`). A flat record keyed by **schema option and positional names** (hyphens preserved, e.g. `"skip-readiness"`). Values are coerced per kind/format:
199
+
200
+ | Schema | Value in `CliLeafInputs` |
201
+ | --- | --- |
202
+ | Presence | `boolean` |
203
+ | Number | `number` or `undefined` if omitted |
204
+ | String (plain) | `string` or `undefined` |
205
+ | `format: duration` | `number` (milliseconds) |
206
+ | `format: comma-list` | `string[]` |
207
+ | `format: date` | `string` (`YYYY-MM-DD`) |
208
+ | `format: date-time` | `string` (normalized UTC ISO) |
209
+ | Single positional | `string` or `undefined` |
210
+ | Varargs positional | `string[]` or `undefined` |
211
+
212
+ Omitted options appear as `undefined` (not absent keys). Options with `default` are filled in post-parse before handlers run, so `readLeafInputs()` and `durationOpt` see defaults. **`ctx.opts` always holds raw strings** — use typed accessors or `readLeafInputs()` for coerced values.
213
+
214
+ `CliLeafInputs` is intentionally untyped at the framework level. Narrow in your app (`read*Flags(ctx)` returning a typed struct) rather than expecting inference from `satisfies CliLeaf`.
215
+
216
+ See [examples/formats.ts](../examples/formats.ts) for a runnable demo.
217
+
196
218
  Cross-field rules (e.g. `--match-remote` requires `--branch`) stay in consumer `resolve*` layers — argsbarg does not validate those.
197
219
 
198
220
  ## Read flags once, resolve once
@@ -248,6 +270,30 @@ handler: async (ctx) => {
248
270
 
249
271
  **JSON-only CLIs** — a single `readCommandOptions(ctx)` wrapping `readLeafInputs()` per shared option set is usually enough; full `resolve*` layering is optional.
250
272
 
273
+ ## Upgrading to 3.6+
274
+
275
+ ### MCP varargs (breaking)
276
+
277
+ Varargs positionals (`argMax: 0`) must be a **JSON array** in `tools/call` — comma-separated strings are no longer accepted.
278
+
279
+ ```json
280
+ // before (removed)
281
+ { "uids": "a,b,c" }
282
+
283
+ // after
284
+ { "uids": ["a", "b", "c"] }
285
+ ```
286
+
287
+ CLI argv is unchanged: space-separated words. Use `format: comma-list` on an **option** when a single flag should accept `a,b` or `["a","b"]` over MCP.
288
+
289
+ ### Value formats (optional)
290
+
291
+ Add `format`, `default`, or `pattern` on string **options**; read with `ctx.durationOpt`, `ctx.commaListOpt`, `ctx.readLeafInputs()`, etc. Replace hand-rolled `split(",")` / `parseDurationMs` try/catch where the schema can declare the shape.
292
+
293
+ ### Handler layering (optional)
294
+
295
+ Ink + headless + MCP apps benefit from `read*Flags(ctx)` + `resolve*Input(flags)` — see above.
296
+
251
297
  ## Headless-capable handlers
252
298
 
253
299
  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:
@@ -350,6 +396,8 @@ The template is ~25 lines: when to read which doc, plus hard rules agents often
350
396
 
351
397
  ## See also
352
398
 
399
+ - [Documentation map](README.md) — which doc to read when
400
+ - [Developing argsbarg](developing.md) — release, consumer sync, npm `files`
353
401
  - [MCP server](mcp.md) — tools, schema resource, env bootstrapping
354
402
  - [Agent skills](ai-skills.md) — `install --skill`
355
- - [Bundled docs](bundled-docs.md) — `docs` topics and `docs mcp`
403
+ - [Bundled docs](bundled-docs.md) — `docs` topics, consumer docgen vs framework docs
@@ -0,0 +1,50 @@
1
+ # Developing argsbarg
2
+
3
+ Notes for maintainers of this repository. Also shipped under `node_modules/argsbarg/docs/` for fork maintainers.
4
+
5
+ ## Prerequisites
6
+
7
+ - [Bun](https://bun.sh) ≥ 1.3
8
+ - [just](https://github.com/casey/just) — `just` lists recipes
9
+ - `gh` and `npm` logged in for release
10
+
11
+ ## Day-to-day
12
+
13
+ ```bash
14
+ just check # typecheck + format
15
+ just test # check + unit tests
16
+ just typegen # regenerate index.d.ts
17
+ ```
18
+
19
+ ## Release
20
+
21
+ ```bash
22
+ just release patch # or minor | major
23
+ ```
24
+
25
+ The release script bumps `package.json`, promotes `[Unreleased]` in `CHANGELOG.md`, commits, tags, pushes, creates a GitHub release, and publishes to npm. Run `just test` first (the `just release` recipe does).
26
+
27
+ Update `CHANGELOG.md` under `[Unreleased]` before releasing.
28
+
29
+ ## Local consumer apps
30
+
31
+ Sibling repos under `../../ss/` (paths are machine-specific; adjust in `justfile` if needed):
32
+
33
+ | Recipe | When | Effect |
34
+ | --- | --- | --- |
35
+ | `just consumer-dev` | Before publish; hacking on argsbarg locally | `bun add argsbarg@file:<relative>` in each consumer |
36
+ | `just consumers-sync` | After release | Sets `"argsbarg": "^<this package.json version>"`, `bun install`, `just build`, `just docgen`, `just install` |
37
+
38
+ `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
+ Re-copy `docs/templates/cursor/rules/cli-program.mdc` into consumer repos when the template changes (append app-specific conventions; do not fork the whole guide).
41
+
42
+ ## npm package contents
43
+
44
+ `npm publish` does **not** honor `.gitignore`. Only paths listed in `package.json` `files` are included in the tarball (plus always-excluded defaults like `node_modules`).
45
+
46
+ When adding docs or examples intended for consumers, ensure they live under whitelisted paths (`docs/`, `examples/`, `src/`, etc.).
47
+
48
+ ## Docs
49
+
50
+ See [README.md](README.md) for the documentation map. Framework authoring guide: [cli-program.md](cli-program.md).
package/docs/mcp.md CHANGED
@@ -208,7 +208,7 @@ Set **`outputSchema` on the leaf** (not under `mcpTool`) — see [cli-program.md
208
208
  Each tool’s `inputSchema` is a JSON Schema object built from your CLI definition:
209
209
 
210
210
  - **Options** — parent-scoped flags are included (e.g. `stat`’s `--json` appears on `stat_owner_lookup`). Presence options are `boolean`; string, number, and **enum** options match their `CliOptionKind` (`Enum` uses JSON Schema `enum`). Required options are listed in `required`.
211
- - **Positionals** — one property per `CliPositional` on the leaf. Single-slot positionals are `string`; varargs tails (`argMax: 0`) are `string[]`. Required positionals are listed in `required`. For varargs, agents may also pass a comma-separated string (`"a,b"`) or a single string (`"a"`) — both are coerced to separate argv tokens at dispatch time.
211
+ - **Positionals** — one property per `CliPositional` on the leaf. Single-slot positionals are `string`; varargs tails (`argMax: 0`) are `string[]`. Required positionals are listed in `required`. **Varargs must be a JSON array** — comma-separated strings are not accepted (use `format: comma-list` on an option when a single flag should accept `"a,b"` or `["a","b"]`).
212
212
 
213
213
  Arguments are a **flat JSON object** keyed by option and positional names (same names as in your schema, including hyphenated option names like `"user-name"`).
214
214
 
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env bun
2
+ /*
3
+ * Value formats demo: duration, comma-list, date, default, and readLeafInputs().
4
+ * Run: bun ./examples/formats.ts run --tags alpha,beta --on 2026-06-22
5
+ * MCP: pass comma-list as string or array; varargs N/A on this leaf.
6
+ */
7
+
8
+ import pkg from "../package.json" with { type: "json" };
9
+ import { cliRun, CliFallbackMode, CliOptionKind, CliValueFormat, type CliProgram } from "../src/index.ts";
10
+
11
+ const cli = {
12
+ key: "formats.ts",
13
+ version: pkg.version,
14
+ description: "Value formats and readLeafInputs demo.",
15
+ fallbackCommand: "run",
16
+ fallbackMode: CliFallbackMode.MissingOnly,
17
+ mcpServer: { enabled: true },
18
+ commands: [
19
+ {
20
+ key: "run",
21
+ description: "Print coerced option values from readLeafInputs().",
22
+ options: [
23
+ {
24
+ name: "timeout",
25
+ description: "Wait budget (default 30s).",
26
+ kind: CliOptionKind.String,
27
+ format: CliValueFormat.Duration,
28
+ default: "30s",
29
+ },
30
+ {
31
+ name: "tags",
32
+ description: "Comma-separated labels.",
33
+ kind: CliOptionKind.String,
34
+ format: CliValueFormat.CommaList,
35
+ },
36
+ {
37
+ name: "on",
38
+ description: "Calendar day (YYYY-MM-DD).",
39
+ kind: CliOptionKind.String,
40
+ format: CliValueFormat.Date,
41
+ },
42
+ {
43
+ name: "verbose",
44
+ description: "Also print raw ctx.opts strings.",
45
+ kind: CliOptionKind.Presence,
46
+ shortName: "v",
47
+ },
48
+ ],
49
+ handler: (ctx) => {
50
+ const inputs = ctx.readLeafInputs();
51
+ const out = {
52
+ readLeafInputs: inputs,
53
+ durationMs: ctx.durationOpt("timeout"),
54
+ tags: ctx.commaListOpt("tags"),
55
+ on: ctx.dateOpt("on"),
56
+ };
57
+ if (ctx.hasFlag("verbose")) {
58
+ Object.assign(out, { rawOpts: ctx.opts });
59
+ }
60
+ process.stdout.write(`${JSON.stringify(out, null, 2)}\n`);
61
+ },
62
+ },
63
+ ],
64
+ } satisfies CliProgram;
65
+
66
+ await cliRun(cli);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "argsbarg",
3
- "version": "3.6.2",
3
+ "version": "3.6.3",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "bun": ">=1.3"