argsbarg 3.1.0 → 3.3.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 +30 -1
- package/README.md +4 -6
- package/docs/ai-skills.md +1 -1
- package/docs/bundled-docs.md +18 -4
- package/docs/install.md +51 -4
- package/docs/mcp.md +4 -6
- package/examples/minimal.ts +6 -0
- package/examples/nested.ts +3 -0
- package/index.d.ts +93 -1
- package/package.json +1 -1
- package/plan.md +10 -185
- package/src/builtins/completion-bash.ts +1 -8
- package/src/builtins/completion-fish.ts +0 -5
- package/src/builtins/completion-zsh.ts +1 -9
- package/src/builtins/dispatch.ts +27 -0
- package/src/builtins/export.ts +4 -0
- package/src/builtins/install.ts +9 -3
- package/src/builtins/presentation.ts +4 -0
- package/src/builtins/shell-helpers.ts +0 -2
- package/src/builtins/update.ts +14 -0
- package/src/capabilities.ts +7 -1
- package/src/docs/api-guide.test.ts +55 -0
- package/src/docs/api-guide.ts +129 -0
- package/src/docs/builtin.ts +3 -0
- package/src/docs/docs.test.ts +47 -1
- package/src/docs/mcp-guide.ts +3 -3
- package/src/docs/resolve.ts +32 -1
- package/src/headless.test.ts +86 -0
- package/src/headless.ts +86 -0
- package/src/help.ts +3 -7
- package/src/index.test.ts +36 -65
- package/src/index.ts +20 -0
- package/src/install/binary.ts +8 -3
- package/src/install/gh-release-update.test.ts +22 -0
- package/src/install/gh-release-update.ts +229 -0
- package/src/install/index.ts +55 -30
- package/src/install/plan.ts +5 -3
- package/src/install/update.test.ts +106 -0
- package/src/install/update.ts +55 -0
- package/src/invoke.ts +1 -11
- package/src/mcp/tools.ts +1 -1
- package/src/parse.ts +0 -27
- package/src/runtime.ts +7 -6
- package/src/schema.ts +7 -2
- package/src/skill/generate.ts +2 -2
- package/src/types.ts +17 -0
- package/src/validate.ts +11 -6
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [3.3.0] - 2026-06-21
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## [3.3.0] - 2026-06-20
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **Headless helpers** — `shouldRunHeadless`, `shouldRunHeadlessWithPositionals`, `shouldRunHeadlessWithYes`, `wantsDryRun`, `wantsExplicitJson`, `requireYesInNonTty`, `formatDryRunMessage` for Ink/MCP CLIs.
|
|
18
|
+
- **`ghReleaseUpdateGetLatest`** — optional `install.updateGetLatest` factory for GitHub releases via `gh`.
|
|
19
|
+
- **`createGhVersionCheck`** — version-check cache, update notices, and background refresh helpers.
|
|
20
|
+
|
|
21
|
+
## [3.2.0] - 2026-06-20
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- **`docs schema`** — print the full command tree as JSON (`myapp docs schema`). Replaces root `--schema` (requires `docs.enabled`).
|
|
26
|
+
- **`docs api`** — print the command tree as markdown (`myapp docs api`). Human-readable companion to `docs schema`.
|
|
27
|
+
- **`docs skill`** — print generated Cursor `SKILL.md` content to stdout (`myapp docs skill`).
|
|
28
|
+
- **`update` built-in** — when `install.updateGetLatest` is set, `myapp update` downloads the latest binary and reinstalls installed artifacts.
|
|
29
|
+
- **`install --reinstall`** — replaces `--update` (still accepted as a deprecated alias). Optional `--from <path>` for the binary source.
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- **Breaking:** root **`--schema`** removed — use **`docs schema`** when `docs.enabled` is `true`.
|
|
34
|
+
- **Breaking:** **`install --update`** renamed to **`install --reinstall`**.
|
|
35
|
+
|
|
10
36
|
## [3.1.0] - 2026-06-20
|
|
11
37
|
|
|
12
38
|
### Added
|
|
@@ -208,7 +234,10 @@ const cli = { ... } satisfies CliProgram; // or : CliProgram
|
|
|
208
234
|
- 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`).
|
|
209
235
|
- Imports: use `CliPositional` where needed; replace `CliOptionDef` with `CliOption` or `CliPositional` as appropriate.
|
|
210
236
|
|
|
211
|
-
[Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v3.
|
|
237
|
+
[Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v3.3.0...HEAD
|
|
238
|
+
[3.3.0]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.3.0
|
|
239
|
+
[3.3.0]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.3.0
|
|
240
|
+
[3.2.0]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.2.0
|
|
212
241
|
[3.1.0]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.1.0
|
|
213
242
|
[3.0.0]: https://github.com/bdombro/bun-argsbarg/releases/tag/v3.0.0
|
|
214
243
|
[2.1.1]: https://github.com/bdombro/bun-argsbarg/releases/tag/v2.1.1
|
package/README.md
CHANGED
|
@@ -95,22 +95,20 @@ Everything you need for a first-class CLI:
|
|
|
95
95
|
Every app gets:
|
|
96
96
|
|
|
97
97
|
- `-h` / `--help` at any routing depth (scoped help).
|
|
98
|
-
- **`--schema`** at the program root — print the full command tree as JSON (for tooling and agents).
|
|
99
98
|
- **`completion bash` / `completion zsh` / `completion fish`** — print shell completion scripts to stdout (injected by `cliRun`).
|
|
100
99
|
- **`version`** — print `CliProgram.version` (`myapp version`).
|
|
101
100
|
- **`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).
|
|
101
|
+
- **`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
102
|
- **`install`** — install the binary, completions, skills, and MCP config to the user environment (`myapp install --all --yes`). See [docs/install.md](docs/install.md).
|
|
104
103
|
|
|
105
104
|
Do not declare a top-level command named **`completion`**, **`version`**, or **`install`** — they are reserved.
|
|
106
105
|
When **`mcpServer.enabled`** is `true`, do not declare a top-level command named **`mcp`** — it is reserved for the MCP built-in.
|
|
107
106
|
When **`docs.enabled`** is `true`, do not declare a top-level command named **`docs`** — it is reserved for the docs built-in.
|
|
108
|
-
Do not declare an option named **`schema`** — it is reserved for `--schema`.
|
|
109
107
|
|
|
110
108
|
|
|
111
109
|
### MCP (AI agents)
|
|
112
110
|
|
|
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
|
|
111
|
+
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` and use `cliInvoke` for headless testing.
|
|
114
112
|
|
|
115
113
|
See **[docs/mcp.md](docs/mcp.md)** for configuration, env bootstrapping, custom resources, Cursor setup, and protocol details.
|
|
116
114
|
|
|
@@ -124,7 +122,7 @@ myapp install --all --yes
|
|
|
124
122
|
|
|
125
123
|
This copies the binary to `~/.local/bin`, installs shell completions (bash/zsh/fish when each shell is on PATH), writes Cursor/Claude skills when agent directories exist, and merges MCP server entries into Cursor and Claude config files.
|
|
126
124
|
|
|
127
|
-
See **[docs/install.md](docs/install.md)** for `--update`, `--status`, `--uninstall`, and flags.
|
|
125
|
+
See **[docs/install.md](docs/install.md)** for `--reinstall`, `update`, `--status`, `--uninstall`, and flags.
|
|
128
126
|
|
|
129
127
|
|
|
130
128
|
### Shell completions
|
|
@@ -189,7 +187,7 @@ Add `CliPositional` entries to the command’s `positionals` list (separate from
|
|
|
189
187
|
|
|
190
188
|
### Capabilities (built-ins)
|
|
191
189
|
|
|
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`.
|
|
190
|
+
`completion`, `version`, `install`, `update`, 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`; `update` when `install.updateGetLatest` is set; `mcp` when `mcpServer.enabled` is `true`; `docs` when `docs.enabled` is `true`.
|
|
193
191
|
|
|
194
192
|
|
|
195
193
|
|
package/docs/ai-skills.md
CHANGED
|
@@ -32,7 +32,7 @@ For library use, call `cliSkillInstall(root, "cursor" | "claude", { global: true
|
|
|
32
32
|
## Generated content
|
|
33
33
|
|
|
34
34
|
- **`SKILL.md`** — YAML frontmatter, when-to-use guidance, shell command catalog, pitfalls
|
|
35
|
-
- **`reference.md`** — full
|
|
35
|
+
- **`reference.md`** — full `docs schema` JSON export
|
|
36
36
|
|
|
37
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
38
|
|
package/docs/bundled-docs.md
CHANGED
|
@@ -27,6 +27,9 @@ const cli = {
|
|
|
27
27
|
myapp docs # first topic (readme) via fallback
|
|
28
28
|
myapp docs readme
|
|
29
29
|
myapp docs architecture
|
|
30
|
+
myapp docs schema # full command tree as JSON
|
|
31
|
+
myapp docs api # command tree as markdown
|
|
32
|
+
myapp docs skill # generated Cursor SKILL.md
|
|
30
33
|
myapp docs all # all user topics; includes auto mcp when MCP enabled
|
|
31
34
|
myapp docs mcp # auto-generated when mcpServer.enabled
|
|
32
35
|
```
|
|
@@ -40,7 +43,7 @@ myapp docs mcp # auto-generated when mcpServer.enabled
|
|
|
40
43
|
| `defaultTopic` | first key in `topics` | `fallbackCommand` for bare `myapp docs` |
|
|
41
44
|
| `topics` | *(required)* | Topic key → `{ text, description? }` |
|
|
42
45
|
|
|
43
|
-
Reserved topic keys in `topics`: **`mcp`**, **`all`** (supplied by the built-in).
|
|
46
|
+
Reserved topic keys in `topics`: **`mcp`**, **`all`**, **`schema`**, **`api`**, **`skill`** (supplied by the built-in).
|
|
44
47
|
|
|
45
48
|
When `description` is omitted on a topic, ArgsBarg generates leaf help (`readme` → "Print README (user guide).").
|
|
46
49
|
|
|
@@ -54,7 +57,15 @@ import readmeText from "../README.md" with { type: "text" };
|
|
|
54
57
|
|
|
55
58
|
Bun embeds the file when you `bun build --compile`. ArgsBarg does not read the filesystem at runtime.
|
|
56
59
|
|
|
57
|
-
|
|
60
|
+
Inline topics in your program root when the set is small; use a separate module only if the import map grows enough to clutter `index.tsx`.
|
|
61
|
+
|
|
62
|
+
## Schema, API, and skill (`docs schema`, `docs api`, `docs skill`)
|
|
63
|
+
|
|
64
|
+
When `docs.enabled` is `true`:
|
|
65
|
+
|
|
66
|
+
- **`docs schema`** — same JSON as the former root `--schema` flag (handlers omitted; built-in subtrees included for leaf roots).
|
|
67
|
+
- **`docs api`** — markdown rendering of the same command tree (options, positionals, subcommands, fallback routing).
|
|
68
|
+
- **`docs skill`** — prints generated Cursor `SKILL.md` content (same prose as `install --skill`, without writing files).
|
|
58
69
|
|
|
59
70
|
## MCP guide (`docs mcp`)
|
|
60
71
|
|
|
@@ -70,8 +81,11 @@ All `docs` subcommands are hidden from MCP `tools/list` (`mcpTool: { enabled: fa
|
|
|
70
81
|
|
|
71
82
|
| Channel | Role |
|
|
72
83
|
| --- | --- |
|
|
73
|
-
| `install --skill` |
|
|
74
|
-
| `docs` |
|
|
84
|
+
| `install --skill` | Writes shell command catalog + `reference.md` to disk |
|
|
85
|
+
| `docs skill` | Print generated `SKILL.md` to stdout |
|
|
86
|
+
| `docs api` | Print command tree markdown to stdout |
|
|
87
|
+
| `docs schema` | Print command tree JSON to stdout |
|
|
88
|
+
| `docs` | Bundled markdown topics on stdout |
|
|
75
89
|
| `mcp` | Callable tools + schema resource |
|
|
76
90
|
|
|
77
91
|
Do not declare a top-level command named **`docs`** when `docs.enabled` is `true` — it is reserved.
|
package/docs/install.md
CHANGED
|
@@ -8,8 +8,11 @@ The `install` built-in installs the binary, shell completions, agent skills, and
|
|
|
8
8
|
# First-time setup
|
|
9
9
|
myapp install --all --yes
|
|
10
10
|
|
|
11
|
-
# Refresh after upgrading
|
|
12
|
-
myapp install --
|
|
11
|
+
# Refresh after upgrading (re-copy running binary + refresh installed artifacts)
|
|
12
|
+
myapp install --reinstall
|
|
13
|
+
|
|
14
|
+
# Download latest release (when install.updateGetLatest is configured)
|
|
15
|
+
myapp update
|
|
13
16
|
|
|
14
17
|
# See what is installed
|
|
15
18
|
myapp install --status
|
|
@@ -42,9 +45,50 @@ On the program root:
|
|
|
42
45
|
install: {
|
|
43
46
|
enabled: false, // opt out of the install built-in
|
|
44
47
|
prefix: "~/.local/bin", // default bin directory
|
|
48
|
+
updateGetLatest: async ({ version }) => {
|
|
49
|
+
// download or locate latest binary; return { path, version, cleanup }
|
|
50
|
+
return { path: "/tmp/myapp", version: "2.0.0" };
|
|
51
|
+
},
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
When `updateGetLatest` is set, ArgsBarg also registers the **`update`** built-in (`myapp update`).
|
|
56
|
+
|
|
57
|
+
### GitHub releases (`ghReleaseUpdateGetLatest`)
|
|
58
|
+
|
|
59
|
+
For compiled binaries published via `gh release`, wire a hook without hand-rolling download logic:
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import {
|
|
63
|
+
createGhFetchLatest,
|
|
64
|
+
createGhVersionCheck,
|
|
65
|
+
ghReleaseUpdateGetLatest,
|
|
66
|
+
} from "argsbarg";
|
|
67
|
+
|
|
68
|
+
const cachePath = path.join(configDir, "version-check.json");
|
|
69
|
+
|
|
70
|
+
install: {
|
|
71
|
+
updateGetLatest: ghReleaseUpdateGetLatest({
|
|
72
|
+
repo: "owner/repo",
|
|
73
|
+
asset: "myapp",
|
|
74
|
+
tempPrefix: "myapp-update.",
|
|
75
|
+
cachePath,
|
|
76
|
+
}),
|
|
45
77
|
}
|
|
78
|
+
|
|
79
|
+
// Optional: summary notice + background refresh
|
|
80
|
+
const versionCheck = createGhVersionCheck({
|
|
81
|
+
currentVersion: "1.0.0",
|
|
82
|
+
commandName: "myapp",
|
|
83
|
+
cachePath,
|
|
84
|
+
fetchLatest: createGhFetchLatest({ repo: "owner/repo" }),
|
|
85
|
+
});
|
|
86
|
+
versionCheck.getUpdateNotice();
|
|
87
|
+
versionCheck.refreshIfStale();
|
|
46
88
|
```
|
|
47
89
|
|
|
90
|
+
Requires `gh` on PATH and `gh auth login`. Consumers keep app-specific config only (~15 lines).
|
|
91
|
+
|
|
48
92
|
Environment:
|
|
49
93
|
|
|
50
94
|
- `INSTALL_PREFIX` — same as `install.prefix` / `--prefix`
|
|
@@ -53,15 +97,18 @@ Environment:
|
|
|
53
97
|
|
|
54
98
|
| Flag | Description |
|
|
55
99
|
| --- | --- |
|
|
56
|
-
| `--yes` | Skip confirmation (required for non-TTY unless `--json` / `--
|
|
100
|
+
| `--yes` | Skip confirmation (required for non-TTY unless `--json` / `--reinstall`) |
|
|
57
101
|
| `--dry` | Preview changes; per-step messages on stderr with `[dry run]` |
|
|
58
102
|
| `--json` | Machine-readable output on stdout (implies `--yes`) |
|
|
59
103
|
| `--quiet` | Suppress summaries and per-step messages (requires `--yes`) |
|
|
60
104
|
| `--prefix <dir>` | Override binary install directory |
|
|
61
|
-
| `--
|
|
105
|
+
| `--reinstall` | Reinstall artifacts already on disk (implies `--bin` + `--yes`) |
|
|
106
|
+
| `--from <path>` | Binary to copy with `--reinstall` (default: running executable) |
|
|
62
107
|
| `--status` | Read-only inventory |
|
|
63
108
|
| `--uninstall` | Remove detected artifacts (scope with `--bin`, `--completions`, `--skill`, `--mcp`) |
|
|
64
109
|
|
|
110
|
+
`--update` is accepted as a deprecated alias for `--reinstall`.
|
|
111
|
+
|
|
65
112
|
## MCP merge behavior
|
|
66
113
|
|
|
67
114
|
When `--mcp` runs, entries are merged into `mcpServers[<sanitized-key>]` with:
|
package/docs/mcp.md
CHANGED
|
@@ -113,7 +113,7 @@ Each tool’s `description` includes the human CLI path and the leaf’s help te
|
|
|
113
113
|
|
|
114
114
|
### Per-leaf visibility
|
|
115
115
|
|
|
116
|
-
Set `mcpTool: { enabled: false }` on a **leaf command** to hide it from `tools/list` while keeping it in the CLI and in
|
|
116
|
+
Set `mcpTool: { enabled: false }` on a **leaf command** to hide it from `tools/list` while keeping it in the CLI and in `docs schema` output:
|
|
117
117
|
|
|
118
118
|
```typescript
|
|
119
119
|
{
|
|
@@ -172,11 +172,11 @@ On success (`isError: false`):
|
|
|
172
172
|
|
|
173
173
|
On failure (parse error, validation error, non-zero exit, thrown error), the message is returned as text content with `isError: true`. Handler stderr is included when present.
|
|
174
174
|
|
|
175
|
-
Help and
|
|
175
|
+
Help and `docs schema` are not available through tool calls; use the schema resource or run the CLI directly for those.
|
|
176
176
|
|
|
177
177
|
## Schema and custom resources
|
|
178
178
|
|
|
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
|
|
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 docs schema`. Override with `schemaResourceUri` if needed.
|
|
180
180
|
|
|
181
181
|
| Property | Value |
|
|
182
182
|
| --- | --- |
|
|
@@ -291,9 +291,7 @@ You should get one JSON line on stdout with `result.capabilities` and `result.se
|
|
|
291
291
|
|
|
292
292
|
When MCP is enabled:
|
|
293
293
|
|
|
294
|
-
- Do not declare a top-level command named **`ai`** — it is reserved for the built-in AI integration group.
|
|
295
294
|
- Do not declare a top-level command named **`completion`** — reserved for shell completions.
|
|
296
|
-
- Do not declare an option named **`schema`** — reserved for `--schema`.
|
|
297
295
|
|
|
298
296
|
Running `myapp mcp` without `mcpServer` on the root fails with an error (exit 1).
|
|
299
297
|
|
|
@@ -304,4 +302,4 @@ Running `myapp mcp` without `mcpServer` on the root fails with an error (exit 1)
|
|
|
304
302
|
- **User schema only** — tool dispatch uses your program root, not merged presentation builtins.
|
|
305
303
|
- **Buffered output** — MCP tool results are sent after the handler finishes. Incremental stdout (log tail, progress) is not streamed; a future release may add MCP progress notifications.
|
|
306
304
|
|
|
307
|
-
For the
|
|
305
|
+
For the `docs schema` export used by the resource, see [docs/bundled-docs.md](bundled-docs.md).
|
package/examples/minimal.ts
CHANGED
package/examples/nested.ts
CHANGED
package/index.d.ts
CHANGED
|
@@ -167,11 +167,28 @@ export interface CliMcpToolConfig {
|
|
|
167
167
|
/**
|
|
168
168
|
* Opt-out and defaults for the `install` built-in (program root only).
|
|
169
169
|
*/
|
|
170
|
+
export interface CliUpdateArtifact {
|
|
171
|
+
/** Path to an executable binary to copy into the install location. */
|
|
172
|
+
path: string;
|
|
173
|
+
/** Release version of `path` (used for already-current checks and success messages). */
|
|
174
|
+
version?: string;
|
|
175
|
+
/** Called after reinstall completes (e.g. remove a temp download directory). */
|
|
176
|
+
cleanup?: () => void | Promise<void>;
|
|
177
|
+
}
|
|
178
|
+
/** Fetches the latest release binary for the `update` built-in. */
|
|
179
|
+
export type CliUpdateGetLatest = (ctx: {
|
|
180
|
+
version: string;
|
|
181
|
+
}) => Promise<CliUpdateArtifact>;
|
|
170
182
|
export interface CliInstallConfig {
|
|
171
183
|
/** When `false`, hide/disable `install` (default: enabled). */
|
|
172
184
|
enabled?: boolean;
|
|
173
185
|
/** Default bin directory (default: `~/.local/bin`). Overridden by `INSTALL_PREFIX` env and `--prefix`. */
|
|
174
186
|
prefix?: string;
|
|
187
|
+
/**
|
|
188
|
+
* When set, enables the `update` built-in (`myapp update`).
|
|
189
|
+
* Should download or locate the latest release binary and return its path.
|
|
190
|
+
*/
|
|
191
|
+
updateGetLatest?: CliUpdateGetLatest;
|
|
175
192
|
}
|
|
176
193
|
/**
|
|
177
194
|
* One bundled documentation topic for the `docs` built-in (program root only).
|
|
@@ -265,7 +282,7 @@ export declare class CliSchemaValidationError extends Error {
|
|
|
265
282
|
constructor(message: string);
|
|
266
283
|
}
|
|
267
284
|
/** Outcome of a non-exiting CLI invocation. */
|
|
268
|
-
export type CliInvokeKind = "ok" | "help" | "
|
|
285
|
+
export type CliInvokeKind = "ok" | "help" | "error";
|
|
269
286
|
/** Result of cliInvoke: captured output and exit metadata without process.exit. */
|
|
270
287
|
export interface CliInvokeResult {
|
|
271
288
|
/** Invocation outcome. */
|
|
@@ -288,5 +305,80 @@ export declare function cliRun(program: CliProgram, argv?: string[]): Promise<ne
|
|
|
288
305
|
export declare function cliErrWithHelp(ctx: CliContext, msg: string): never;
|
|
289
306
|
/** True when stdin is a TTY. */
|
|
290
307
|
export declare const isInteractiveTty: boolean;
|
|
308
|
+
/** Minimal context for headless routing helpers. */
|
|
309
|
+
export type HeadlessContext = Pick<CliContext, "invocation">;
|
|
310
|
+
/** True when `--dry-run` was passed. */
|
|
311
|
+
export declare function wantsDryRun(hasDryRunFlag: boolean): boolean;
|
|
312
|
+
/** True when `--json` was passed or the handler was invoked via MCP. */
|
|
313
|
+
export declare function wantsExplicitJson(ctx: HeadlessContext, hasJsonFlag: boolean): boolean;
|
|
314
|
+
/**
|
|
315
|
+
* Headless when MCP, `--json`, `--dry-run`, or stdin is not a TTY.
|
|
316
|
+
* Use for commands that should auto-emit JSON in pipelines.
|
|
317
|
+
*/
|
|
318
|
+
export declare function shouldRunHeadless(ctx: HeadlessContext, hasJsonFlag: boolean, hasDryRunFlag?: boolean, interactive?: boolean): boolean;
|
|
319
|
+
/**
|
|
320
|
+
* Like {@link shouldRunHeadless}, but only auto-headless in non-TTY when positionals are present.
|
|
321
|
+
* Avoids turning empty invocations into JSON errors.
|
|
322
|
+
*/
|
|
323
|
+
export declare function shouldRunHeadlessWithPositionals(ctx: HeadlessContext, hasJsonFlag: boolean, positionals: string[], hasDryRunFlag?: boolean, interactive?: boolean): boolean;
|
|
324
|
+
/**
|
|
325
|
+
* Headless when MCP, `--dry-run` with required args, or non-TTY with `--yes` and required args.
|
|
326
|
+
* Use for mutating commands that require explicit `--yes` in scripts.
|
|
327
|
+
*/
|
|
328
|
+
export declare function shouldRunHeadlessWithYes(ctx: HeadlessContext, opts: {
|
|
329
|
+
yes: boolean;
|
|
330
|
+
hasRequiredArgs: boolean;
|
|
331
|
+
dryRun?: boolean;
|
|
332
|
+
}, interactive?: boolean): boolean;
|
|
333
|
+
/**
|
|
334
|
+
* Exits when non-interactive mode is used without `--yes`.
|
|
335
|
+
* @param hint - Command-specific guidance appended to the error
|
|
336
|
+
*/
|
|
337
|
+
export declare function requireYesInNonTty(yes: boolean, hint: string, dryRun?: boolean, interactive?: boolean): void;
|
|
338
|
+
/** Prefixes a success message when running in dry-run mode. */
|
|
339
|
+
export declare function formatDryRunMessage(message: string, dryRun: boolean): string;
|
|
340
|
+
/** Config for {@link ghReleaseUpdateGetLatest}. */
|
|
341
|
+
export interface GhReleaseUpdateConfig {
|
|
342
|
+
/** GitHub `owner/repo` slug. */
|
|
343
|
+
repo: string;
|
|
344
|
+
/** Release asset filename (e.g. `myapp`). */
|
|
345
|
+
asset: string;
|
|
346
|
+
/** Temp directory name prefix for downloads. */
|
|
347
|
+
tempPrefix: string;
|
|
348
|
+
/** Path to the on-disk version-check cache JSON file. */
|
|
349
|
+
cachePath: string;
|
|
350
|
+
/** Optional hint when `gh auth` fails or no releases exist. */
|
|
351
|
+
repoEnvHint?: string;
|
|
352
|
+
}
|
|
353
|
+
/** Config for {@link createGhVersionCheck}. */
|
|
354
|
+
export interface GhVersionCheckConfig {
|
|
355
|
+
/** Installed semver string. */
|
|
356
|
+
currentVersion: string;
|
|
357
|
+
/** CLI command name for update notices (e.g. `qa`). */
|
|
358
|
+
commandName: string;
|
|
359
|
+
/** Path to the on-disk version-check cache JSON file. */
|
|
360
|
+
cachePath: string;
|
|
361
|
+
/** Cache TTL in milliseconds (default 24h). */
|
|
362
|
+
ttlMs?: number;
|
|
363
|
+
/** When true, skip background refresh (e.g. test subprocess). */
|
|
364
|
+
skipRefresh?: () => boolean;
|
|
365
|
+
/** When true, skip refresh because `gh` is unavailable. */
|
|
366
|
+
ghAvailable?: () => boolean;
|
|
367
|
+
/** Fetches latest release version via `gh`. */
|
|
368
|
+
fetchLatest: () => Promise<string>;
|
|
369
|
+
}
|
|
370
|
+
/** Returns whether the installed version matches the latest release. */
|
|
371
|
+
export declare function isAlreadyCurrent(current: string, latest: string): boolean;
|
|
372
|
+
/** Strips a leading `v` from a release tag. */
|
|
373
|
+
export declare function parseReleaseTag(tag: string): string;
|
|
374
|
+
/** Builds a `CliUpdateGetLatest` hook that downloads a release via `gh`. */
|
|
375
|
+
export declare function ghReleaseUpdateGetLatest(config: GhReleaseUpdateConfig): CliUpdateGetLatest;
|
|
376
|
+
/** Version-check cache helpers for summary notices and background refresh. */
|
|
377
|
+
export declare function createGhVersionCheck(config: GhVersionCheckConfig): {
|
|
378
|
+
getUpdateNotice: () => string | null;
|
|
379
|
+
refreshIfStale: () => void;
|
|
380
|
+
};
|
|
381
|
+
/** Shared `gh release view` fetcher for hooks and version-check refresh. */
|
|
382
|
+
export declare function createGhFetchLatest(config: Pick<GhReleaseUpdateConfig, "repo" | "repoEnvHint">): () => Promise<string>;
|
|
291
383
|
|
|
292
384
|
export {};
|
package/package.json
CHANGED
package/plan.md
CHANGED
|
@@ -1,194 +1,19 @@
|
|
|
1
1
|
# bun-argsbarg Plan
|
|
2
2
|
|
|
3
|
-
## Plan: bun-argsbarg — Bun CLI Argument Parser
|
|
4
|
-
|
|
5
|
-
**TL;DR**: Convert the Swift `argsbarg` declarative CLI framework into a TypeScript/Bun library with the same CLI features (schema-driven parsing, help rendering, shell completion, subcommand routing, fallback commands) while leveraging TypeScript's type system for compile-time schema safety.
|
|
6
|
-
|
|
7
3
|
## Current Status
|
|
8
4
|
|
|
9
|
-
**Overall**:
|
|
10
|
-
|
|
11
|
-
### ✅ Completed
|
|
12
|
-
|
|
13
|
-
- **Phase 1**: Core Schema Types (`src/types.ts`)
|
|
14
|
-
- `CliOptionKind` enum (Presence, String, Number)
|
|
15
|
-
- `CliFallbackMode` enum (MissingOnly, MissingOrUnknown, UnknownOnly)
|
|
16
|
-
- `CliCommand`, `CliOption`, `CliPositional`, `CliHandler`, `CliContext` interfaces
|
|
17
|
-
- `CliSchemaValidationError` class
|
|
18
|
-
- `CliOption` on `options`, `CliPositional` on `positionals`, nested routes under `commands`
|
|
19
|
-
|
|
20
|
-
- **Phase 2**: Argument Parser (`src/parse.ts`)
|
|
21
|
-
- `parse(root, argv)` with long/short options, bundling, equals syntax
|
|
22
|
-
- Option consumption logic with strict number validation
|
|
23
|
-
- Subcommand routing and positional argument collection
|
|
24
|
-
- Help token detection (`-h`, `--help`)
|
|
25
|
-
- `postParseValidate()` for strict option validation
|
|
26
|
-
- `cliValidateRoot()` for schema validation (root rules, child uniqueness, reserved names, positional ordering)
|
|
27
|
-
- Support for all fallback modes
|
|
28
|
-
|
|
29
|
-
- **Phase 3**: Runtime Context (`src/context.ts`)
|
|
30
|
-
- `CliContext` class with typed accessors
|
|
31
|
-
- `flag(name)` — boolean presence check
|
|
32
|
-
- `stringOpt(name)` — string value or undefined
|
|
33
|
-
- `numberOpt(name)` — strict double parsing or null
|
|
34
|
-
- `typedOpt<T>(name, parse)` — generic typed accessor (TypeScript advantage)
|
|
35
|
-
|
|
36
|
-
- **Phase 4**: Help Rendering (`src/help.ts`)
|
|
37
|
-
- `cliHelpRender()` for formatted help output
|
|
38
|
-
- TTY-aware ANSI colors (red, aqua, gray, bold)
|
|
39
|
-
- Unicode box drawing (╭╮├┤╰╯)
|
|
40
|
-
- Terminal width detection (`process.stdout.columns`)
|
|
41
|
-
- Text wrapping with visible width calculation (strips ANSI)
|
|
42
|
-
- Help sections: usage box, options table, positionals table, subcommands table, notes box
|
|
43
|
-
- `cliOptionLabel()` for formatted option display
|
|
44
|
-
|
|
45
|
-
- **Phase 5**: Shell Completion (`src/completion.ts`)
|
|
46
|
-
- `completionBashScript(schema)` — bash tab-completion generator
|
|
47
|
-
- `completionZshScript(schema)` — zsh tab-completion generator
|
|
48
|
-
- Scope walking for command tree traversal
|
|
49
|
-
- Option/command/positional matching logic for both shells
|
|
50
|
-
|
|
51
|
-
### 🚧 In Progress
|
|
52
|
-
|
|
53
|
-
- **Phase 6**: Main Entry Point (`src/index.ts`)
|
|
54
|
-
- **Status**: Placeholder `hello()` function remains
|
|
55
|
-
- **Needs**: Implement `cliRun(root: CliCommand): Promise<void>`
|
|
56
|
-
- Validate schema via `cliValidateRoot()`
|
|
57
|
-
- Auto-merge built-in `completion` command with `bash`/`zsh` subcommands
|
|
58
|
-
- Call `parse()` on `process.argv.slice(2)`
|
|
59
|
-
- Call `postParseValidate()`
|
|
60
|
-
- Handle `ParseKind.Help` → render via `cliHelpRender()` → exit(0)
|
|
61
|
-
- Handle `ParseKind.Error` → render red error + contextual help → exit(1)
|
|
62
|
-
- Route to handler function with `CliContext`
|
|
63
|
-
- Support async handlers with `await`
|
|
64
|
-
|
|
65
|
-
- **Phase 7**: Examples & Tests (`src/index.test.ts`, `examples/`)
|
|
66
|
-
- **Status**: Only placeholder tests exist
|
|
67
|
-
- **Needs**:
|
|
68
|
-
- Replace `src/index.test.ts` with comprehensive test suite covering:
|
|
69
|
-
- Option parsing (long, short, bundled, equals syntax)
|
|
70
|
-
- Help detection and rendering
|
|
71
|
-
- Subcommand routing and fallback modes
|
|
72
|
-
- Positional argument collection and arity validation
|
|
73
|
-
- Unknown options/commands
|
|
74
|
-
- Schema validation errors
|
|
75
|
-
- Async handler support
|
|
76
|
-
- Typed option accessors
|
|
77
|
-
- Create `examples/minimal.ts` — hello with `--name` and `--verbose`
|
|
78
|
-
- Create `examples/nested.ts` — nested subcommands with positionals (mirroring Swift examples)
|
|
79
|
-
|
|
80
|
-
### ❌ Not Started
|
|
81
|
-
|
|
82
|
-
- **Phase 8**: Project Polish
|
|
83
|
-
- Add `biome.json` for linting/formatting
|
|
84
|
-
- Add CLI binary entry point (`bin/argsbarg`)
|
|
85
|
-
- Create `README.md` with API docs and usage examples
|
|
86
|
-
- Update `package.json` scripts and bin entry
|
|
87
|
-
- Verify all verification steps pass
|
|
88
|
-
|
|
89
|
-
## Next Immediate Steps
|
|
90
|
-
|
|
91
|
-
1. Implement `cliRun()` in `src/index.ts`
|
|
92
|
-
2. Rewrite `src/index.test.ts` with actual test coverage
|
|
93
|
-
3. Create working examples in `examples/`
|
|
94
|
-
4. Run `bun test` and verify all tests pass
|
|
95
|
-
5. Run examples and verify output matches expectations
|
|
96
|
-
|
|
97
|
-
**Steps**
|
|
98
|
-
|
|
99
|
-
### Phase 1: Core Schema Types (types.ts)
|
|
100
|
-
- Define TypeScript equivalents of Swift's `CliOptionKind`, `CliOption`, `CliCommand`, `CliFallbackMode`
|
|
101
|
-
- Leverage TypeScript generics/union types for compile-time safety (e.g., typed option values instead of string-only)
|
|
102
|
-
- Add `CliHandler` type as `(ctx: CliContext) => void | Promise<void>` (support async handlers)
|
|
103
|
-
- Add `CliSchemaValidationError` enum/class
|
|
104
|
-
- **Parallel with Phase 2**
|
|
105
|
-
|
|
106
|
-
### Phase 2: Argument Parser (parse.ts)
|
|
107
|
-
- Implement `parse(root: CliCommand, argv: string[]): ParseResult` — same logic as Swift
|
|
108
|
-
- Long options (`--name`, `--name=value`)
|
|
109
|
-
- Short options (`-n`, bundled `-abc`)
|
|
110
|
-
- Subcommand routing through nested `CliCommand` tree
|
|
111
|
-
- Positional argument collection with arity validation (argMin/argMax)
|
|
112
|
-
- Help token detection (`-h`/`--help`)
|
|
113
|
-
- Root-level `fallbackCommand`/`fallbackMode` support
|
|
114
|
-
- Implement `postParseValidate()` — strict number validation, option key verification
|
|
115
|
-
- Implement `cliValidateRoot()` — schema validation (no handler on routing nodes, no positionals on root, unique short names, reserved `-h`, etc.)
|
|
116
|
-
- **Depends on Phase 1**
|
|
117
|
-
|
|
118
|
-
### Phase 3: Context & Runtime (context.ts)
|
|
119
|
-
- Implement `CliContext` class with typed accessors:
|
|
120
|
-
- `flag(name)` — boolean presence check
|
|
121
|
-
- `stringOpt(name)` — string value
|
|
122
|
-
- `numberOpt(name)` — strict double parse
|
|
123
|
-
- **TypeScript enhancement**: `typedOpt<T>(name, parseFn)` — generic typed accessor
|
|
124
|
-
- Implement `cliErrWithHelp(ctx, msg)` — red error + contextual help on stderr
|
|
125
|
-
- **Depends on Phase 1**
|
|
126
|
-
|
|
127
|
-
### Phase 4: Help Rendering (help.ts)
|
|
128
|
-
- Terminal-aware help with rounded box drawing (same Unicode box chars as Swift)
|
|
129
|
-
- TTY detection (Node's `process.stdout.isTTY` instead of Swift's `isatty`)
|
|
130
|
-
- Terminal width detection (`TIOCGWINSZ` via `ioctl` or fallback to `process.stdout.columns`)
|
|
131
|
-
- ANSI color support (TTY-aware, same palette: red/green/aqua/gray/bold)
|
|
132
|
-
- Help sections: Usage box, Options table, Arguments table, Subcommands table, Notes box
|
|
133
|
-
- `cliHelpRender(schema, helpPath, useStderr)` — full help for root or nested command
|
|
134
|
-
- **Depends on Phase 1**
|
|
135
|
-
|
|
136
|
-
### Phase 5: Shell Completion (completion.ts)
|
|
137
|
-
- `completionBashScript(schema)` — generate bash tab-completion script
|
|
138
|
-
- `completionZshScript(schema)` — generate zsh tab-completion script
|
|
139
|
-
- Same scope-walking algorithm as Swift (depth-first, per-node arrays)
|
|
140
|
-
- **Depends on Phase 1**
|
|
141
|
-
|
|
142
|
-
### Phase 6: Main Entry Point (index.ts)
|
|
143
|
-
- `cliRun(root: CliCommand)` — orchestrates: validate → merge builtins → parse → validate → dispatch
|
|
144
|
-
- Auto-merge `completion`/`bash`/`zsh` reserved commands
|
|
145
|
-
- Exit code handling (0 for help/success, 1 for errors)
|
|
146
|
-
- **Depends on Phases 2-5**
|
|
147
|
-
|
|
148
|
-
### Phase 7: Examples & Tests
|
|
149
|
-
- `examples/minimal.ts` — hello world with options (like Swift's Minimal example)
|
|
150
|
-
- `examples/nested.ts` — deeply nested subcommands with positionals (like Swift's Nested example)
|
|
151
|
-
- `src/index.test.ts` — comprehensive tests mirroring Swift's ParseTests
|
|
152
|
-
- Bundled short flags, long option equals, fallback modes
|
|
153
|
-
- Unknown command, implicit help, invalid number validation
|
|
154
|
-
- Completion script generation verification
|
|
155
|
-
- Schema validation (root handler, root positionals, nested fallback, reserved names)
|
|
156
|
-
- **TypeScript-specific**: async handler support, typed option accessors
|
|
5
|
+
**Overall**: Core CLI, MCP, install, docs, and update built-ins are complete. Public API is stable at **3.x**.
|
|
157
6
|
|
|
158
|
-
###
|
|
159
|
-
- Add `biome.json` config (lint/format)
|
|
160
|
-
- Add `bin/` entry in `package.json` for CLI executable
|
|
161
|
-
- Add `README.md` with API docs and usage examples
|
|
162
|
-
- Update `package.json` scripts
|
|
163
|
-
- **Parallel with Phase 7**
|
|
7
|
+
### Shipped
|
|
164
8
|
|
|
165
|
-
|
|
166
|
-
-
|
|
167
|
-
-
|
|
168
|
-
-
|
|
169
|
-
- `/Users/briandombrowski/dev/bdombro/bun-argsbarg/tsconfig.json` — keep as-is (already correct for Bun)
|
|
170
|
-
- `/Users/briandombrowski/dev/bdombro/bun-argsbarg/examples/local-check.ts` — replace with minimal/nested examples
|
|
9
|
+
- Schema-driven parsing, help, completions, subcommand routing, fallback commands
|
|
10
|
+
- MCP server (`mcpServer: { enabled: true }`), `ctx.invocation`, `cliInvoke`
|
|
11
|
+
- `install` / `update` built-ins, agent skills, bundled `docs` (topics, schema, api, skill, mcp)
|
|
12
|
+
- Headless helpers and `ghReleaseUpdateGetLatest` for GitHub release consumers
|
|
171
13
|
|
|
172
|
-
|
|
173
|
-
1. `bun test` — all tests pass
|
|
174
|
-
2. `bun ./examples/minimal.ts hello --name World --verbose` — outputs "hello World" with verbose mode
|
|
175
|
-
3. `bun ./examples/minimal.ts hello --help` — shows formatted help with options table
|
|
176
|
-
4. `bun ./examples/nested.ts stat owner lookup --user-name bob /etc/passwd` — outputs "lookup user=bob path=/etc/passwd"
|
|
177
|
-
5. `bun ./examples/minimal.ts completion bash` — outputs valid bash completion script
|
|
178
|
-
6. `bun ./examples/minimal.ts completion zsh` — outputs valid zsh completion script
|
|
179
|
-
7. `bun lint` and `bun check-types` — no errors
|
|
180
|
-
8. `bun ./examples/minimal.ts unknown-cmd` — shows fallback command help with red error
|
|
14
|
+
### Consumers
|
|
181
15
|
|
|
182
|
-
**
|
|
183
|
-
- **
|
|
184
|
-
- **Typed options**: Add `typedOpt<T>(name, parse: (s: string) => T)` to leverage TypeScript's type system — this is the key TypeScript advantage over Swift's string-only approach
|
|
185
|
-
- **Async handlers**: Support `async (ctx) => Promise<void>` handlers — Bun/Node advantage over Swift's synchronous-only
|
|
186
|
-
- **TTY detection**: Use `process.stdout.isTTY` and `process.stdout.columns` (Node built-in) instead of `ioctl`/`isatty` FFI
|
|
187
|
-
- **No runtime dependencies**: Keep zero runtime deps, only `@types/bun` as dev dep
|
|
188
|
-
- **CLI binary**: Add `bin/argsbarg` entry point so the library can also be used as a CLI tool
|
|
189
|
-
- **Schema validation**: Same rules as Swift — root can't have handler/positionals, no duplicate shorts, `-h` reserved, etc.
|
|
16
|
+
- **qa-cli** — argsbarg program with Ink UI; commands under `src/commands/`
|
|
17
|
+
- **idp-trees** — argsbarg program with headless JSON ops; `cli/dispatch.ts` pattern
|
|
190
18
|
|
|
191
|
-
|
|
192
|
-
1. Should we add a `@argsbarg()` decorator pattern for declarative schema definition (like Python's argparse decorators)? This would be a TypeScript-native enhancement.
|
|
193
|
-
2. Should the CLI binary (`bin/argsbarg`) support loading schema from a config file (JSON/YAML) for dynamic CLIs?
|
|
194
|
-
3. Error exit codes: Swift uses exit(1) for help (implicit) and exit(0) for explicit help. Should we match this or use more conventional exit codes?
|
|
19
|
+
See [README.md](README.md) and [CHANGELOG.md](CHANGELOG.md) for release history.
|