argsbarg 1.4.3 → 2.0.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/.cursor/plans/cliprogram_capabilities_refactor_081e1737.plan.md +224 -0
- package/.private/scratch.md +1 -1
- package/CHANGELOG.md +39 -1
- package/README.md +29 -21
- package/docs/ai-skills.md +24 -52
- package/docs/install.md +84 -0
- package/docs/mcp.md +8 -8
- package/examples/mcp-test.ts +3 -3
- package/examples/minimal.ts +3 -3
- package/examples/nested.ts +3 -3
- package/examples/option-required.ts +3 -3
- package/index.d.ts +44 -50
- package/package.json +1 -1
- package/src/builtins/builtins.test.ts +101 -0
- package/src/builtins/completion-bash.ts +240 -0
- package/src/builtins/completion-fish.ts +73 -0
- package/src/builtins/completion-group.ts +50 -0
- package/src/builtins/completion-zsh.ts +244 -0
- package/src/builtins/dispatch.ts +138 -0
- package/src/builtins/export.ts +53 -0
- package/src/builtins/index.ts +10 -0
- package/src/builtins/install.ts +99 -0
- package/src/builtins/mcp.ts +13 -0
- package/src/builtins/presentation.ts +50 -0
- package/src/builtins/scopes.ts +46 -0
- package/src/builtins/shell-helpers.ts +24 -0
- package/src/capabilities.ts +32 -0
- package/src/completion.ts +10 -693
- package/src/context.ts +21 -6
- package/src/help.ts +21 -9
- package/src/index.test.ts +114 -118
- package/src/index.ts +2 -1
- package/src/install/binary.ts +82 -0
- package/src/install/compiled.ts +15 -0
- package/src/install/completions.ts +52 -0
- package/src/install/detect-installed.ts +67 -0
- package/src/install/index.ts +196 -0
- package/src/install/install.test.ts +124 -0
- package/src/install/mcp-config.ts +70 -0
- package/src/install/paths.ts +69 -0
- package/src/install/plan.ts +183 -0
- package/src/install/shell.ts +56 -0
- package/src/install/status.ts +63 -0
- package/src/install/uninstall.ts +111 -0
- package/src/invoke.ts +14 -5
- package/src/mcp/server.ts +3 -3
- package/src/mcp/tools.ts +17 -17
- package/src/mcp.ts +2 -2
- package/src/parse.ts +55 -27
- package/src/runtime.ts +47 -100
- package/src/schema.ts +10 -52
- package/src/skill/generate.ts +10 -10
- package/src/skill/install.ts +21 -19
- package/src/types.test.ts +40 -0
- package/src/types.ts +59 -49
- package/src/validate.ts +89 -83
- package/src/ai.ts +0 -7
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: CliProgram capabilities refactor
|
|
3
|
+
overview: Introduce `CliNode` / `CliProgram` types and an internal capabilities resolver, replacing `CliCommand` in the public API as a **2.0.0 breaking change**. Keep capability machinery private to avoid locking in unstable internals.
|
|
4
|
+
todos:
|
|
5
|
+
- id: types-split
|
|
6
|
+
content: "Refactor src/types.ts: CliNodeBase, CliLeaf, CliRouter, CliNode, CliProgram; remove CliCommand"
|
|
7
|
+
status: completed
|
|
8
|
+
- id: capabilities-module
|
|
9
|
+
content: Add internal src/capabilities.ts (resolveCapabilities, reservedCommandNames)
|
|
10
|
+
status: completed
|
|
11
|
+
- id: wire-validate-presentation
|
|
12
|
+
content: Update validate.ts, presentation.ts, export.ts, dispatch.ts, runtime.ts, invoke.ts to use CliProgram + caps
|
|
13
|
+
status: completed
|
|
14
|
+
- id: internal-walkers
|
|
15
|
+
content: Update parse, context, mcp/tools, completion scopes, install paths to CliNode/CliProgram as appropriate
|
|
16
|
+
status: completed
|
|
17
|
+
- id: public-api-2
|
|
18
|
+
content: Update index.ts exports (CliProgram only), run typegen, bump 2.0.0 CHANGELOG; verify qa-cli + idp-trees compile against local checkout
|
|
19
|
+
status: completed
|
|
20
|
+
- id: examples-docs
|
|
21
|
+
content: Migrate examples + README to CliProgram / satisfies pattern
|
|
22
|
+
status: completed
|
|
23
|
+
- id: tests-migrate
|
|
24
|
+
content: Migrate tests; keep runtime negative tests with cast helpers
|
|
25
|
+
status: completed
|
|
26
|
+
- id: nice-to-haves
|
|
27
|
+
content: "Optional: ctx.program getter, cliValidateProgram rename, satisfies examples, @ts-expect-error type tests"
|
|
28
|
+
status: completed
|
|
29
|
+
isProject: false
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
# CliProgram + internal capabilities (2.0)
|
|
33
|
+
|
|
34
|
+
## Goals
|
|
35
|
+
|
|
36
|
+
- **Types**: `CliNode` (user tree) + `CliProgram` (what `cliRun` accepts) with root-only `mcpServer` / `install` only on `CliProgram`.
|
|
37
|
+
- **Capabilities**: One internal resolver drives reserved names, help/schema/completion visibility, and dispatch guards.
|
|
38
|
+
- **Exports**: Minimal public surface — no `resolveCapabilities`, no presentation helpers, no builtin command builders.
|
|
39
|
+
- **Breaking**: Drop `CliCommand` from the public API — ship **2.0.0 directly** (Option B; no deprecated alias release).
|
|
40
|
+
|
|
41
|
+
## Type model
|
|
42
|
+
|
|
43
|
+
Add to [`src/types.ts`](src/types.ts):
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
interface CliNodeBase { key; description; notes?; options? }
|
|
47
|
+
|
|
48
|
+
type CliLeaf = CliNodeBase & { handler; positionals?; mcpTool? }
|
|
49
|
+
type CliRouter = CliNodeBase & { commands: CliNode[]; fallbackCommand?; fallbackMode? }
|
|
50
|
+
type CliNode = CliLeaf | CliRouter
|
|
51
|
+
|
|
52
|
+
type CliProgram = CliNode & { mcpServer?; install? }
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Remove `mcpServer`, `install`, `mcpTool` from a shared `CliCommandBase`. Remove the old `CliCommand` union entirely **inside the repo**.
|
|
56
|
+
|
|
57
|
+
**Leaf program roots** (`examples/minimal.ts`) remain valid: `CliProgram` = leaf + root config.
|
|
58
|
+
|
|
59
|
+
```mermaid
|
|
60
|
+
flowchart TB
|
|
61
|
+
subgraph public [Public API]
|
|
62
|
+
CliProgram
|
|
63
|
+
cliRun["cliRun(program)"]
|
|
64
|
+
cliInvoke["cliInvoke(program, argv)"]
|
|
65
|
+
end
|
|
66
|
+
subgraph internal [Internal only]
|
|
67
|
+
resolveCaps["resolveCapabilities(program)"]
|
|
68
|
+
presentation["presentationRoot(program)"]
|
|
69
|
+
dispatch["dispatchBuiltin(...)"]
|
|
70
|
+
end
|
|
71
|
+
CliProgram --> cliRun
|
|
72
|
+
CliProgram --> resolveCaps
|
|
73
|
+
resolveCaps --> presentation
|
|
74
|
+
resolveCaps --> dispatch
|
|
75
|
+
presentation --> help["help / schema / completions"]
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Export policy (intentionally narrow)
|
|
79
|
+
|
|
80
|
+
### Export from [`src/index.ts`](src/index.ts) only
|
|
81
|
+
|
|
82
|
+
| Symbol | Action |
|
|
83
|
+
|--------|--------|
|
|
84
|
+
| `CliProgram` | **Add** — primary schema type |
|
|
85
|
+
| `CliCommand` | **Remove** — breaking |
|
|
86
|
+
| `CliNode`, `CliLeaf`, `CliRouter` | **Do not export** — authors use `satisfies CliProgram` or `typeof program.commands[n]` |
|
|
87
|
+
| `CliOption`, `CliPositional`, config types | unchanged |
|
|
88
|
+
| `cliRun`, `cliInvoke`, `CliContext`, enums | unchanged signatures, `CliProgram` param |
|
|
89
|
+
|
|
90
|
+
Run `just typegen` so [`index.d.ts`](index.d.ts) reflects only the barrel.
|
|
91
|
+
|
|
92
|
+
### Keep internal (not in barrel, no deep `package.json` exports)
|
|
93
|
+
|
|
94
|
+
- [`src/capabilities.ts`](src/capabilities.ts) (new): `resolveCapabilities`, `reservedCommandNames`
|
|
95
|
+
- [`src/builtins/presentation.ts`](src/builtins/presentation.ts), [`export.ts`](src/builtins/export.ts), [`dispatch.ts`](src/builtins/dispatch.ts)
|
|
96
|
+
- Completion emitters, install module, `setCompiledExecutableOverride`
|
|
97
|
+
- [`src/completion.ts`](src/completion.ts) shim — trim re-exports if any leak toward public paths; tests import from `builtins/` or `completion.ts` directly in-repo only
|
|
98
|
+
|
|
99
|
+
**Rule**: If it decides *when* a builtin appears, it stays internal. Consumers only see the resulting CLI behavior.
|
|
100
|
+
|
|
101
|
+
## Internal capabilities module
|
|
102
|
+
|
|
103
|
+
New [`src/capabilities.ts`](src/capabilities.ts):
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
interface CliCapabilities {
|
|
107
|
+
completion: true;
|
|
108
|
+
mcp: boolean; // !!program.mcpServer
|
|
109
|
+
install: boolean; // isCompiledExecutable() && program.install?.enabled !== false
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function resolveCapabilities(program: CliProgram): CliCapabilities
|
|
113
|
+
function reservedCommandNames(caps: CliCapabilities): string[]
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Wire callers to use this instead of re-deriving:
|
|
117
|
+
|
|
118
|
+
| File | Change |
|
|
119
|
+
|------|--------|
|
|
120
|
+
| [`src/validate.ts`](src/validate.ts) | `cliValidateProgram(program)`; reserved names from `caps`; **keep** runtime root-only checks for untyped/JS abuse |
|
|
121
|
+
| [`src/builtins/presentation.ts`](src/builtins/presentation.ts) | `presentationBuiltins(program, caps)` |
|
|
122
|
+
| [`src/builtins/export.ts`](src/builtins/export.ts) | same |
|
|
123
|
+
| [`src/builtins/dispatch.ts`](src/builtins/dispatch.ts) | derive `caps` once from `program` |
|
|
124
|
+
| [`src/runtime.ts`](src/runtime.ts) | `cliRun(program: CliProgram)` |
|
|
125
|
+
|
|
126
|
+
Walkers (`parse`, `mcp/tools`, completion scopes) take `CliNode` where they recurse; entrypoints take `CliProgram`.
|
|
127
|
+
|
|
128
|
+
**Presentation vs user tree**: Help, `--schema`, and completion emitters consume `cliPresentationRoot(program)` (synthetic router with builtin stubs), not raw `CliProgram`. Capability logic decides what gets injected; emitters keep walking the same presentation shape.
|
|
129
|
+
|
|
130
|
+
**Validate edge cases** (keep at runtime even when TS catches most mistakes):
|
|
131
|
+
|
|
132
|
+
- `mcpServer` / `install` on inner nodes — reject (untyped/JS abuse)
|
|
133
|
+
- `mcpTool` on program root (leaf-shaped `CliProgram`) — reject (same as today)
|
|
134
|
+
- Reserved command names from `reservedCommandNames(caps)` — drop the old `cliPresentationRoot` escape hatch that skips injection when user already declared `completion`
|
|
135
|
+
|
|
136
|
+
## Context typing
|
|
137
|
+
|
|
138
|
+
[`src/context.ts`](src/context.ts):
|
|
139
|
+
|
|
140
|
+
- Change `ctx.schema` type to `CliProgram` (field name unchanged — avoids extra public surface).
|
|
141
|
+
- **Nice-to-have**: add `get program(): CliProgram` alias returning `this.schema` with JSDoc pointing to `schema` for familiarity. Do **not** export a new type for this.
|
|
142
|
+
|
|
143
|
+
## Consumer migration (2.0)
|
|
144
|
+
|
|
145
|
+
### Before/after (representative of qa-cli, idp-trees, and all `: CliCommand`-typed consumers)
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
// Before (1.x)
|
|
149
|
+
import { cliRun, type CliCommand, CliOptionKind, CliFallbackMode } from "argsbarg";
|
|
150
|
+
const cli: CliCommand = { key: 'myapp', commands: [...], mcpServer: {...} };
|
|
151
|
+
await cliRun(cli);
|
|
152
|
+
|
|
153
|
+
// After (2.0)
|
|
154
|
+
import { cliRun, type CliProgram, CliOptionKind, CliFallbackMode } from "argsbarg";
|
|
155
|
+
const cli = { key: 'myapp', commands: [...], mcpServer: {...} } satisfies CliProgram;
|
|
156
|
+
await cliRun(cli);
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
No structural change for well-formed apps — only import + type annotation. `: CliProgram` also works if the consumer prefers explicit annotation over `satisfies`. Both patterns are supported and type-check identically.
|
|
160
|
+
|
|
161
|
+
### Consumer impact (verified)
|
|
162
|
+
|
|
163
|
+
| Consumer | Files importing argsbarg | Uses `CliCommand`? | Uses `mcpServer`/`install`? | Migration cost |
|
|
164
|
+
|---|---|---|---|---|
|
|
165
|
+
| qa-cli | 3 (`index.tsx`, `mcpConfig.ts`, `mcp.ts`) | `const cli: CliCommand` | `mcpServer` on root | Replace `CliCommand` → `CliProgram` in 1 import, 1 annotation |
|
|
166
|
+
| idp-trees | 3 (`index.tsx`, `mcp/config.ts`, `headless/mode.ts`) | `const cli: CliCommand` | `mcpServer` on root | Replace `CliCommand` → `CliProgram` in 1 import, 1 annotation |
|
|
167
|
+
|
|
168
|
+
Both consumers only use `CliCommand` for the root schema annotation. Neither imports `CliNode`/`CliLeaf`/`CliRouter` (they can't — they don't exist yet). Neither has deeply nested command trees (max depth 2). All other imported types (`CliOptionKind`, `CliFallbackMode`, `CliMcpServerConfig`, `CliMcpToolConfig`, `CliInvocation`, `CliContext`, `isInteractiveTty`) remain unchanged — those files need zero changes.
|
|
169
|
+
|
|
170
|
+
### `install` builtin default behavior
|
|
171
|
+
|
|
172
|
+
Both qa-cli and idp-trees rely on the `install` builtin being **enabled by default** (they do not set `install` on the root). The capabilities resolver must preserve this: `install: isCompiledExecutable() && program.install?.enabled !== false` — which defaults to enabled when `install` is absent.
|
|
173
|
+
|
|
174
|
+
## Tests and negative cases
|
|
175
|
+
|
|
176
|
+
- Update fixtures in [`src/index.test.ts`](src/index.test.ts), [`src/builtins/builtins.test.ts`](src/builtins/builtins.test.ts), [`src/install/install.test.ts`](src/install/install.test.ts): `CliProgram` / `CliNode` internally.
|
|
177
|
+
- Runtime rejection tests (`mcpServer` on nested node) use `as unknown as CliProgram` or a small `invalidProgram()` helper — proves validate still catches misuse without TS.
|
|
178
|
+
|
|
179
|
+
## Docs and changelog
|
|
180
|
+
|
|
181
|
+
- [`README.md`](README.md): `CliProgram`, capabilities mental model (1 short paragraph), reserved names derived from config.
|
|
182
|
+
- [`CHANGELOG.md`](CHANGELOG.md): **2.0.0** — `CliCommand` removed; `CliProgram` added; show before/after migration snippet. Include a note that structural schema shape is unchanged — only the type name and annotation pattern differ.
|
|
183
|
+
- Optional short **Architecture** note in README (not a new doc file unless you want one).
|
|
184
|
+
|
|
185
|
+
### 2.0.0 migration snippet (for CHANGELOG)
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
// 1.x
|
|
189
|
+
import { type CliCommand } from "argsbarg";
|
|
190
|
+
const cli: CliCommand = { ... };
|
|
191
|
+
// 2.0
|
|
192
|
+
import { type CliProgram } from "argsbarg";
|
|
193
|
+
const cli = { ... } satisfies CliProgram; // or : CliProgram
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Version and release
|
|
197
|
+
|
|
198
|
+
**2.0.0** — rename-only breaking change for typed consumers; runtime behavior unchanged.
|
|
199
|
+
|
|
200
|
+
**Release path (chosen): Option B** — jump straight to 2.0.0. No `CliCommand` deprecated alias in 1.6. Breaking changes are acceptable; known consumers (qa-cli, idp-trees) migrate in one import + one annotation each.
|
|
201
|
+
|
|
202
|
+
### Pre-release checklist (required before tag)
|
|
203
|
+
|
|
204
|
+
1. `just test` green in argsbarg
|
|
205
|
+
2. `just typegen` — `index.d.ts` exports `CliProgram` only (no `CliCommand`)
|
|
206
|
+
3. Point qa-cli and idp-trees `package.json` at local argsbarg checkout; confirm `tsc` / build passes with `CliProgram` migration applied in those repos
|
|
207
|
+
4. CHANGELOG 2.0.0 entry with migration snippet
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Nice-to-haves (defer if time-boxed)
|
|
212
|
+
|
|
213
|
+
1. **`satisfies CliProgram`** in all examples (better DX than `: CliProgram` annotation). Verify that `satisfies` still infers precise sub-command types (not widening to `object`), particularly in nested structures like `examples/nested.ts`.
|
|
214
|
+
2. **`ctx.program` getter** — alias for `ctx.schema`; document `schema` as legacy name in JSDoc only (no removal in 2.0).
|
|
215
|
+
3. **Internal rename** `cliValidateRoot` → `cliValidateProgram` (not exported today; safe).
|
|
216
|
+
4. **Type tests** in `src/types.test.ts` — compile-only assertions that invalid shapes fail (e.g. `mcpServer` on `CliNode`) using `@ts-expect-error` snippets.
|
|
217
|
+
5. **README diagram** — small mermaid of user tree vs injected capabilities (documentation only).
|
|
218
|
+
|
|
219
|
+
## Explicitly out of scope (avoid future breaks)
|
|
220
|
+
|
|
221
|
+
- Exporting `CliCapabilities`, `resolveCapabilities`, `presentationRoot`, builtin command builders
|
|
222
|
+
- Exporting `CliNode` / `CliLeaf` / `CliRouter` (can add in 2.x if demand appears; not needed for `nested.ts`-style apps)
|
|
223
|
+
- `package.json` subpath exports (`argsbarg/builtins`, etc.)
|
|
224
|
+
- Renaming `ctx.schema` in 2.0 (would break handlers that read `.schema`)
|
package/.private/scratch.md
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
- [x] --schema feature for ai agents
|
|
2
|
-
- [
|
|
2
|
+
- [x] opt-out install feature?
|
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,42 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.0.0] - 2026-06-20
|
|
11
|
+
|
|
12
|
+
### Changed (breaking)
|
|
13
|
+
|
|
14
|
+
- **`CliCommand` removed** — use `CliProgram` as the schema type passed to `cliRun` / `cliInvoke`. The runtime object shape is unchanged; only the type name and how you annotate it differ.
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
// 1.x
|
|
18
|
+
import { type CliCommand } from "argsbarg";
|
|
19
|
+
const cli: CliCommand = { ... };
|
|
20
|
+
// 2.0
|
|
21
|
+
import { type CliProgram } from "argsbarg";
|
|
22
|
+
const cli = { ... } satisfies CliProgram; // or : CliProgram
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
- **Internal type split** — `CliNode` / `CliLeaf` / `CliRouter` model the user command tree; `CliProgram` adds root-only `mcpServer` and `install`. These are not exported from the public API.
|
|
26
|
+
- **Capabilities resolver** — reserved built-in names (`completion`, `install`, `mcp`) are derived from program config and runtime (compiled binary), not from user-declared commands.
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- **`ctx.program`** — alias for `ctx.schema` on `CliContext` (same `CliProgram` value).
|
|
31
|
+
|
|
32
|
+
## [1.5.0] - 2026-06-20
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
|
|
36
|
+
- **`install` built-in** (compiled binaries only) — install binary, bash/zsh/fish completions, Cursor/Claude skills, and MCP config (`install --all --yes`, `--update`, `--status`, `--uninstall`).
|
|
37
|
+
- **`completion fish`** — fish tab-completion script generation.
|
|
38
|
+
- Root **`install`** config (`{ enabled?: boolean, prefix?: string }`).
|
|
39
|
+
|
|
40
|
+
### Changed (breaking)
|
|
41
|
+
|
|
42
|
+
- **Removed `ai` command group** — no more `ai mcp` or `ai skill`.
|
|
43
|
+
- **Restored top-level `mcp`** — `myapp mcp` (reserved only when `mcpServer` is set).
|
|
44
|
+
- **Removed `aiSkill` config** — skill directory name defaults to sanitized root `key`; use `install --skill` instead of `ai skill`.
|
|
45
|
+
|
|
10
46
|
## [1.4.3] - 2026-06-19
|
|
11
47
|
|
|
12
48
|
### Added
|
|
@@ -135,7 +171,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
135
171
|
- 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`).
|
|
136
172
|
- Imports: use `CliPositional` where needed; replace `CliOptionDef` with `CliOption` or `CliPositional` as appropriate.
|
|
137
173
|
|
|
138
|
-
[Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/
|
|
174
|
+
[Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v2.0.0...HEAD
|
|
175
|
+
[2.0.0]: https://github.com/bdombro/bun-argsbarg/releases/tag/v2.0.0
|
|
176
|
+
[1.5.0]: https://github.com/bdombro/bun-argsbarg/releases/tag/v1.5.0
|
|
139
177
|
[1.4.3]: https://github.com/bdombro/bun-argsbarg/releases/tag/v1.4.3
|
|
140
178
|
[1.4.2]: https://github.com/bdombro/bun-argsbarg/releases/tag/v1.4.2
|
|
141
179
|
[1.4.1]: https://github.com/bdombro/bun-argsbarg/releases/tag/v1.4.1
|
package/README.md
CHANGED
|
@@ -14,9 +14,9 @@ Why another CLI parser?
|
|
|
14
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
16
|
|
|
17
|
-
*Shell completions* — `completion bash` and `completion
|
|
17
|
+
*Shell completions* — `completion bash`, `completion zsh`, and `completion fish` built-ins generate installable scripts from your schema so users get tab completion for commands, flags, and positionals without extra tooling.
|
|
18
18
|
|
|
19
|
-
*Optional MCP server* — set `mcpServer: {}` on the program root to expose leaf commands as MCP tools and the full CLI tree as a schema resource (`myapp
|
|
19
|
+
*Optional MCP server* — set `mcpServer: {}` on the program root to expose leaf commands as MCP tools and the full CLI tree as a schema resource (`myapp mcp` over stdio). See [docs/mcp.md](docs/mcp.md). Compiled binaries can install binary, completions, skills, and MCP config with `myapp install` — see [docs/install.md](docs/install.md).
|
|
20
20
|
|
|
21
21
|
*Bun-optimized* — built from the ground up for Bun and TypeScript, leveraging Bun’s performance and modern JavaScript features without any extra dependencies.
|
|
22
22
|
|
|
@@ -35,9 +35,9 @@ Shell completions! -->
|
|
|
35
35
|
## Usage
|
|
36
36
|
|
|
37
37
|
```typescript
|
|
38
|
-
import { cliRun,
|
|
38
|
+
import { cliRun, type CliProgram, CliOptionKind } from "argsbarg";
|
|
39
39
|
|
|
40
|
-
const cli
|
|
40
|
+
const cli = {
|
|
41
41
|
key: "helloapp",
|
|
42
42
|
description: "Tiny demo.",
|
|
43
43
|
positionals: [
|
|
@@ -64,7 +64,7 @@ const cli: CliCommand = {
|
|
|
64
64
|
}
|
|
65
65
|
console.log(`hello ${name}`);
|
|
66
66
|
},
|
|
67
|
-
};
|
|
67
|
+
} satisfies CliProgram;
|
|
68
68
|
|
|
69
69
|
await cliRun(cli);
|
|
70
70
|
```
|
|
@@ -77,7 +77,7 @@ await cliRun(cli);
|
|
|
77
77
|
|
|
78
78
|
Everything you need for a first-class CLI:
|
|
79
79
|
|
|
80
|
-
- **Nested subcommands** (
|
|
80
|
+
- **Nested subcommands** (router nodes with `commands`, leaf nodes with `handler`)
|
|
81
81
|
- **POSIX-style options** (`-x`, `--long`, `--long=value`) — kinds: presence, string, number, **enum** (`choices` array)
|
|
82
82
|
- **Bundled presence flags** (`-abc`)
|
|
83
83
|
- **Positional arguments and varargs tails** (`CliPositional` objects on `positionals`)
|
|
@@ -95,30 +95,32 @@ Every app gets:
|
|
|
95
95
|
|
|
96
96
|
- `-h` / `--help` at any routing depth (scoped help).
|
|
97
97
|
- **`--schema`** at the program root — print the full command tree as JSON (for tooling and agents).
|
|
98
|
-
- **`completion bash` / `completion zsh`** — print shell completion scripts to stdout (injected by `cliRun`).
|
|
99
|
-
- **`
|
|
98
|
+
- **`completion bash` / `completion zsh` / `completion fish`** — print shell completion scripts to stdout (injected by `cliRun`).
|
|
99
|
+
- **`mcp`** — when `mcpServer` is set on the program root, run as an MCP stdio server (`myapp mcp`).
|
|
100
|
+
- **`install`** — when running as a compiled binary (`bun build --compile`), install the binary, completions, skills, and MCP config to the user environment (`myapp install --all --yes`). See [docs/install.md](docs/install.md).
|
|
100
101
|
|
|
101
|
-
Do not declare a top-level command named **`completion`** —
|
|
102
|
-
|
|
102
|
+
Do not declare a top-level command named **`completion`** or **`install`** — they are reserved.
|
|
103
|
+
When **`mcpServer`** is set, do not declare a top-level command named **`mcp`** — it is reserved for the MCP built-in.
|
|
103
104
|
Do not declare an option named **`schema`** — it is reserved for `--schema`.
|
|
104
105
|
|
|
105
106
|
|
|
106
107
|
### MCP (AI agents)
|
|
107
108
|
|
|
108
|
-
Opt in on the program root with `mcpServer: {}` (or `{ name, version, … }`), then run `myapp
|
|
109
|
+
Opt in on the program root with `mcpServer: {}` (or `{ name, version, … }`), then run `myapp mcp` for a stdio MCP server. Each leaf command becomes a tool; the CLI tree is available as resource `argsbarg://schema`. Handlers can read `ctx.invocation` and use `cliInvoke` for headless testing.
|
|
109
110
|
|
|
110
111
|
See **[docs/mcp.md](docs/mcp.md)** for configuration, env bootstrapping, custom resources, Cursor setup, and protocol details.
|
|
111
112
|
|
|
112
|
-
###
|
|
113
|
+
### Install (compiled binaries)
|
|
113
114
|
|
|
114
|
-
|
|
115
|
+
After `bun build --compile`, ship a self-contained binary and let users run:
|
|
115
116
|
|
|
116
117
|
```bash
|
|
117
|
-
myapp
|
|
118
|
-
myapp ai skill claude --global # ~/.claude/skills/<name>/
|
|
118
|
+
myapp install --all --yes
|
|
119
119
|
```
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
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.
|
|
122
|
+
|
|
123
|
+
See **[docs/install.md](docs/install.md)** for `--update`, `--status`, `--uninstall`, and flags.
|
|
122
124
|
|
|
123
125
|
|
|
124
126
|
### Shell completions
|
|
@@ -130,6 +132,8 @@ myapp completion bash > ~/.bash_completion.d/myapp
|
|
|
130
132
|
myapp completion zsh > ~/.zsh/completions/_myapp
|
|
131
133
|
# then: fpath+=(~/.zsh/completions); autoload -Uz compinit && compinit
|
|
132
134
|
# or, for a one-off test in the current shell: eval "$(myapp completion zsh)"
|
|
135
|
+
|
|
136
|
+
myapp completion fish > ~/.config/fish/completions/myapp.fish
|
|
133
137
|
```
|
|
134
138
|
|
|
135
139
|
|
|
@@ -143,7 +147,7 @@ bun add bun-argsbarg
|
|
|
143
147
|
|
|
144
148
|
## How it works
|
|
145
149
|
|
|
146
|
-
1. Build a **program root** `
|
|
150
|
+
1. Build a **program root** with `satisfies CliProgram` (or `: CliProgram`): `key` is the app/binary 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).
|
|
147
151
|
2. Call `await cliRun(root)` with that root — 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**).
|
|
148
152
|
3. From a handler, `cliErrWithHelp(ctx, "message")` prints a red error line plus contextual help on stderr and exits **1**.
|
|
149
153
|
|
|
@@ -177,7 +181,11 @@ Add `CliPositional` entries to the command’s `positionals` list (separate from
|
|
|
177
181
|
- `ctx.typedOpt<T>("custom", parseFn)` — pass a custom parsing function for type-safe option resolution.
|
|
178
182
|
- `ctx.args` — positional words in order as `string[]`.
|
|
179
183
|
- `ctx.positional("name")` — named positional lookup; varargs slots return `string[]`, single slots return `string | undefined`.
|
|
180
|
-
- `ctx.schema` —
|
|
184
|
+
- `ctx.schema` / `ctx.program` — program root (`CliProgram`) for contextual help.
|
|
185
|
+
|
|
186
|
+
### Capabilities (built-ins)
|
|
187
|
+
|
|
188
|
+
`completion`, `install`, and `mcp` are not part of your schema — they are injected at runtime from program-level config (`mcpServer`, compiled binary + `install`). Reserved command names follow from that config: `completion` and `install` are always reserved; `mcp` is reserved when `mcpServer` is set.
|
|
181
189
|
|
|
182
190
|
|
|
183
191
|
|
|
@@ -188,7 +196,7 @@ Check the `examples/` directory for full working scripts:
|
|
|
188
196
|
| Example | File | Shows |
|
|
189
197
|
| --- | --- | --- |
|
|
190
198
|
| `ArgsBargMinimal` | `examples/minimal.ts` | String + presence flags, `MissingOrUnknown` fallback. |
|
|
191
|
-
| `ArgsBargNested` | `examples/nested.ts` | Nested
|
|
199
|
+
| `ArgsBargNested` | `examples/nested.ts` | Nested command tree, positional tails, async handlers. |
|
|
192
200
|
|
|
193
201
|
```bash
|
|
194
202
|
export PATH="$PATH:$(pwd)/examples"
|
|
@@ -210,7 +218,7 @@ The package root (`argsbarg` / `src/index.ts`) exports the types and runtime you
|
|
|
210
218
|
|
|
211
219
|
| Symbol | Role |
|
|
212
220
|
| --- | --- |
|
|
213
|
-
| `
|
|
221
|
+
| `CliProgram`, `CliOption`, `CliPositional`, `CliHandler` | Schema and handler types. |
|
|
214
222
|
| `CliOptionKind`, `CliFallbackMode` | Option kinds (`Presence`, `String`, `Number`, `Enum`) and root fallback behavior. |
|
|
215
223
|
| `CliSchemaValidationError` | Thrown when the static command tree violates schema rules. |
|
|
216
224
|
| `CliContext` | Handler context (`ctx.flag`, `ctx.stringOpt`, `ctx.args`, `ctx.invocation`, …). |
|
|
@@ -218,7 +226,7 @@ The package root (`argsbarg` / `src/index.ts`) exports the types and runtime you
|
|
|
218
226
|
| `cliInvoke(root, argv)` | Parse and dispatch without exiting; returns captured stdout/stderr. |
|
|
219
227
|
| `cliErrWithHelp(ctx, msg)` | Print error + scoped help on stderr, exit 1. |
|
|
220
228
|
|
|
221
|
-
Reserved
|
|
229
|
+
Reserved identifiers (validated at startup): root commands **`completion`**, **`install`**, and **`mcp`** (only when `mcpServer` is set).
|
|
222
230
|
|
|
223
231
|
---
|
|
224
232
|
|
package/docs/ai-skills.md
CHANGED
|
@@ -1,75 +1,47 @@
|
|
|
1
|
-
# Agent skills
|
|
1
|
+
# Agent skills
|
|
2
2
|
|
|
3
|
-
ArgsBarg can
|
|
3
|
+
ArgsBarg can generate Cursor and Claude Code skill directories (`SKILL.md` + `reference.md`) from your CLI schema.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
| --- | --- |
|
|
7
|
-
| `SKILL.md` | Frontmatter + command catalog, execution notes, pitfalls |
|
|
8
|
-
| `reference.md` | Full `--schema` JSON export |
|
|
9
|
-
|
|
10
|
-
Skills are **install-only** — there is no print-to-stdout mode, because the artifact is always a two-file directory.
|
|
5
|
+
## Install via `install` (recommended)
|
|
11
6
|
|
|
12
|
-
|
|
7
|
+
In a **compiled binary**, install skills to the user environment:
|
|
13
8
|
|
|
14
9
|
```bash
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
# User-wide Claude Code skill
|
|
19
|
-
myapp ai skill claude --global
|
|
10
|
+
myapp install --skill --yes
|
|
11
|
+
# or
|
|
12
|
+
myapp install --all --yes
|
|
20
13
|
```
|
|
21
14
|
|
|
22
|
-
|
|
15
|
+
Skills are written when the agent home exists:
|
|
23
16
|
|
|
24
|
-
|
|
17
|
+
- Cursor: `~/.cursor/skills/<dir>/` when `~/.cursor` exists
|
|
18
|
+
- Claude Code: `~/.claude/skills/<dir>/` when `~/.claude` exists
|
|
25
19
|
|
|
26
|
-
|
|
20
|
+
The skill directory name defaults to the sanitized program `key` (e.g. `minimal.ts` → `minimal_ts`).
|
|
27
21
|
|
|
28
|
-
|
|
29
|
-
const cli: CliCommand = {
|
|
30
|
-
key: "myapp",
|
|
31
|
-
description: "My app.",
|
|
32
|
-
aiSkill: { enabled: false },
|
|
33
|
-
commands: [/* ... */],
|
|
34
|
-
};
|
|
35
|
-
```
|
|
22
|
+
Existing skill directories are removed and rewritten on each install.
|
|
36
23
|
|
|
37
|
-
|
|
24
|
+
## Programmatic install
|
|
38
25
|
|
|
39
26
|
```typescript
|
|
40
|
-
|
|
27
|
+
import { cliSkillInstall } from "argsbarg/skill/install"; // internal module
|
|
41
28
|
```
|
|
42
29
|
|
|
43
|
-
|
|
30
|
+
For library use, call `cliSkillInstall(root, "cursor" | "claude", { global: true, rimraf: true })` — it returns changed file paths.
|
|
44
31
|
|
|
45
|
-
|
|
32
|
+
## Generated content
|
|
46
33
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
| `--global` | Install under the user skills directory instead of the project |
|
|
50
|
-
| `--force` | Overwrite an existing skill directory |
|
|
51
|
-
|
|
52
|
-
## Install locations
|
|
53
|
-
|
|
54
|
-
| Target | Project (default) | `--global` |
|
|
55
|
-
| --- | --- | --- |
|
|
56
|
-
| Cursor | `.cursor/skills/<name>/` | `~/.cursor/skills/<name>/` |
|
|
57
|
-
| Claude Code | `.claude/skills/<name>/` | `~/.claude/skills/<name>/` |
|
|
58
|
-
|
|
59
|
-
`<name>` defaults to the sanitized program root `key` (same rules as MCP tool name segments).
|
|
60
|
-
|
|
61
|
-
Do **not** install under `~/.cursor/skills-cursor/` — that path is reserved for Cursor built-ins.
|
|
34
|
+
- **`SKILL.md`** — YAML frontmatter, when-to-use guidance, command catalog, MCP setup hints
|
|
35
|
+
- **`reference.md`** — full `--schema` JSON export
|
|
62
36
|
|
|
63
37
|
## MCP vs skills
|
|
64
38
|
|
|
65
|
-
| Mechanism |
|
|
39
|
+
| Mechanism | Role |
|
|
66
40
|
| --- | --- |
|
|
67
|
-
| **`myapp
|
|
68
|
-
| **`myapp
|
|
69
|
-
|
|
70
|
-
Generated `SKILL.md` recommends MCP when `mcpServer` is configured, and documents shell invocation as a fallback.
|
|
41
|
+
| **`myapp mcp`** (requires `mcpServer`) | Runtime tool execution over MCP |
|
|
42
|
+
| **`myapp install --skill`** | Static discovery files for agents |
|
|
71
43
|
|
|
72
|
-
|
|
44
|
+
See also:
|
|
73
45
|
|
|
74
|
-
- [MCP server](mcp.md) — `mcpServer` config and `
|
|
75
|
-
- [
|
|
46
|
+
- [MCP server](mcp.md) — `mcpServer` config and `mcp` protocol
|
|
47
|
+
- [Install](install.md) — binary, completions, skills, and MCP config
|
package/docs/install.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Install command
|
|
2
|
+
|
|
3
|
+
The `install` built-in is available only in **compiled binaries** (`bun build --compile`). It is hidden from help, `--schema`, and shell completions when running via `bun run`.
|
|
4
|
+
|
|
5
|
+
## Quick start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# First-time setup
|
|
9
|
+
myapp install --all --yes
|
|
10
|
+
|
|
11
|
+
# Refresh after upgrading
|
|
12
|
+
myapp install --update
|
|
13
|
+
|
|
14
|
+
# See what is installed
|
|
15
|
+
myapp install --status
|
|
16
|
+
|
|
17
|
+
# Remove everything detected
|
|
18
|
+
myapp install --uninstall --yes
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## What gets installed
|
|
22
|
+
|
|
23
|
+
| Target | Flag | Destination |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| Binary | `--bin` | `~/.local/bin/<key>` (or `--prefix`) |
|
|
26
|
+
| Bash completion | `--completions` | `~/.bash_completion.d/<key>` + `.bashrc` PATH snippet |
|
|
27
|
+
| Zsh completion | `--completions` | `~/.zsh/completions/_<key>` + `.zshrc` fpath snippet |
|
|
28
|
+
| Fish completion | `--completions` | `~/.config/fish/completions/<key>.fish` |
|
|
29
|
+
| Cursor skill | `--skill` | `~/.cursor/skills/<dir>/` when `~/.cursor` exists |
|
|
30
|
+
| Claude skill | `--skill` | `~/.claude/skills/<dir>/` when `~/.claude` exists |
|
|
31
|
+
| MCP config | `--mcp` | `~/.cursor/mcp.json` and `~/.claude.json` when MCP is enabled |
|
|
32
|
+
|
|
33
|
+
`--all` expands to `--bin`, `--completions`, `--skill`, and `--mcp` (when `mcpServer` is set).
|
|
34
|
+
|
|
35
|
+
Shells not on PATH are skipped silently (no warnings).
|
|
36
|
+
|
|
37
|
+
## Configuration
|
|
38
|
+
|
|
39
|
+
On the program root:
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
install: {
|
|
43
|
+
enabled: false, // opt out of the install built-in
|
|
44
|
+
prefix: "~/.local/bin", // default bin directory
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Environment:
|
|
49
|
+
|
|
50
|
+
- `INSTALL_PREFIX` — same as `install.prefix` / `--prefix`
|
|
51
|
+
|
|
52
|
+
## Flags
|
|
53
|
+
|
|
54
|
+
| Flag | Description |
|
|
55
|
+
| --- | --- |
|
|
56
|
+
| `--yes` | Skip confirmation (required for non-TTY unless `--json` / `--update`) |
|
|
57
|
+
| `--dry` | Preview changes; per-step messages on stderr with `[dry run]` |
|
|
58
|
+
| `--json` | Machine-readable output on stdout (implies `--yes`) |
|
|
59
|
+
| `--quiet` | Suppress summaries and per-step messages (requires `--yes`) |
|
|
60
|
+
| `--prefix <dir>` | Override binary install directory |
|
|
61
|
+
| `--update` | Update only artifacts already installed (implies `--bin` + `--yes`) |
|
|
62
|
+
| `--status` | Read-only inventory |
|
|
63
|
+
| `--uninstall` | Remove detected artifacts (scope with `--bin`, `--completions`, `--skill`, `--mcp`) |
|
|
64
|
+
|
|
65
|
+
## MCP merge behavior
|
|
66
|
+
|
|
67
|
+
When `--mcp` runs, entries are merged into `mcpServers[<name>]` with:
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{ "command": "<root.key>", "args": ["mcp"] }
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
If an existing entry differs, the command exits with an error unless `--yes` is passed (then it overwrites).
|
|
74
|
+
|
|
75
|
+
## Opt out
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
const cli = {
|
|
79
|
+
key: "myapp",
|
|
80
|
+
description: "...",
|
|
81
|
+
install: { enabled: false },
|
|
82
|
+
// ...
|
|
83
|
+
} satisfies CliProgram;
|
|
84
|
+
```
|