@phnx-labs/agents-cli 1.20.4 → 1.20.5

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 (190) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +48 -17
  3. package/dist/commands/cli.js +1 -1
  4. package/dist/commands/cloud.js +1 -1
  5. package/dist/commands/commands.js +2 -0
  6. package/dist/commands/doctor.js +1 -1
  7. package/dist/commands/exec.js +52 -16
  8. package/dist/commands/hooks.js +6 -6
  9. package/dist/commands/inspect.d.ts +26 -0
  10. package/dist/commands/inspect.js +590 -0
  11. package/dist/commands/mcp.js +17 -16
  12. package/dist/commands/models.js +1 -1
  13. package/dist/commands/packages.js +6 -4
  14. package/dist/commands/permissions.js +13 -12
  15. package/dist/commands/plugins.d.ts +13 -0
  16. package/dist/commands/plugins.js +100 -11
  17. package/dist/commands/prune.js +3 -2
  18. package/dist/commands/pull.d.ts +12 -5
  19. package/dist/commands/pull.js +26 -422
  20. package/dist/commands/push.d.ts +14 -0
  21. package/dist/commands/push.js +30 -0
  22. package/dist/commands/repo.d.ts +1 -1
  23. package/dist/commands/repo.js +155 -112
  24. package/dist/commands/resource-view.d.ts +2 -0
  25. package/dist/commands/resource-view.js +12 -3
  26. package/dist/commands/routines.js +32 -7
  27. package/dist/commands/rules.js +1 -1
  28. package/dist/commands/sessions.js +1 -0
  29. package/dist/commands/setup.d.ts +3 -3
  30. package/dist/commands/setup.js +15 -15
  31. package/dist/commands/skills.js +6 -5
  32. package/dist/commands/subagents.js +5 -4
  33. package/dist/commands/sync.d.ts +18 -5
  34. package/dist/commands/sync.js +251 -65
  35. package/dist/commands/teams.js +1 -0
  36. package/dist/commands/tmux.d.ts +25 -0
  37. package/dist/commands/tmux.js +415 -0
  38. package/dist/commands/trash.d.ts +2 -2
  39. package/dist/commands/trash.js +1 -1
  40. package/dist/commands/versions.js +2 -2
  41. package/dist/commands/view.js +9 -4
  42. package/dist/commands/workflows.js +4 -3
  43. package/dist/commands/worktree.d.ts +4 -5
  44. package/dist/commands/worktree.js +4 -4
  45. package/dist/index.js +68 -20
  46. package/dist/lib/agents.d.ts +19 -10
  47. package/dist/lib/agents.js +79 -25
  48. package/dist/lib/auto-pull-worker.d.ts +1 -1
  49. package/dist/lib/auto-pull-worker.js +2 -2
  50. package/dist/lib/auto-pull.d.ts +1 -1
  51. package/dist/lib/auto-pull.js +1 -1
  52. package/dist/lib/beta.d.ts +1 -1
  53. package/dist/lib/beta.js +1 -1
  54. package/dist/lib/capabilities.js +2 -0
  55. package/dist/lib/commands.d.ts +28 -1
  56. package/dist/lib/commands.js +125 -20
  57. package/dist/lib/doctor-diff.js +2 -2
  58. package/dist/lib/exec.d.ts +14 -0
  59. package/dist/lib/exec.js +39 -5
  60. package/dist/lib/fuzzy.d.ts +12 -2
  61. package/dist/lib/fuzzy.js +29 -4
  62. package/dist/lib/git.js +8 -1
  63. package/dist/lib/hooks.d.ts +2 -2
  64. package/dist/lib/hooks.js +97 -10
  65. package/dist/lib/mcp.js +32 -2
  66. package/dist/lib/migrate.d.ts +51 -0
  67. package/dist/lib/migrate.js +227 -1
  68. package/dist/lib/models.js +62 -15
  69. package/dist/lib/permissions.d.ts +36 -2
  70. package/dist/lib/permissions.js +217 -7
  71. package/dist/lib/plugin-marketplace.d.ts +98 -40
  72. package/dist/lib/plugin-marketplace.js +196 -93
  73. package/dist/lib/plugins.d.ts +21 -4
  74. package/dist/lib/plugins.js +130 -49
  75. package/dist/lib/profiles-presets.js +12 -12
  76. package/dist/lib/project-launch.d.ts +65 -0
  77. package/dist/lib/project-launch.js +367 -0
  78. package/dist/lib/pty-client.js +1 -1
  79. package/dist/lib/pty-server.d.ts +1 -1
  80. package/dist/lib/pty-server.js +1 -1
  81. package/dist/lib/refresh.d.ts +26 -0
  82. package/dist/lib/refresh.js +315 -0
  83. package/dist/lib/resource-patterns.d.ts +1 -1
  84. package/dist/lib/resource-patterns.js +1 -1
  85. package/dist/lib/resources/commands.js +2 -2
  86. package/dist/lib/resources/hooks.d.ts +1 -1
  87. package/dist/lib/resources/hooks.js +1 -1
  88. package/dist/lib/resources/mcp.d.ts +1 -1
  89. package/dist/lib/resources/mcp.js +5 -6
  90. package/dist/lib/resources/permissions.js +5 -2
  91. package/dist/lib/resources/rules.js +3 -2
  92. package/dist/lib/resources/skills.js +3 -2
  93. package/dist/lib/resources/types.d.ts +1 -1
  94. package/dist/lib/resources.js +2 -2
  95. package/dist/lib/rotate.d.ts +1 -1
  96. package/dist/lib/rotate.js +1 -1
  97. package/dist/lib/routines.d.ts +16 -4
  98. package/dist/lib/routines.js +67 -17
  99. package/dist/lib/rules/compile.js +22 -10
  100. package/dist/lib/rules/rules.js +3 -3
  101. package/dist/lib/runner.js +16 -3
  102. package/dist/lib/scheduler.js +15 -1
  103. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  104. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  105. package/dist/lib/secrets/Agents CLI.app/Contents/_CodeSignature/CodeResources +9 -1
  106. package/dist/lib/secrets/Agents CLI.app/Contents/embedded.provisionprofile +0 -0
  107. package/dist/lib/secrets/linux.d.ts +44 -9
  108. package/dist/lib/secrets/linux.js +302 -48
  109. package/dist/lib/session/db.js +15 -2
  110. package/dist/lib/session/discover.js +118 -3
  111. package/dist/lib/session/parse.js +3 -0
  112. package/dist/lib/session/types.d.ts +1 -1
  113. package/dist/lib/session/types.js +1 -1
  114. package/dist/lib/shims.d.ts +10 -9
  115. package/dist/lib/shims.js +101 -50
  116. package/dist/lib/skills.d.ts +1 -1
  117. package/dist/lib/skills.js +10 -9
  118. package/dist/lib/staleness/detectors/commands.d.ts +3 -0
  119. package/dist/lib/staleness/detectors/commands.js +46 -0
  120. package/dist/lib/staleness/detectors/hooks.d.ts +3 -0
  121. package/dist/lib/staleness/detectors/hooks.js +44 -0
  122. package/dist/lib/staleness/detectors/mcp.d.ts +3 -0
  123. package/dist/lib/staleness/detectors/mcp.js +31 -0
  124. package/dist/lib/staleness/detectors/permissions.d.ts +3 -0
  125. package/dist/lib/staleness/detectors/permissions.js +201 -0
  126. package/dist/lib/staleness/detectors/plugins.d.ts +8 -0
  127. package/dist/lib/staleness/detectors/plugins.js +23 -0
  128. package/dist/lib/staleness/detectors/rules.d.ts +3 -0
  129. package/dist/lib/staleness/detectors/rules.js +34 -0
  130. package/dist/lib/staleness/detectors/skills.d.ts +3 -0
  131. package/dist/lib/staleness/detectors/skills.js +71 -0
  132. package/dist/lib/staleness/detectors/subagents.d.ts +3 -0
  133. package/dist/lib/staleness/detectors/subagents.js +50 -0
  134. package/dist/lib/staleness/detectors/types.d.ts +22 -0
  135. package/dist/lib/staleness/detectors/types.js +1 -0
  136. package/dist/lib/staleness/detectors/workflows.d.ts +3 -0
  137. package/dist/lib/staleness/detectors/workflows.js +28 -0
  138. package/dist/lib/staleness/registry.d.ts +26 -0
  139. package/dist/lib/staleness/registry.js +123 -0
  140. package/dist/lib/staleness/writers/commands.d.ts +3 -0
  141. package/dist/lib/staleness/writers/commands.js +111 -0
  142. package/dist/lib/staleness/writers/hooks.d.ts +3 -0
  143. package/dist/lib/staleness/writers/hooks.js +47 -0
  144. package/dist/lib/staleness/writers/kinds.d.ts +10 -0
  145. package/dist/lib/staleness/writers/kinds.js +15 -0
  146. package/dist/lib/staleness/writers/lazy-map.d.ts +13 -0
  147. package/dist/lib/staleness/writers/lazy-map.js +19 -0
  148. package/dist/lib/staleness/writers/mcp.d.ts +10 -0
  149. package/dist/lib/staleness/writers/mcp.js +19 -0
  150. package/dist/lib/staleness/writers/permissions.d.ts +13 -0
  151. package/dist/lib/staleness/writers/permissions.js +26 -0
  152. package/dist/lib/staleness/writers/plugins.d.ts +7 -0
  153. package/dist/lib/staleness/writers/plugins.js +31 -0
  154. package/dist/lib/staleness/writers/rules.d.ts +7 -0
  155. package/dist/lib/staleness/writers/rules.js +55 -0
  156. package/dist/lib/staleness/writers/skills.d.ts +3 -0
  157. package/dist/lib/staleness/writers/skills.js +81 -0
  158. package/dist/lib/staleness/writers/sources.d.ts +16 -0
  159. package/dist/lib/staleness/writers/sources.js +72 -0
  160. package/dist/lib/staleness/writers/subagents.d.ts +3 -0
  161. package/dist/lib/staleness/writers/subagents.js +53 -0
  162. package/dist/lib/staleness/writers/types.d.ts +36 -0
  163. package/dist/lib/staleness/writers/types.js +1 -0
  164. package/dist/lib/staleness/writers/workflows.d.ts +7 -0
  165. package/dist/lib/staleness/writers/workflows.js +31 -0
  166. package/dist/lib/state.d.ts +34 -11
  167. package/dist/lib/state.js +58 -13
  168. package/dist/lib/subagents.d.ts +0 -2
  169. package/dist/lib/subagents.js +6 -6
  170. package/dist/lib/teams/agents.js +1 -1
  171. package/dist/lib/teams/parsers.d.ts +1 -1
  172. package/dist/lib/tmux/binary.d.ts +67 -0
  173. package/dist/lib/tmux/binary.js +141 -0
  174. package/dist/lib/tmux/index.d.ts +8 -0
  175. package/dist/lib/tmux/index.js +8 -0
  176. package/dist/lib/tmux/paths.d.ts +17 -0
  177. package/dist/lib/tmux/paths.js +30 -0
  178. package/dist/lib/tmux/session.d.ts +122 -0
  179. package/dist/lib/tmux/session.js +305 -0
  180. package/dist/lib/types.d.ts +58 -7
  181. package/dist/lib/types.js +1 -1
  182. package/dist/lib/usage.js +1 -1
  183. package/dist/lib/versions.d.ts +4 -4
  184. package/dist/lib/versions.js +135 -493
  185. package/dist/lib/workflows.d.ts +2 -4
  186. package/dist/lib/workflows.js +3 -4
  187. package/package.json +2 -2
  188. package/scripts/postinstall.js +16 -63
  189. package/dist/commands/status.d.ts +0 -9
  190. package/dist/commands/status.js +0 -25
@@ -1,7 +1,8 @@
1
1
  import chalk from 'chalk';
2
2
  import ora from 'ora';
3
3
  import { checkbox } from '@inquirer/prompts';
4
- import { AGENTS, MCP_CAPABLE_AGENTS, getAllCliStates, resolveAgentName, formatAgentError, registerMcpToTargets, unregisterMcpFromTargets, listInstalledMcpsWithScope, parseMcpConfig, getMcpConfigPathForHome, agentLabel, } from '../lib/agents.js';
4
+ import { capableAgents, isCapable } from '../lib/capabilities.js';
5
+ import { AGENTS, getAllCliStates, resolveAgentName, formatAgentError, registerMcpToTargets, unregisterMcpFromTargets, listInstalledMcpsWithScope, parseMcpConfig, getMcpConfigPathForHome, agentLabel, } from '../lib/agents.js';
5
6
  import { readManifest, writeManifest, createDefaultManifest } from '../lib/manifest.js';
6
7
  import { listMcpServerConfigs, discoverMcpConfigsFromRepo, installMcpConfigCentrally, } from '../lib/mcp.js';
7
8
  import { cloneRepo } from '../lib/git.js';
@@ -36,7 +37,7 @@ function parseMcpAgentTargets(value) {
36
37
  const targets = [];
37
38
  for (const t of rawTargets) {
38
39
  if (t === 'all' || t === 'all@all') {
39
- for (const a of MCP_CAPABLE_AGENTS) {
40
+ for (const a of capableAgents('mcp')) {
40
41
  if (listInstalledVersions(a).length > 0) {
41
42
  targets.push(`${a}@all`);
42
43
  }
@@ -57,8 +58,8 @@ function parseMcpAgentTargets(value) {
57
58
  throw new Error(`Missing version in --agents entry '${target}'. Use agent@x.y.z, agent@default, or agent@all.`);
58
59
  }
59
60
  const agentId = resolveAgentName(agentToken);
60
- if (!agentId || !MCP_CAPABLE_AGENTS.includes(agentId)) {
61
- throw new Error(formatAgentError(agentToken, MCP_CAPABLE_AGENTS));
61
+ if (!agentId || !isCapable(agentId, 'mcp')) {
62
+ throw new Error(formatAgentError(agentToken, capableAgents('mcp')));
62
63
  }
63
64
  if (!versionToken) {
64
65
  if (!agents.includes(agentId)) {
@@ -154,7 +155,7 @@ When to use:
154
155
  const resolved = resolveAgentName(parts[0]);
155
156
  if (!resolved) {
156
157
  spinner.stop();
157
- console.log(chalk.red(formatAgentError(parts[0], MCP_CAPABLE_AGENTS)));
158
+ console.log(chalk.red(formatAgentError(parts[0], capableAgents('mcp'))));
158
159
  process.exit(1);
159
160
  }
160
161
  filterAgent = resolved;
@@ -178,7 +179,7 @@ When to use:
178
179
  mcpCmd
179
180
  .command('add <name> [command_or_url...]')
180
181
  .description('Add an MCP server to the manifest (run "agents mcp register" afterward to apply)')
181
- .option('-a, --agents <list>', 'Targets: claude, codex@0.116.0', MCP_CAPABLE_AGENTS.join(','))
182
+ .option('-a, --agents <list>', 'Targets: claude, codex@0.116.0', capableAgents('mcp').join(','))
182
183
  .option('-s, --scope <scope>', 'user (global) or project (repo-specific)', 'user')
183
184
  .option('-t, --transport <type>', 'stdio (default) or http', 'stdio')
184
185
  .option('--names <list>', 'When source is a repo: MCP server names to install (comma-separated)')
@@ -254,7 +255,7 @@ Examples:
254
255
  manifest.mcp = manifest.mcp || {};
255
256
  // Pre-flight: prompt-and-install any requested agent@version that isn't
256
257
  // installed yet, before parseMcpAgentTargets validates the selector.
257
- const okInstall = await ensureAgentVersionsInstalled(options.agents, MCP_CAPABLE_AGENTS, { yes: options.yes });
258
+ const okInstall = await ensureAgentVersionsInstalled(options.agents, capableAgents('mcp'), { yes: options.yes });
258
259
  if (!okInstall) {
259
260
  console.log(chalk.gray('Cancelled.'));
260
261
  return;
@@ -313,7 +314,7 @@ Examples:
313
314
  const cwd = process.cwd();
314
315
  const cliStates = await getAllCliStates();
315
316
  const mcpTargetMap = new Map();
316
- for (const agentId of MCP_CAPABLE_AGENTS) {
317
+ for (const agentId of capableAgents('mcp')) {
317
318
  if (!cliStates[agentId]?.installed && listInstalledVersions(agentId).length === 0)
318
319
  continue;
319
320
  for (const version of listInstalledVersions(agentId)) {
@@ -383,7 +384,7 @@ Examples:
383
384
  // If --agents was specified, filter targets
384
385
  let availableTargets = mcpInfo.targets;
385
386
  if (options?.agents) {
386
- const requestedTargets = resolveInstalledAgentTargets(options.agents, MCP_CAPABLE_AGENTS);
387
+ const requestedTargets = resolveInstalledAgentTargets(options.agents, capableAgents('mcp'));
387
388
  const requested = new Set();
388
389
  for (const aid of requestedTargets.directAgents) {
389
390
  for (const ver of listInstalledVersions(aid)) {
@@ -458,7 +459,7 @@ Examples:
458
459
  const cliStates = await getAllCliStates();
459
460
  // Gather all unique MCPs across agents
460
461
  const mcpMap = new Map();
461
- for (const agentId of MCP_CAPABLE_AGENTS) {
462
+ for (const agentId of capableAgents('mcp')) {
462
463
  if (!cliStates[agentId]?.installed)
463
464
  continue;
464
465
  const mcps = listInstalledMcpsWithScope(agentId, cwd, { home: getEffectiveHome(agentId) });
@@ -562,7 +563,7 @@ Examples:
562
563
  console.log(`\n ${chalk.cyan(mcpName)}:`);
563
564
  let targets;
564
565
  if (options.agents) {
565
- const resolved = await resolveInstalledAgentTargetsAutoInstalling(options.agents, MCP_CAPABLE_AGENTS, { yes: options.yes });
566
+ const resolved = await resolveInstalledAgentTargetsAutoInstalling(options.agents, capableAgents('mcp'), { yes: options.yes });
566
567
  if (!resolved) {
567
568
  console.log(chalk.gray(' Cancelled.'));
568
569
  continue;
@@ -570,7 +571,7 @@ Examples:
570
571
  targets = resolved;
571
572
  }
572
573
  else {
573
- targets = resolveConfiguredAgentTargets(config.agents, config.agentVersions, MCP_CAPABLE_AGENTS);
574
+ targets = resolveConfiguredAgentTargets(config.agents, config.agentVersions, capableAgents('mcp'));
574
575
  }
575
576
  const results = await registerMcpToTargets(targets, mcpName, commandOrUrl, config.scope || 'user', transport, { headers: config.headers });
576
577
  for (const result of results) {
@@ -639,10 +640,10 @@ async function installMcpsFromRepoSource(source, options) {
639
640
  // Agent/version selection — same default as the non-repo form: every
640
641
  // MCP-capable agent. Routes through resolveAgentTargetsAutoInstalling so
641
642
  // a typo'd `claude@2.1.999` prompts to install (and --yes auto-installs).
642
- const agentsValue = options.agents ?? MCP_CAPABLE_AGENTS.join(',');
643
+ const agentsValue = options.agents ?? capableAgents('mcp').join(',');
643
644
  let targets;
644
645
  try {
645
- const resolved = await resolveAgentTargetsAutoInstalling(agentsValue, MCP_CAPABLE_AGENTS, { yes: options.yes });
646
+ const resolved = await resolveAgentTargetsAutoInstalling(agentsValue, capableAgents('mcp'), { yes: options.yes });
646
647
  if (!resolved) {
647
648
  console.log(chalk.gray('\nCancelled.'));
648
649
  return;
@@ -672,9 +673,9 @@ async function installMcpsFromRepoSource(source, options) {
672
673
  /** Enumerate (agent, version) pairs that support MCP and have a version home. */
673
674
  function iterMcpCapableVersions(filter) {
674
675
  const out = [];
675
- const agents = filter?.agent ? [filter.agent] : MCP_CAPABLE_AGENTS;
676
+ const agents = filter?.agent ? [filter.agent] : capableAgents('mcp');
676
677
  for (const agent of agents) {
677
- if (!MCP_CAPABLE_AGENTS.includes(agent))
678
+ if (!isCapable(agent, 'mcp'))
678
679
  continue;
679
680
  const versions = listInstalledVersions(agent);
680
681
  for (const version of versions) {
@@ -116,7 +116,7 @@ function printCatalog(agent, version, isDefault, options) {
116
116
  const src = locateModelSource(agent, version);
117
117
  if (!src) {
118
118
  console.log(chalk.yellow(` Could not locate model source for ${agent}@${version}.`));
119
- console.log(chalk.gray(` Expected the agent's CLI bundle or native binary under ~/.agents-system/versions/${agent}/${version}/.`));
119
+ console.log(chalk.gray(` Expected the agent's CLI bundle or native binary under ~/.agents/.history/versions/${agent}/${version}/.`));
120
120
  return;
121
121
  }
122
122
  const catalog = getModelCatalog(agent, version);
@@ -7,7 +7,8 @@
7
7
  */
8
8
  import chalk from 'chalk';
9
9
  import ora from 'ora';
10
- import { AGENTS, ALL_AGENT_IDS, MCP_CAPABLE_AGENTS, getAllCliStates, agentLabel, } from '../lib/agents.js';
10
+ import { AGENTS, ALL_AGENT_IDS, getAllCliStates, agentLabel, } from '../lib/agents.js';
11
+ import { capableAgents } from '../lib/capabilities.js';
11
12
  import { DEFAULT_REGISTRIES } from '../lib/types.js';
12
13
  import { getRegistries, setRegistry, removeRegistry, search as searchRegistries, resolvePackage, validatedNpmSpec, validatedPyPISpec, } from '../lib/registry.js';
13
14
  import { cloneRepo } from '../lib/git.js';
@@ -110,6 +111,7 @@ export function registerPackagesCommands(program) {
110
111
  }
111
112
  console.log();
112
113
  }
114
+ console.log(chalk.gray(" See also: agents plugins marketplaces — plugin marketplaces (managed via 'agents repo')"));
113
115
  });
114
116
  registryCmd
115
117
  .command('add <type> <name> <url>')
@@ -410,10 +412,10 @@ When to use:
410
412
  process.exit(1);
411
413
  }
412
414
  const cliStates = await getAllCliStates();
413
- const installedAgents = MCP_CAPABLE_AGENTS.filter((id) => cliStates[id]?.installed || listInstalledVersions(id).length > 0);
415
+ const installedAgents = capableAgents('mcp').filter((id) => cliStates[id]?.installed || listInstalledVersions(id).length > 0);
414
416
  let targets;
415
417
  if (options.agents) {
416
- const resolved = await resolveInstalledAgentTargetsAutoInstalling(options.agents, MCP_CAPABLE_AGENTS, { yes: options.yes });
418
+ const resolved = await resolveInstalledAgentTargetsAutoInstalling(options.agents, capableAgents('mcp'), { yes: options.yes });
417
419
  if (!resolved) {
418
420
  console.log(chalk.gray('Cancelled.'));
419
421
  return;
@@ -421,7 +423,7 @@ When to use:
421
423
  targets = resolved;
422
424
  }
423
425
  else {
424
- targets = resolveConfiguredAgentTargets(installedAgents, undefined, MCP_CAPABLE_AGENTS);
426
+ targets = resolveConfiguredAgentTargets(installedAgents, undefined, capableAgents('mcp'));
425
427
  }
426
428
  if (targets.selectedAgents.length === 0) {
427
429
  console.log(chalk.yellow('\nNo MCP-capable agents installed.'));
@@ -6,7 +6,8 @@ import * as path from 'path';
6
6
  import { confirm, checkbox } from '@inquirer/prompts';
7
7
  import { AGENTS, resolveAgentName, formatAgentError, agentLabel, } from '../lib/agents.js';
8
8
  import { cloneRepo } from '../lib/git.js';
9
- import { PERMISSIONS_CAPABLE_AGENTS, listInstalledPermissions, discoverPermissionsFromRepo, installPermissionSet, removePermissionSet, applyPermissionsToVersion, readAgentPermissions, exportPermissionsFromPath, getDefaultPermissionSet, computePermissionsDiff, mergePermissionSets, saveDefaultPermissionSet, containsBroadGrants, } from '../lib/permissions.js';
9
+ import { capableAgents, isCapable } from '../lib/capabilities.js';
10
+ import { listInstalledPermissions, discoverPermissionsFromRepo, installPermissionSet, removePermissionSet, applyPermissionsToVersion, readAgentPermissions, exportPermissionsFromPath, getDefaultPermissionSet, computePermissionsDiff, mergePermissionSets, saveDefaultPermissionSet, containsBroadGrants, } from '../lib/permissions.js';
10
11
  import { listInstalledVersions, getGlobalDefault, getVersionHomePath, promptAgentVersionSelection, resolveVersionAlias, } from '../lib/versions.js';
11
12
  import { recordVersionResources } from '../lib/state.js';
12
13
  import { isPromptCancelled, isInteractiveTerminal, parseCommaSeparatedList, printWithPager, requireInteractiveSelection, resolveAgentTargetsAutoInstalling, } from './utils.js';
@@ -112,11 +113,11 @@ When to use:
112
113
  const agentName = parts[0];
113
114
  const agentId = resolveAgentName(agentName);
114
115
  if (!agentId) {
115
- console.log(chalk.red(formatAgentError(agentName, PERMISSIONS_CAPABLE_AGENTS)));
116
+ console.log(chalk.red(formatAgentError(agentName, capableAgents('allowlist'))));
116
117
  process.exit(1);
117
118
  }
118
119
  const requestedVersion = resolveVersionAlias(agentId, parts[1]) ?? null;
119
- if (!PERMISSIONS_CAPABLE_AGENTS.includes(agentId)) {
120
+ if (!isCapable(agentId, 'allowlist')) {
120
121
  console.log(chalk.yellow(`${AGENTS[agentId].name} does not support fine-grained permissions`));
121
122
  return;
122
123
  }
@@ -279,7 +280,7 @@ Examples:
279
280
  let selectedAgents;
280
281
  let versionSelections;
281
282
  if (options.agents) {
282
- const result = await resolveAgentTargetsAutoInstalling(options.agents, PERMISSIONS_CAPABLE_AGENTS, {
283
+ const result = await resolveAgentTargetsAutoInstalling(options.agents, capableAgents('allowlist'), {
283
284
  yes: options.yes,
284
285
  allVersions: options.all,
285
286
  });
@@ -291,7 +292,7 @@ Examples:
291
292
  versionSelections = result.versionSelections;
292
293
  }
293
294
  else if (options.all) {
294
- selectedAgents = [...PERMISSIONS_CAPABLE_AGENTS];
295
+ selectedAgents = [...capableAgents('allowlist')];
295
296
  versionSelections = new Map();
296
297
  for (const agentId of selectedAgents) {
297
298
  const versions = listInstalledVersions(agentId);
@@ -301,7 +302,7 @@ Examples:
301
302
  }
302
303
  }
303
304
  else {
304
- const result = await promptAgentVersionSelection(PERMISSIONS_CAPABLE_AGENTS, { skipPrompts: options.yes });
305
+ const result = await promptAgentVersionSelection(capableAgents('allowlist'), { skipPrompts: options.yes });
305
306
  selectedAgents = result.selectedAgents;
306
307
  versionSelections = result.versionSelections;
307
308
  }
@@ -417,7 +418,7 @@ Examples:
417
418
  let selectedAgents;
418
419
  let versionSelections;
419
420
  if (options.agents) {
420
- const result = await resolveAgentTargetsAutoInstalling(options.agents, PERMISSIONS_CAPABLE_AGENTS, {
421
+ const result = await resolveAgentTargetsAutoInstalling(options.agents, capableAgents('allowlist'), {
421
422
  yes: options.yes,
422
423
  allVersions: options.all,
423
424
  });
@@ -429,7 +430,7 @@ Examples:
429
430
  versionSelections = result.versionSelections;
430
431
  }
431
432
  else if (options.all) {
432
- selectedAgents = [...PERMISSIONS_CAPABLE_AGENTS];
433
+ selectedAgents = [...capableAgents('allowlist')];
433
434
  versionSelections = new Map();
434
435
  for (const agentId of selectedAgents) {
435
436
  const versions = listInstalledVersions(agentId);
@@ -444,7 +445,7 @@ Examples:
444
445
  default: true,
445
446
  });
446
447
  if (applyNow) {
447
- const result = await promptAgentVersionSelection(PERMISSIONS_CAPABLE_AGENTS, { skipPrompts: false });
448
+ const result = await promptAgentVersionSelection(capableAgents('allowlist'), { skipPrompts: false });
448
449
  selectedAgents = result.selectedAgents;
449
450
  versionSelections = result.versionSelections;
450
451
  }
@@ -547,7 +548,7 @@ Examples:
547
548
  let selectedAgents;
548
549
  let versionSelections;
549
550
  if (options.agents) {
550
- const result = await resolveAgentTargetsAutoInstalling(options.agents, PERMISSIONS_CAPABLE_AGENTS, {
551
+ const result = await resolveAgentTargetsAutoInstalling(options.agents, capableAgents('allowlist'), {
551
552
  yes: options.yes,
552
553
  allVersions: options.all,
553
554
  });
@@ -559,7 +560,7 @@ Examples:
559
560
  versionSelections = result.versionSelections;
560
561
  }
561
562
  else if (options.all) {
562
- selectedAgents = [...PERMISSIONS_CAPABLE_AGENTS];
563
+ selectedAgents = [...capableAgents('allowlist')];
563
564
  versionSelections = new Map();
564
565
  for (const agentId of selectedAgents) {
565
566
  const versions = listInstalledVersions(agentId);
@@ -574,7 +575,7 @@ Examples:
574
575
  default: true,
575
576
  });
576
577
  if (applyNow) {
577
- const result = await promptAgentVersionSelection(PERMISSIONS_CAPABLE_AGENTS, { skipPrompts: false });
578
+ const result = await promptAgentVersionSelection(capableAgents('allowlist'), { skipPrompts: false });
578
579
  selectedAgents = result.selectedAgents;
579
580
  versionSelections = result.versionSelections;
580
581
  }
@@ -10,3 +10,16 @@ import { type PluginCapabilities } from '../lib/plugins.js';
10
10
  export declare function shouldRefusePluginInstall(capabilities: PluginCapabilities, allowExecSurfaces: boolean): boolean;
11
11
  /** Register the `agents plugins` command tree. */
12
12
  export declare function registerPluginsCommands(program: Command): void;
13
+ interface MarketplaceRow {
14
+ name: string;
15
+ source: string;
16
+ plugins: number;
17
+ enabled: number;
18
+ }
19
+ /**
20
+ * Build one row per discovered marketplace. `plugins` counts plugin manifests
21
+ * under the marketplace's source pluginsRoot; `enabled` counts entries in the
22
+ * default Claude version's settings.json#enabledPlugins keyed on @<marketplace>.
23
+ */
24
+ export declare function collectMarketplaceRows(): MarketplaceRow[];
25
+ export {};
@@ -9,7 +9,8 @@ import * as fs from 'fs';
9
9
  import * as path from 'path';
10
10
  import chalk from 'chalk';
11
11
  import { input } from '@inquirer/prompts';
12
- import { PLUGINS_CAPABLE_AGENTS, agentLabel } from '../lib/agents.js';
12
+ import { agentLabel } from '../lib/agents.js';
13
+ import { capableAgents, isCapable } from '../lib/capabilities.js';
13
14
  import { discoverPlugins, getPlugin, pluginSupportsAgent, removePluginFromVersion, isPluginSynced, installPlugin, updatePlugin, loadUserConfig, saveUserConfig, checkPluginDependencies, hasPluginExecSurfaces, inspectPluginCapabilities, pluginCapabilityLabels, parseInstallSpec, syncPluginToVersion, } from '../lib/plugins.js';
14
15
  import { listInstalledVersions, syncResourcesToVersion, getGlobalDefault, getVersionHomePath, } from '../lib/versions.js';
15
16
  import { isPromptCancelled, isInteractiveTerminal, requireDestructiveArg, requireInteractiveSelection, promptRemovalTargets, } from './utils.js';
@@ -17,6 +18,7 @@ import { itemPicker } from '../lib/picker.js';
17
18
  import { showResourceList, buildTargetsSection, } from './resource-view.js';
18
19
  import { getPluginsDir } from '../lib/state.js';
19
20
  import { safeJoin } from '../lib/paths.js';
21
+ import { discoverMarketplaces } from '../lib/plugin-marketplace.js';
20
22
  /** Replace the home directory prefix with ~ for display. */
21
23
  function formatPath(p) {
22
24
  const home = process.env.HOME || '';
@@ -66,6 +68,7 @@ When to use:
66
68
  resourcePlural: 'plugins',
67
69
  resourceSingular: 'plugin',
68
70
  extraLabel: 'Version',
71
+ extra2Label: 'Marketplace',
69
72
  rows: buildPluginRows(plugins),
70
73
  emptyMessage: 'No plugins in ~/.agents/plugins/.',
71
74
  centralPath: getPluginsDir(),
@@ -78,6 +81,42 @@ When to use:
78
81
  .command('list')
79
82
  .description('Show plugins in a table with sync status across agent versions')
80
83
  .action(runList);
84
+ // agents plugins marketplaces
85
+ const marketplacesCmd = pluginsCmd
86
+ .command('marketplaces')
87
+ .description('List plugin marketplaces — one per DotAgents repo with a plugins/ directory')
88
+ .option('--json', 'Emit machine-readable JSON')
89
+ .action((options) => {
90
+ const rows = collectMarketplaceRows();
91
+ if (options.json) {
92
+ console.log(JSON.stringify(rows, null, 2));
93
+ return;
94
+ }
95
+ if (rows.length === 0) {
96
+ console.log(chalk.gray('No plugin marketplaces found.'));
97
+ console.log(chalk.gray('Add one with: agents repo add <path|gh:user/repo>'));
98
+ return;
99
+ }
100
+ const nameW = Math.max(12, ...rows.map((r) => r.name.length));
101
+ const srcW = Math.max(20, ...rows.map((r) => formatPath(r.source).length));
102
+ console.log();
103
+ console.log(` ${chalk.bold(padCol('NAME', nameW))} ${chalk.bold(padCol('SOURCE', srcW))} ${chalk.bold(padCol('PLUGINS', 7))} ${chalk.bold('ENABLED')}`);
104
+ for (const r of rows) {
105
+ console.log(` ${chalk.cyan(padCol(r.name, nameW))} ${chalk.gray(padCol(formatPath(r.source), srcW))} ${padCol(String(r.plugins), 7)} ${r.enabled}`);
106
+ }
107
+ console.log();
108
+ console.log(chalk.gray(`${rows.length} marketplace(s) — manage via 'agents repo'.`));
109
+ });
110
+ // Redirect add/remove/etc. on marketplaces to repo commands.
111
+ const marketplaceRedirect = (verb) => () => {
112
+ console.log(chalk.gray(`Use 'agents repo ${verb === 'add' ? 'add' : verb} <path|gh:user/repo>' to ${verb} a marketplace (one repo = one marketplace).`));
113
+ };
114
+ for (const verb of ['add', 'remove', 'enable', 'disable', 'install', 'rm']) {
115
+ marketplacesCmd
116
+ .command(`${verb} [target]`)
117
+ .description(`Redirects to 'agents repo ${verb}' — marketplaces follow repos`)
118
+ .action(marketplaceRedirect(verb));
119
+ }
81
120
  // agents plugins info [name]
82
121
  pluginsCmd
83
122
  .command('info [name]')
@@ -145,7 +184,7 @@ Examples:
145
184
  console.log(` ${plugin.manifest.description}`);
146
185
  console.log(` ${chalk.gray(`Version: ${plugin.manifest.version}`)}`);
147
186
  console.log(` ${chalk.gray(`Path: ${formatPath(plugin.root)}`)}`);
148
- const agents = PLUGINS_CAPABLE_AGENTS
187
+ const agents = capableAgents('plugins')
149
188
  .filter(a => pluginSupportsAgent(plugin, a))
150
189
  .map(a => agentLabel(a));
151
190
  console.log(` ${chalk.gray(`Agents: ${agents.join(', ')}`)}`);
@@ -210,7 +249,7 @@ Examples:
210
249
  // Show installation status per agent version
211
250
  console.log(chalk.bold('\n Installation Status'));
212
251
  let anyInstalled = false;
213
- for (const agentId of PLUGINS_CAPABLE_AGENTS) {
252
+ for (const agentId of capableAgents('plugins')) {
214
253
  if (!pluginSupportsAgent(plugin, agentId))
215
254
  continue;
216
255
  const versions = listInstalledVersions(agentId);
@@ -259,7 +298,7 @@ Examples:
259
298
  let targetAgents;
260
299
  if (agentArg) {
261
300
  const agentId = agentArg;
262
- if (!PLUGINS_CAPABLE_AGENTS.includes(agentId)) {
301
+ if (!isCapable(agentId, 'plugins')) {
263
302
  console.log(chalk.red(`Agent '${agentArg}' does not support plugins`));
264
303
  process.exit(1);
265
304
  }
@@ -270,7 +309,7 @@ Examples:
270
309
  targetAgents = [agentId];
271
310
  }
272
311
  else {
273
- targetAgents = PLUGINS_CAPABLE_AGENTS.filter(a => pluginSupportsAgent(plugin, a));
312
+ targetAgents = capableAgents('plugins').filter(a => pluginSupportsAgent(plugin, a));
274
313
  }
275
314
  const allowExec = options.allowExecSurfaces === true;
276
315
  for (const agentId of targetAgents) {
@@ -327,7 +366,7 @@ Examples:
327
366
  }
328
367
  // Build list of targets that have this plugin synced
329
368
  const availableTargets = [];
330
- for (const agentId of PLUGINS_CAPABLE_AGENTS) {
369
+ for (const agentId of capableAgents('plugins')) {
331
370
  if (plugin && !pluginSupportsAgent(plugin, agentId))
332
371
  continue;
333
372
  const versions = listInstalledVersions(agentId);
@@ -476,7 +515,7 @@ Examples:
476
515
  // Sync to all supported installed versions
477
516
  console.log();
478
517
  let synced = 0;
479
- for (const agentId of PLUGINS_CAPABLE_AGENTS) {
518
+ for (const agentId of capableAgents('plugins')) {
480
519
  if (!pluginSupportsAgent(plugin, agentId))
481
520
  continue;
482
521
  const versions = listInstalledVersions(agentId);
@@ -530,7 +569,7 @@ Examples:
530
569
  }
531
570
  console.log(chalk.green('done'));
532
571
  // Re-sync to all supported installed versions
533
- for (const agentId of PLUGINS_CAPABLE_AGENTS) {
572
+ for (const agentId of capableAgents('plugins')) {
534
573
  if (!pluginSupportsAgent(plugin, agentId))
535
574
  continue;
536
575
  const versions = listInstalledVersions(agentId);
@@ -578,19 +617,68 @@ async function promptUserConfig(manifest, existingConfig = {}) {
578
617
  }
579
618
  return result;
580
619
  }
620
+ function padCol(s, w) {
621
+ const raw = s.replace(/\x1b\[[0-9;]*m/g, '');
622
+ if (raw.length >= w)
623
+ return s;
624
+ return s + ' '.repeat(w - raw.length);
625
+ }
626
+ /**
627
+ * Build one row per discovered marketplace. `plugins` counts plugin manifests
628
+ * under the marketplace's source pluginsRoot; `enabled` counts entries in the
629
+ * default Claude version's settings.json#enabledPlugins keyed on @<marketplace>.
630
+ */
631
+ export function collectMarketplaceRows() {
632
+ const marketplaces = discoverMarketplaces();
633
+ const rows = [];
634
+ // Find the default Claude version (if any) and read its enabledPlugins map.
635
+ const claudeDefault = isCapable('claude', 'plugins') ? getGlobalDefault('claude') : null;
636
+ let enabledMap = {};
637
+ if (claudeDefault) {
638
+ const versionHome = getVersionHomePath('claude', claudeDefault);
639
+ const settingsPath = path.join(versionHome, '.claude', 'settings.json');
640
+ if (fs.existsSync(settingsPath)) {
641
+ try {
642
+ const parsed = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
643
+ enabledMap = parsed.enabledPlugins ?? {};
644
+ }
645
+ catch { /* ignore parse errors */ }
646
+ }
647
+ }
648
+ for (const m of marketplaces) {
649
+ let pluginCount = 0;
650
+ try {
651
+ for (const entry of fs.readdirSync(m.pluginsRoot, { withFileTypes: true })) {
652
+ if (entry.name.startsWith('.'))
653
+ continue;
654
+ const root = path.join(m.pluginsRoot, entry.name);
655
+ const manifestFile = path.join(root, '.claude-plugin', 'plugin.json');
656
+ if (fs.existsSync(manifestFile))
657
+ pluginCount++;
658
+ }
659
+ }
660
+ catch { /* ignore unreadable dir */ }
661
+ const suffix = `@${m.name}`;
662
+ const enabled = Object.entries(enabledMap)
663
+ .filter(([key, val]) => val === true && key.endsWith(suffix))
664
+ .length;
665
+ rows.push({ name: m.name, source: m.pluginsRoot, plugins: pluginCount, enabled });
666
+ }
667
+ return rows;
668
+ }
581
669
  /** Convert discovered plugins into rows suitable for the resource list view. */
582
670
  function buildPluginRows(plugins) {
583
671
  const rows = [];
584
672
  // Cache version lists per agent once.
585
673
  const versionsByAgent = new Map();
586
674
  const defaultsByAgent = new Map();
587
- for (const agent of PLUGINS_CAPABLE_AGENTS) {
675
+ for (const agent of capableAgents('plugins')) {
588
676
  versionsByAgent.set(agent, listInstalledVersions(agent));
589
677
  defaultsByAgent.set(agent, getGlobalDefault(agent));
590
678
  }
591
679
  for (const plugin of plugins) {
592
680
  const targets = [];
593
- for (const agent of PLUGINS_CAPABLE_AGENTS) {
681
+ for (const agent of capableAgents('plugins')) {
594
682
  if (!pluginSupportsAgent(plugin, agent))
595
683
  continue;
596
684
  for (const version of versionsByAgent.get(agent) || []) {
@@ -608,6 +696,7 @@ function buildPluginRows(plugins) {
608
696
  name: plugin.name,
609
697
  description: plugin.manifest.description,
610
698
  extra: plugin.manifest.version ? `v${plugin.manifest.version}` : '-',
699
+ extra2: plugin.marketplace ?? '-',
611
700
  targets,
612
701
  buildDetail: () => formatPluginDetail(plugin, targets),
613
702
  });
@@ -631,7 +720,7 @@ function formatPluginDetail(plugin, targets) {
631
720
  if (plugin.manifest.description) {
632
721
  lines.push(chalk.gray(plugin.manifest.description));
633
722
  }
634
- const supported = PLUGINS_CAPABLE_AGENTS
723
+ const supported = capableAgents('plugins')
635
724
  .filter((a) => pluginSupportsAgent(plugin, a))
636
725
  .map((a) => agentLabel(a));
637
726
  if (supported.length > 0) {
@@ -48,8 +48,9 @@ function collectOrphans(types, all) {
48
48
  if (types.includes('commands')) {
49
49
  for (const { agent, version } of scopePairs(iterCommandsCapableVersions(), all)) {
50
50
  const diff = diffVersionCommands(agent, version);
51
- if (diff.orphans.length > 0) {
52
- groups.push({ type: 'commands', agent, version, orphans: diff.orphans });
51
+ const removable = [...diff.orphans, ...diff.toRemove];
52
+ if (removable.length > 0) {
53
+ groups.push({ type: 'commands', agent, version, orphans: removable });
53
54
  }
54
55
  }
55
56
  }
@@ -1,10 +1,17 @@
1
1
  /**
2
- * Config pull command.
2
+ * Removed `agents pull` command.
3
3
  *
4
- * Registers the `agents pull` command which clones or updates the
5
- * system ~/.agents-system/ git repo and syncs CLI versions, MCP servers,
6
- * resources, and hooks to installed agent versions.
4
+ * `agents pull` was a god-command bundling git fetch+ff with local
5
+ * materialization (install CLIs, register MCP, sync resources, register hooks,
6
+ * etc.). It is replaced by the explicit split:
7
+ *
8
+ * - `agents repo pull <alias>` — git fetch+ff on system / user / extra
9
+ * - `agents repo refresh [agent]` — re-materialize installed version homes
10
+ * - `agents setup` — first-time bootstrap
11
+ *
12
+ * The command is kept registered so old muscle-memory invocations get a clear
13
+ * redirect instead of an "unknown command" error.
7
14
  */
8
15
  import type { Command } from 'commander';
9
- /** Register the `agents pull` command. */
16
+ /** Register the deprecated `agents pull` command as a hard-error redirect. */
10
17
  export declare function registerPullCommand(program: Command): void;