@phnx-labs/agents-cli 1.20.71 → 1.20.73

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 (238) hide show
  1. package/CHANGELOG.md +325 -1
  2. package/README.md +40 -4
  3. package/dist/bin/agents +0 -0
  4. package/dist/commands/activity.d.ts +12 -0
  5. package/dist/commands/activity.js +68 -0
  6. package/dist/commands/apply.d.ts +13 -0
  7. package/dist/commands/apply.js +28 -3
  8. package/dist/commands/browser.js +1 -1
  9. package/dist/commands/cloud.js +21 -11
  10. package/dist/commands/commands.js +2 -0
  11. package/dist/commands/doctor.js +8 -4
  12. package/dist/commands/events.d.ts +11 -10
  13. package/dist/commands/events.js +30 -21
  14. package/dist/commands/exec.d.ts +34 -0
  15. package/dist/commands/exec.js +337 -39
  16. package/dist/commands/feed.d.ts +13 -0
  17. package/dist/commands/feed.js +130 -29
  18. package/dist/commands/hq.d.ts +2 -0
  19. package/dist/commands/hq.js +58 -0
  20. package/dist/commands/lease.d.ts +19 -0
  21. package/dist/commands/lease.js +138 -11
  22. package/dist/commands/login.d.ts +2 -0
  23. package/dist/commands/login.js +123 -0
  24. package/dist/commands/logs.js +39 -10
  25. package/dist/commands/mcp.js +2 -0
  26. package/dist/commands/mine.d.ts +27 -0
  27. package/dist/commands/mine.js +207 -0
  28. package/dist/commands/monitors.js +79 -49
  29. package/dist/commands/plugins.js +1 -0
  30. package/dist/commands/profiles.js +158 -0
  31. package/dist/commands/repo.js +2 -60
  32. package/dist/commands/resource-view.d.ts +2 -0
  33. package/dist/commands/resource-view.js +8 -0
  34. package/dist/commands/resources.d.ts +5 -0
  35. package/dist/commands/resources.js +95 -0
  36. package/dist/commands/routines.d.ts +2 -0
  37. package/dist/commands/routines.js +139 -37
  38. package/dist/commands/secrets.js +234 -47
  39. package/dist/commands/send.d.ts +15 -0
  40. package/dist/commands/send.js +62 -0
  41. package/dist/commands/sessions-tail.d.ts +1 -0
  42. package/dist/commands/sessions-tail.js +20 -9
  43. package/dist/commands/sessions.d.ts +6 -0
  44. package/dist/commands/sessions.js +26 -3
  45. package/dist/commands/setup-mine.d.ts +18 -0
  46. package/dist/commands/setup-mine.js +106 -0
  47. package/dist/commands/setup-share.js +2 -2
  48. package/dist/commands/setup.js +3 -1
  49. package/dist/commands/share.d.ts +8 -1
  50. package/dist/commands/share.js +122 -37
  51. package/dist/commands/skills.js +2 -0
  52. package/dist/commands/ssh.d.ts +9 -0
  53. package/dist/commands/ssh.js +196 -26
  54. package/dist/commands/status.js +8 -2
  55. package/dist/commands/subagents.js +3 -1
  56. package/dist/commands/sync.js +1 -1
  57. package/dist/commands/teams.js +11 -2
  58. package/dist/commands/uninstall.d.ts +11 -0
  59. package/dist/commands/uninstall.js +158 -0
  60. package/dist/commands/utils.d.ts +29 -0
  61. package/dist/commands/utils.js +24 -0
  62. package/dist/commands/versions.js +120 -11
  63. package/dist/index.js +83 -12
  64. package/dist/lib/activity.d.ts +124 -0
  65. package/dist/lib/activity.js +542 -0
  66. package/dist/lib/agents.js +16 -5
  67. package/dist/lib/artifact-actions.d.ts +1 -1
  68. package/dist/lib/artifact-actions.js +1 -1
  69. package/dist/lib/ask-classifier.d.ts +2 -1
  70. package/dist/lib/ask-classifier.js +3 -3
  71. package/dist/lib/auth-health.d.ts +32 -4
  72. package/dist/lib/auth-health.js +40 -1
  73. package/dist/lib/auto-pull.js +8 -1
  74. package/dist/lib/brand.d.ts +40 -0
  75. package/dist/lib/brand.js +122 -0
  76. package/dist/lib/browser/drivers/ssh.js +4 -7
  77. package/dist/lib/browser/service.js +6 -8
  78. package/dist/lib/channels/providers/index.d.ts +2 -0
  79. package/dist/lib/channels/providers/index.js +20 -0
  80. package/dist/lib/channels/providers/mailbox.d.ts +2 -0
  81. package/dist/lib/channels/providers/mailbox.js +26 -0
  82. package/dist/lib/channels/providers/openclaw-telegram.d.ts +2 -0
  83. package/dist/lib/channels/providers/openclaw-telegram.js +34 -0
  84. package/dist/lib/channels/providers/rush.d.ts +6 -0
  85. package/dist/lib/channels/providers/rush.js +55 -0
  86. package/dist/lib/channels/registry.d.ts +42 -0
  87. package/dist/lib/channels/registry.js +20 -0
  88. package/dist/lib/channels/resolve.d.ts +11 -0
  89. package/dist/lib/channels/resolve.js +12 -0
  90. package/dist/lib/cli-resources.d.ts +18 -0
  91. package/dist/lib/cli-resources.js +53 -4
  92. package/dist/lib/cloud/codex.js +6 -3
  93. package/dist/lib/cloud/factory.d.ts +1 -0
  94. package/dist/lib/cloud/factory.js +10 -4
  95. package/dist/lib/cloud/rush.d.ts +3 -1
  96. package/dist/lib/cloud/rush.js +6 -1
  97. package/dist/lib/cloud/types.d.ts +2 -0
  98. package/dist/lib/codex-home.d.ts +35 -0
  99. package/dist/lib/codex-home.js +136 -0
  100. package/dist/lib/crabbox/cli.d.ts +44 -0
  101. package/dist/lib/crabbox/cli.js +120 -20
  102. package/dist/lib/crabbox/lease.d.ts +52 -1
  103. package/dist/lib/crabbox/lease.js +117 -16
  104. package/dist/lib/crabbox/progress.d.ts +31 -0
  105. package/dist/lib/crabbox/progress.js +76 -0
  106. package/dist/lib/crabbox/runtimes.d.ts +4 -0
  107. package/dist/lib/crabbox/runtimes.js +33 -8
  108. package/dist/lib/crabbox/setup-copy.d.ts +87 -0
  109. package/dist/lib/crabbox/setup-copy.js +127 -0
  110. package/dist/lib/daemon.d.ts +14 -5
  111. package/dist/lib/daemon.js +52 -9
  112. package/dist/lib/drive-sync.js +6 -3
  113. package/dist/lib/event-stream.d.ts +36 -0
  114. package/dist/lib/event-stream.js +68 -0
  115. package/dist/lib/events.d.ts +1 -1
  116. package/dist/lib/exec.d.ts +11 -0
  117. package/dist/lib/exec.js +23 -2
  118. package/dist/lib/feed-policy.d.ts +1 -1
  119. package/dist/lib/feed-policy.js +14 -9
  120. package/dist/lib/feed-ranking.d.ts +32 -0
  121. package/dist/lib/feed-ranking.js +224 -0
  122. package/dist/lib/feed.d.ts +35 -2
  123. package/dist/lib/feed.js +66 -3
  124. package/dist/lib/fleet/auth-sync.d.ts +53 -0
  125. package/dist/lib/fleet/auth-sync.js +92 -0
  126. package/dist/lib/fleet/remote-login.d.ts +187 -0
  127. package/dist/lib/fleet/remote-login.js +556 -0
  128. package/dist/lib/format.d.ts +30 -3
  129. package/dist/lib/format.js +34 -5
  130. package/dist/lib/fs-atomic.d.ts +7 -2
  131. package/dist/lib/fs-atomic.js +8 -12
  132. package/dist/lib/git.d.ts +16 -0
  133. package/dist/lib/git.js +79 -2
  134. package/dist/lib/heal.js +11 -3
  135. package/dist/lib/hosts/logs.d.ts +12 -0
  136. package/dist/lib/hosts/logs.js +18 -0
  137. package/dist/lib/hosts/progress.d.ts +28 -10
  138. package/dist/lib/hosts/progress.js +79 -22
  139. package/dist/lib/hosts/remote-cmd.js +4 -0
  140. package/dist/lib/hq/floor.d.ts +87 -0
  141. package/dist/lib/hq/floor.js +226 -0
  142. package/dist/lib/menubar/install-menubar.js +14 -20
  143. package/dist/lib/notify.d.ts +1 -0
  144. package/dist/lib/notify.js +3 -3
  145. package/dist/lib/open-url.d.ts +2 -0
  146. package/dist/lib/open-url.js +19 -0
  147. package/dist/lib/openclaw-keychain.d.ts +56 -0
  148. package/dist/lib/openclaw-keychain.js +236 -0
  149. package/dist/lib/overdue.js +10 -0
  150. package/dist/lib/permissions.d.ts +44 -1
  151. package/dist/lib/permissions.js +284 -7
  152. package/dist/lib/project-launch.d.ts +6 -12
  153. package/dist/lib/project-launch.js +13 -228
  154. package/dist/lib/project-resources.d.ts +7 -0
  155. package/dist/lib/project-resources.js +291 -0
  156. package/dist/lib/pty-client.d.ts +27 -0
  157. package/dist/lib/pty-client.js +136 -10
  158. package/dist/lib/refresh.js +14 -10
  159. package/dist/lib/resource-profiles.d.ts +26 -0
  160. package/dist/lib/resource-profiles.js +157 -0
  161. package/dist/lib/resources/permissions.js +7 -1
  162. package/dist/lib/resources/types.d.ts +1 -1
  163. package/dist/lib/resources.d.ts +1 -1
  164. package/dist/lib/resources.js +32 -3
  165. package/dist/lib/routines.d.ts +11 -0
  166. package/dist/lib/routines.js +56 -15
  167. package/dist/lib/runner.d.ts +1 -0
  168. package/dist/lib/runner.js +66 -5
  169. package/dist/lib/secrets/bundles.d.ts +16 -3
  170. package/dist/lib/secrets/bundles.js +206 -37
  171. package/dist/lib/secrets/icloud-import.d.ts +2 -2
  172. package/dist/lib/secrets/icloud-import.js +9 -6
  173. package/dist/lib/secrets/mcp.js +1 -1
  174. package/dist/lib/secrets/vault-age-helper.d.ts +1 -0
  175. package/dist/lib/secrets/vault-age-helper.js +34 -0
  176. package/dist/lib/secrets/vault.d.ts +49 -0
  177. package/dist/lib/secrets/vault.js +397 -0
  178. package/dist/lib/self-heal/checks/path.js +3 -1
  179. package/dist/lib/self-heal/checks/shadowing.js +10 -2
  180. package/dist/lib/self-heal/checks/shims.js +19 -11
  181. package/dist/lib/session/cloud.d.ts +2 -2
  182. package/dist/lib/session/cloud.js +2 -2
  183. package/dist/lib/session/db.d.ts +4 -0
  184. package/dist/lib/session/db.js +44 -7
  185. package/dist/lib/session/discover.d.ts +2 -0
  186. package/dist/lib/session/discover.js +114 -3
  187. package/dist/lib/session/stream-render.d.ts +3 -0
  188. package/dist/lib/session/stream-render.js +130 -0
  189. package/dist/lib/session/types.d.ts +6 -0
  190. package/dist/lib/share/analytics.d.ts +13 -0
  191. package/dist/lib/share/analytics.js +45 -0
  192. package/dist/lib/share/config.d.ts +19 -5
  193. package/dist/lib/share/config.js +44 -8
  194. package/dist/lib/share/provision.d.ts +58 -6
  195. package/dist/lib/share/provision.js +97 -22
  196. package/dist/lib/share/publish.d.ts +36 -13
  197. package/dist/lib/share/publish.js +55 -8
  198. package/dist/lib/share/worker-template.js +83 -17
  199. package/dist/lib/shims.d.ts +36 -0
  200. package/dist/lib/shims.js +120 -16
  201. package/dist/lib/ssh-exec.d.ts +14 -0
  202. package/dist/lib/ssh-exec.js +57 -0
  203. package/dist/lib/staleness/detectors/hooks.js +25 -1
  204. package/dist/lib/staleness/detectors/permissions.js +66 -0
  205. package/dist/lib/staleness/detectors/workflows.js +20 -0
  206. package/dist/lib/staleness/writers/hooks.js +58 -4
  207. package/dist/lib/staleness/writers/permissions.js +2 -2
  208. package/dist/lib/staleness/writers/skills.js +1 -1
  209. package/dist/lib/staleness/writers/sources.d.ts +10 -1
  210. package/dist/lib/staleness/writers/sources.js +68 -1
  211. package/dist/lib/star-nudge.d.ts +45 -0
  212. package/dist/lib/star-nudge.js +91 -0
  213. package/dist/lib/startup/command-registry.d.ts +7 -1
  214. package/dist/lib/startup/command-registry.js +19 -3
  215. package/dist/lib/state.d.ts +2 -0
  216. package/dist/lib/state.js +3 -0
  217. package/dist/lib/subagents-registry.d.ts +2 -0
  218. package/dist/lib/subagents-registry.js +3 -0
  219. package/dist/lib/teams/parsers.js +214 -6
  220. package/dist/lib/teams/supervisor.d.ts +7 -0
  221. package/dist/lib/teams/supervisor.js +2 -1
  222. package/dist/lib/template.d.ts +1 -1
  223. package/dist/lib/template.js +1 -1
  224. package/dist/lib/triggers/webhook.js +36 -3
  225. package/dist/lib/types.d.ts +73 -0
  226. package/dist/lib/uninstall.d.ts +84 -0
  227. package/dist/lib/uninstall.js +347 -0
  228. package/dist/lib/usage.d.ts +13 -1
  229. package/dist/lib/usage.js +32 -14
  230. package/dist/lib/version.d.ts +40 -0
  231. package/dist/lib/version.js +94 -16
  232. package/dist/lib/versions.d.ts +27 -0
  233. package/dist/lib/versions.js +248 -79
  234. package/dist/lib/workflows.d.ts +2 -0
  235. package/dist/lib/workflows.js +88 -0
  236. package/package.json +2 -1
  237. package/dist/commands/daemon.d.ts +0 -10
  238. package/dist/commands/daemon.js +0 -121
@@ -23,9 +23,9 @@
23
23
  import chalk from 'chalk';
24
24
  import * as fs from 'fs';
25
25
  import { discoverSessions, resolveSessionById } from '../lib/session/discover.js';
26
- import { parseAgentFilter, renderSessionLog } from './sessions.js';
26
+ import { parseAgentFilter, renderSessionLog, renderSessionLogJson } from './sessions.js';
27
27
  import { streamSessionTail, isTailable } from './sessions-tail.js';
28
- import { showHostTaskLog } from '../lib/hosts/logs.js';
28
+ import { showHostTaskLog, hostTaskLogJson } from '../lib/hosts/logs.js';
29
29
  import { listTasks } from '../lib/hosts/tasks.js';
30
30
  import { itemPicker } from '../lib/picker.js';
31
31
  import { query, stats, getLogsPath, rotate, levelFor, } from '../lib/events.js';
@@ -43,29 +43,57 @@ function candidateLabel(c) {
43
43
  const title = s.label || s.topic || '';
44
44
  return `${chalk.gray('sess')} ${s.shortId.padEnd(9)} ${(s.agent + ver).padEnd(14)} ${chalk.gray(s.timestamp.slice(0, 16))} ${title.slice(0, 40)}`;
45
45
  }
46
+ /** Emit a host-dispatch task's log as JSON: `{ kind, task, log }`. */
47
+ function emitHostTaskJson(id) {
48
+ const hj = hostTaskLogJson(id);
49
+ if (!hj.found)
50
+ return false;
51
+ process.stdout.write(JSON.stringify({ kind: 'task', task: hj.task, log: hj.log ?? null }, null, 2) + '\n');
52
+ return true;
53
+ }
46
54
  /** Show a resolved session — follow (tail), concise summary, or (`full`) transcript. */
47
- async function showSession(session, follow, full) {
55
+ async function showSession(session, follow, full, json = false) {
56
+ if (json) {
57
+ await renderSessionLogJson(session);
58
+ return;
59
+ }
48
60
  if (follow) {
49
61
  if (!isTailable(session.agent)) {
50
62
  console.error(chalk.red(`Tailing is supported for claude and codex sessions only (got ${session.agent}).`));
51
63
  process.exit(2);
52
64
  }
53
- await streamSessionTail(session, {});
65
+ await streamSessionTail(session, { raw: full });
54
66
  return;
55
67
  }
56
68
  await renderSessionLog(session, full ? 'markdown' : 'summary');
57
69
  }
58
- async function showCandidate(c, follow, full) {
70
+ async function showCandidate(c, follow, full, json = false) {
59
71
  if (c.kind === 'task') {
72
+ if (json) {
73
+ emitHostTaskJson(c.task.id);
74
+ return;
75
+ }
60
76
  const res = await showHostTaskLog(c.task.id, follow, full);
61
77
  if (res.exitCode !== undefined)
62
78
  process.exitCode = res.exitCode;
63
79
  return;
64
80
  }
65
- await showSession(c.session, follow, full);
81
+ await showSession(c.session, follow, full, json);
66
82
  }
67
83
  /** Resolve an explicit id/--session: host task first, then a session. */
68
- async function showById(id, follow, full) {
84
+ async function showById(id, follow, full, json = false) {
85
+ if (json) {
86
+ if (emitHostTaskJson(id))
87
+ return;
88
+ const sessions = await discoverSessions({ all: true, limit: 5000 });
89
+ const matches = resolveSessionById(sessions, id);
90
+ if (matches.length === 0) {
91
+ console.error(chalk.red(`No run or session found matching "${id}".`));
92
+ process.exit(1);
93
+ }
94
+ await renderSessionLogJson(matches[0]);
95
+ return;
96
+ }
69
97
  const hostRes = await showHostTaskLog(id, follow, full);
70
98
  if (hostRes.found) {
71
99
  if (hostRes.exitCode !== undefined)
@@ -85,7 +113,7 @@ async function runLogs(id, opts) {
85
113
  const full = !!opts.full;
86
114
  const directId = opts.session ?? id;
87
115
  if (directId) {
88
- await showById(directId, follow, full);
116
+ await showById(directId, follow, full, !!opts.json);
89
117
  return;
90
118
  }
91
119
  const { agent, version } = parseAgentFilter(opts.agent);
@@ -110,7 +138,7 @@ async function runLogs(id, opts) {
110
138
  process.exit(1);
111
139
  }
112
140
  if (candidates.length === 1) {
113
- await showCandidate(candidates[0], follow, full);
141
+ await showCandidate(candidates[0], follow, full, !!opts.json);
114
142
  return;
115
143
  }
116
144
  // Multiple sessions matched → picker if interactive, else a list to pick from.
@@ -134,7 +162,7 @@ async function runLogs(id, opts) {
134
162
  });
135
163
  if (!picked)
136
164
  return;
137
- await showCandidate(picked.item, follow, full);
165
+ await showCandidate(picked.item, follow, full, !!opts.json);
138
166
  }
139
167
  function parseSince(s) {
140
168
  const m = s.match(/^(\d+)([smhdw])$/);
@@ -343,6 +371,7 @@ export function registerLogsCommand(program) {
343
371
  .option('--session <id>', 'Select a session/run by id (same as the positional id)')
344
372
  .option('-f, --follow', 'Follow live output')
345
373
  .option('-m, --full', 'Show the full raw transcript / stdout instead of the concise summary')
374
+ .option('--json', 'Machine-readable JSON: a host task as { kind, task, log }, a session as the redacted { session, events } (same shape as `sessions <id> --json`)')
346
375
  .action((id, opts) => runLogs(id, opts));
347
376
  logsCmd
348
377
  .command('audit')
@@ -147,6 +147,7 @@ When to use:
147
147
  .command('list [agent]')
148
148
  .description('Show which MCP servers are registered and which agent versions they are synced to')
149
149
  .option('-a, --agent <agent>', 'Filter to a specific agent (alternative to positional arg)')
150
+ .option('--json', 'Emit machine-readable JSON instead of the table/picker')
150
151
  .action(async (agentArg, options) => {
151
152
  const spinner = ora({ text: 'Loading...', isSilent: !process.stdout.isTTY }).start();
152
153
  const agentInput = agentArg || options.agent;
@@ -176,6 +177,7 @@ When to use:
176
177
  centralPath: getMcpDir(),
177
178
  filterAgent,
178
179
  filterVersion,
180
+ json: options.json,
179
181
  });
180
182
  });
181
183
  mcpCmd
@@ -0,0 +1,27 @@
1
+ /**
2
+ * `agents mine` — white-label the CLI under your own name.
3
+ *
4
+ * `agents mine init <name>` mints a personally-named binary (e.g. `jack`) that
5
+ * IS agents-cli: a pure pass-through shim on PATH that runs every `agents` verb
6
+ * under the brand's name, with the brand's disabled commands and curated
7
+ * resource profile applied. `list` / `toggle` / `remove` manage brands.
8
+ *
9
+ * The discoverable entry point is the `agents setup mine` wizard
10
+ * (see setup-mine.ts), which delegates to `initBrand` here.
11
+ *
12
+ * Storage: brand config in `meta.brands` (agents.yaml); the curated resource set
13
+ * reuses the resource-profile engine — each brand owns a preset named
14
+ * `mine-<name>` in `meta.profiles.presets`. See lib/brand.ts.
15
+ */
16
+ import type { Command } from 'commander';
17
+ /**
18
+ * Create (or re-mint) a brand. Shared by `mine init` and the `setup mine`
19
+ * wizard. Writes the shim, the brand config, and an empty resource preset.
20
+ */
21
+ export declare function initBrand(name: string, opts?: {
22
+ disabledCommands?: string[];
23
+ force?: boolean;
24
+ }): {
25
+ pathWarning: boolean;
26
+ };
27
+ export declare function registerMineCommand(program: Command): void;
@@ -0,0 +1,207 @@
1
+ import chalk from 'chalk';
2
+ import { validateBrandName, listBrands, getBrandConfig, upsertBrand, removeBrand, brandPresetName, } from '../lib/brand.js';
3
+ import { createBrandShim, removeBrandShim, isShimsInPath } from '../lib/shims.js';
4
+ import { updateMeta } from '../lib/state.js';
5
+ import { COMMAND_LOADERS } from '../lib/startup/command-registry.js';
6
+ /** Built-in top-level command names, for validating `--disable <cmd>`. */
7
+ function knownCommandNames() {
8
+ const names = new Set(Object.keys(COMMAND_LOADERS));
9
+ // Inline aliases registered outside COMMAND_LOADERS (see src/index.ts).
10
+ for (const n of ['perms', 'exec', 'jobs', 'cron', 'upgrade'])
11
+ names.add(n);
12
+ return names;
13
+ }
14
+ /**
15
+ * Add/remove a `!name` exclusion on a preset's pattern list for one kind,
16
+ * keeping `*` so everything not explicitly disabled stays enabled. Deletes the
17
+ * key entirely once nothing but `*` remains, so a clean brand has an empty preset.
18
+ */
19
+ function applyResourceToggle(preset, kind, name, enable) {
20
+ // Cast to a plain string-bag: writing through the union-keyed `preset[kind]`
21
+ // collapses to `never` under strict TS, so index the bag instead.
22
+ const bag = preset;
23
+ const arr = [...(bag[kind] ?? [])];
24
+ if (arr.length === 0)
25
+ arr.push('*');
26
+ const excl = `!${name}`;
27
+ const idx = arr.indexOf(excl);
28
+ if (enable) {
29
+ if (idx !== -1)
30
+ arr.splice(idx, 1);
31
+ }
32
+ else if (idx === -1) {
33
+ arr.push(excl);
34
+ }
35
+ const onlyStar = arr.length === 1 && arr[0] === '*';
36
+ if (onlyStar)
37
+ delete bag[kind];
38
+ else
39
+ bag[kind] = arr;
40
+ }
41
+ /** Ensure the brand's preset exists in meta.profiles.presets and return a mutable copy path. */
42
+ function ensurePresetExists(name) {
43
+ const presetName = brandPresetName(name);
44
+ updateMeta((meta) => {
45
+ const profiles = meta.profiles ?? {};
46
+ const presets = { ...(profiles.presets ?? {}) };
47
+ if (!presets[presetName]) {
48
+ presets[presetName] = { description: `Resource set for the "${name}" brand` };
49
+ }
50
+ return { ...meta, profiles: { ...profiles, presets } };
51
+ });
52
+ }
53
+ /** Mutate the brand's resource preset under lock. */
54
+ function editPreset(name, fn) {
55
+ const presetName = brandPresetName(name);
56
+ updateMeta((meta) => {
57
+ const profiles = meta.profiles ?? {};
58
+ const presets = { ...(profiles.presets ?? {}) };
59
+ const preset = { ...(presets[presetName] ?? {}) };
60
+ fn(preset);
61
+ presets[presetName] = preset;
62
+ return { ...meta, profiles: { ...profiles, presets } };
63
+ });
64
+ }
65
+ /**
66
+ * Create (or re-mint) a brand. Shared by `mine init` and the `setup mine`
67
+ * wizard. Writes the shim, the brand config, and an empty resource preset.
68
+ */
69
+ export function initBrand(name, opts = {}) {
70
+ const err = validateBrandName(name);
71
+ if (err) {
72
+ console.error(chalk.red(err));
73
+ process.exit(1);
74
+ }
75
+ if (getBrandConfig(name) && !opts.force) {
76
+ console.error(chalk.red(`Brand "${name}" already exists. Use --force to re-mint, or 'agents mine toggle ${name}'.`));
77
+ process.exit(1);
78
+ }
79
+ ensurePresetExists(name);
80
+ const disabled = (opts.disabledCommands ?? []).filter((c) => c.length > 0);
81
+ const known = knownCommandNames();
82
+ for (const c of disabled) {
83
+ if (!known.has(c))
84
+ console.error(chalk.yellow(` note: "${c}" is not a known command — kept anyway.`));
85
+ }
86
+ const cfg = {
87
+ name,
88
+ enabled: true,
89
+ profile: brandPresetName(name),
90
+ ...(disabled.length > 0 ? { disabledCommands: disabled } : {}),
91
+ };
92
+ upsertBrand(cfg);
93
+ createBrandShim(name);
94
+ const pathWarning = !isShimsInPath();
95
+ return { pathWarning };
96
+ }
97
+ function printMinted(name, pathWarning) {
98
+ console.log(`${chalk.green('Minted')} ${chalk.bold(name)} — your own agents CLI.`);
99
+ console.log(chalk.dim(` try: ${name} --help ${name} run claude "hello"`));
100
+ if (pathWarning) {
101
+ console.log(chalk.yellow(` note: the shims dir isn't on your PATH yet — run 'agents setup' or open a new shell.`));
102
+ }
103
+ }
104
+ export function registerMineCommand(program) {
105
+ const cmd = program
106
+ .command('mine')
107
+ .description('White-label the CLI: your own personally-named binary (e.g. `jack`)');
108
+ cmd
109
+ .command('init <name>')
110
+ .description('Mint your own branded CLI that runs every agents verb under <name>')
111
+ .option('--disable <commands...>', 'Built-in commands to hide from this brand (e.g. teams cloud)')
112
+ .option('--force', 'Re-mint even if the brand already exists')
113
+ .action((name, options) => {
114
+ const { pathWarning } = initBrand(name, {
115
+ disabledCommands: options.disable,
116
+ force: options.force,
117
+ });
118
+ printMinted(name, pathWarning);
119
+ });
120
+ cmd
121
+ .command('list')
122
+ .alias('ls')
123
+ .description('Show your brands and what each has turned off')
124
+ .action(() => {
125
+ const brands = listBrands();
126
+ const entries = Object.entries(brands);
127
+ if (entries.length === 0) {
128
+ console.log(chalk.gray("No brands yet. Try: agents setup mine (or: agents mine init jack)"));
129
+ return;
130
+ }
131
+ const width = entries.reduce((m, [n]) => Math.max(m, n.length), 0);
132
+ for (const [name, cfg] of entries) {
133
+ const off = cfg.disabledCommands?.length ? `disabled: ${cfg.disabledCommands.join(', ')}` : 'all commands on';
134
+ const state = cfg.enabled === false ? chalk.yellow('(disabled) ') : '';
135
+ console.log(` ${chalk.bold(name.padEnd(width))} ${state}${chalk.dim(off)}`);
136
+ }
137
+ });
138
+ cmd
139
+ .command('toggle <name>')
140
+ .description('Enable/disable features for a brand')
141
+ .option('--disable <commands...>', 'Hide these built-in commands')
142
+ .option('--enable <commands...>', 'Un-hide these built-in commands')
143
+ .option('--disable-plugin <names...>', 'Disable these plugins for the brand')
144
+ .option('--enable-plugin <names...>', 'Re-enable these plugins')
145
+ .option('--disable-skill <names...>', 'Disable these skills for the brand')
146
+ .option('--enable-skill <names...>', 'Re-enable these skills')
147
+ .action((name, options) => {
148
+ const cfg = getBrandConfig(name);
149
+ if (!cfg) {
150
+ console.error(chalk.red(`No brand named "${name}". Create it with 'agents mine init ${name}'.`));
151
+ process.exit(1);
152
+ }
153
+ // Built-in command toggles → brand.disabledCommands.
154
+ const disabledSet = new Set(cfg.disabledCommands ?? []);
155
+ const known = knownCommandNames();
156
+ for (const c of options.disable ?? []) {
157
+ if (!known.has(c))
158
+ console.error(chalk.yellow(` note: "${c}" is not a known command — kept anyway.`));
159
+ disabledSet.add(c);
160
+ }
161
+ for (const c of options.enable ?? [])
162
+ disabledSet.delete(c);
163
+ const nextDisabled = [...disabledSet];
164
+ const nextCfg = { ...cfg };
165
+ if (nextDisabled.length > 0)
166
+ nextCfg.disabledCommands = nextDisabled;
167
+ else
168
+ delete nextCfg.disabledCommands;
169
+ upsertBrand(nextCfg);
170
+ // Resource toggles → the brand's profile preset.
171
+ const resourceOps = [];
172
+ for (const p of options.disablePlugin ?? [])
173
+ resourceOps.push(['plugins', p, false]);
174
+ for (const p of options.enablePlugin ?? [])
175
+ resourceOps.push(['plugins', p, true]);
176
+ for (const s of options.disableSkill ?? [])
177
+ resourceOps.push(['skills', s, false]);
178
+ for (const s of options.enableSkill ?? [])
179
+ resourceOps.push(['skills', s, true]);
180
+ if (resourceOps.length > 0) {
181
+ ensurePresetExists(name);
182
+ editPreset(name, (preset) => {
183
+ for (const [kind, n, enable] of resourceOps)
184
+ applyResourceToggle(preset, kind, n, enable);
185
+ });
186
+ }
187
+ console.log(`${chalk.green('Updated')} ${chalk.bold(name)}.`);
188
+ const finalCfg = getBrandConfig(name);
189
+ const off = finalCfg.disabledCommands?.length ? finalCfg.disabledCommands.join(', ') : '(none)';
190
+ console.log(chalk.dim(` disabled commands: ${off}`));
191
+ });
192
+ cmd
193
+ .command('remove <name>')
194
+ .alias('rm')
195
+ .description('Remove a brand (its shim + config)')
196
+ .option('--purge', "Also delete the brand's resource profile preset")
197
+ .action((name, options) => {
198
+ const existed = getBrandConfig(name) !== undefined;
199
+ const shimRemoved = removeBrandShim(name);
200
+ if (!existed && !shimRemoved) {
201
+ console.error(chalk.red(`No brand named "${name}".`));
202
+ process.exit(1);
203
+ }
204
+ removeBrand(name, options.purge === true);
205
+ console.log(`${chalk.yellow('Removed')} brand ${chalk.bold(name)}`);
206
+ });
207
+ }