argsbarg 6.3.2 → 7.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +17 -3
  2. package/README.md +2 -2
  3. package/docs/README.md +2 -2
  4. package/docs/ai-skills.md +7 -7
  5. package/docs/bundled-docs.md +2 -2
  6. package/docs/cli-program.md +4 -4
  7. package/docs/configure.md +57 -85
  8. package/docs/developing.md +3 -3
  9. package/docs/distribution-homebrew.md +22 -23
  10. package/docs/mcp.md +3 -3
  11. package/examples/full-example/Formula/full-example.rb +7 -9
  12. package/examples/full-example/docs/cli-schema.json +48 -60
  13. package/examples/full-example/docs/cli.md +66 -36
  14. package/examples/full-example/docs/mcp.md +2 -2
  15. package/examples/full-example/docs/skill.md +1 -1
  16. package/examples/full-example/justfile +12 -12
  17. package/examples/full-example/scripts/formula-shared.ts +7 -13
  18. package/examples/full-example-json/Formula/full-example-json.rb +7 -9
  19. package/examples/full-example-json/docs/cli-schema.json +216 -270
  20. package/examples/full-example-json/docs/cli.md +297 -162
  21. package/examples/full-example-json/docs/mcp.md +2 -2
  22. package/examples/full-example-json/docs/skill.md +1 -1
  23. package/examples/full-example-json/justfile +12 -13
  24. package/examples/full-example-json/scripts/formula-shared.ts +7 -13
  25. package/index.d.ts +7 -8
  26. package/package.json +1 -1
  27. package/src/builtins/builtins.test.ts +21 -28
  28. package/src/builtins/configure-copy.ts +17 -20
  29. package/src/builtins/configure.ts +45 -74
  30. package/src/builtins/dispatch.ts +1 -8
  31. package/src/builtins/index.ts +1 -1
  32. package/src/cli-tool/create.ts +3 -1
  33. package/src/cli-tool/post-create.ts +5 -1
  34. package/src/config/file.ts +1 -0
  35. package/src/config/resolve.ts +1 -1
  36. package/src/configure/artifacts/mcp-config.ts +18 -12
  37. package/src/configure/artifacts/target-mcp-json.ts +19 -18
  38. package/src/configure/artifacts/target-skill.ts +8 -3
  39. package/src/configure/artifacts/targets/agents-mcp.ts +1 -1
  40. package/src/configure/artifacts/targets/configure.ts +2 -3
  41. package/src/configure/artifacts/uninstall.ts +5 -1
  42. package/src/configure/configure.test.ts +45 -113
  43. package/src/configure/index.ts +64 -354
  44. package/src/core/types.ts +7 -8
  45. package/src/docs/docs.test.ts +2 -2
  46. package/src/docs/mcp-guide.ts +2 -2
  47. package/src/skill/generate.ts +1 -1
  48. package/src/skill/install.ts +2 -1
@@ -8,12 +8,12 @@ full-example-json exposes an MCP server with features similar to the CLI.
8
8
 
9
9
  ### `.agents` auto-install
10
10
 
11
- When `mcpServer.enabled` is set, `configure --refresh` merges this server into `~/.agents/mcp.json` per the https://dotagentsprotocol.com.
11
+ When `mcpServer.enabled` is set, `configure install` merges this server into `~/.agents/mcp.json` per the https://dotagentsprotocol.com.
12
12
 
13
13
  Install the CLI first so `full-example-json` is on your PATH (e.g. `brew install full-example-json`).
14
14
 
15
15
  ```bash
16
- full-example-json configure --refresh --yes
16
+ full-example-json configure install
17
17
  ```
18
18
 
19
19
  Writes or updates `~/.agents/mcp.json` with a `mcpServers` entry for this app.
@@ -43,7 +43,7 @@ For full detail, open `reference.md` in this skill directory (same as `full-exam
43
43
 
44
44
  Install follows the https://dotagentsprotocol.com:
45
45
 
46
- - Auto-install: `full-example-json configure --refresh --yes` when `skill.enabled` → `~/.agents/skills/full-example-json/`
46
+ - Auto-install: `full-example-json configure install` when `skill.enabled` → `~/.agents/skills/full-example-json/`
47
47
  - Cursor and most coding agents read `~/.agents/skills/` natively
48
48
 
49
49
  **Claude Code (manual):** symlink or copy into Claude's skill directory:
@@ -76,30 +76,32 @@ http:
76
76
  # Alias for backward compatibility
77
77
  install: install-local
78
78
 
79
- # Dev install: build, stage dev formula, brew install, restore release formula
79
+ # Dev install: build, stage dev formula, brew install, refresh agent artifacts
80
80
  install-local: uninstall build
81
81
  mkdir -p {{tap_parent}}
82
82
  ln -sfn '{{justfile_directory()}}' {{tap_path}}
83
83
  bun scripts/dev-formula.ts install
84
84
  HOMEBREW_NO_ASK=1 brew reinstall --formula {{tap}}/{{cli_key}} || HOMEBREW_NO_ASK=1 brew install --force --formula {{tap}}/{{cli_key}}
85
85
  bun scripts/dev-formula.ts reset
86
- @echo ""
87
- @echo "Next: {{cli_key}} configure"
86
+ {{cli_key}} configure install
88
87
 
89
88
  # Remove local dev install, then install from GitHub tap (requires gh auth login)
90
89
  install-production: uninstall
91
90
  brew tap {{release_repo}} {{tap_git_url}}
92
91
  brew install --formula {{release_repo}}/{{cli_key}}
93
- @echo ""
94
- @echo "Next: {{cli_key}} configure"
92
+ {{cli_key}} configure install
95
93
 
96
94
  # Alias for backward compatibility
97
95
  reinstall: reinstall-local
98
96
 
99
- # Rebuild binary and swap into Cellar (run install-local first)
97
+ # Rebuild binary and swap into Cellar (run install-local first; run `just refresh` for skills/MCP)
100
98
  reinstall-local: build
101
99
  install -m 755 dist/{{cli_key}} "$(brew --prefix {{cli_key}})/bin/{{cli_key}}"
102
100
 
101
+ # Refresh agent skills/MCP without reinstalling the binary
102
+ refresh:
103
+ {{cli_key}} configure install
104
+
103
105
  # Lint sources without writing
104
106
  lint:
105
107
  bun run biome check ./src ./scripts
@@ -112,10 +114,10 @@ run *ARGS:
112
114
  schemagen:
113
115
  argsbarg schemagen
114
116
 
115
- # Install bun/npm dependencies
116
117
  # Install bun/npm dependencies and generate schemas
117
118
  setup:
118
119
  bun install
120
+ test -f node_modules/argsbarg/bin/argsbarg && ln -sf ../argsbarg/bin/argsbarg node_modules/.bin/argsbarg
119
121
  just schemagen
120
122
 
121
123
  # Run unit tests (after check)
@@ -139,12 +141,9 @@ test-release:
139
141
  typecheck:
140
142
  bun run tsc --noEmit
141
143
 
142
- # Undo dev/Homebrew install (formula uninstall hook runs configure --remove-all)
144
+ # Undo dev/Homebrew install (remove agent artifacts, then keg + untap)
143
145
  uninstall:
146
+ @{{cli_key}} configure uninstall --yes 2>/dev/null || just run configure uninstall --yes
144
147
  @HOMEBREW_NO_ASK=1 brew uninstall --formula {{tap}}/{{cli_key}} 2>/dev/null || true
145
148
  @HOMEBREW_NO_ASK=1 brew uninstall --formula {{tap}}/{{cli_key}}-local 2>/dev/null || true
146
- @HOMEBREW_NO_ASK=1 brew untap {{tap}} 2>/dev/null || true
147
-
148
- # Remove app config file only
149
- uninstall-config:
150
- just run configure --remove-config --yes
149
+ @HOMEBREW_NO_ASK=1 brew untap {{tap}} 2>/dev/null || true
@@ -19,17 +19,15 @@ export const formulaInstallRuby = `def install
19
19
  generate_completions_from_executable(bin/"${key}", "completion", base_name: "${key}")
20
20
  end`;
21
21
 
22
- export const formulaPostInstallRuby = `def post_install
23
- system bin/"${key}", "configure", "--refresh", "--yes"
24
- end`;
25
-
26
- export const formulaUninstallRuby = `def uninstall
27
- system bin/"${key}", "configure", "--remove-all", "--yes"
28
- end`;
29
-
30
22
  export const formulaCaveatsRuby = `def caveats
31
23
  <<~EOS
32
- Run \`${key} configure\` to set up agent artifacts and app config (interactive).
24
+ After install or upgrade:
25
+ ${key} configure install
26
+
27
+ Before uninstall:
28
+ ${key} configure uninstall
29
+ brew uninstall <tap>/${key}
30
+
33
31
  Restart MCP chat apps (Cursor, Claude Desktop, etc.) after install or upgrade so they load the updated server.
34
32
  EOS
35
33
  end`;
@@ -136,10 +134,6 @@ export function renderFormula(coords: FormulaCoords): string {
136
134
 
137
135
  ${formulaInstallRuby}
138
136
 
139
- ${formulaPostInstallRuby}
140
-
141
- ${formulaUninstallRuby}
142
-
143
137
  ${formulaCaveatsRuby}
144
138
 
145
139
  ${formulaTestRuby}
package/index.d.ts CHANGED
@@ -535,13 +535,12 @@ export interface CliCompletionConfig {
535
535
  }
536
536
  /** Opt-in agent skill install to `~/.agents/skills/<key>/` (default: disabled). */
537
537
  export interface CliSkillConfig {
538
- /** When `true`, install and refresh the agent skill via `configure --refresh`. Default false when omitted. */
538
+ /** When `true`, install the agent skill via `configure install`. Default false when omitted. */
539
539
  enabled?: boolean;
540
540
  }
541
541
  /** Context for {@link CliConfigureConfig} lifecycle hooks. */
542
542
  export interface ConfigureHookContext {
543
543
  program: CliProgram;
544
- /** When true, the configure run is `--dry` (hook should not write files). */
545
544
  dry: boolean;
546
545
  paths: {
547
546
  agentsSkillDir: string;
@@ -554,18 +553,18 @@ export interface ConfigureHookContext {
554
553
  export interface CliConfigureConfig {
555
554
  /** When `false`, hide/disable `configure` (default: enabled). */
556
555
  enabled?: boolean;
557
- /** Per-artifact gates for configure refresh and interactive wizard. See {@link resolveEffectiveInstallTargets}. */
556
+ /** Per-artifact gates for configure install. See {@link resolveEffectiveInstallTargets}. */
558
557
  targets?: CliConfigureTargets;
559
- /** Runs after framework artifacts are installed/refreshed (`configure --refresh`). */
560
- afterRefresh?: (ctx: ConfigureHookContext) => void | Promise<void>;
561
- /** Runs before framework artifacts are removed (`configure --remove-all`). */
562
- beforeRemoveAll?: (ctx: ConfigureHookContext) => void | Promise<void>;
558
+ /** Runs after framework artifacts are installed (`configure install`). */
559
+ afterInstall?: (ctx: ConfigureHookContext) => void | Promise<void>;
560
+ /** Runs before framework artifacts are removed (`configure uninstall`). */
561
+ beforeUninstall?: (ctx: ConfigureHookContext) => void | Promise<void>;
563
562
  }
564
563
  /** Boolean or structured gate for one install artifact. */
565
564
  export type InstallTargetSpec = boolean | {
566
565
  /** When false, artifact is never installed (even with scoped CLI flags). Default true. */
567
566
  enabled?: boolean;
568
- /** When true, included in `configure --refresh`. Default varies by key. */
567
+ /** When true, included in `configure install`. Default varies by key. */
569
568
  includedInAll?: boolean;
570
569
  };
571
570
  export interface ResolvedInstallTarget {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "argsbarg",
3
- "version": "6.3.2",
3
+ "version": "7.0.0",
4
4
  "main": "./src/index.ts",
5
5
  "module": "./src/index.ts",
6
6
  "dependencies": {
@@ -8,8 +8,8 @@ import type { CliProgram } from "../core/types.ts";
8
8
  import { cliBuiltinDocsGroup } from "../docs/builtin.ts";
9
9
  import { resolveCapabilities } from "../runtime/capabilities.ts";
10
10
  import { completionBashScript, completionFishScript, completionZshScript } from ".";
11
- import { cliBuiltinConfigureCommand, configureBuiltinOptions } from "./configure.ts";
12
- import { configureCommandDescription, configureRefreshOptionDescription } from "./configure-copy.ts";
11
+ import { cliBuiltinConfigureCommand } from "./configure.ts";
12
+ import { configureCommandDescription } from "./configure-copy.ts";
13
13
  import { exportPresentationBuiltins } from "./export.ts";
14
14
  import { cliBuiltinMcpCommand } from "./mcp.ts";
15
15
  import { cliParseRoot, cliPresentationRoot } from "./presentation.ts";
@@ -19,6 +19,7 @@ const fixture: CliProgram = {
19
19
  version: "0.0.0",
20
20
  description: "Demo app.",
21
21
  mcpServer: { enabled: true },
22
+ skill: { enabled: true },
22
23
  commands: [
23
24
  {
24
25
  key: "hello",
@@ -32,21 +33,23 @@ const noMcp: CliProgram = {
32
33
  key: "skillonly",
33
34
  version: "0.0.0",
34
35
  description: "Skills only.",
36
+ skill: { enabled: true },
35
37
  commands: [{ key: "ping", description: "Ping.", handler: () => {} }],
36
38
  };
37
39
 
38
40
  /** Tests for builtins help copy. */
39
41
  describe("builtins help copy", () => {
40
- test("configure command includes Homebrew-oriented description", () => {
42
+ test("configure command includes capability-aware description", () => {
41
43
  const configure = cliBuiltinConfigureCommand(fixture);
42
44
  expect(configure.description).toContain("agent skills");
43
45
  expect(configure.description).toContain("MCP config");
44
46
  expect(configure.notes).toContain("brew upgrade");
45
- const names = configureBuiltinOptions(fixture).map((o) => o.name);
46
- expect(names).toContain("refresh");
47
- expect(names).toContain("remove-all");
48
- expect(names).toContain("status");
49
- const yesOpt = configureBuiltinOptions(fixture).find((o) => o.name === "yes");
47
+ const commandKeys = configure.commands.map((c) => c.key);
48
+ expect(commandKeys).toContain("install");
49
+ expect(commandKeys).toContain("uninstall");
50
+ expect(commandKeys).toContain("status");
51
+ const uninstall = configure.commands.find((c) => c.key === "uninstall");
52
+ const yesOpt = uninstall?.options?.find((o) => o.name === "yes");
50
53
  expect(yesOpt?.shortName).toBe("y");
51
54
  });
52
55
 
@@ -54,34 +57,26 @@ describe("builtins help copy", () => {
54
57
  const caps = resolveCapabilities(noMcp);
55
58
  expect(configureCommandDescription(noMcp, caps)).toBe("Set up agent skills for this app (binary via Homebrew).");
56
59
  expect(configureCommandDescription(noMcp, caps)).not.toContain("MCP");
57
- expect(configureRefreshOptionDescription(noMcp, caps)).not.toContain("MCP");
58
60
  const configure = cliBuiltinConfigureCommand(noMcp);
59
61
  expect(configure.description).not.toContain("MCP");
60
62
  });
61
63
 
62
- /** Configure notes mention brew upgrade and interactive configure. */
63
- test("configure notes mention brew upgrade and interactive configure", () => {
64
+ test("configure notes mention brew upgrade and two-step install", () => {
64
65
  const configure = cliBuiltinConfigureCommand(fixture);
65
66
  expect(configure.notes).toContain("brew upgrade");
66
- expect(configure.notes).toContain("configure --refresh --yes");
67
+ expect(configure.notes).toContain("configure install");
68
+ expect(configure.notes).toContain("configure uninstall");
69
+ expect(configure.notes).not.toContain("post_install");
70
+ expect(configure.notes).not.toContain("uninstall hook");
67
71
  expect(configure.notes).toContain(`${fixture.key} configure`);
68
-
69
- const withConfig: CliProgram = {
70
- ...fixture,
71
- appConfig: {
72
- entries: { token: { description: "Token.", env: "TOKEN" } },
73
- },
74
- };
75
- expect(configureBuiltinOptions(withConfig).map((o) => o.name)).toContain("remove-config");
76
72
  });
77
73
 
78
- test("configure -y parses as --yes", () => {
74
+ test("configure uninstall -y parses as --yes", () => {
79
75
  const root = cliParseRoot(fixture);
80
- const pr = postParseValidate(root, parse(root, ["configure", "-y", "--refresh"]));
76
+ const pr = postParseValidate(root, parse(root, ["configure", "uninstall", "-y"]));
81
77
  expect(pr.kind).toBe(ParseKind.Ok);
82
78
  if (pr.kind === ParseKind.Ok) {
83
79
  expect(pr.opts.yes).toBe("1");
84
- expect(pr.opts.refresh).toBe("1");
85
80
  }
86
81
  });
87
82
 
@@ -130,11 +125,11 @@ describe("completion emitters", () => {
130
125
  expect(fish).toContain("configure");
131
126
  });
132
127
 
133
- test("bash script includes configure flags", () => {
128
+ test("bash script includes configure subcommands", () => {
134
129
  const schema = cliPresentationRoot(fixture);
135
130
  const bash = completionBashScript(schema);
136
131
  expect(bash).toContain("hello");
137
- expect(bash).toContain("--refresh");
132
+ expect(bash).toContain("install");
138
133
  });
139
134
 
140
135
  test("zsh script registers compdef", () => {
@@ -152,7 +147,6 @@ describe("completion emitters", () => {
152
147
 
153
148
  /** Tests for schema export builtins. */
154
149
  describe("schema export builtins", () => {
155
- /** ExportPresentationBuiltins nests configure get/set when appConfig set. */
156
150
  test("exportPresentationBuiltins nests configure get/set when appConfig set", () => {
157
151
  const withConfig: CliProgram = {
158
152
  ...fixture,
@@ -169,7 +163,7 @@ describe("schema export builtins", () => {
169
163
  expect(configureNode && "commands" in configureNode).toBe(true);
170
164
  if (configureNode && "commands" in configureNode) {
171
165
  const keys = configureNode.commands?.map((c) => c.key) ?? [];
172
- expect(keys).toEqual(expect.arrayContaining(["get", "set"]));
166
+ expect(keys).toEqual(expect.arrayContaining(["get", "set", "install", "uninstall", "status"]));
173
167
  }
174
168
  });
175
169
 
@@ -181,7 +175,6 @@ describe("schema export builtins", () => {
181
175
 
182
176
  /** Tests for docs skill topic copy. */
183
177
  describe("docs skill topic copy", () => {
184
- /** Tests that mentions configure when configure is enabled. */
185
178
  test("mentions configure when configure is enabled", () => {
186
179
  const withDocs: CliProgram = {
187
180
  ...noMcp,
@@ -12,9 +12,10 @@ const LABEL: Record<Kind, { prose: string; short: string }> = {
12
12
  };
13
13
 
14
14
  function enabledKinds(program: CliProgram, caps: CliCapabilities): Kind[] {
15
- const kinds: Kind[] = ["skills"];
16
- if (caps.mcp) kinds.push("mcp");
17
- if (program.appConfig) kinds.push("config");
15
+ const kinds: Kind[] = [];
16
+ if (program.skill?.enabled) kinds.push("skills");
17
+ if (caps.mcp && program.mcpServer?.enabled) kinds.push("mcp");
18
+ if (program.appConfig && Object.keys(program.appConfig.entries).length > 0) kinds.push("config");
18
19
  return kinds;
19
20
  }
20
21
 
@@ -29,21 +30,18 @@ function prose(program: CliProgram, caps: CliCapabilities): string {
29
30
  return joinEnglish(enabledKinds(program, caps).map((k) => LABEL[k].prose));
30
31
  }
31
32
 
32
- function short(program: CliProgram, caps: CliCapabilities): string {
33
- return joinEnglish(enabledKinds(program, caps).map((k) => LABEL[k].short));
33
+ /** True when brew caveats should mention `configure install` / `configure uninstall`. */
34
+ export function needsConfigureCaveats(program: CliProgram, caps: CliCapabilities): boolean {
35
+ return enabledKinds(program, caps).length > 0;
34
36
  }
35
37
 
36
38
  export function configureCommandDescription(program: CliProgram, caps: CliCapabilities): string {
37
39
  return `Set up ${prose(program, caps)} for this app (binary via Homebrew).`;
38
40
  }
39
41
 
40
- export function configureRefreshOptionDescription(program: CliProgram, caps: CliCapabilities): string {
41
- return `Refresh installed ${short(program, caps)}. Used by Homebrew post_install.`;
42
- }
43
-
44
42
  export function docsSkillTopicDescription(_program: CliProgram, caps: CliCapabilities): string {
45
43
  if (caps.configure) {
46
- return "Print a reference agent SKILL; run `configure` to install an optimized copy.";
44
+ return "Print a reference agent SKILL; run `configure install` to install an optimized copy.";
47
45
  }
48
46
  return "Print a reference agent SKILL for AI agents.";
49
47
  }
@@ -53,30 +51,29 @@ export function configureCommandNotes(program: CliProgram, _caps: CliCapabilitie
53
51
  const lines = [
54
52
  "Set up agent artifacts after the binary is installed via Homebrew (see README for tap install).",
55
53
  "",
56
- "Homebrew post_install runs:",
57
- ` ${app} configure --refresh --yes`,
54
+ "Homebrew installs the binary and shell completions only. Agent artifacts live under ~/.agents and are not written during brew install.",
58
55
  "",
59
- "Interactive setup (per target):",
60
- ` ${app} configure`,
56
+ "After install or upgrade:",
57
+ ` ${app} configure install`,
61
58
  "",
62
59
  "Upgrade:",
63
60
  ` brew upgrade ${app}`,
61
+ ` ${app} configure install`,
64
62
  "",
65
63
  "Shell completions are installed by Homebrew during brew install.",
66
64
  "See: https://docs.brew.sh/Shell-Completion",
67
65
  "",
68
66
  "See what is installed:",
69
- ` ${app} configure --status`,
67
+ ` ${app} configure status`,
70
68
  "",
71
69
  "Uninstall:",
70
+ ` ${app} configure uninstall`,
72
71
  ` brew uninstall <tap>/${app}`,
73
72
  "",
74
- "The formula uninstall hook runs `configure --remove-all --yes` (skills, MCP, and app config).",
75
- "",
76
73
  ];
77
- if (program.appConfig) {
78
- lines.push("Remove app config only:", ` ${app} configure --remove-config --yes`, "");
74
+ if (program.appConfig && Object.keys(program.appConfig.entries).length > 0) {
75
+ lines.push("Set configuration values:", ` ${app} configure set <key> <value>`, "");
79
76
  }
80
- lines.push("Use --dry to preview changes without writing files.", "Use --json for machine-readable output.");
77
+ lines.push("Use `configure status --json` for machine-readable output.");
81
78
  return lines.join("\n");
82
79
  }
@@ -1,90 +1,64 @@
1
1
  import { configCommandsEnabled, configMcpSetEnabled } from "../config/entry.ts";
2
- import {
3
- CliFallbackMode,
4
- type CliLeaf,
5
- type CliOption,
6
- CliOptionKind,
7
- type CliProgram,
8
- type CliRouter,
9
- } from "../core/types.ts";
2
+ import { cliConfigureInstall, cliConfigureStatus, cliConfigureUninstall } from "../configure/index.ts";
3
+ import { type CliLeaf, type CliOption, CliOptionKind, type CliProgram, type CliRouter } from "../core/types.ts";
10
4
  import { resolveCapabilities } from "../runtime/capabilities.ts";
11
5
  import { configureConfigSubcommands } from "./config.ts";
12
- import {
13
- configureCommandDescription,
14
- configureCommandNotes,
15
- configureRefreshOptionDescription,
16
- } from "./configure-copy.ts";
6
+ import { configureCommandDescription, configureCommandNotes } from "./configure-copy.ts";
17
7
 
18
- /** Hidden fallback leaf for bare `configure` (interactive / flag modes). */
19
- export const CONFIGURE_RUN_KEY = "run";
8
+ const YES_OPTION: CliOption = {
9
+ name: "yes",
10
+ description: "Skip uninstall confirmation.",
11
+ kind: CliOptionKind.Presence,
12
+ shortName: "y",
13
+ };
20
14
 
21
- /** Configure command options. */
22
- export function configureBuiltinOptions(root: CliProgram): CliOption[] {
23
- const caps = resolveCapabilities(root);
24
- const opts: CliOption[] = [
25
- {
26
- name: "refresh",
27
- description: configureRefreshOptionDescription(root, caps),
28
- kind: CliOptionKind.Presence,
29
- },
30
- {
31
- name: "remove-all",
32
- description: "Remove all detected agent artifacts (skills and MCP).",
33
- kind: CliOptionKind.Presence,
34
- },
35
- ];
15
+ const JSON_OPTION: CliOption = {
16
+ name: "json",
17
+ description: "Print status JSON on stdout.",
18
+ kind: CliOptionKind.Presence,
19
+ };
36
20
 
37
- if (root.appConfig) {
38
- opts.push({
39
- name: "remove-config",
40
- description: "Remove the app config file only.",
41
- kind: CliOptionKind.Presence,
42
- });
43
- }
21
+ /** True when argv resolved to `configure get` or `configure set`. */
22
+ export function isConfigureConfigPath(path: string[]): boolean {
23
+ return path.length >= 2 && (path[1] === "get" || path[1] === "set");
24
+ }
44
25
 
45
- opts.push(
46
- {
47
- name: "status",
48
- description: "Print what is currently installed (read-only).",
49
- kind: CliOptionKind.Presence,
50
- },
51
- {
52
- name: "yes",
53
- description: "Skip confirmation (required for --refresh, --remove-all, --remove-config).",
54
- kind: CliOptionKind.Presence,
55
- shortName: "y",
56
- },
57
- {
58
- name: "dry",
59
- description: "Show what would change without writing files.",
60
- kind: CliOptionKind.Presence,
61
- },
62
- {
63
- name: "json",
64
- description: "Print changed paths or status JSON on stdout.",
65
- kind: CliOptionKind.Presence,
26
+ function configureInstallLeaf(program: CliProgram): CliLeaf {
27
+ return {
28
+ key: "install",
29
+ description: "Install agent artifacts and bootstrap app config.",
30
+ handler: async () => {
31
+ await cliConfigureInstall(program);
66
32
  },
67
- );
33
+ };
34
+ }
68
35
 
69
- return opts;
36
+ function configureUninstallLeaf(program: CliProgram): CliLeaf {
37
+ return {
38
+ key: "uninstall",
39
+ description: "Remove agent artifacts and app config.",
40
+ options: [YES_OPTION],
41
+ handler: async (ctx) => {
42
+ await cliConfigureUninstall(program, { yes: ctx.hasFlag("yes") });
43
+ },
44
+ };
70
45
  }
71
46
 
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");
47
+ function configureStatusLeaf(program: CliProgram): CliLeaf {
48
+ return {
49
+ key: "status",
50
+ description: "Print what is currently installed (read-only).",
51
+ options: [JSON_OPTION],
52
+ handler: (ctx) => {
53
+ cliConfigureStatus(program, { json: ctx.hasFlag("json") });
54
+ },
55
+ };
75
56
  }
76
57
 
77
58
  /** Builds the `configure` built-in router. */
78
59
  export function cliBuiltinConfigureCommand(root: CliProgram): CliRouter {
79
60
  const caps = resolveCapabilities(root);
80
- const run: CliLeaf = {
81
- key: CONFIGURE_RUN_KEY,
82
- cli: { hidden: true },
83
- description: "Interactive or flag-driven configure (skills, MCP, app config).",
84
- handler: () => {},
85
- };
86
-
87
- const commands: CliLeaf[] = [run];
61
+ const commands: CliLeaf[] = [configureInstallLeaf(root), configureUninstallLeaf(root), configureStatusLeaf(root)];
88
62
  if (configCommandsEnabled(root)) {
89
63
  commands.push(...configureConfigSubcommands(root, configMcpSetEnabled(root)));
90
64
  }
@@ -92,10 +66,7 @@ export function cliBuiltinConfigureCommand(root: CliProgram): CliRouter {
92
66
  return {
93
67
  key: "configure",
94
68
  description: configureCommandDescription(root, caps),
95
- options: configureBuiltinOptions(root),
96
69
  notes: configureCommandNotes(root, caps),
97
- fallbackCommand: CONFIGURE_RUN_KEY,
98
- fallbackMode: CliFallbackMode.MissingOnly,
99
70
  commands,
100
71
  };
101
72
  }
@@ -1,4 +1,3 @@
1
- import { cliConfigure } from "../configure/index.ts";
2
1
  import type { ParseResult } from "../core/parse.ts";
3
2
  import { ParseKind } from "../core/parse.ts";
4
3
  import type { CliNode, CliProgram, CliRouter } from "../core/types.ts";
@@ -12,7 +11,7 @@ import { completionBashScript } from "./completion-bash.ts";
12
11
  import { completionFishScript } from "./completion-fish.ts";
13
12
  import { cliBuiltinCompletionGroup as completionGroup } from "./completion-group.ts";
14
13
  import { completionZshScript } from "./completion-zsh.ts";
15
- import { CONFIGURE_RUN_KEY, cliBuiltinConfigureCommand, isConfigureConfigPath } from "./configure.ts";
14
+ import { cliBuiltinConfigureCommand, isConfigureConfigPath } from "./configure.ts";
16
15
  import { cliBuiltinHttpCommand } from "./http.ts";
17
16
  import { cliBuiltinMcpCommand } from "./mcp.ts";
18
17
  import { cliPresentationRoot } from "./presentation.ts";
@@ -115,12 +114,6 @@ export async function dispatchBuiltin(program: CliProgram, pr: ParseResult, opts
115
114
  if (isConfigureConfigPath(pr.path)) {
116
115
  return;
117
116
  }
118
- const runSeg = pr.path[1];
119
- if (pr.path.length > 2 || (pr.path.length === 2 && runSeg !== CONFIGURE_RUN_KEY)) {
120
- process.stderr.write(`Unknown subcommand: configure ${pr.path.slice(1).join(" ")}\n`);
121
- process.exit(1);
122
- }
123
- await cliConfigure(program, pr.opts);
124
117
  }
125
118
  }
126
119
 
@@ -2,7 +2,7 @@ export { completionBashScript } from "./completion-bash.ts";
2
2
  export { completionFishScript } from "./completion-fish.ts";
3
3
  export { cliBuiltinCompletionGroup } from "./completion-group.ts";
4
4
  export { completionZshScript } from "./completion-zsh.ts";
5
- export { cliBuiltinConfigureCommand, configureBuiltinOptions } from "./configure.ts";
5
+ export { cliBuiltinConfigureCommand } from "./configure.ts";
6
6
  export { builtinInterceptRoot, dispatchBuiltin } from "./dispatch.ts";
7
7
  export { type CliSchemaExport, exportPresentationBuiltins } from "./export.ts";
8
8
  export { cliBuiltinMcpCommand } from "./mcp.ts";
@@ -294,7 +294,9 @@ export function substituteTemplateContent(content: string, opts: CreateOptions):
294
294
  out = out.replace(/@@PROTECT(\d+)@@/g, (_, idx: string) => protectedSpans[Number(idx)] ?? "");
295
295
 
296
296
  if (!opts.devTemplate) {
297
- out = out.replace(/"argsbarg":\s*"file:\.\.\/\.\."/, `"argsbarg": "^${argsbargVersion}"`);
297
+ out = out
298
+ .replace(/"argsbarg":\s*"workspace:\*"/, `"argsbarg": "^${argsbargVersion}"`)
299
+ .replace(/"argsbarg":\s*"file:\.\.\/\.\."/, `"argsbarg": "^${argsbargVersion}"`);
298
300
  }
299
301
 
300
302
  return out;
@@ -55,6 +55,10 @@ export async function runPostCreate(
55
55
  cwd: abs,
56
56
  stdout: "inherit",
57
57
  stderr: "inherit",
58
+ env: {
59
+ ...process.env,
60
+ PATH: `${join(abs, "node_modules/.bin")}:${process.env.PATH ?? ""}`,
61
+ },
58
62
  });
59
63
  if (proc.exitCode !== 0) throw new Error("schemagen failed");
60
64
  },
@@ -113,7 +117,7 @@ export function printPostCreatePlan(templateId: CreateTemplateId = "cli"): void
113
117
  process.stderr.write("Post-create steps:\n");
114
118
  process.stderr.write(" 1. bun install\n");
115
119
  if (templateId === "json") {
116
- process.stderr.write(" 2. argsbarg schemagen\n");
120
+ process.stderr.write(" 2. just schemagen\n");
117
121
  process.stderr.write(" 3. bun test\n");
118
122
  process.stderr.write(" 4. git init + Initial commit (skipped inside existing git work tree)\n");
119
123
  } else {
@@ -168,6 +168,7 @@ export function uninstallAppConfig(program: CliProgram, dry: boolean): string[]
168
168
  if (!dry) {
169
169
  if (hasFile) unlinkSync(path);
170
170
  if (hasDir) rmSync(dir, { recursive: true, force: true });
171
+ process.stdout.write(`Removed app config ${displayAppConfigPath(program)}\n`);
171
172
  }
172
173
  return changed;
173
174
  }
@@ -223,7 +223,7 @@ export function formatMissingConfigMessage(program: CliProgram, keys: string[]):
223
223
  const path = displayAppConfigPath(program);
224
224
  return [
225
225
  `Missing required configuration: ${list}`,
226
- `Configure interactively: ${program.key} configure`,
226
+ `Configure interactively: ${program.key} configure install`,
227
227
  `Or set via: ${program.key} configure set <key> <value>`,
228
228
  `Config file: ${path}`,
229
229
  `See: ${program.key} docs mcp`,