argsbarg 4.1.0 → 5.0.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.
- package/CHANGELOG.md +74 -1
- package/README.md +91 -85
- package/docs/README.md +8 -8
- package/docs/ai-skills.md +9 -9
- package/docs/bundled-docs.md +5 -5
- package/docs/cli-program.md +13 -11
- package/docs/config-schema.md +36 -9
- package/docs/configure.md +177 -0
- package/docs/developing.md +7 -7
- package/docs/distribution-homebrew.md +104 -0
- package/docs/mcp.md +11 -12
- package/docs/output-schema.md +1 -1
- package/examples/full-example/Formula/.gitkeep +0 -0
- package/examples/full-example/README.md +98 -0
- package/examples/full-example/biome.json +22 -0
- package/examples/{consumer-app → full-example}/bun.lock +2 -0
- package/examples/full-example/justfile +134 -0
- package/examples/{consumer-app → full-example}/package.json +10 -3
- package/examples/{consumer-app → full-example}/schemas/generated/app-config.json +1 -1
- package/examples/{consumer-app → full-example}/schemas/generated/status.json +1 -1
- package/examples/full-example/scripts/create-identity.ts +11 -0
- package/examples/full-example/scripts/formula-shared.ts +73 -0
- package/examples/full-example/scripts/gen-dev-formula.ts +26 -0
- package/examples/full-example/scripts/print-identity.ts +27 -0
- package/examples/full-example/src/commands/echo/command.ts +21 -0
- package/examples/full-example/src/commands/status/command.test.ts +10 -0
- package/examples/full-example/src/commands/status/command.ts +36 -0
- package/examples/{consumer-app → full-example}/src/commands/status/types.ts +1 -1
- package/examples/full-example/src/index.ts +10 -0
- package/examples/full-example/src/program.ts +57 -0
- package/examples/{consumer-app → full-example}/src/types.ts +1 -1
- package/examples/nested.ts +1 -3
- package/index.d.ts +49 -81
- package/package.json +2 -2
- package/src/builtins/builtins.test.ts +84 -64
- package/src/builtins/completion-group.ts +17 -17
- package/src/builtins/configure-copy.ts +86 -0
- package/src/builtins/configure.ts +70 -0
- package/src/builtins/dispatch.ts +13 -9
- package/src/builtins/index.ts +1 -1
- package/src/builtins/mcp.ts +2 -2
- package/src/builtins/registry.ts +6 -4
- package/src/capabilities.ts +22 -15
- package/src/cli-tool/cli-smoke.test.ts +29 -0
- package/src/cli-tool/create.test.ts +141 -0
- package/src/cli-tool/create.ts +402 -0
- package/{examples/consumer-app/capabilities.test.ts → src/cli-tool/full-example-capabilities.test.ts} +16 -15
- package/src/cli-tool/main.ts +8 -0
- package/src/cli-tool/post-create.ts +111 -0
- package/src/cli-tool/program.ts +97 -0
- package/src/cli-tool/prompt.ts +28 -0
- package/src/cli-tool/run-create.ts +138 -0
- package/src/cli.ts +0 -2
- package/src/config/bootstrap.ts +27 -18
- package/src/config/file.test.ts +1 -1
- package/src/config/resolve.test.ts +167 -0
- package/src/config/resolve.ts +52 -8
- package/src/configure/configure.test.ts +148 -0
- package/src/configure/index.ts +284 -0
- package/src/configure/prompt.ts +40 -0
- package/src/docs/api-guide.test.ts +4 -5
- package/src/docs/builtin.ts +3 -5
- package/src/docs/docs.test.ts +6 -5
- package/src/docs/mcp-guide.ts +11 -12
- package/src/index.ts +5 -12
- package/src/install/binary-placement.test.ts +101 -0
- package/src/install/binary-placement.ts +47 -0
- package/src/install/install-validate.test.ts +5 -5
- package/src/install/normalize-uninstall.ts +11 -0
- package/src/install/normalize.ts +4 -19
- package/src/install/opts.ts +17 -0
- package/src/install/paths.ts +0 -22
- package/src/install/plan.ts +14 -6
- package/src/install/shell.ts +0 -14
- package/src/install/status.test.ts +6 -6
- package/src/install/status.ts +0 -6
- package/src/install/target-effective.ts +8 -10
- package/src/install/target-scope.ts +26 -36
- package/src/install/target-types.ts +0 -16
- package/src/install/targets/app.ts +19 -28
- package/src/install/targets/configure.ts +6 -2
- package/src/install/targets/index.ts +0 -3
- package/src/install/targets.test.ts +26 -44
- package/src/invoke.test.ts +1 -1
- package/src/mcp/env.test.ts +92 -0
- package/src/mcp/env.ts +15 -14
- package/src/mcp/tools.ts +1 -1
- package/src/mcp.integration.test.ts +4 -4
- package/src/parse.test.ts +13 -14
- package/src/prompt.ts +10 -0
- package/src/schema.ts +1 -1
- package/src/skill/hint.ts +2 -2
- package/src/types.ts +48 -22
- package/src/validate.ts +22 -28
- package/docs/install.md +0 -290
- package/docs/templates/cursor/rules/cli-program.mdc +0 -31
- package/examples/config-app/main.ts +0 -20
- package/examples/config-app/program.ts +0 -78
- package/examples/config-app/schema.ts +0 -37
- package/examples/config-app/types.ts +0 -19
- package/examples/consumer-app/README.md +0 -56
- package/examples/consumer-app/src/main.ts +0 -15
- package/examples/consumer-app/src/program.ts +0 -108
- package/src/builtins/install.ts +0 -136
- package/src/install/app.ts +0 -94
- package/src/install/bootstrap.ts +0 -22
- package/src/install/completions.ts +0 -56
- package/src/install/index.ts +0 -415
- package/src/install/install.test.ts +0 -333
- package/src/install/targets/completions.ts +0 -133
- package/src/install/update.test.ts +0 -123
- package/src/install/update.ts +0 -54
- /package/examples/{consumer-app → full-example}/schemas/configSchemas.ts +0 -0
- /package/examples/{consumer-app → full-example}/schemas/outputSchemas.ts +0 -0
- /package/examples/{consumer-app → full-example}/scripts/schemagen/discover-schema-roots.test.ts +0 -0
- /package/examples/{consumer-app → full-example}/scripts/schemagen/discover-schema-roots.ts +0 -0
- /package/examples/{consumer-app → full-example}/scripts/schemagen/naming.ts +0 -0
- /package/examples/{consumer-app → full-example}/scripts/schemagen.ts +0 -0
- /package/examples/{consumer-app → full-example}/tsconfig.json +0 -0
package/src/types.ts
CHANGED
|
@@ -202,6 +202,26 @@ export interface CliUpdateArtifact {
|
|
|
202
202
|
/** Fetches the latest release binary for `install --update`. */
|
|
203
203
|
export type CliUpdateGetLatest = (ctx: { version: string }) => Promise<CliUpdateArtifact>;
|
|
204
204
|
|
|
205
|
+
/** Context passed to {@link CliAppConfigEntry.resolve} for one config key. */
|
|
206
|
+
export interface CliAppConfigResolveContext {
|
|
207
|
+
/** Schema key being resolved. */
|
|
208
|
+
key: string;
|
|
209
|
+
/** Entry metadata for this key. */
|
|
210
|
+
entry: CliAppConfigEntry;
|
|
211
|
+
/** Program root (read-only). */
|
|
212
|
+
program: CliProgram;
|
|
213
|
+
/** Raw value from the config file, if any. */
|
|
214
|
+
fileValue: unknown;
|
|
215
|
+
/** Non-empty host env string when `entry.env` is set; otherwise `undefined`. */
|
|
216
|
+
envValue: string | undefined;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Optional fallback resolver for one config key (e.g. `gh auth token` when `GH_TOKEN` is unset).
|
|
221
|
+
* Return `undefined` to continue resolution (env, then default).
|
|
222
|
+
*/
|
|
223
|
+
export type CliAppConfigResolveFn = (ctx: CliAppConfigResolveContext) => unknown;
|
|
224
|
+
|
|
205
225
|
/**
|
|
206
226
|
* Metadata overlay for one key in {@link CliAppConfig.entries}.
|
|
207
227
|
* Types and validation come from {@link CliAppConfig.jsonSchema} when set; otherwise all values are strings.
|
|
@@ -222,6 +242,11 @@ export interface CliAppConfigEntry {
|
|
|
222
242
|
sensitive?: boolean;
|
|
223
243
|
/** When set: non-empty `process.env[env]` overrides file; value exported after resolve. */
|
|
224
244
|
env?: string;
|
|
245
|
+
/**
|
|
246
|
+
* Optional fallback after file when env is empty.
|
|
247
|
+
* Return `undefined` to fall back to `env` (if set) and schema defaults.
|
|
248
|
+
*/
|
|
249
|
+
resolve?: CliAppConfigResolveFn;
|
|
225
250
|
}
|
|
226
251
|
|
|
227
252
|
/**
|
|
@@ -236,23 +261,24 @@ export interface CliAppConfig {
|
|
|
236
261
|
entries: Record<string, CliAppConfigEntry>;
|
|
237
262
|
}
|
|
238
263
|
|
|
239
|
-
|
|
240
|
-
|
|
264
|
+
/** Opt-out for the `completion` built-in (default: enabled). */
|
|
265
|
+
export interface CliCompletionConfig {
|
|
266
|
+
/** When `false`, hide/disable `completion` (default: enabled). */
|
|
267
|
+
enabled?: boolean;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export interface CliConfigureConfig {
|
|
271
|
+
/** When `false`, hide/disable `configure` (default: enabled). */
|
|
241
272
|
enabled?: boolean;
|
|
242
273
|
/**
|
|
243
|
-
* Default agent integration for
|
|
244
|
-
* - `'mcp'` when `mcpServer.enabled` (default): MCP targets in
|
|
245
|
-
* - `'skill'` when MCP is off (default): skill targets in
|
|
246
|
-
* - `'both'`:
|
|
274
|
+
* Default agent integration for sync (`configure --sync`).
|
|
275
|
+
* - `'mcp'` when `mcpServer.enabled` (default): MCP targets in sync; paired skills excluded.
|
|
276
|
+
* - `'skill'` when MCP is off (default): skill targets in sync; paired MCP excluded.
|
|
277
|
+
* - `'both'`: sync MCP and skill for the same host when both are available.
|
|
247
278
|
*/
|
|
248
279
|
agentIntegration?: InstallAgentIntegration;
|
|
249
|
-
/** Per-artifact gates for
|
|
250
|
-
targets?:
|
|
251
|
-
/**
|
|
252
|
-
* When set, enables `install --update` on the program root.
|
|
253
|
-
* Should download or locate the latest release binary and return its path.
|
|
254
|
-
*/
|
|
255
|
-
updateGetLatest?: CliUpdateGetLatest;
|
|
280
|
+
/** Per-artifact gates for configure sync and interactive wizard. See {@link resolveEffectiveInstallTargets}. */
|
|
281
|
+
targets?: CliConfigureTargets;
|
|
256
282
|
}
|
|
257
283
|
|
|
258
284
|
/** Agent integration mode for install — MCP vs shell skill per host. */
|
|
@@ -264,7 +290,7 @@ export type InstallTargetSpec =
|
|
|
264
290
|
| {
|
|
265
291
|
/** When false, artifact is never installed (even with scoped CLI flags). Default true. */
|
|
266
292
|
enabled?: boolean;
|
|
267
|
-
/** When true, included in
|
|
293
|
+
/** When true, included in `configure --sync`. Default varies by key. */
|
|
268
294
|
includedInAll?: boolean;
|
|
269
295
|
};
|
|
270
296
|
|
|
@@ -273,9 +299,9 @@ export interface ResolvedInstallTarget {
|
|
|
273
299
|
includedInAll: boolean;
|
|
274
300
|
}
|
|
275
301
|
|
|
276
|
-
/** Per-artifact gates for
|
|
277
|
-
export interface
|
|
278
|
-
/**
|
|
302
|
+
/** Per-artifact gates for configure. See {@link resolveEffectiveInstallTargets}. */
|
|
303
|
+
export interface CliConfigureTargets {
|
|
304
|
+
/** App binary status only (Homebrew PATH); no self-install. */
|
|
279
305
|
app?: InstallTargetSpec;
|
|
280
306
|
/** ChatGPT desktop MCP. Default false. */
|
|
281
307
|
chatgptMcp?: InstallTargetSpec;
|
|
@@ -289,9 +315,7 @@ export interface CliInstallTargets {
|
|
|
289
315
|
codexMcp?: InstallTargetSpec;
|
|
290
316
|
/** Codex skill. Default false. */
|
|
291
317
|
codexSkill?: InstallTargetSpec;
|
|
292
|
-
/**
|
|
293
|
-
completions?: InstallTargetSpec;
|
|
294
|
-
/** App config: wizard on install, file removal on uninstall. Default includedInAll true. */
|
|
318
|
+
/** App config: interactive wizard step in `configure`. Default not in sync. */
|
|
295
319
|
configure?: InstallTargetSpec;
|
|
296
320
|
/** Cursor MCP. Default false. */
|
|
297
321
|
cursorMcp?: InstallTargetSpec;
|
|
@@ -396,8 +420,10 @@ export type CliProgram = CliNode & {
|
|
|
396
420
|
appConfig?: CliAppConfig;
|
|
397
421
|
/** When set with `enabled: true`, enables the `mcp` built-in subcommand. */
|
|
398
422
|
mcpServer?: CliMcpServerConfig;
|
|
399
|
-
/** Opt-out and defaults for `
|
|
400
|
-
|
|
423
|
+
/** Opt-out and defaults for `configure`. */
|
|
424
|
+
configure?: CliConfigureConfig;
|
|
425
|
+
/** Opt-out for shell completion generation (`completion bash|zsh|fish`). */
|
|
426
|
+
completion?: CliCompletionConfig;
|
|
401
427
|
/** When set with `enabled: true`, enables the `docs` built-in command group. */
|
|
402
428
|
docs?: CliDocsConfig;
|
|
403
429
|
};
|
package/src/validate.ts
CHANGED
|
@@ -81,6 +81,11 @@ function validateConfigBlock(appConfigBlock: import("./types.ts").CliAppConfig):
|
|
|
81
81
|
}
|
|
82
82
|
envNames.add(entry.env);
|
|
83
83
|
}
|
|
84
|
+
if (entry.resolve !== undefined && typeof entry.resolve !== "function") {
|
|
85
|
+
throw new CliSchemaValidationError(
|
|
86
|
+
`program.appConfig.entries['${key}'].resolve must be a function when set`,
|
|
87
|
+
);
|
|
88
|
+
}
|
|
84
89
|
}
|
|
85
90
|
|
|
86
91
|
const jsonSchema = appConfigBlock.jsonSchema;
|
|
@@ -122,28 +127,28 @@ function installTargetExplicitTruthy(spec: InstallTargetSpec | undefined): boole
|
|
|
122
127
|
return spec.enabled !== false;
|
|
123
128
|
}
|
|
124
129
|
|
|
125
|
-
/** Validates `program.
|
|
126
|
-
function
|
|
127
|
-
const
|
|
128
|
-
if (!
|
|
130
|
+
/** Validates `program.configure` targets and agentIntegration. */
|
|
131
|
+
function validateConfigureConfig(program: CliProgram): void {
|
|
132
|
+
const configure = program.configure;
|
|
133
|
+
if (!configure) return;
|
|
129
134
|
|
|
130
|
-
if ("prefix" in
|
|
135
|
+
if ("prefix" in configure) {
|
|
131
136
|
throw new CliSchemaValidationError(
|
|
132
|
-
"
|
|
137
|
+
"configure.prefix removed; app binary installs via Homebrew",
|
|
133
138
|
);
|
|
134
139
|
}
|
|
135
140
|
|
|
136
|
-
if (!
|
|
141
|
+
if (!configure.targets) return;
|
|
137
142
|
|
|
138
|
-
const targets =
|
|
143
|
+
const targets = configure.targets;
|
|
139
144
|
if ("allSkills" in targets || "allMcps" in targets) {
|
|
140
145
|
throw new CliSchemaValidationError(
|
|
141
|
-
"
|
|
146
|
+
"configure.targets.allSkills/allMcps removed; use agentIntegration and per-key targets",
|
|
142
147
|
);
|
|
143
148
|
}
|
|
144
149
|
|
|
145
150
|
const integration: InstallAgentIntegration =
|
|
146
|
-
|
|
151
|
+
configure.agentIntegration ?? (program.mcpServer?.enabled === true ? "mcp" : "skill");
|
|
147
152
|
|
|
148
153
|
for (const [mcpKey, skillKey] of AGENT_PAIRS) {
|
|
149
154
|
const mcpSpec = targets[mcpKey];
|
|
@@ -154,18 +159,18 @@ function validateInstallConfig(program: CliProgram): void {
|
|
|
154
159
|
|
|
155
160
|
if (mcpOn && skillOn && integration !== "both") {
|
|
156
161
|
throw new CliSchemaValidationError(
|
|
157
|
-
`
|
|
162
|
+
`configure.targets: ${host} has both MCP and skill configured; set agentIntegration: 'both' or disable one side`,
|
|
158
163
|
);
|
|
159
164
|
}
|
|
160
165
|
|
|
161
166
|
if (integration === "skill" && mcpOn) {
|
|
162
167
|
throw new CliSchemaValidationError(
|
|
163
|
-
`
|
|
168
|
+
`configure.targets.${mcpKey} requires agentIntegration: 'both' when agentIntegration is 'skill'`,
|
|
164
169
|
);
|
|
165
170
|
}
|
|
166
171
|
if (integration === "mcp" && skillOn) {
|
|
167
172
|
throw new CliSchemaValidationError(
|
|
168
|
-
`
|
|
173
|
+
`configure.targets.${skillKey} requires agentIntegration: 'both' when agentIntegration is 'mcp'`,
|
|
169
174
|
);
|
|
170
175
|
}
|
|
171
176
|
}
|
|
@@ -197,19 +202,8 @@ export function cliValidateProgram(program: CliProgram): void {
|
|
|
197
202
|
validateConfigBlock(program.appConfig);
|
|
198
203
|
}
|
|
199
204
|
|
|
200
|
-
if (program.
|
|
201
|
-
|
|
202
|
-
throw new CliSchemaValidationError(
|
|
203
|
-
"install.updateGetLatest requires install to be enabled (omit install.enabled: false)",
|
|
204
|
-
);
|
|
205
|
-
}
|
|
206
|
-
if (typeof program.install.updateGetLatest !== "function") {
|
|
207
|
-
throw new CliSchemaValidationError("install.updateGetLatest must be a function");
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
if (program.install !== undefined) {
|
|
212
|
-
validateInstallConfig(program);
|
|
205
|
+
if (program.configure !== undefined) {
|
|
206
|
+
validateConfigureConfig(program);
|
|
213
207
|
}
|
|
214
208
|
|
|
215
209
|
const caps = resolveCapabilities(program);
|
|
@@ -234,9 +228,9 @@ function walkNode(node: CliNode, program: CliProgram, isRoot: boolean): void {
|
|
|
234
228
|
`mcpServer is only supported on the program root (not on ${node.key})`,
|
|
235
229
|
);
|
|
236
230
|
}
|
|
237
|
-
if (rogue.
|
|
231
|
+
if (rogue.configure !== undefined) {
|
|
238
232
|
throw new CliSchemaValidationError(
|
|
239
|
-
`
|
|
233
|
+
`configure is only supported on the program root (not on ${node.key})`,
|
|
240
234
|
);
|
|
241
235
|
}
|
|
242
236
|
if (rogue.docs !== undefined) {
|
package/docs/install.md
DELETED
|
@@ -1,290 +0,0 @@
|
|
|
1
|
-
# Install command
|
|
2
|
-
|
|
3
|
-
The `install` built-in installs the app, shell completions, agent skills, and MCP config. Opt out with `install: { enabled: false }` on the program root.
|
|
4
|
-
|
|
5
|
-
## End-user install
|
|
6
|
-
|
|
7
|
-
Ship a compiled binary (or app bundle). Users install interactively — no `--yes` required when stdin is a TTY:
|
|
8
|
-
|
|
9
|
-
- **Terminal:** run `./myapp`, `myapp`, or `myapp install` (bare `install` is equivalent to `--all`).
|
|
10
|
-
- **macOS app:** double-click the `.app`; when the binary is not yet on PATH and stdin is a TTY, launching with no arguments bootstraps to **`myapp install`**.
|
|
11
|
-
|
|
12
|
-
Interactive flow prints a **`{app} Setup`** banner, a numbered plan, and a confirm prompt. When the app needs API keys or other settings, a **`Configuration Setup`** section runs after install (or immediately for **`install --configure`**).
|
|
13
|
-
|
|
14
|
-
**Uninstall is CLI-only** — there is no GUI uninstaller. Users run:
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
myapp install --uninstall # remove all detected artifacts
|
|
18
|
-
myapp install --uninstall --app # scoped removal
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
Non-interactive / CI: pass **`--yes`** (or **`--json`**, **`--reinstall`**, **`--update`**) — see [Confirmation](#confirmation).
|
|
22
|
-
|
|
23
|
-
## Quick start (automation)
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
|
-
# First-time setup (bare `install` is equivalent to `--all`)
|
|
27
|
-
myapp install --yes
|
|
28
|
-
|
|
29
|
-
# Or explicitly
|
|
30
|
-
myapp install --all --yes
|
|
31
|
-
|
|
32
|
-
# Refresh after upgrading (re-copy running app + refresh detected artifacts in scope)
|
|
33
|
-
myapp install --reinstall
|
|
34
|
-
|
|
35
|
-
# Upgrade to latest release (when this app supports remote updates)
|
|
36
|
-
myapp install --update
|
|
37
|
-
|
|
38
|
-
# See what is installed
|
|
39
|
-
myapp install --status
|
|
40
|
-
|
|
41
|
-
# Remove everything detected on disk (bare `install --uninstall` is equivalent to `--uninstall --all`)
|
|
42
|
-
myapp install --uninstall --yes
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
## What gets installed
|
|
46
|
-
|
|
47
|
-
| Target | Flag | Destination |
|
|
48
|
-
| --- | --- | --- |
|
|
49
|
-
| App | `--app` | `~/.local/bin/<key>` |
|
|
50
|
-
| Bash completion | `--completions` | `~/.bash_completion.d/<key>` + `.bashrc` PATH snippet |
|
|
51
|
-
| Zsh completion | `--completions` | `~/.zsh/completions/_<key>` + `.zshrc` fpath snippet |
|
|
52
|
-
| Fish completion | `--completions` | `~/.config/fish/completions/<key>.fish` |
|
|
53
|
-
| Cursor skill | `--skill` | `~/.cursor/skills/<dir>/` when `~/.cursor` exists |
|
|
54
|
-
| Claude skill | `--skill` | `~/.claude/skills/<dir>/` when `~/.claude` exists |
|
|
55
|
-
| Codex / OpenCode / OpenClaw skills | `--skill` | Agent-specific dirs when the agent home or CLI is available |
|
|
56
|
-
| MCP config | `--mcp` | Cursor, Claude Code/Desktop, OpenCode, Codex, OpenClaw, ChatGPT desktop (when app data exists). ChatGPT web uses Connectors — see `docs mcp` |
|
|
57
|
-
| App config | `--configure` | Interactive wizard writes app settings; `--uninstall --configure` removes the file |
|
|
58
|
-
|
|
59
|
-
### Default `--all` behavior
|
|
60
|
-
|
|
61
|
-
Bare **`install`** and **`install --all`** install targets with **`includedInAll: true`**. Core defaults:
|
|
62
|
-
|
|
63
|
-
- **Always included:** `app`, `completions`, `configure` (wizard when `program.appConfig` is set)
|
|
64
|
-
- **Agent integration** (`install.agentIntegration`, default from `mcpServer.enabled`):
|
|
65
|
-
- **`skill`** (default when MCP off): all `*Skill` keys in `--all`; paired `*Mcp` keys excluded
|
|
66
|
-
- **`mcp`** (default when `mcpServer.enabled`): all `*Mcp` keys in `--all`; paired skills excluded
|
|
67
|
-
- **`both`**: MCP and skill for the same host when available
|
|
68
|
-
|
|
69
|
-
Desktop-only MCP hosts (`claudeDesktopMcp`, `chatgptMcp`) follow the MCP side only — no skill pair.
|
|
70
|
-
|
|
71
|
-
Scoped flags (`--app`, `--completions`, `--configure`) run that artifact category. **`--skill`** and **`--mcp`** install only targets enabled by `agentIntegration` and per-key `install.targets`. Honor `enabled: false` as a hard off.
|
|
72
|
-
|
|
73
|
-
Use **`install --status --json`** to preview effective targets (`effective.all`, `effective.mcp`, `effective.skill`) before installing.
|
|
74
|
-
|
|
75
|
-
### Asymmetric uninstall
|
|
76
|
-
|
|
77
|
-
- **`install --uninstall --all`** (including bare **`install --uninstall`**) removes **every detected artifact type**, ignoring `install.targets`.
|
|
78
|
-
- Scoped uninstall (`--app`, `--skill`, …) removes only that category.
|
|
79
|
-
|
|
80
|
-
Missing targets are skipped silently (no error if nothing is on disk or a shell/agent directory does not exist). Shells not on PATH are skipped silently (no warnings).
|
|
81
|
-
|
|
82
|
-
## `install.targets`
|
|
83
|
-
|
|
84
|
-
Configure which artifacts participate in `--all`, `--reinstall`, and `--update`:
|
|
85
|
-
|
|
86
|
-
```typescript
|
|
87
|
-
install: {
|
|
88
|
-
agentIntegration: "mcp", // | "skill" | "both" — default from mcpServer.enabled
|
|
89
|
-
targets: {
|
|
90
|
-
app: { includedInAll: false },
|
|
91
|
-
chatgptMcp: false,
|
|
92
|
-
cursorSkill: { includedInAll: true },
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
`InstallTargetSpec` is `boolean` or `{ enabled?: boolean; includedInAll?: boolean }`. Shorthand `true` enables the target with default `includedInAll`; `false` disables it.
|
|
98
|
-
|
|
99
|
-
Artifact keys: `app`, `chatgptMcp`, `claudeCodeMcp`, `claudeDesktopMcp`, `claudeSkill`, `codexMcp`, `codexSkill`, `completions`, `configure`, `cursorMcp`, `cursorSkill`, `openclawMcp`, `openclawSkill`, `opencodeMcp`, `opencodeSkill`.
|
|
100
|
-
|
|
101
|
-
Conflicting targets (e.g. both `cursorMcp` and `cursorSkill` without `agentIntegration: 'both'`) fail at program validation time.
|
|
102
|
-
|
|
103
|
-
## Examples
|
|
104
|
-
|
|
105
|
-
### MCP CLI (default)
|
|
106
|
-
|
|
107
|
-
```typescript
|
|
108
|
-
const program = {
|
|
109
|
-
key: "myapp",
|
|
110
|
-
version: "1.0.0",
|
|
111
|
-
description: "…",
|
|
112
|
-
mcpServer: { enabled: true },
|
|
113
|
-
install: {}, // agentIntegration defaults to "mcp"
|
|
114
|
-
// …
|
|
115
|
-
} satisfies CliProgram;
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
Bare **`myapp install --yes`** installs the app, completions, configure wizard (when `appConfig` is set), and MCP hosts — not shell skills for paired agents.
|
|
119
|
-
|
|
120
|
-
### Shell-only CLI (default)
|
|
121
|
-
|
|
122
|
-
```typescript
|
|
123
|
-
const program = {
|
|
124
|
-
key: "myapp",
|
|
125
|
-
version: "1.0.0",
|
|
126
|
-
description: "…",
|
|
127
|
-
install: {}, // agentIntegration defaults to "skill"
|
|
128
|
-
// …
|
|
129
|
-
} satisfies CliProgram;
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
Bare install includes agent skills (when each host is available), not MCP config.
|
|
133
|
-
|
|
134
|
-
### Overrides
|
|
135
|
-
|
|
136
|
-
```typescript
|
|
137
|
-
install: {
|
|
138
|
-
agentIntegration: "both", // MCP + skill on the same host
|
|
139
|
-
targets: {
|
|
140
|
-
chatgptMcp: false, // opt out of one MCP host
|
|
141
|
-
app: { includedInAll: false }, // skip app on --all
|
|
142
|
-
},
|
|
143
|
-
},
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
Preview resolved targets: **`myapp install --status --json`**.
|
|
147
|
-
|
|
148
|
-
## Configuration
|
|
149
|
-
|
|
150
|
-
On the program root:
|
|
151
|
-
|
|
152
|
-
```typescript
|
|
153
|
-
install: {
|
|
154
|
-
enabled: false, // opt out of the install built-in
|
|
155
|
-
updateGetLatest: async ({ version }) => {
|
|
156
|
-
// download or locate latest release; return { path, version, cleanup }
|
|
157
|
-
return { path: "/tmp/myapp", version: "2.0.0" };
|
|
158
|
-
},
|
|
159
|
-
}
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
When `updateGetLatest` is set, ArgsBarg adds **`install --update`** (download latest release and reinstall installed artifacts in scope).
|
|
163
|
-
|
|
164
|
-
### GitHub releases (`ghReleaseUpdateGetLatest`)
|
|
165
|
-
|
|
166
|
-
For compiled apps published via `gh release`, wire a hook without hand-rolling download logic:
|
|
167
|
-
|
|
168
|
-
```typescript
|
|
169
|
-
import {
|
|
170
|
-
createGhFetchLatest,
|
|
171
|
-
createGhVersionCheck,
|
|
172
|
-
ghReleaseUpdateGetLatest,
|
|
173
|
-
} from "argsbarg";
|
|
174
|
-
|
|
175
|
-
const cachePath = path.join(configDir, "version-check.json");
|
|
176
|
-
|
|
177
|
-
install: {
|
|
178
|
-
updateGetLatest: ghReleaseUpdateGetLatest({
|
|
179
|
-
repo: "owner/repo",
|
|
180
|
-
asset: "myapp",
|
|
181
|
-
tempPrefix: "myapp-update.",
|
|
182
|
-
cachePath,
|
|
183
|
-
}),
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Optional: summary notice + background refresh
|
|
187
|
-
const versionCheck = createGhVersionCheck({
|
|
188
|
-
currentVersion: "1.0.0",
|
|
189
|
-
commandName: "myapp",
|
|
190
|
-
cachePath,
|
|
191
|
-
fetchLatest: createGhFetchLatest({ repo: "owner/repo" }),
|
|
192
|
-
});
|
|
193
|
-
versionCheck.getUpdateNotice();
|
|
194
|
-
versionCheck.refreshIfStale();
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
Requires `gh` on PATH and `gh auth login`. Consumers keep app-specific config only (~15 lines).
|
|
198
|
-
|
|
199
|
-
## App config (`program.appConfig`)
|
|
200
|
-
|
|
201
|
-
When `program.appConfig` is set on the program root, ArgsBarg manages a flat JSON config file:
|
|
202
|
-
|
|
203
|
-
```typescript
|
|
204
|
-
appConfig: {
|
|
205
|
-
entries: {
|
|
206
|
-
apiToken: {
|
|
207
|
-
description: "Create at https://example.com/settings/tokens",
|
|
208
|
-
env: "API_TOKEN",
|
|
209
|
-
sensitive: true,
|
|
210
|
-
},
|
|
211
|
-
},
|
|
212
|
-
},
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
Config file path: `~/.local/lib/<sanitized-key>/config.json`.
|
|
216
|
-
|
|
217
|
-
| Flag | Description |
|
|
218
|
-
| --- | --- |
|
|
219
|
-
| `--configure` | Interactive prompt for each setting; writes or updates the config file. On full install, the wizard runs automatically when configuration is in scope. Standalone **`install --configure`** runs the wizard only (no other install steps). |
|
|
220
|
-
| `--uninstall --configure` | Remove the config directory (`~/.local/lib/<key>/`) |
|
|
221
|
-
| `--status` | Shows config path and which required keys are set or missing |
|
|
222
|
-
|
|
223
|
-
**Configure UX** (TTY):
|
|
224
|
-
|
|
225
|
-
```
|
|
226
|
-
Configuration Setup
|
|
227
|
-
|
|
228
|
-
API token (API_TOKEN)
|
|
229
|
-
Create at https://example.com/settings/tokens
|
|
230
|
-
Current: REDACTED
|
|
231
|
-
Value (Enter to copy from env):
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
Non-sensitive vars show the current value; first-time setup omits the `Current:` line. When the current value comes from a mapped environment variable, Enter copies it into `config.json`; otherwise Enter keeps the existing file value. At runtime, a non-empty mapped environment variable always wins over `config.json` (the file is the fallback when env is unset).
|
|
235
|
-
|
|
236
|
-
## Flags
|
|
237
|
-
|
|
238
|
-
### Target flags
|
|
239
|
-
|
|
240
|
-
| Flag | Description |
|
|
241
|
-
| --- | --- |
|
|
242
|
-
| `--all` | Install the default set (app, shell completions, and configuration when supported) |
|
|
243
|
-
| `--app` | Copy this app to the install directory |
|
|
244
|
-
| `--completions` | Install bash, zsh, and fish tab-completion scripts |
|
|
245
|
-
| `--skill` | Install agent skills for Cursor, Claude, and other supported AI tools |
|
|
246
|
-
| `--mcp` | Add MCP server configuration for Cursor, Claude Code, and other supported agents |
|
|
247
|
-
| `--configure` | Run the configuration wizard (install) or remove the config file (`--uninstall`) |
|
|
248
|
-
|
|
249
|
-
### Operation flags
|
|
250
|
-
|
|
251
|
-
| Flag | Description |
|
|
252
|
-
| --- | --- |
|
|
253
|
-
| `--status` | Read-only inventory |
|
|
254
|
-
| `--reinstall` | Refresh everything already installed (implies `--yes`; no numbered confirm) |
|
|
255
|
-
| `--update` | Download the latest release and refresh installed files (implies `--yes`) |
|
|
256
|
-
| `--uninstall` | Remove installed files (`--all` removes everything; use individual flags for one category) |
|
|
257
|
-
| `--from <path>` | App executable to copy with `--reinstall` / `--update` (default: running executable) |
|
|
258
|
-
|
|
259
|
-
### Behavior flags
|
|
260
|
-
|
|
261
|
-
| Flag | Description |
|
|
262
|
-
| --- | --- |
|
|
263
|
-
| `--yes`, `-y` | Skip confirmation (required for non-TTY unless `--json`, `--reinstall`, or `--update`) |
|
|
264
|
-
| `--dry` | Preview changes; per-step messages on stderr with `[dry run]` |
|
|
265
|
-
| `--json` | Machine-readable output on stdout (implies `--yes`) |
|
|
266
|
-
|
|
267
|
-
## Confirmation
|
|
268
|
-
|
|
269
|
-
Install and uninstall (except `--yes`, `--json`, `--dry`, `--reinstall`, `--update`) print a **`{app} Setup`** banner on stderr, then a numbered list of planned actions on stdout. Reply **`y`** for all, **`n`** or Enter to abort, or numbers for a subset. On **install**, when the plan includes the app as item **1**, it is always installed (prompt example: **`2,3`**); MCP and other targets need the binary on PATH. On **uninstall**, use any subset (e.g. **`1,3`**). After you confirm, **`Done.`** prints on stderr. Per-step progress is suppressed until you confirm; the final **`Installed N file(s).`** summary still prints.
|
|
270
|
-
|
|
271
|
-
## MCP merge behavior
|
|
272
|
-
|
|
273
|
-
When `--mcp` runs, entries are merged into host config with:
|
|
274
|
-
|
|
275
|
-
```json
|
|
276
|
-
{ "command": "<root.key>", "args": ["mcp"] }
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
If an existing entry differs, the command exits with an error unless `--yes` is passed (then it overwrites). MCP conflict checks run only for hosts present in the current plan.
|
|
280
|
-
|
|
281
|
-
## Opt out
|
|
282
|
-
|
|
283
|
-
```typescript
|
|
284
|
-
const cli = {
|
|
285
|
-
key: "myapp",
|
|
286
|
-
description: "...",
|
|
287
|
-
install: { enabled: false },
|
|
288
|
-
// ...
|
|
289
|
-
} satisfies CliProgram;
|
|
290
|
-
```
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Argsbarg schema — read framework docs before editing CLI commands
|
|
3
|
-
globs: "src/**/commands/**/*.{ts,tsx},src/index.{ts,tsx}"
|
|
4
|
-
alwaysApply: false
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
When adding or changing argsbarg schema, leaf handlers, or MCP exposure:
|
|
8
|
-
|
|
9
|
-
1. **Read** `node_modules/argsbarg/docs/cli-program.md` (required — authoritative guide).
|
|
10
|
-
2. MCP tools, varargs, `inputSchema` → also `node_modules/argsbarg/docs/mcp.md`.
|
|
11
|
-
3. JSON stdout / `outputSchema` guide and codegen → `node_modules/argsbarg/docs/output-schema.md`.
|
|
12
|
-
4. App config / `program.appConfig` guide and codegen → `node_modules/argsbarg/docs/config-schema.md`.
|
|
13
|
-
5. `install`, `install.targets`, completions, skills → `node_modules/argsbarg/docs/install.md`.
|
|
14
|
-
6. Bundled `docs` built-in → `node_modules/argsbarg/docs/bundled-docs.md`.
|
|
15
|
-
7. **Examples** (shipped under `node_modules/argsbarg/examples/`):
|
|
16
|
-
- Concepts / minimal config → `examples/config-app/`
|
|
17
|
-
- **Copy template** (all builtins, schemagen, `outputSchema`) → `examples/consumer-app/`
|
|
18
|
-
|
|
19
|
-
**Hard rules** (details and examples are in the docs above — do not contradict them):
|
|
20
|
-
|
|
21
|
-
- Reserved root commands: `completion`, `install`, `mcp`, `version`, `docs`, `update`, `config`.
|
|
22
|
-
- `satisfies CliProgram` / `CliLeaf`; action-oriented `description` on root, commands, options, and positionals.
|
|
23
|
-
- Omit `mcpTool` unless genuinely CLI-only (`enabled: false`) or an irreducible wire limit — fix schema and headless handlers first.
|
|
24
|
-
- Interactive leaves: one headless path for MCP, non-TTY CLI, and `--yes` / `--dry-run` / `--json` (`shouldRunHeadless*`, `requireYesInNonTty`); not raw `isTTY`.
|
|
25
|
-
- String options: `format` / `default` / `pattern` per `cli-program.md`; `readLeafInputs()` for multi-flag leaves.
|
|
26
|
-
- Varargs (`argMax: 0`): CLI space-separated; MCP JSON array only — no comma-splitting positionals.
|
|
27
|
-
- Multi-surface leaves (Ink + headless + MCP): one **`read*Flags(ctx)`** per command (or shared family helper + extensions); one **`resolve*Input(flags)`** for cross-field rules — handler reads ctx once, all paths share the struct.
|
|
28
|
-
- JSON stdout: `outputSchema` on the leaf from generated constants in `outputSchemas.ts` — see `output-schema.md`; mark roots with **`JSON payload`** JSDoc in `src/**/types.ts`; do not hand-edit `src/schemas/generated/` or `outputSchemas.ts`.
|
|
29
|
-
- App config: `program.appConfig.jsonSchema` from generated `configSchemas.ts` — see `config-schema.md`; mark roots with **`Config schema`** JSDoc; prefer the layout in `node_modules/argsbarg/examples/consumer-app/` when adding new schema roots.
|
|
30
|
-
|
|
31
|
-
**App-specific conventions:** replace this line with a `**<your-app> conventions:**` section (bullets only). Keep it at the bottom of this file — `just consumer-dev` / `just consumers-sync` in the argsbarg repo refresh the template above and preserve this block. Do not duplicate `cli-program.md` here; link paths and patterns only. For a second rule file (e.g. `.cursor/argsbarg.mdc`), that is fine too.
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
/*
|
|
3
|
-
Multi-file consumer example for program.appConfig.
|
|
4
|
-
|
|
5
|
-
Files:
|
|
6
|
-
types.ts — AppConfig interface (Config schema JSDoc marker for schemagen)
|
|
7
|
-
schema.ts — APP_CONFIG_JSON_SCHEMA (inline; production apps generate this)
|
|
8
|
-
program.ts — CliProgram with appConfig block and commands using ctx.appConfig
|
|
9
|
-
|
|
10
|
-
Try:
|
|
11
|
-
CONFIG_APP_API_TOKEN=dev bun ./examples/config-app/main.ts show --json
|
|
12
|
-
CONFIG_APP_API_TOKEN=dev bun ./examples/config-app/main.ts config get
|
|
13
|
-
CONFIG_APP_API_TOKEN=dev bun ./examples/config-app/main.ts ping
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import { Cli } from "../../src/index.ts";
|
|
17
|
-
import { program } from "./program.ts";
|
|
18
|
-
|
|
19
|
-
const cli = new Cli(program);
|
|
20
|
-
await cli.run();
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
CliProgram for the config-app example — program.appConfig with jsonSchema + metadata overlay.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import pkg from "../../package.json" with { type: "json" };
|
|
6
|
-
import {
|
|
7
|
-
type CliAppConfig,
|
|
8
|
-
type CliAppConfigEntry,
|
|
9
|
-
CliOptionKind,
|
|
10
|
-
type CliProgram,
|
|
11
|
-
} from "../../src/index.ts";
|
|
12
|
-
import { APP_CONFIG_JSON_SCHEMA } from "./schema.ts";
|
|
13
|
-
|
|
14
|
-
const configSchema = {
|
|
15
|
-
apiToken: {
|
|
16
|
-
description: "Create at https://example.com/settings/tokens",
|
|
17
|
-
env: "CONFIG_APP_API_TOKEN",
|
|
18
|
-
sensitive: true,
|
|
19
|
-
},
|
|
20
|
-
defaultRegion: {
|
|
21
|
-
description: "AWS region for API calls.",
|
|
22
|
-
required: false,
|
|
23
|
-
},
|
|
24
|
-
maxRetries: {
|
|
25
|
-
description: "HTTP retry count (0–10).",
|
|
26
|
-
},
|
|
27
|
-
prefs: {
|
|
28
|
-
description: "Local cache preferences (not exported to env).",
|
|
29
|
-
required: false,
|
|
30
|
-
},
|
|
31
|
-
} as const satisfies Record<string, CliAppConfigEntry>;
|
|
32
|
-
|
|
33
|
-
export const program = {
|
|
34
|
-
key: "config-app",
|
|
35
|
-
version: pkg.version,
|
|
36
|
-
description: "Demonstrates program.appConfig, ctx.appConfig, and built-in config get/set.",
|
|
37
|
-
appConfig: {
|
|
38
|
-
jsonSchema: APP_CONFIG_JSON_SCHEMA,
|
|
39
|
-
entries: configSchema,
|
|
40
|
-
} satisfies CliAppConfig,
|
|
41
|
-
commands: [
|
|
42
|
-
{
|
|
43
|
-
key: "show",
|
|
44
|
-
description: "Print resolved config (secrets redacted).",
|
|
45
|
-
options: [
|
|
46
|
-
{
|
|
47
|
-
name: "json",
|
|
48
|
-
description: "Emit JSON.",
|
|
49
|
-
kind: CliOptionKind.Presence,
|
|
50
|
-
},
|
|
51
|
-
],
|
|
52
|
-
handler: (ctx) => {
|
|
53
|
-
const out = {
|
|
54
|
-
defaultRegion: ctx.appConfig.get("defaultRegion"),
|
|
55
|
-
maxRetries: ctx.appConfig.get("maxRetries"),
|
|
56
|
-
prefs: ctx.appConfig.get("prefs"),
|
|
57
|
-
apiTokenSet: ctx.appConfig.get("apiToken") !== undefined,
|
|
58
|
-
};
|
|
59
|
-
if (ctx.hasFlag("json")) {
|
|
60
|
-
console.log(JSON.stringify(out, null, 2));
|
|
61
|
-
} else {
|
|
62
|
-
console.log(`region=${out.defaultRegion ?? "(not set)"}`);
|
|
63
|
-
console.log(`maxRetries=${out.maxRetries ?? "(not set)"}`);
|
|
64
|
-
console.log(`prefs=${out.prefs ? JSON.stringify(out.prefs) : "(not set)"}`);
|
|
65
|
-
console.log(`apiToken=${out.apiTokenSet ? "set" : "missing"}`);
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
key: "ping",
|
|
71
|
-
description: "Require apiToken and print a short confirmation.",
|
|
72
|
-
handler: (ctx) => {
|
|
73
|
-
const token = ctx.appConfig.require("apiToken");
|
|
74
|
-
console.log(`ok (token length ${String(token).length})`);
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
],
|
|
78
|
-
} satisfies CliProgram;
|