argsbarg 4.1.0 → 4.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/CHANGELOG.md +48 -1
  2. package/README.md +90 -84
  3. package/docs/README.md +6 -6
  4. package/docs/bundled-docs.md +1 -1
  5. package/docs/cli-program.md +5 -3
  6. package/docs/config-schema.md +36 -9
  7. package/docs/developing.md +7 -7
  8. package/docs/distribution-homebrew.md +103 -0
  9. package/docs/install.md +105 -189
  10. package/docs/mcp.md +2 -3
  11. package/docs/output-schema.md +1 -1
  12. package/examples/full-example/Formula/.gitkeep +0 -0
  13. package/examples/full-example/README.md +98 -0
  14. package/examples/full-example/biome.json +22 -0
  15. package/examples/{consumer-app → full-example}/bun.lock +2 -0
  16. package/examples/full-example/justfile +134 -0
  17. package/examples/{consumer-app → full-example}/package.json +10 -3
  18. package/examples/{consumer-app → full-example}/schemas/generated/app-config.json +1 -1
  19. package/examples/{consumer-app → full-example}/schemas/generated/status.json +1 -1
  20. package/examples/full-example/scripts/create-identity.ts +11 -0
  21. package/examples/full-example/scripts/formula-shared.ts +73 -0
  22. package/examples/full-example/scripts/gen-dev-formula.ts +26 -0
  23. package/examples/full-example/scripts/print-identity.ts +27 -0
  24. package/examples/full-example/src/commands/echo/command.ts +21 -0
  25. package/examples/full-example/src/commands/status/command.test.ts +10 -0
  26. package/examples/full-example/src/commands/status/command.ts +36 -0
  27. package/examples/{consumer-app → full-example}/src/commands/status/types.ts +1 -1
  28. package/examples/full-example/src/index.ts +10 -0
  29. package/examples/full-example/src/program.ts +57 -0
  30. package/examples/{consumer-app → full-example}/src/types.ts +1 -1
  31. package/examples/nested.ts +1 -3
  32. package/index.d.ts +27 -66
  33. package/package.json +2 -2
  34. package/src/builtins/builtins.test.ts +22 -23
  35. package/src/builtins/completion-group.ts +17 -15
  36. package/src/builtins/dispatch.ts +25 -1
  37. package/src/builtins/install.ts +22 -52
  38. package/src/builtins/registry.ts +2 -0
  39. package/src/builtins/uninstall.ts +80 -0
  40. package/src/capabilities.ts +1 -3
  41. package/src/cli-tool/cli-smoke.test.ts +19 -0
  42. package/src/cli-tool/create.test.ts +119 -0
  43. package/src/cli-tool/create.ts +380 -0
  44. package/{examples/consumer-app/capabilities.test.ts → src/cli-tool/full-example-capabilities.test.ts} +15 -14
  45. package/src/cli-tool/main.ts +8 -0
  46. package/src/cli-tool/post-create.ts +111 -0
  47. package/src/cli-tool/program.ts +82 -0
  48. package/src/cli-tool/prompt.ts +28 -0
  49. package/src/cli-tool/run-create.ts +149 -0
  50. package/src/cli.ts +0 -2
  51. package/src/config/bootstrap.ts +16 -9
  52. package/src/config/resolve.test.ts +167 -0
  53. package/src/config/resolve.ts +50 -6
  54. package/src/docs/api-guide.test.ts +4 -5
  55. package/src/docs/docs.test.ts +2 -1
  56. package/src/docs/mcp-guide.ts +7 -8
  57. package/src/index.ts +3 -10
  58. package/src/install/binary-placement.test.ts +101 -0
  59. package/src/install/binary-placement.ts +47 -0
  60. package/src/install/index.ts +117 -123
  61. package/src/install/install.test.ts +89 -105
  62. package/src/install/normalize-uninstall.ts +11 -0
  63. package/src/install/normalize.ts +4 -19
  64. package/src/install/paths.ts +0 -22
  65. package/src/install/plan.ts +14 -6
  66. package/src/install/shell.ts +0 -14
  67. package/src/install/status.test.ts +6 -6
  68. package/src/install/status.ts +0 -6
  69. package/src/install/target-effective.ts +0 -2
  70. package/src/install/target-scope.ts +15 -28
  71. package/src/install/target-types.ts +0 -16
  72. package/src/install/targets/app.ts +19 -28
  73. package/src/install/targets/configure.ts +5 -1
  74. package/src/install/targets/index.ts +0 -3
  75. package/src/install/targets.test.ts +24 -42
  76. package/src/mcp/env.test.ts +92 -0
  77. package/src/mcp/env.ts +15 -14
  78. package/src/parse.test.ts +3 -2
  79. package/src/prompt.ts +10 -0
  80. package/src/schema.ts +9 -1
  81. package/src/types.ts +27 -9
  82. package/src/validate.ts +5 -11
  83. package/docs/templates/cursor/rules/cli-program.mdc +0 -31
  84. package/examples/config-app/main.ts +0 -20
  85. package/examples/config-app/program.ts +0 -78
  86. package/examples/config-app/schema.ts +0 -37
  87. package/examples/config-app/types.ts +0 -19
  88. package/examples/consumer-app/README.md +0 -56
  89. package/examples/consumer-app/src/main.ts +0 -15
  90. package/examples/consumer-app/src/program.ts +0 -108
  91. package/src/install/app.ts +0 -94
  92. package/src/install/bootstrap.ts +0 -22
  93. package/src/install/completions.ts +0 -56
  94. package/src/install/targets/completions.ts +0 -133
  95. package/src/install/update.test.ts +0 -123
  96. package/src/install/update.ts +0 -54
  97. /package/examples/{consumer-app → full-example}/schemas/configSchemas.ts +0 -0
  98. /package/examples/{consumer-app → full-example}/schemas/outputSchemas.ts +0 -0
  99. /package/examples/{consumer-app → full-example}/scripts/schemagen/discover-schema-roots.test.ts +0 -0
  100. /package/examples/{consumer-app → full-example}/scripts/schemagen/discover-schema-roots.ts +0 -0
  101. /package/examples/{consumer-app → full-example}/scripts/schemagen/naming.ts +0 -0
  102. /package/examples/{consumer-app → full-example}/scripts/schemagen.ts +0 -0
  103. /package/examples/{consumer-app → full-example}/tsconfig.json +0 -0
package/CHANGELOG.md CHANGED
@@ -7,6 +7,52 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [4.1.1] - 2026-07-03
11
+
12
+ ### Added
13
+
14
+ - **`argsbarg create`** — interactive bootstrap from `examples/full-example`; copies template with substitutions; post-create runs `bun install`, schemagen, Cursor rule merge, `bun test`, and git init when appropriate.
15
+
16
+ ### Changed
17
+
18
+ - **Breaking: `bunx argsbarg scaffold homebrew` → `bunx argsbarg create`** — single template in `examples/full-example/`; removed `docs/templates/homebrew/`.
19
+ - **`examples/full-example/`** — `src/index.ts`, per-command modules, Biome, `.cursor/rules/` (`cli-program.mdc`, `code.mdc`).
20
+
21
+ ### Removed
22
+
23
+ - **`argsbarg scaffold`** subcommands and **`docs/templates/homebrew/`**.
24
+
25
+ ### Added
26
+
27
+ - **`CliAppConfigEntry.resolve`** — optional per-key fallback resolver after file (e.g. `gh auth token`); return `undefined` to fall back to `entry.env` and defaults. Resolution order: env → file → `resolve` → env → default.
28
+ - **Install `--mcp` / `--skill` / `--configure` combined** — scoped flags compose (configure no longer blocks skill/MCP plan); configure wizard runs after install when combined.
29
+ - **Top-level `uninstall` command** — sibling of `install` for removing agent artifacts; bare `uninstall` defaults to `--all`.
30
+ - **Homebrew-first distribution** — tap-from-repo formula pattern; [docs/distribution-homebrew.md](docs/distribution-homebrew.md).
31
+ - **Homebrew dev just recipes** — `install-local`, `reinstall-local`, `install-production` (+ `install` / `reinstall` aliases); `uninstall`, `uninstall-config`, `uninstall-release`, `uninstall-release-tap`, `test-release` in full-example template.
32
+ - **CLI bin split** — `argsbarg` package bin points to `src/cli-tool/main.ts`; library API remains `import from "argsbarg"`.
33
+ - **Config path exports** — `resolveAppConfigPath`, `displayAppConfigPath` exported from `argsbarg`.
34
+ - **`--reinstall` greenfield fallback** — when no artifacts detected, `--reinstall` runs full `--all` plan (fresh `brew install` post_install).
35
+
36
+ ### Changed
37
+
38
+ - **`mcpServer.shellEnv` default on** — login-shell env is captured at MCP startup unless `shellEnv: false`. PATH is merged; other vars fill gaps in host env.
39
+ - **`CliAppConfigEntry.resolve` must be synchronous** — returning a Promise is ignored with a stderr warning; use `Bun.spawnSync` with piped stdout for subprocess resolvers (e.g. `gh auth token`).
40
+
41
+ - **Breaking: `examples/consumer-app/` → `examples/full-example/`** — expanded justfile (dev/build/test/schemagen + Homebrew); CLI key `full-example`; removed redundant `examples/config-app/`.
42
+
43
+ - **Breaking: `install --uninstall` removed** — use `<key> uninstall` instead (`install --uninstall` exits with a redirect message).
44
+ - **Breaking: Homebrew-only install model** — drop self-install to `~/.local/bin`, `install --app`, `install --update` / `updateGetLatest`, home-dir completion installer (`install --completions`), bare-argv install bootstrap.
45
+ - **Breaking: configure opt-in** — `configure` target excluded from `--all`; no post-install wizard; run `install --configure` explicitly.
46
+ - **Install `--all` / `--reinstall`** — skills and MCP only (binary + completions via Homebrew formula).
47
+ - **Completion built-in notes** — Homebrew installs completions; link to Shell-Completion docs.
48
+
49
+ ### Removed
50
+
51
+ - **`examples/config-app/`** — superseded by `full-example` (`program.appConfig`, schemagen, and `config get`/`set` covered there).
52
+ - **`install --update`**, **`updateGetLatest`**, **`ghReleaseUpdateGetLatest`** usage in install flow.
53
+ - **Completion installer** — `install/targets/completions.ts`, home-dir completion paths.
54
+ - **Install bootstrap** — bare argv no longer rewrites to `install`.
55
+
10
56
  ## [4.1.0] - 2026-07-01
11
57
 
12
58
  ### Added
@@ -497,7 +543,8 @@ const cli = { ... } satisfies CliProgram; // or : CliProgram
497
543
  - 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`).
498
544
  - Imports: use `CliPositional` where needed; replace `CliOptionDef` with `CliOption` or `CliPositional` as appropriate.
499
545
 
500
- [Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v4.1.0...HEAD
546
+ [Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v4.1.1...HEAD
547
+ [4.1.1]: https://github.com/bdombro/bun-argsbarg/releases/tag/v4.1.1
501
548
  [4.1.0]: https://github.com/bdombro/bun-argsbarg/releases/tag/v4.1.0
502
549
  [4.0.4]: https://github.com/bdombro/bun-argsbarg/releases/tag/v4.0.4
503
550
  [4.0.3]: https://github.com/bdombro/bun-argsbarg/releases/tag/v4.0.3
package/README.md CHANGED
@@ -1,36 +1,36 @@
1
- ![Logo](https://github.com/bdombro/bun-argsbarg/blob/main/logo.png)
2
- <!-- Big money NE - https://patorjk.com/software/taag/#p=testall&f=Bulbhead&t=shebangsy&x=none&v=4&h=4&w=80&we=false> -->
1
+ Logo
3
2
 
4
- [![GitHub](https://img.shields.io/badge/GitHub-bdombro%2Fbun--argsbarg-181717?logo=github)](https://github.com/bdombro/bun-argsbarg)
5
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
6
- [![npm version](https://img.shields.io/npm/v/argsbarg.svg)](https://www.npmjs.com/package/argsbarg)
7
- [![Bun](https://img.shields.io/badge/Bun-%23000000.svg?logo=bun&logoColor=white)](https://bun.sh)
3
+
4
+
5
+ [GitHub](https://github.com/bdombro/bun-argsbarg)
6
+ [License: MIT](LICENSE)
7
+ [npm version](https://www.npmjs.com/package/argsbarg)
8
+ [Bun](https://bun.sh)
8
9
 
9
10
  Build beautiful, well-behaved CLI+MCP apps with Bun — **no third-party runtime dependencies**.
10
11
 
11
12
  Why another CLI parser?
12
13
 
13
- *Schema-first* — define your entire CLI’s structure, commands, options, and help in a single, explicit data model, making the command-line interface centralized, clear, and self-describing upfront.
14
+ *Schema-first* — define your entire CLI’s structure, commands, options, and help in a single, explicit data model, making the command-line interface auto-validated, centralized, clear, and self-describing upfront.
14
15
 
15
- *Beautiful `-h` screens* — scoped help at any routing depth, rendered in rounded UTF-8 boxes with tables, terminal-width wrapping, and color when stdout is a TTY. Errors print in red with contextual help on stderr.
16
+ *AI Friendly* — Generate and install rich skills, mcp server, docs based on the schema.
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
+ *Beautiful* `-h` *screens* — scoped help at any routing depth, rendered in rounded UTF-8 boxes with tables, terminal-width wrapping, and color when stdout is a TTY. Errors print in red with contextual help on stderr.
18
19
 
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 apps can install the app, completions, skills, and MCP config with `myapp install` — see [docs/install.md](docs/install.md).
20
+ *Shell completions* — `completion bash`, `completion zsh`, and `completion fish` built-ins generate scripts consumed by Homebrew during formula `install` (`generate_completions_from_executable`). See [docs/distribution-homebrew.md](docs/distribution-homebrew.md).
20
21
 
21
22
  *Bun-optimized* — built from the ground up for Bun and TypeScript, leveraging Bun’s performance and modern JavaScript features without any extra dependencies.
22
23
 
23
24
  Also checkout ArgsBarg for [cpp](https://github.com/bdombro/cpp-argsbarg), [nim](https://github.com/bdombro/nim-argsbarg), and [swift](https://github.com/bdombro/swift-argsbarg)!
24
25
 
25
26
  Halps! -->
26
- ![help-preview.png](https://github.com/bdombro/bun-argsbarg/blob/main/docs/help-preview.png)
27
+ help-preview.png
27
28
 
28
29
  Sub-level Halps! -->
29
- ![help-l2-preview.png](https://github.com/bdombro/bun-argsbarg/blob/main/docs/help-l2-preview.png)
30
+ help-l2-preview.png
30
31
 
31
32
  Shell completions! -->
32
- ![completions-preview.png](https://github.com/bdombro/bun-argsbarg/blob/main/docs/completions-preview.png)
33
-
33
+ completions-preview.png
34
34
 
35
35
  ## Usage
36
36
 
@@ -73,8 +73,6 @@ await cli.run();
73
73
 
74
74
  `Cli.run()` parses `process.argv`, prints help or errors, dispatches the leaf handler, and **exits the process**.
75
75
 
76
-
77
-
78
76
  ## What is it?
79
77
 
80
78
  Everything you need for a first-class CLI:
@@ -96,50 +94,45 @@ Everything you need for a first-class CLI:
96
94
  Every app gets:
97
95
 
98
96
  - `-h` / `--help` at any routing depth (scoped help).
99
- - **`completion bash` / `completion zsh` / `completion fish`** — print shell completion scripts to stdout (injected by `Cli.run()`).
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, schema JSON, API markdown, and generated skill content (`myapp docs`, `myapp docs readme`, `myapp docs schema`, `myapp docs api`, `myapp docs skill`, …). See [docs/bundled-docs.md](docs/bundled-docs.md).
103
- - **`install`** — install the app, completions, skills, and MCP config to the user environment (`myapp install --yes`). See [docs/install.md](docs/install.md).
104
-
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.
97
+ - `completion bash` **/** `completion zsh` **/** `completion fish` — print shell completion scripts to stdout (injected by `Cli.run()`).
98
+ - `version` — print `CliProgram.version` (`myapp version`).
99
+ - `mcp` — when `mcpServer.enabled` is `true`, run as an MCP stdio server (`myapp mcp`).
100
+ - `docs` — when `docs.enabled` is `true`, print bundled markdown topics, schema JSON, API markdown, and generated skill content (`myapp docs`, `myapp docs readme`, `myapp docs schema`, `myapp docs api`, `myapp docs skill`, …). See [docs/bundled-docs.md](docs/bundled-docs.md).
101
+ - `install` — refresh agent skills and MCP config (`myapp install --reinstall --yes` after Homebrew install). See [docs/install.md](docs/install.md).
108
102
 
103
+ Do not declare a top-level command named `completion`, `version`, or `install` — they are reserved.
104
+ When `mcpServer.enabled` is `true`, do not declare a top-level command named `mcp` — it is reserved for the MCP built-in.
105
+ When `docs.enabled` is `true`, do not declare a top-level command named `docs` — it is reserved for the docs built-in.
109
106
 
110
107
  ### MCP (AI agents)
111
108
 
112
109
  Opt in on the program root with `mcpServer: { enabled: true }`, then run `myapp mcp` for a stdio MCP server. Each leaf command becomes a tool; the CLI tree is available as resource `<sanitized-key>://schema` (same as `myapp docs schema`). Handlers can read `ctx.invocation`; use `cli.invoke(argv)` for headless testing.
113
110
 
114
- See **[docs/mcp.md](docs/mcp.md)** for configuration, env bootstrapping, custom resources, Cursor setup, and protocol details. See **[docs/cli-program.md](docs/cli-program.md)** for schema authoring (consumer apps: copy **`docs/templates/cursor/rules/cli-program.mdc`** to **`.cursor/rules/cli-program.mdc`**).
111
+ See **[docs/mcp.md](docs/mcp.md)** for configuration, env bootstrapping, custom resources, Cursor setup, and protocol details. See **[docs/cli-program.md](docs/cli-program.md)** for schema authoring (consumer apps: run `bunx argsbarg create` or refresh with `bun scripts/merge-cli-program-rule.ts .` from the argsbarg package).
115
112
 
116
113
  ### Install CLI
117
114
 
118
- argsbarg includes CLI features to manage installation of your compiled bun app. After `bun build --compile` (or when running via `bun`), ship your CLI and let users run:
115
+ Ship via **Homebrew** (tap-from-repo). The formula installs the binary and shell completions; `post_install` runs agent artifact refresh:
119
116
 
120
117
  ```bash
121
- myapp install --yes
118
+ brew tap <org>/<repo>
119
+ brew install <tap>/myapp
120
+ myapp install --configure # opt-in app config wizard
122
121
  ```
123
122
 
124
- This copies the app to `~/.local/bin`, installs shell completions (bash/zsh/fish when each shell is on PATH), and runs the configure wizard when `program.appConfig` is set. Agent skills or MCP config are included in `--all` per `install.agentIntegration` (skills when MCP is off; MCP when `mcpServer.enabled`).
125
-
126
- See **[docs/install.md](docs/install.md)** for `--reinstall`, `install --update`, `--status`, `--uninstall`, and flags.
127
-
123
+ See **[docs/distribution-homebrew.md](docs/distribution-homebrew.md)** for formula patterns and `bunx argsbarg create`. See **[docs/install.md](docs/install.md)** for `install`, `uninstall`, `--reinstall`, and `--status`.
128
124
 
129
125
  ### Shell completions
130
126
 
131
- ```bash
132
- myapp completion bash > ~/.bash_completion.d/myapp
133
- # or: source <(myapp completion bash)
127
+ Homebrew installs completion scripts during `brew install` via `generate_completions_from_executable`. The CLI still exposes generation for formula authors:
134
128
 
135
- myapp completion zsh > ~/.zsh/completions/_myapp
136
- # then: fpath+=(~/.zsh/completions); autoload -Uz compinit && compinit
137
- # or, for a one-off test in the current shell: eval "$(myapp completion zsh)"
138
-
139
- myapp completion fish > ~/.config/fish/completions/myapp.fish
129
+ ```bash
130
+ myapp completion bash
131
+ myapp completion zsh
132
+ myapp completion fish
140
133
  ```
141
134
 
142
-
135
+ Users configure their shell per [Homebrew Shell Completion](https://docs.brew.sh/Shell-Completion).
143
136
 
144
137
  ## Quick Start
145
138
 
@@ -147,31 +140,38 @@ myapp completion fish > ~/.config/fish/completions/myapp.fish
147
140
  bun add argsbarg
148
141
  ```
149
142
 
143
+
144
+
150
145
  ### Cursor / AI agents
151
146
 
152
147
  Argsbarg ships authoring docs in `node_modules/argsbarg/docs/`. Agents do not load them unless your repo points there — copy the thin Cursor rule after install (it tells agents to **read** `cli-program.md`, not duplicate it):
153
148
 
154
149
  ```bash
155
150
  mkdir -p .cursor/rules
156
- cp node_modules/argsbarg/docs/templates/cursor/rules/cli-program.mdc .cursor/rules/cli-program.mdc
151
+ mkdir -p .cursor/rules
152
+ bun scripts/merge-cli-program-rule.ts . \
153
+ node_modules/argsbarg/examples/full-example/.cursor/rules/cli-program.mdc
157
154
  ```
158
155
 
159
156
  Add app-specific conventions in a second rule if needed. Copy the rule from the template, then add a `**<your-app> conventions:**` block at the bottom (see **Cursor rule** in [docs/cli-program.md](docs/cli-program.md)). Documentation map: **[docs/README.md](docs/README.md)**.
160
157
 
161
-
162
158
  ## How it works
163
159
 
164
160
  1. Build a **program root** with `satisfies CliProgram` (or `: CliProgram`): `key` is the app name, `commands` are top-level subcommands, `options` are global flags. A router root must not set `handler` or declare `positionals` (validated at startup). A leaf root may set `handler` and `positionals` directly. Use `fallbackCommand` / `fallbackMode` on any **routing node** for default subcommand routing (not root-only).
165
161
  2. Call `await new Cli(program).run()` — validates, parses argv, renders help or errors, invokes the leaf handler, and `process.exit`s with status **0** on success, **1** on implicit help or error (explicit `--help` → **0**).
166
162
  3. From a handler, `cliErrWithHelp(ctx, "message")` prints a red error line plus contextual help on stderr and exits **1**.
167
163
 
164
+
165
+
168
166
  ### Fallback modes (`CliFallbackMode`)
169
167
 
170
- | Mode | Empty argv | Unknown first token |
171
- | --- | --- | --- |
172
- | `MissingOnly` | Default command | Error |
173
- | `MissingOrUnknown` | Default command | Default command (token becomes argv for the default) |
174
- | `UnknownOnly` | Root help (exit 1) | Default command |
168
+
169
+ | Mode | Empty argv | Unknown first token |
170
+ | ------------------ | ------------------ | ---------------------------------------------------- |
171
+ | `MissingOnly` | Default command | Error |
172
+ | `MissingOrUnknown` | Default command | Default command (token becomes argv for the default) |
173
+ | `UnknownOnly` | Root help (exit 1) | Default command |
174
+
175
175
 
176
176
  With `MissingOrUnknown` / `UnknownOnly`, unrecognized flags at the **current routing node** stop option consumption and the remainder is passed to the default command.
177
177
 
@@ -181,12 +181,16 @@ Set `fallbackCommand` / `fallbackMode` on nested routers too — e.g. `docs` wit
181
181
 
182
182
  Add `CliPositional` entries to the command’s `positionals` list (separate from `CliOption` flags). With `argMax: 0`, the tail accepts at least `argMin` tokens and has no upper bound unless you set `argMax` > 0.
183
183
 
184
- | Fields | Label |
185
- | --- | --- |
186
- | omit `argMin` / `argMax` (defaults `1` / `1`, one required word) | `<n>` |
187
- | `argMin: 0`, `argMax: 1` | `[n]` |
188
- | `argMin: 0`, `argMax: 0` | `[n...]` |
189
- | `argMin: 1`, `argMax: 0` | `<n...>` |
184
+
185
+ | Fields | Label |
186
+ | ---------------------------------------------------------------- | -------- |
187
+ | omit `argMin` / `argMax` (defaults `1` / `1`, one required word) | `<n>` |
188
+ | `argMin: 0`, `argMax: 1` | `[n]` |
189
+ | `argMin: 0`, `argMax: 0` | `[n...]` |
190
+ | `argMin: 1`, `argMax: 0` | `<n...>` |
191
+
192
+
193
+
190
194
 
191
195
  ### Reading values (`CliContext`)
192
196
 
@@ -201,25 +205,26 @@ Add `CliPositional` entries to the command’s `positionals` list (separate from
201
205
  - `ctx.positional("name")` — named positional lookup; varargs slots return `string[]`, single slots return `string | undefined`.
202
206
  - `ctx.program` — program root (`CliProgram`) for contextual help.
203
207
 
204
- ### Capabilities (built-ins)
205
208
 
206
- `completion`, `version`, `install`, and `mcp` are not part of your schema — they are injected at runtime from program-level config (`mcpServer`, `install`, `docs`). Reserved command names: `completion` and `version` always; `install` unless `install.enabled: false`; `mcp` when `mcpServer.enabled` is `true`; `docs` when `docs.enabled` is `true`. When `install.updateGetLatest` is set, `install --update` is available (not a separate command).
207
209
 
210
+ ### Capabilities (built-ins)
208
211
 
212
+ `completion`, `version`, `install`, and `mcp` are not part of your schema — they are injected at runtime from program-level config (`mcpServer`, `install`, `docs`). Reserved command names: `completion` and `version` always; `install` unless `install.enabled: false`; `mcp` when `mcpServer.enabled` is `true`; `docs` when `docs.enabled` is `true`.
209
213
 
210
214
  ## Examples
211
215
 
212
216
  Check the `examples/` directory for full working scripts:
213
217
 
214
- | Example | File | Shows |
215
- | --- | --- | --- |
216
- | `ArgsBargMinimal` | `examples/minimal.ts` | String + presence flags, `MissingOrUnknown` fallback. |
217
- | `ArgsBargNested` | `examples/nested.ts` | Nested command tree, positional tails, async handlers. |
218
- | `ArgsBargFormats` | `examples/formats.ts` | `CliValueFormat`, `default`, `readLeafInputs()`. |
219
- | `ArgsBargConfigApp` | `examples/config-app/` | `program.appConfig`, `ctx.appConfig`, built-in `config get`/`set`, inline JSON Schema. |
220
- | `ArgsBargConsumerApp` | `examples/consumer-app/` | **Copy template:** all builtins, schemagen discovery, `outputSchema`, `from "argsbarg"`. |
221
218
 
222
- Examples ship in the npm package under `node_modules/argsbarg/examples/`. Agents should read **`config-app`** for concepts and **`consumer-app`** when scaffolding a full CLI.
219
+ | Example | File | Shows |
220
+ | --------------------- | ------------------------ | ---------------------------------------------------------------------------------------- |
221
+ | `ArgsBargMinimal` | `examples/minimal.ts` | String + presence flags, `MissingOrUnknown` fallback. |
222
+ | `ArgsBargNested` | `examples/nested.ts` | Nested command tree, positional tails, async handlers. |
223
+ | `ArgsBargFormats` | `examples/formats.ts` | `CliValueFormat`, `default`, `readLeafInputs()`. |
224
+ | `ArgsBargFullExample` | `examples/full-example/` | **Copy template:** all builtins, schemagen, Homebrew justfile, `outputSchema`, `from "argsbarg"`. |
225
+
226
+
227
+ Examples ship in the npm package under `node_modules/argsbarg/examples/`. Bootstrap a production CLI with `bunx argsbarg create my-cli`.
223
228
 
224
229
  ```bash
225
230
  export PATH="$PATH:$(pwd)/examples"
@@ -234,11 +239,8 @@ nested.ts read ./README.md
234
239
 
235
240
  bun ./examples/formats.ts run --tags demo,docs --on 2026-06-22
236
241
 
237
- CONFIG_APP_API_TOKEN=dev bun ./examples/config-app/main.ts show --json
238
- CONFIG_APP_API_TOKEN=dev bun ./examples/config-app/main.ts config get
239
-
240
- cd examples/consumer-app && bun install && bun run schemagen
241
- CONSUMER_APP_API_TOKEN=dev bun run start status --json
242
+ cd examples/full-example && just setup && just schemagen
243
+ FULL_EXAMPLE_API_TOKEN=dev just run status --json
242
244
  ```
243
245
 
244
246
 
@@ -247,23 +249,27 @@ CONSUMER_APP_API_TOKEN=dev bun run start status --json
247
249
 
248
250
  The package root (`argsbarg` / `src/index.ts`) exports the types and runtime you need to define a schema and run it. Parsing, completion script generation, help rendering, and schema pre-validation live in other modules under `src/` for tests and advanced integrations.
249
251
 
250
- | Symbol | Role |
251
- | --- | --- |
252
- | `CliProgram`, `CliOption`, `CliPositional`, `CliHandler` | Schema and handler types. |
253
- | `CliOptionKind`, `CliValueFormat`, `CliFallbackMode` | Option kinds, value formats (`duration`, `comma-list`, `date`, `date-time`), and root fallback behavior. |
254
- | `CliSchemaValidationError` | Thrown when the static command tree violates schema rules. |
255
- | `CliContext` | Handler context (`ctx.hasFlag`, `ctx.stringOpt`, `ctx.durationOpt`, `ctx.readLeafInputs`, `ctx.invocation`, …). |
256
- | `CliLeafInputs` | Record type returned by `readLeafInputs()` — coerced option/positional values keyed by schema name. |
257
- | `Cli` | Runtime: validate + freeze program, `run()`, `invoke()`, `serveMcp()`, `appConfig` getter, `exportCommandSchema()`, `exportAppConfigSchema()`. |
258
- | `CliInvokeResult`, `CliInvokeKind` | Result types from `cli.invoke()`. |
259
- | `CliAppConfig`, `CliAppConfigEntry` | App config block on the program root (`entries` metadata overlay + optional `jsonSchema`). |
260
- | `cliErrWithHelp(ctx, msg)` | Print error + scoped help on stderr, exit 1. |
261
- | `parseDurationMs`, `parseCommaList`, `parseDate`, `parseDateTime` | Optional format parsers for use outside handlers. |
262
-
263
- Reserved identifiers (validated at startup): root commands **`completion`**, **`version`**, **`install`**, **`docs`** (when `docs.enabled` is `true`), and **`mcp`** (when `mcpServer.enabled` is `true`).
252
+
253
+ | Symbol | Role |
254
+ | ----------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
255
+ | `CliProgram`, `CliOption`, `CliPositional`, `CliHandler` | Schema and handler types. |
256
+ | `CliOptionKind`, `CliValueFormat`, `CliFallbackMode` | Option kinds, value formats (`duration`, `comma-list`, `date`, `date-time`), and root fallback behavior. |
257
+ | `CliSchemaValidationError` | Thrown when the static command tree violates schema rules. |
258
+ | `CliContext` | Handler context (`ctx.hasFlag`, `ctx.stringOpt`, `ctx.durationOpt`, `ctx.readLeafInputs`, `ctx.invocation`, …). |
259
+ | `CliLeafInputs` | Record type returned by `readLeafInputs()` — coerced option/positional values keyed by schema name. |
260
+ | `Cli` | Runtime: validate + freeze program, `run()`, `invoke()`, `serveMcp()`, `appConfig` getter, `exportCommandSchema()`, `exportAppConfigSchema()`. |
261
+ | `CliInvokeResult`, `CliInvokeKind` | Result types from `cli.invoke()`. |
262
+ | `CliAppConfig`, `CliAppConfigEntry` | App config block on the program root (`entries` metadata overlay + optional `jsonSchema`). |
263
+ | `cliErrWithHelp(ctx, msg)` | Print error + scoped help on stderr, exit 1. |
264
+ | `parseDurationMs`, `parseCommaList`, `parseDate`, `parseDateTime` | Optional format parsers for use outside handlers. |
265
+
266
+
267
+ Reserved identifiers (validated at startup): root commands `completion`, `version`, `install`, `docs` (when `docs.enabled` is `true`), and `mcp` (when `mcpServer.enabled` is `true`).
264
268
 
265
269
  ---
266
270
 
271
+
272
+
267
273
  ## License
268
274
 
269
- MIT
275
+ MIT
package/docs/README.md CHANGED
@@ -9,11 +9,12 @@ Start here to pick the right guide.
9
9
  | **JSON stdout / `outputSchema`** | [output-schema.md](output-schema.md) — codegen pipeline, JSDoc, narrowing |
10
10
  | **App config / `program.appConfig`** | [config-schema.md](config-schema.md) — flat JSON file, `ctx.appConfig`, codegen |
11
11
  | **Exposing MCP tools** | [mcp.md](mcp.md) — stdio server, `inputSchema`, varargs, `install --mcp` |
12
- | **Shipping install / completions / skills** | [install.md](install.md) — `myapp install`, shell completions |
12
+ | **Shipping install / agent artifacts** | [install.md](install.md) — Homebrew + `myapp install --reinstall` |
13
+ | **Homebrew tap-from-repo distribution** | [distribution-homebrew.md](distribution-homebrew.md) — formula pattern, `argsbarg create` |
13
14
  | **Bundling `myapp docs` topics** | [bundled-docs.md](bundled-docs.md) — consumer docgen vs framework docs |
14
15
  | **Agent skills** | [ai-skills.md](ai-skills.md) — `install --skill`, `docs skill` |
15
16
  | **Maintaining the argsbarg repo** | [developing.md](developing.md) — release, consumers, npm `files` |
16
- | **Cursor / IDE agents in a consumer app** | Copy [templates/cursor/rules/cli-program.mdc](templates/cursor/rules/cli-program.mdc) to `.cursor/rules/` |
17
+ | **Cursor / IDE agents in a consumer app** | `bunx argsbarg create` (includes rule) or `bun scripts/merge-cli-program-rule.ts .` from argsbarg checkout |
17
18
  | **Runnable examples** (shipped in npm) | [examples/](examples/) — see table below |
18
19
 
19
20
  ## Examples (agents: read these)
@@ -22,9 +23,8 @@ Examples are included in the npm tarball (`package.json` `files`). After `bun ad
22
23
 
23
24
  | Tier | Path | Use when |
24
25
  | --- | --- | --- |
25
- | Learn | [examples/minimal.ts](../examples/minimal.ts), [config-app/](../examples/config-app/) | One feature at a time |
26
- | Reference | [examples/nested.ts](../examples/nested.ts), [formats.ts](../examples/formats.ts) | Routing, formats, MCP snippet |
27
- | **Copy** | [examples/consumer-app/](../examples/consumer-app/) | Bootstrapping a production CLI (all builtins + schemagen) |
26
+ | Learn | [examples/minimal.ts](../examples/minimal.ts), [examples/nested.ts](../examples/nested.ts), [formats.ts](../examples/formats.ts) | One feature at a time |
27
+ | **Copy** | [examples/full-example/](../examples/full-example/) | Bootstrapping a production CLI (all builtins + schemagen + Homebrew justfile) |
28
28
 
29
29
  ## Framework docs vs consumer docgen
30
30
 
@@ -32,6 +32,6 @@ Examples are included in the npm tarball (`package.json` `files`). After `bun ad
32
32
  | --- | --- | --- |
33
33
  | **Framework docs** | How argsbarg works; authoring conventions | This directory — shipped in `node_modules/argsbarg/docs/` after `bun add argsbarg` |
34
34
  | **Consumer docgen** | *Your* command tree, API, MCP guide for *your* app | `myapp docs api`, `docs schema`, `docs mcp` — written to `./docs/` with `--save` |
35
- | **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 |
35
+ | **Cursor rule** | Thin tripwire telling agents to read framework docs | `node_modules/argsbarg/examples/full-example/.cursor/rules/cli-program.mdc` — included by `create`; refresh with `merge-cli-program-rule.ts` |
36
36
 
37
37
  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.
@@ -8,7 +8,7 @@ Two documentation layers often coexist in a consumer repo:
8
8
 
9
9
  | Layer | Contents | How agents/humans get it |
10
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` |
11
+ | **Argsbarg framework** | How to author `CliProgram`, MCP varargs policy, headless patterns | `node_modules/argsbarg/docs/` — wire via [full-example Cursor rule](../examples/full-example/.cursor/rules/cli-program.mdc) or `AGENTS.md` |
12
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
13
 
14
14
  `docs api` and `docs schema` embed each leaf’s `outputSchema` when set — see [output-schema.md](output-schema.md) for how to generate and wire schemas.
@@ -417,7 +417,8 @@ await cli.run();
417
417
  | `default` | — | Used when `jsonSchema` omitted (all-string mode) |
418
418
  | `required` | `true` | When `false`, optional unless required by `jsonSchema` |
419
419
  | `sensitive` | name heuristic (`token`, `secret`, …) | Redact in prompts, `config get`, and status |
420
- | `env` | — | When set: non-empty host env overrides file; exported to `process.env` after resolve |
420
+ | `env` | — | When set: non-empty host env overrides file; consulted again after `resolve` when `resolve` returns `undefined`; exported to `process.env` after resolve |
421
+ | `resolve` | — | Optional fallback after file; return `undefined` to fall back to `env` (if set) and defaults |
421
422
 
422
423
  **Config file** (created on demand):
423
424
 
@@ -447,10 +448,11 @@ Agents do **not** discover package docs automatically. Wire them in after `bun a
447
448
 
448
449
  ```bash
449
450
  mkdir -p .cursor/rules
450
- cp node_modules/argsbarg/docs/templates/cursor/rules/cli-program.mdc .cursor/rules/cli-program.mdc
451
+ bun scripts/merge-cli-program-rule.ts . \
452
+ node_modules/argsbarg/examples/full-example/.cursor/rules/cli-program.mdc
451
453
  ```
452
454
 
453
- The template is ~25 lines: when to read which doc, plus hard rules agents often get wrong. It does **not** duplicate this guide.
455
+ The template is ~30 lines: when to read which doc, plus hard rules agents often get wrong. It does **not** duplicate this guide. `bunx argsbarg create` copies this file into new projects automatically.
454
456
 
455
457
  2. **Add an app-specific block at the bottom** (recommended). Replace the template placeholder with a heading like `**myapp conventions:**` and short bullets — shared flag modules, `read*Flags` / `resolve*` paths, Ink vs JSON-only, etc. Example:
456
458
 
@@ -39,7 +39,7 @@ await cli.run();
39
39
  | Where argsbarg uses it | Purpose |
40
40
  | --- | --- |
41
41
  | Config file | Flat JSON keyed by schema names; strict load (unknown keys rejected) |
42
- | `install --configure` / `--status` | Interactive setup and status |
42
+ | `install --configure` / `--status` | Interactive setup (configure is opt-in, not in `--all`) and status |
43
43
  | Built-in `config get` / `config set` | Read/write resolved values (opt-out via `commands: false`) |
44
44
  | MCP bundle / Claude plugin | `userConfig` for entries with `env` set |
45
45
  | `ctx.appConfig` in handlers | `get`, `require`, `set`, `read`, `path`, `dir` — prefer over `process.env` |
@@ -60,6 +60,7 @@ export interface CliAppConfigEntry {
60
60
  required?: boolean; // default: true (can override jsonSchema required)
61
61
  sensitive?: boolean; // default: name heuristic
62
62
  env?: string; // env override + export to process.env after resolve
63
+ resolve?: CliAppConfigResolveFn; // fallback after file; must be synchronous
63
64
  }
64
65
 
65
66
  export interface CliAppConfig {
@@ -92,13 +93,40 @@ No nested `env` bag. No extra keys — rejected on load.
92
93
 
93
94
  ## Resolution order (per schema key)
94
95
 
95
- | Key has `env`? | Resolved value |
96
- | --- | --- |
97
- | **Yes** | non-empty `process.env[env]` → else file[key] → else default |
98
- | **No** | file[key] → else default |
96
+ | Step | Source | Notes |
97
+ | --- | --- | --- |
98
+ | 1 | **Env** (`entry.env`) | Non-empty host env wins over file and `resolve` |
99
+ | 2 | **File** | `config.json` value for the key |
100
+ | 3 | **`resolve()`** | Optional synchronous callback (e.g. `gh auth token`); return `undefined` to continue. Async/Promise return values are ignored. |
101
+ | 4 | **Env** (`entry.env`) | Fallback when `resolve` returned `undefined` |
102
+ | 5 | **Default** | `jsonSchema` / `entry.default` |
99
103
 
100
104
  Empty string in env or file counts as **missing** for required entries. After resolution, mapped values are exported to `process.env`.
101
105
 
106
+ Example — GitHub token with `env: "GH_TOKEN"` and `resolve` calling `gh auth token`:
107
+
108
+ ```typescript
109
+ githubToken: {
110
+ description: "GitHub API token.",
111
+ env: "GH_TOKEN",
112
+ sensitive: true,
113
+ resolve: () => {
114
+ try {
115
+ const r = Bun.spawnSync(["gh", "auth", "token"], { stdout: "pipe", stderr: "ignore" });
116
+ if (r.exitCode === 0) {
117
+ const token = new TextDecoder().decode(r.stdout).trim();
118
+ return token.length > 0 ? token : undefined;
119
+ }
120
+ } catch {
121
+ // `gh` not installed
122
+ }
123
+ return undefined;
124
+ },
125
+ },
126
+ ```
127
+
128
+ `install --configure` does not persist values supplied only by env or `resolve` when you press Enter to accept the current value.
129
+
102
130
  ## Hand-written vs generated
103
131
 
104
132
  | Approach | When |
@@ -180,10 +208,9 @@ Object/array/`$ref` properties require `--json` on `config set`.
180
208
 
181
209
  | Example | Role |
182
210
  | --- | --- |
183
- | [`examples/config-app/`](../examples/config-app/) | **Learn** — hand-written schema, minimal setup |
184
- | [`examples/consumer-app/`](../examples/consumer-app/) | **Copy** — schemagen discovery, `APP_CONFIG_JSON_SCHEMA` bridge |
211
+ | [`examples/full-example/`](../examples/full-example/) | **Copy template** — schemagen discovery, `APP_CONFIG_JSON_SCHEMA` bridge, `program.appConfig`, built-in `config get`/`set` |
185
212
 
186
213
  ```bash
187
- cd examples/consumer-app && bun install && bun run schemagen
188
- CONSUMER_APP_API_TOKEN=dev bun run start config get apiToken --json
214
+ cd examples/full-example && just setup && just schemagen
215
+ FULL_EXAMPLE_API_TOKEN=dev just run config get apiToken --json
189
216
  ```
@@ -33,15 +33,15 @@ Sibling repos under `../../ss/` (paths are machine-specific; adjust in `justfile
33
33
  | Recipe | When | Effect |
34
34
  | --- | --- | --- |
35
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 **argsbarg Cursor rule**, `just build`, `just docgen`, `just install` (consumer app binary, completions, and **app** skill) |
36
+ | `just consumers-sync` | After release | Sets `"argsbarg": "^<this package.json version>"`, `bun install`, merge **argsbarg Cursor rule**, `just build`, `just docgen`, `just install-local` (Homebrew dev formula + agent artifacts; `just install` is an alias) |
37
37
 
38
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
39
 
40
- **Argsbarg authoring rule** — `scripts/merge-cli-program-rule.ts` copies `docs/templates/cursor/rules/cli-program.mdc` into each consumer’s `.cursor/rules/cli-program.mdc`, preserving any existing `**… conventions:**` footer block.
40
+ **Argsbarg authoring rule** — `scripts/merge-cli-program-rule.ts` copies `examples/full-example/.cursor/rules/cli-program.mdc` into each consumer’s `.cursor/rules/cli-program.mdc`, preserving any existing `**… conventions:**` footer block.
41
41
 
42
42
  **Recommended in each consumer:** replace the template placeholder with `**<app> conventions:**` bullets (paths to `read*Flags`, shared flags, Ink vs JSON-only). Commit that file; merges refresh the shared top, not your footer.
43
43
 
44
- **Consumer app skill** — `just install` in each consumer (part of `consumers-sync`) runs `myapp install --skill`, which updates `~/.cursor/skills/<app>/` from that app’s schema — not the argsbarg framework rule.
44
+ **Consumer app skill** — `just install-local` in each consumer (part of `consumers-sync`) runs Homebrew dev install then `myapp install --reinstall --yes`, which updates `~/.cursor/skills/<app>/` from that app’s schema — not the argsbarg framework rule.
45
45
 
46
46
  ## npm package contents
47
47
 
@@ -49,14 +49,14 @@ Sibling repos under `../../ss/` (paths are machine-specific; adjust in `justfile
49
49
 
50
50
  When adding docs or examples intended for consumers, ensure they live under whitelisted paths (`docs/`, `examples/`, `src/`, etc.).
51
51
 
52
- Exclude `examples/consumer-app/node_modules/` from the npm tarball via [`.npmignore`](../.npmignore).
52
+ Exclude `examples/full-example/node_modules/` from the npm tarball via [`.npmignore`](../.npmignore).
53
53
 
54
- ## Kitchen-sink example
54
+ ## Full example
55
55
 
56
- [`examples/consumer-app/`](../examples/consumer-app/) must enable every builtin (`capabilities.test.ts`). After builtin or schemagen doc changes:
56
+ [`examples/full-example/`](../examples/full-example/) must enable every builtin (`capabilities.test.ts`). After builtin or schemagen doc changes:
57
57
 
58
58
  ```bash
59
- just consumer-app-schemagen
59
+ just full-example-schemagen
60
60
  just test
61
61
  ```
62
62