argsbarg 5.0.3 → 5.1.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 CHANGED
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [5.1.0] - 2026-07-04
11
+
12
+ ### Changed
13
+
14
+ - **Breaking: `config get`/`set` → `configure get`/`set`** — top-level `config` removed; app config introspection lives under the `configure` built-in.
15
+
10
16
  ## [5.0.3] - 2026-07-04
11
17
 
12
18
  ### Changed
@@ -579,7 +585,8 @@ const cli = { ... } satisfies CliProgram; // or : CliProgram
579
585
  - 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`).
580
586
  - Imports: use `CliPositional` where needed; replace `CliOptionDef` with `CliOption` or `CliPositional` as appropriate.
581
587
 
582
- [Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v5.0.3...HEAD
588
+ [Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v5.1.0...HEAD
589
+ [5.1.0]: https://github.com/bdombro/bun-argsbarg/releases/tag/v5.1.0
583
590
  [5.0.3]: https://github.com/bdombro/bun-argsbarg/releases/tag/v5.0.3
584
591
  [5.0.2]: https://github.com/bdombro/bun-argsbarg/releases/tag/v5.0.2
585
592
  [5.0.1]: https://github.com/bdombro/bun-argsbarg/releases/tag/v5.0.1
@@ -412,11 +412,11 @@ await cli.run();
412
412
 
413
413
  | Field | Default | Purpose |
414
414
  | --- | --- | --- |
415
- | `description` | *(required)* | Shown in prompts, `config get`, and bundle manifests |
415
+ | `description` | *(required)* | Shown in prompts, `configure get`, and bundle manifests |
416
416
  | `title` | config key | Short label in interactive `configure` |
417
417
  | `default` | — | Used when `jsonSchema` omitted (all-string mode) |
418
418
  | `required` | `true` | When `false`, optional unless required by `jsonSchema` |
419
- | `sensitive` | name heuristic (`token`, `secret`, …) | Redact in prompts, `config get`, and status |
419
+ | `sensitive` | name heuristic (`token`, `secret`, …) | Redact in prompts, `configure get`, and status |
420
420
  | `env` | — | When set: non-empty host env overrides file; consulted again after `resolve` when `resolve` returns `undefined`; exported to `process.env` after resolve |
421
421
  | `resolve` | — | Optional fallback after file; return `undefined` to fall back to `env` (if set) and defaults |
422
422
 
@@ -425,7 +425,7 @@ await cli.run();
425
425
  - Default: `$XDG_CONFIG_HOME/<sanitized-key>/config` or `%APPDATA%/<key>/config`.
426
426
  - JSON: flat object keyed by schema names — `{ "apiToken": "…", "maxRetries": 5 }`.
427
427
  - **Strict:** unknown keys rejected on load.
428
- - **CLI:** missing required config exits 1 before the leaf handler (TTY prompt when interactive). Built-in `docs` and `config get`/`set` skip this exit.
428
+ - **CLI:** missing required config exits 1 before the leaf handler (TTY prompt when interactive). Built-in `docs` and `configure get`/`set` skip this exit.
429
429
  - **MCP:** server stays up; missing config returns `isError: true` at `tools/call`.
430
430
  - **Configure:** interactive `configure` runs the app config wizard; **`configure --sync`** refreshes agent artifacts.
431
431
  - **Agent integration:** `configure.agentIntegration` (`mcp` | `skill` | `both`) sets default sync targets; see [configure.md](configure.md#configuretargets).
@@ -436,7 +436,7 @@ See [config-schema.md](config-schema.md) for codegen, [configure.md](configure.m
436
436
 
437
437
  ## Reserved names
438
438
 
439
- Do not declare user commands named `completion`, `configure`, `mcp`, `version`, `docs`, or `config` at the root — ArgsBarg injects these when configured.
439
+ Do not declare user commands named `completion`, `configure`, `mcp`, `version`, or `docs` at the root — ArgsBarg injects these when configured. App config uses `configure get` / `configure set` subcommands (not a top-level `config` command).
440
440
 
441
441
  ## Cursor rule for consumer repos
442
442
 
@@ -40,7 +40,7 @@ await cli.run();
40
40
  | --- | --- |
41
41
  | Config file | Flat JSON keyed by schema names; strict load (unknown keys rejected) |
42
42
  | Interactive `configure` / `--status` | Auto-runs config wizard when `entries` is non-empty; `--status` for read-only inventory |
43
- | Built-in `config get` / `config set` | Read/write resolved values (opt-out via `commands: false`) |
43
+ | Built-in `configure get` / `configure set` | Read/write resolved values (opt-out via `commands: false`) |
44
44
  | MCP bundle / Claude plugin | `userConfig` for entries with `env` set |
45
45
  | `ctx.appConfig` in handlers | `get`, `require`, `set`, `read`, `path`, `dir` — prefer over `process.env` |
46
46
 
@@ -48,7 +48,7 @@ await cli.run();
48
48
 
49
49
  **No public config I/O exports** — consumers use `program.appConfig` for authoring and `ctx.appConfig` in handlers.
50
50
 
51
- See [cli-program.md — Configuration](cli-program.md#configuration-programappconfig) for resolution order, bootstrap timing, and reserved `config` command.
51
+ See [cli-program.md — Configuration](cli-program.md#configuration-programappconfig) for resolution order, bootstrap timing, and `configure get`/`set`.
52
52
 
53
53
  ## `CliAppConfig` and `CliAppConfigEntry`
54
54
 
@@ -191,26 +191,26 @@ appConfig: {
191
191
 
192
192
  All file values are strings. Defaults come from `entry.default`.
193
193
 
194
- ## Built-in `config` command
194
+ ## Built-in `configure get` / `configure set`
195
195
 
196
196
  When `program.appConfig` is set and `commands !== false`:
197
197
 
198
198
  | Subcommand | Purpose |
199
199
  | --- | --- |
200
- | `config get [key]` | Resolved value(s); `--json`; `--json --pretty` |
201
- | `config set <key> <value>` | One key; full document re-validated after merge |
200
+ | `configure get [key]` | Resolved value(s); `--json`; `--json --pretty` |
201
+ | `configure set <key> <value>` | One key; full document re-validated after merge |
202
202
 
203
- `config get`/`set` skip required-config exit and TTY prompts. Sensitive values redact on `get` (`REDACTED` / `{ "set": true }` with `--json`).
203
+ `configure get`/`set` skip required-config exit and TTY prompts. Sensitive values redact on `get` (`REDACTED` / `{ "set": true }` with `--json`).
204
204
 
205
- Object/array/`$ref` properties require `--json` on `config set`.
205
+ Object/array/`$ref` properties require `--json` on `configure set`.
206
206
 
207
207
  ## Example in this repo
208
208
 
209
209
  | Example | Role |
210
210
  | --- | --- |
211
- | [`examples/full-example/`](../examples/full-example/) | **Copy template** — schemagen discovery, `APP_CONFIG_JSON_SCHEMA` bridge, `program.appConfig`, built-in `config get`/`set` |
211
+ | [`examples/full-example/`](../examples/full-example/) | **Copy template** — schemagen discovery, `APP_CONFIG_JSON_SCHEMA` bridge, `program.appConfig`, built-in `configure get`/`set` |
212
212
 
213
213
  ```bash
214
214
  cd examples/full-example && just setup && just schemagen
215
- FULL_EXAMPLE_API_TOKEN=dev just run config get apiToken --json
215
+ FULL_EXAMPLE_API_TOKEN=dev just run configure get apiToken --json
216
216
  ```
package/docs/configure.md CHANGED
@@ -47,6 +47,10 @@ Dev flow matches release: formula `install` copies the binary and generates comp
47
47
 
48
48
  # Remove app config only (not skills/MCP)
49
49
  <key> configure --remove-config --yes
50
+
51
+ # Read or write app config (non-interactive; when program.appConfig is set)
52
+ <key> configure get [key] [--json] [--pretty]
53
+ <key> configure set <key> <value> [--json]
50
54
  ```
51
55
 
52
56
  Non-interactive / CI: pass **`--yes`** (or **`--json`**, **`--sync`**, **`--remove-all`**, **`--remove-config`**) — see [Confirmation](#confirmation).
package/docs/mcp.md CHANGED
@@ -327,7 +327,7 @@ At server start (`Cli.serveMcp()`), before the NDJSON loop:
327
327
  - Loaded at MCP startup; host `process.env` wins for mapped env vars already set.
328
328
  - Missing required config does **not** exit the MCP server — enforced at `tools/call` with a helpful error.
329
329
  - Configure interactively: `myapp configure` (see [configure.md](configure.md)).
330
- - Built-in `config get` / `config set` when `program.appConfig.commands` is enabled (default). Hosts inject `user_config` → env at spawn; they never write the argsbarg config file.
330
+ - Built-in `configure get` / `configure set` when `program.appConfig.commands` is enabled (default). Hosts inject `user_config` → env at spawn; they never write the argsbarg config file.
331
331
 
332
332
  Example:
333
333
 
@@ -6,7 +6,7 @@
6
6
 
7
7
  | Area | Files / wiring |
8
8
  | --- | --- |
9
- | All builtins | `completion`, `version`, `install`, `docs`, `mcp`, `config get`/`set` |
9
+ | All builtins | `completion`, `version`, `configure`, `docs`, `mcp`, `configure get`/`set` |
10
10
  | `program.appConfig` | `src/types.ts` (`AppConfig`) → `schemas/configSchemas.ts` |
11
11
  | `outputSchema` | `src/commands/status/types.ts` (`StatusJsonOutput`) → `schemas/outputSchemas.ts` |
12
12
  | Schemagen | `scripts/schemagen.ts` + `scripts/schemagen/discover-schema-roots.ts` |
@@ -47,7 +47,7 @@ cd examples/full-example
47
47
  just setup
48
48
  just schemagen # after changing src/**/types.ts
49
49
  FULL_EXAMPLE_API_TOKEN=dev just run status --json
50
- FULL_EXAMPLE_API_TOKEN=dev just run config get apiToken --json
50
+ FULL_EXAMPLE_API_TOKEN=dev just run configure get apiToken --json
51
51
  FULL_EXAMPLE_API_TOKEN=dev just run docs readme
52
52
  ```
53
53
 
@@ -50,8 +50,5 @@ export const program = {
50
50
  mcpd: true,
51
51
  claudePlugin: true,
52
52
  },
53
- configure: {
54
- // Defaults: agentIntegration picks skill vs MCP for sync; app config is opt-in in interactive configure.
55
- },
56
53
  commands: [echoCommand, statusCommand],
57
54
  } satisfies CliProgram;
package/index.d.ts CHANGED
@@ -281,7 +281,7 @@ export interface CliAppConfigEntry {
281
281
  /** When `false`, optional for bootstrap and MCP enforcement. Default: `true`. */
282
282
  required?: boolean;
283
283
  /**
284
- * Mask stdin during prompts and redact on `config get`.
284
+ * Mask stdin during prompts and redact on `configure get`.
285
285
  * Default: `/key|token|secret|password/i.test(name)`.
286
286
  */
287
287
  sensitive?: boolean;
@@ -297,7 +297,7 @@ export interface CliAppConfigEntry {
297
297
  * App configuration block on the program root ({@link CliProgram.appConfig}).
298
298
  */
299
299
  export interface CliAppConfig {
300
- /** Built-in `config get` / `config set`. Default: enabled when `appConfig` is set. */
300
+ /** Built-in `configure get` / `configure set`. Default: enabled when `appConfig` is set. */
301
301
  commands?: boolean | {
302
302
  enabled?: boolean;
303
303
  mcpSet?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "argsbarg",
3
- "version": "5.0.3",
3
+ "version": "5.1.0",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "bun": ">=1.3"
@@ -154,8 +154,8 @@ describe("completion emitters", () => {
154
154
 
155
155
  /** Tests for schema export builtins. */
156
156
  describe("schema export builtins", () => {
157
- /** ExportPresentationBuiltins includes config when appConfig set. */
158
- test("exportPresentationBuiltins includes config when appConfig set", () => {
157
+ /** ExportPresentationBuiltins nests configure get/set when appConfig set. */
158
+ test("exportPresentationBuiltins nests configure get/set when appConfig set", () => {
159
159
  const withConfig: CliProgram = {
160
160
  ...fixture,
161
161
  appConfig: {
@@ -165,8 +165,14 @@ describe("schema export builtins", () => {
165
165
  },
166
166
  };
167
167
  const builtins = exportPresentationBuiltins(withConfig);
168
- expect(builtins.map((b) => b.key)).toContain("config");
169
168
  expect(builtins.map((b) => b.key)).toContain("configure");
169
+ expect(builtins.map((b) => b.key)).not.toContain("config");
170
+ const configureNode = builtins.find((b) => b.key === "configure");
171
+ expect(configureNode && "commands" in configureNode).toBe(true);
172
+ if (configureNode && "commands" in configureNode) {
173
+ const keys = configureNode.commands?.map((c) => c.key) ?? [];
174
+ expect(keys).toEqual(expect.arrayContaining(["get", "set"]));
175
+ }
170
176
  });
171
177
 
172
178
  test("exportPresentationBuiltins omits hidden completion", () => {
@@ -38,7 +38,7 @@ describe("builtins/config", () => {
38
38
  const configPath = resolveAppConfigPath(program);
39
39
  mkdirSync(dirname(configPath), { recursive: true });
40
40
  writeFileSync(configPath, `${JSON.stringify({ apiToken: "secret" })}\n`);
41
- const result = await new Cli(program).invoke(["config", "get", "apiToken"]);
41
+ const result = await new Cli(program).invoke(["configure", "get", "apiToken"]);
42
42
  expect(result.exitCode).toBe(0);
43
43
  expect(result.stdout.trim()).toBe("REDACTED");
44
44
  } finally {
@@ -61,7 +61,7 @@ describe("builtins/config", () => {
61
61
  const configPath = resolveAppConfigPath(program);
62
62
  mkdirSync(dirname(configPath), { recursive: true });
63
63
  writeFileSync(configPath, `${JSON.stringify({ apiToken: "secret" })}\n`);
64
- const result = await new Cli(program).invoke(["config", "get", "apiToken", "--json"]);
64
+ const result = await new Cli(program).invoke(["configure", "get", "apiToken", "--json"]);
65
65
  expect(result.exitCode).toBe(0);
66
66
  expect(JSON.parse(result.stdout)).toEqual({ set: true });
67
67
  } finally {
@@ -82,9 +82,9 @@ describe("builtins/config", () => {
82
82
  try {
83
83
  const program = configFixture();
84
84
  writeAppConfigFile(program, { apiToken: "seed" });
85
- const result = await new Cli(program).invoke(["config", "set", "port", "9090"]);
85
+ const result = await new Cli(program).invoke(["configure", "set", "port", "9090"]);
86
86
  expect(result.exitCode).toBe(0);
87
- const get = await new Cli(program).invoke(["config", "get", "port"]);
87
+ const get = await new Cli(program).invoke(["configure", "get", "port"]);
88
88
  expect(get.stdout.trim()).toBe("9090");
89
89
  } finally {
90
90
  if (prevHome === undefined) delete process.env.HOME;
@@ -1,14 +1,19 @@
1
1
  /*
2
- Built-in `config get` / `config set` commands.
2
+ Built-in `configure get` / `configure set` subcommands.
3
3
  */
4
4
 
5
5
  import { bootstrapAppConfig } from "../config/bootstrap.ts";
6
- import { configEntrySensitive, defaultConfigEntryTitle } from "../config/entry.ts";
6
+ import {
7
+ configCommandsEnabled,
8
+ configEntrySensitive,
9
+ configMcpSetEnabled,
10
+ defaultConfigEntryTitle,
11
+ } from "../config/entry.ts";
7
12
  import { writeAppConfigFile } from "../config/file.ts";
8
13
  import { captureMappedHostEnv, exportConfigToEnv, resolveAppConfig } from "../config/resolve.ts";
9
14
  import { configPropertySchema, effectiveJsonSchema } from "../config/schema.ts";
10
15
  import { parseConfigSetValue } from "../config/validate.ts";
11
- import type { CliLeaf, CliOption, CliProgram, CliRouter } from "../types.ts";
16
+ import type { CliLeaf, CliOption, CliProgram } from "../types.ts";
12
17
  import { CliOptionKind } from "../types.ts";
13
18
 
14
19
  const JSON_OPTION: CliOption = {
@@ -182,16 +187,16 @@ function configSetLeaf(program: CliProgram, mcpSetEnabled: boolean): CliLeaf {
182
187
  handler: (ctx) => {
183
188
  const key = ctx.args[0];
184
189
  if (!key) {
185
- process.stderr.write("config set requires a key.\n");
190
+ process.stderr.write("configure set requires a key.\n");
186
191
  process.exit(1);
187
192
  }
188
193
  const raw = ctx.args[1];
189
194
  if (raw === undefined || raw.length === 0) {
190
195
  if (!ctx.hasFlag("json")) {
191
- process.stderr.write("config set requires a value (or --json).\n");
196
+ process.stderr.write("configure set requires a value (or --json).\n");
192
197
  process.exit(1);
193
198
  }
194
- process.stderr.write("config set requires a value.\n");
199
+ process.stderr.write("configure set requires a value.\n");
195
200
  process.exit(1);
196
201
  }
197
202
  configSetRun(program, key, raw, ctx.hasFlag("json"));
@@ -199,23 +204,15 @@ function configSetLeaf(program: CliProgram, mcpSetEnabled: boolean): CliLeaf {
199
204
  };
200
205
  }
201
206
 
202
- import { configCommandsEnabled, configMcpSetEnabled } from "../config/entry.ts";
203
-
204
- /** Built-in `config` router when program.appConfig is set. */
205
- export function cliBuiltinConfigGroup(program: CliProgram): CliRouter {
207
+ /** `configure get` / `configure set` leaves when app config commands are enabled. */
208
+ export function configureConfigSubcommands(
209
+ program: CliProgram,
210
+ mcpSetEnabled = configMcpSetEnabled(program),
211
+ ): CliLeaf[] {
206
212
  if (!program.appConfig) {
207
- throw new Error("config not enabled");
213
+ throw new Error("configure config subcommands require program.appConfig");
208
214
  }
209
- return {
210
- key: "config",
211
- description: "Read or write app configuration.",
212
- commands: [configGetLeaf(program), configSetLeaf(program, configMcpSetEnabled(program))],
213
- };
215
+ return [configGetLeaf(program), configSetLeaf(program, mcpSetEnabled)];
214
216
  }
215
217
 
216
- export function cliBuiltinConfigGroupIfEnabled(program: CliProgram): CliRouter | undefined {
217
- if (!configCommandsEnabled(program)) {
218
- return undefined;
219
- }
220
- return cliBuiltinConfigGroup(program);
221
- }
218
+ export { configCommandsEnabled };
@@ -1,11 +1,23 @@
1
1
  import { resolveCapabilities } from "../capabilities.ts";
2
- import { type CliLeaf, type CliOption, CliOptionKind, type CliProgram } from "../types.ts";
2
+ import { configCommandsEnabled, configMcpSetEnabled } from "../config/entry.ts";
3
+ import {
4
+ CliFallbackMode,
5
+ type CliLeaf,
6
+ type CliOption,
7
+ CliOptionKind,
8
+ type CliProgram,
9
+ type CliRouter,
10
+ } from "../types.ts";
11
+ import { configureConfigSubcommands } from "./config.ts";
3
12
  import {
4
13
  configureCommandDescription,
5
14
  configureCommandNotes,
6
15
  configureSyncOptionDescription,
7
16
  } from "./configure-copy.ts";
8
17
 
18
+ /** Hidden fallback leaf for bare `configure` (interactive / flag modes). */
19
+ export const CONFIGURE_RUN_KEY = "run";
20
+
9
21
  /** Configure command options. */
10
22
  export function configureBuiltinOptions(root: CliProgram): CliOption[] {
11
23
  const caps = resolveCapabilities(root);
@@ -57,14 +69,33 @@ export function configureBuiltinOptions(root: CliProgram): CliOption[] {
57
69
  return opts;
58
70
  }
59
71
 
60
- /** Builds the `configure` built-in command. */
61
- export function cliBuiltinConfigureCommand(root: CliProgram): CliLeaf {
72
+ /** True when argv resolved to `configure get` or `configure set`. */
73
+ export function isConfigureConfigPath(path: string[]): boolean {
74
+ return path.length >= 2 && (path[1] === "get" || path[1] === "set");
75
+ }
76
+
77
+ /** Builds the `configure` built-in router. */
78
+ export function cliBuiltinConfigureCommand(root: CliProgram): CliRouter {
62
79
  const caps = resolveCapabilities(root);
80
+ const run: CliLeaf = {
81
+ key: CONFIGURE_RUN_KEY,
82
+ hidden: true,
83
+ description: "Interactive or flag-driven configure (skills, MCP, app config).",
84
+ handler: () => {},
85
+ };
86
+
87
+ const commands: CliLeaf[] = [run];
88
+ if (configCommandsEnabled(root)) {
89
+ commands.push(...configureConfigSubcommands(root, configMcpSetEnabled(root)));
90
+ }
91
+
63
92
  return {
64
93
  key: "configure",
65
94
  description: configureCommandDescription(root, caps),
66
95
  options: configureBuiltinOptions(root),
67
96
  notes: configureCommandNotes(root, caps),
68
- handler: () => {},
97
+ fallbackCommand: CONFIGURE_RUN_KEY,
98
+ fallbackMode: CliFallbackMode.MissingOnly,
99
+ commands,
69
100
  };
70
101
  }
@@ -11,8 +11,11 @@ import { completionBashScript } from "./completion-bash.ts";
11
11
  import { completionFishScript } from "./completion-fish.ts";
12
12
  import { cliBuiltinCompletionGroup as completionGroup } from "./completion-group.ts";
13
13
  import { completionZshScript } from "./completion-zsh.ts";
14
- import { cliBuiltinConfigGroupIfEnabled } from "./config.ts";
15
- import { cliBuiltinConfigureCommand } from "./configure.ts";
14
+ import {
15
+ CONFIGURE_RUN_KEY,
16
+ cliBuiltinConfigureCommand,
17
+ isConfigureConfigPath,
18
+ } from "./configure.ts";
16
19
  import { cliBuiltinMcpCommand } from "./mcp.ts";
17
20
  import { cliPresentationRoot } from "./presentation.ts";
18
21
  import { cliBuiltinVersionCommand } from "./version.ts";
@@ -101,7 +104,11 @@ export async function dispatchBuiltin(
101
104
  process.stderr.write(capabilityDeniedMessage("configure"));
102
105
  process.exit(1);
103
106
  }
104
- if (pr.path.length !== 1) {
107
+ if (isConfigureConfigPath(pr.path)) {
108
+ return;
109
+ }
110
+ const runSeg = pr.path[1];
111
+ if (pr.path.length > 2 || (pr.path.length === 2 && runSeg !== CONFIGURE_RUN_KEY)) {
105
112
  process.stderr.write(`Unknown subcommand: configure ${pr.path.slice(1).join(" ")}\n`);
106
113
  process.exit(1);
107
114
  }
@@ -177,17 +184,5 @@ export function builtinInterceptRoot(
177
184
  };
178
185
  }
179
186
 
180
- const configGroup = cliBuiltinConfigGroupIfEnabled(program);
181
- if (first === "config" && configGroup) {
182
- return {
183
- parseRoot: {
184
- key: program.key,
185
- description: program.description,
186
- commands: [configGroup],
187
- },
188
- isLeafCompletionIntercept: false,
189
- };
190
- }
191
-
192
187
  return { parseRoot: program, isLeafCompletionIntercept: false };
193
188
  }
@@ -2,7 +2,6 @@ import type { CliCapabilities } from "../capabilities.ts";
2
2
  import { cliBuiltinDocsGroupIfEnabled } from "../docs/builtin.ts";
3
3
  import type { CliNode, CliProgram } from "../types.ts";
4
4
  import { cliBuiltinCompletionGroup } from "./completion-group.ts";
5
- import { cliBuiltinConfigGroupIfEnabled } from "./config.ts";
6
5
  import { cliBuiltinConfigureCommand } from "./configure.ts";
7
6
  import { cliBuiltinMcpCommand } from "./mcp.ts";
8
7
  import { cliBuiltinVersionCommand } from "./version.ts";
@@ -37,6 +36,5 @@ export function resolveBuiltins(program: CliProgram, caps: CliCapabilities): Cli
37
36
  if (caps.mcp) {
38
37
  pushBuiltin(builtins, program, (p) => cliBuiltinMcpCommand(p));
39
38
  }
40
- pushBuiltin(builtins, program, (p) => cliBuiltinConfigGroupIfEnabled(p) ?? null);
41
39
  return builtins;
42
40
  }
@@ -42,17 +42,17 @@ export function reservedCommandNames(caps: CliCapabilities): string[] {
42
42
  if (caps.mcp) {
43
43
  names.push("mcp");
44
44
  }
45
- if (caps.configCommands) {
46
- names.push("config");
47
- }
48
45
  return names;
49
46
  }
50
47
 
51
48
  /** Commands that may run without required appConfig values (read-only / config introspection). */
52
49
  export function skipsRequiredAppConfigExit(path: string[], caps: CliCapabilities): boolean {
53
50
  const root = path[0];
54
- if (root === "config" && caps.configCommands) {
55
- return true;
51
+ if (root === "configure" && caps.configCommands) {
52
+ const sub = path[1];
53
+ if (sub === "get" || sub === "set") {
54
+ return true;
55
+ }
56
56
  }
57
57
  if (root === "docs" && caps.docs) {
58
58
  return true;
@@ -60,7 +60,7 @@ export function skipsRequiredAppConfigExit(path: string[], caps: CliCapabilities
60
60
  return false;
61
61
  }
62
62
 
63
- export type CapabilityFeature = "mcp" | "configure" | "docs" | "config" | "completion";
63
+ export type CapabilityFeature = "mcp" | "configure" | "docs" | "completion";
64
64
 
65
65
  /** Stderr message when a disabled built-in is invoked from the CLI. */
66
66
  export function capabilityDeniedMessage(feature: CapabilityFeature): string {
@@ -73,8 +73,6 @@ export function capabilityDeniedMessage(feature: CapabilityFeature): string {
73
73
  return "Configure is not available for this app.\n";
74
74
  case "docs":
75
75
  return "Documentation commands are not available for this app.\n";
76
- case "config":
77
- return "Configuration commands are not available for this app.\n";
78
76
  }
79
77
  }
80
78
 
@@ -100,8 +98,4 @@ export function assertBuiltinAllowed(argv: string[], caps: CliCapabilities): voi
100
98
  process.stderr.write(capabilityDeniedMessage("docs"));
101
99
  process.exit(1);
102
100
  }
103
- if (first === "config" && !caps.configCommands) {
104
- process.stderr.write(capabilityDeniedMessage("config"));
105
- process.exit(1);
106
- }
107
101
  }
@@ -29,7 +29,7 @@ export function configEntryRequired(
29
29
  return true;
30
30
  }
31
31
 
32
- /** Whether prompts and `config get` should redact this entry. */
32
+ /** Whether prompts and `configure get` should redact this entry. */
33
33
  export function configEntrySensitive(key: string, entry: CliAppConfigEntry): boolean {
34
34
  return entry.sensitive ?? defaultConfigEntrySensitive(key);
35
35
  }
@@ -56,7 +56,7 @@ export function jsonSchemaRequiredKeys(
56
56
  return new Set(required.filter((k): k is string => typeof k === "string"));
57
57
  }
58
58
 
59
- /** Whether built-in config get/set commands are enabled. */
59
+ /** Whether built-in `configure get` / `configure set` subcommands are enabled. */
60
60
  export function configCommandsEnabled(program: CliProgram): boolean {
61
61
  if (!program.appConfig) {
62
62
  return false;
@@ -227,7 +227,7 @@ export function formatMissingConfigMessage(program: CliProgram, keys: string[]):
227
227
  return [
228
228
  `Missing required configuration: ${list}`,
229
229
  `Configure interactively: ${program.key} configure`,
230
- `Or set via: ${program.key} config set <key> <value>`,
230
+ `Or set via: ${program.key} configure set <key> <value>`,
231
231
  `Config file: ${path}`,
232
232
  `See: ${program.key} docs mcp`,
233
233
  ].join("\n");
@@ -240,7 +240,7 @@ export function formatMcpMissingConfigMessage(program: CliProgram, keys: string[
240
240
  return [
241
241
  `Missing required configuration: ${list}`,
242
242
  `Configure: ${program.key} configure`,
243
- `Or set via: ${program.key} config set`,
243
+ `Or set via: ${program.key} configure set`,
244
244
  `Config file: ${path}`,
245
245
  ].join("\n");
246
246
  }
@@ -167,7 +167,7 @@ test("skipsRequiredAppConfigExit includes docs and config builtins", () => {
167
167
  };
168
168
  const caps = resolveCapabilities(program);
169
169
  expect(skipsRequiredAppConfigExit(["docs", "api"], caps)).toBe(true);
170
- expect(skipsRequiredAppConfigExit(["config", "get"], caps)).toBe(true);
170
+ expect(skipsRequiredAppConfigExit(["configure", "get"], caps)).toBe(true);
171
171
  expect(skipsRequiredAppConfigExit(["run"], caps)).toBe(false);
172
172
  });
173
173
 
package/src/schema.ts CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  leafOutputSchema,
14
14
  } from "./types.ts";
15
15
 
16
- const RESERVED = new Set(["completion", "configure", "docs", "mcp", "version", "config"]);
16
+ const RESERVED = new Set(["completion", "configure", "docs", "mcp", "version"]);
17
17
 
18
18
  function exportCommand(cmd: CliNode, root: CliProgram): CliSchemaExport | null {
19
19
  if (cmd.hidden) {
package/src/types.ts CHANGED
@@ -236,7 +236,7 @@ export interface CliAppConfigEntry {
236
236
  /** When `false`, optional for bootstrap and MCP enforcement. Default: `true`. */
237
237
  required?: boolean;
238
238
  /**
239
- * Mask stdin during prompts and redact on `config get`.
239
+ * Mask stdin during prompts and redact on `configure get`.
240
240
  * Default: `/key|token|secret|password/i.test(name)`.
241
241
  */
242
242
  sensitive?: boolean;
@@ -253,7 +253,7 @@ export interface CliAppConfigEntry {
253
253
  * App configuration block on the program root ({@link CliProgram.appConfig}).
254
254
  */
255
255
  export interface CliAppConfig {
256
- /** Built-in `config get` / `config set`. Default: enabled when `appConfig` is set. */
256
+ /** Built-in `configure get` / `configure set`. Default: enabled when `appConfig` is set. */
257
257
  commands?: boolean | { enabled?: boolean; mcpSet?: boolean };
258
258
  /** Block JSON Schema (draft-07). When omitted, synthesize all-string schema from `entries`. */
259
259
  jsonSchema?: Record<string, unknown>;