argsbarg 6.3.1 → 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 +21 -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 +25 -25
  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 +19 -36
  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 +19 -37
  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,31 +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
80
- install-local: build
81
- @NONINTERACTIVE=1 brew untap {{tap}} 2>/dev/null || true
79
+ # Dev install: build, stage dev formula, brew install, refresh agent artifacts
80
+ install-local: uninstall build
82
81
  mkdir -p {{tap_parent}}
83
82
  ln -sfn '{{justfile_directory()}}' {{tap_path}}
84
83
  bun scripts/dev-formula.ts install
85
- NONINTERACTIVE=1 brew reinstall --formula {{tap}}/{{cli_key}} || NONINTERACTIVE=1 brew install --force --formula {{tap}}/{{cli_key}}
84
+ HOMEBREW_NO_ASK=1 brew reinstall --formula {{tap}}/{{cli_key}} || HOMEBREW_NO_ASK=1 brew install --force --formula {{tap}}/{{cli_key}}
86
85
  bun scripts/dev-formula.ts reset
87
- @echo ""
88
- @echo "Next: {{cli_key}} configure"
86
+ {{cli_key}} configure install
89
87
 
90
88
  # Remove local dev install, then install from GitHub tap (requires gh auth login)
91
89
  install-production: uninstall
92
90
  brew tap {{release_repo}} {{tap_git_url}}
93
91
  brew install --formula {{release_repo}}/{{cli_key}}
94
- @echo ""
95
- @echo "Next: {{cli_key}} configure"
92
+ {{cli_key}} configure install
96
93
 
97
94
  # Alias for backward compatibility
98
95
  reinstall: reinstall-local
99
96
 
100
- # 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)
101
98
  reinstall-local: build
102
99
  install -m 755 dist/{{cli_key}} "$(brew --prefix {{cli_key}})/bin/{{cli_key}}"
103
100
 
101
+ # Refresh agent skills/MCP without reinstalling the binary
102
+ refresh:
103
+ {{cli_key}} configure install
104
+
104
105
  # Lint sources without writing
105
106
  lint:
106
107
  bun run biome check ./src ./scripts
@@ -113,10 +114,10 @@ run *ARGS:
113
114
  schemagen:
114
115
  argsbarg schemagen
115
116
 
116
- # Install bun/npm dependencies
117
117
  # Install bun/npm dependencies and generate schemas
118
118
  setup:
119
119
  bun install
120
+ test -f node_modules/argsbarg/bin/argsbarg && ln -sf ../argsbarg/bin/argsbarg node_modules/.bin/argsbarg
120
121
  just schemagen
121
122
 
122
123
  # Run unit tests (after check)
@@ -129,10 +130,10 @@ release *ARGS:
129
130
 
130
131
  # Install release formula from tap and run formula test
131
132
  test-release:
132
- NONINTERACTIVE=1 brew untap {{tap}} 2>/dev/null || true
133
+ HOMEBREW_NO_ASK=1 brew untap {{tap}} 2>/dev/null || true
133
134
  mkdir -p {{tap_parent}}
134
135
  ln -sfn '{{justfile_directory()}}' {{tap_path}}
135
- NONINTERACTIVE=1 brew uninstall --formula {{tap}}/{{cli_key}} 2>/dev/null || true
136
+ HOMEBREW_NO_ASK=1 brew uninstall --formula {{tap}}/{{cli_key}} 2>/dev/null || true
136
137
  brew install --formula {{tap}}/{{cli_key}}
137
138
  brew test {{cli_key}}
138
139
 
@@ -140,28 +141,9 @@ test-release:
140
141
  typecheck:
141
142
  bun run tsc --noEmit
142
143
 
143
- # Undo just install-local: agent artifacts first, then formula
144
- uninstall: uninstall-artifacts uninstall-formula
145
-
146
- # Remove agent artifacts only (skills, MCP)
147
- uninstall-artifacts:
148
- just run configure --remove-all --yes
149
-
150
- # Remove app config file only
151
- uninstall-config:
152
- just run configure --remove-config --yes
153
-
154
- # Remove formula and untap
155
- uninstall-formula:
156
- @NONINTERACTIVE=1 brew uninstall --formula {{tap}}/{{cli_key}} 2>/dev/null || true
157
- @NONINTERACTIVE=1 brew uninstall --formula {{tap}}/{{cli_key}}-local 2>/dev/null || true
158
- @NONINTERACTIVE=1 brew untap {{tap}} 2>/dev/null || true
159
-
160
- # Remove release formula (does not untap)
161
- uninstall-release:
162
- @NONINTERACTIVE=1 brew uninstall --formula {{tap}}/{{cli_key}} 2>/dev/null || true
163
-
164
- # Remove release formula and untap
165
- uninstall-release-tap:
166
- @NONINTERACTIVE=1 brew uninstall --formula {{tap}}/{{cli_key}} 2>/dev/null || true
167
- @NONINTERACTIVE=1 brew untap {{tap}} 2>/dev/null || true
144
+ # Undo dev/Homebrew install (remove agent artifacts, then keg + untap)
145
+ uninstall:
146
+ @{{cli_key}} configure uninstall --yes 2>/dev/null || just run configure uninstall --yes
147
+ @HOMEBREW_NO_ASK=1 brew uninstall --formula {{tap}}/{{cli_key}} 2>/dev/null || true
148
+ @HOMEBREW_NO_ASK=1 brew uninstall --formula {{tap}}/{{cli_key}}-local 2>/dev/null || true
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.1",
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
  }