agent-switchboard 0.2.2 → 0.3.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 (107) hide show
  1. package/README.md +68 -42
  2. package/dist/agents/registry.d.ts +0 -6
  3. package/dist/agents/registry.js +3 -13
  4. package/dist/agents/registry.js.map +1 -1
  5. package/dist/agents/trae.d.ts +16 -0
  6. package/dist/agents/trae.js +36 -0
  7. package/dist/agents/trae.js.map +1 -0
  8. package/dist/commands/distribution.d.ts +3 -4
  9. package/dist/commands/distribution.js +18 -116
  10. package/dist/commands/distribution.js.map +1 -1
  11. package/dist/config/application-config.d.ts +1 -1
  12. package/dist/config/application-config.js +2 -10
  13. package/dist/config/application-config.js.map +1 -1
  14. package/dist/config/mcp-config.js +1 -3
  15. package/dist/config/mcp-config.js.map +1 -1
  16. package/dist/config/paths.d.ts +24 -3
  17. package/dist/config/paths.js +63 -5
  18. package/dist/config/paths.js.map +1 -1
  19. package/dist/config/schemas.d.ts +331 -43
  20. package/dist/config/schemas.js +109 -15
  21. package/dist/config/schemas.js.map +1 -1
  22. package/dist/config/switchboard-config.js +0 -1
  23. package/dist/config/switchboard-config.js.map +1 -1
  24. package/dist/extensions/api.d.ts +49 -0
  25. package/dist/extensions/api.js +41 -0
  26. package/dist/extensions/api.js.map +1 -0
  27. package/dist/extensions/loader.d.ts +17 -0
  28. package/dist/extensions/loader.js +73 -0
  29. package/dist/extensions/loader.js.map +1 -0
  30. package/dist/hooks/distribution.js +1 -16
  31. package/dist/hooks/distribution.js.map +1 -1
  32. package/dist/index.js +59 -113
  33. package/dist/index.js.map +1 -1
  34. package/dist/library/distribute-bundle.js +1 -19
  35. package/dist/library/distribute-bundle.js.map +1 -1
  36. package/dist/library/fs.d.ts +12 -0
  37. package/dist/library/fs.js +81 -0
  38. package/dist/library/fs.js.map +1 -1
  39. package/dist/library/sources.d.ts +6 -1
  40. package/dist/library/sources.js +73 -16
  41. package/dist/library/sources.js.map +1 -1
  42. package/dist/rules/agents.d.ts +0 -4
  43. package/dist/rules/agents.js +0 -8
  44. package/dist/rules/agents.js.map +1 -1
  45. package/dist/rules/distribution.d.ts +1 -2
  46. package/dist/rules/distribution.js +20 -71
  47. package/dist/rules/distribution.js.map +1 -1
  48. package/dist/skills/distribution.d.ts +0 -22
  49. package/dist/skills/distribution.js +84 -157
  50. package/dist/skills/distribution.js.map +1 -1
  51. package/dist/skills/importer.js +2 -33
  52. package/dist/skills/importer.js.map +1 -1
  53. package/dist/subagents/codex-distribute.d.ts +13 -0
  54. package/dist/subagents/codex-distribute.js +273 -0
  55. package/dist/subagents/codex-distribute.js.map +1 -0
  56. package/dist/subagents/distribution.d.ts +3 -4
  57. package/dist/subagents/distribution.js +30 -410
  58. package/dist/subagents/distribution.js.map +1 -1
  59. package/dist/targets/builtin/claude-code.d.ts +2 -0
  60. package/dist/targets/builtin/claude-code.js +73 -0
  61. package/dist/targets/builtin/claude-code.js.map +1 -0
  62. package/dist/targets/builtin/claude-desktop.d.ts +2 -0
  63. package/dist/targets/builtin/claude-desktop.js +10 -0
  64. package/dist/targets/builtin/claude-desktop.js.map +1 -0
  65. package/dist/targets/builtin/codex.d.ts +3 -0
  66. package/dist/targets/builtin/codex.js +57 -0
  67. package/dist/targets/builtin/codex.js.map +1 -0
  68. package/dist/targets/builtin/common.d.ts +22 -0
  69. package/dist/targets/builtin/common.js +55 -0
  70. package/dist/targets/builtin/common.js.map +1 -0
  71. package/dist/targets/builtin/cursor.d.ts +2 -0
  72. package/dist/targets/builtin/cursor.js +95 -0
  73. package/dist/targets/builtin/cursor.js.map +1 -0
  74. package/dist/targets/builtin/gemini.d.ts +2 -0
  75. package/dist/targets/builtin/gemini.js +62 -0
  76. package/dist/targets/builtin/gemini.js.map +1 -0
  77. package/dist/targets/builtin/index.d.ts +10 -0
  78. package/dist/targets/builtin/index.js +19 -0
  79. package/dist/targets/builtin/index.js.map +1 -0
  80. package/dist/targets/builtin/opencode.d.ts +2 -0
  81. package/dist/targets/builtin/opencode.js +67 -0
  82. package/dist/targets/builtin/opencode.js.map +1 -0
  83. package/dist/targets/builtin/trae.d.ts +3 -0
  84. package/dist/targets/builtin/trae.js +54 -0
  85. package/dist/targets/builtin/trae.js.map +1 -0
  86. package/dist/targets/dsl/compiler.d.ts +13 -0
  87. package/dist/targets/dsl/compiler.js +215 -0
  88. package/dist/targets/dsl/compiler.js.map +1 -0
  89. package/dist/targets/dsl/index.d.ts +2 -0
  90. package/dist/targets/dsl/index.js +3 -0
  91. package/dist/targets/dsl/index.js.map +1 -0
  92. package/dist/targets/dsl/transforms.d.ts +77 -0
  93. package/dist/targets/dsl/transforms.js +159 -0
  94. package/dist/targets/dsl/transforms.js.map +1 -0
  95. package/dist/targets/init.d.ts +14 -0
  96. package/dist/targets/init.js +28 -0
  97. package/dist/targets/init.js.map +1 -0
  98. package/dist/targets/registry.d.ts +36 -0
  99. package/dist/targets/registry.js +97 -0
  100. package/dist/targets/registry.js.map +1 -0
  101. package/dist/targets/types.d.ts +91 -0
  102. package/dist/targets/types.js +28 -0
  103. package/dist/targets/types.js.map +1 -0
  104. package/dist/ui/plugin-ui.d.ts +1 -1
  105. package/dist/ui/plugin-ui.js +5 -12
  106. package/dist/ui/plugin-ui.js.map +1 -1
  107. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -10,7 +10,6 @@ import { confirm } from '@inquirer/prompts';
10
10
  import chalk from 'chalk';
11
11
  import { Command } from 'commander';
12
12
  import ora from 'ora';
13
- import { getAgentById } from './agents/registry.js';
14
13
  import { distributeCommands } from './commands/distribution.js';
15
14
  import { importCommandFromFile } from './commands/importer.js';
16
15
  import { buildCommandInventory } from './commands/inventory.js';
@@ -21,12 +20,11 @@ import { getAgentsDir, getAgentsHome, getClaudeDir, getCodexDir, getCommandsDir,
21
20
  import { loadSwitchboardConfig, loadSwitchboardConfigWithLayers, } from './config/switchboard-config.js';
22
21
  import { distributeHooks } from './hooks/distribution.js';
23
22
  import { loadHookLibrary } from './hooks/library.js';
24
- import { ensureLibraryDirectories, writeFileSecure } from './library/fs.js';
23
+ import { copyDirRecursive, ensureLibraryDirectories, isDir, isFile, listFilesRecursively, writeFileSecure, } from './library/fs.js';
25
24
  import { addLocalSource, addRemoteSource, getSources, inferSourceName, isGitUrl, parseGitUrl, removeSource, updateRemoteSources, validateSourcePath, } from './library/sources.js';
26
25
  import { loadLibraryStateSection, loadMcpEnabledState, saveMcpEnabledState, } from './library/state.js';
27
26
  import { readMarketplace } from './marketplace/reader.js';
28
27
  import { buildPluginIndex } from './plugins/index.js';
29
- import { RULE_SUPPORTED_AGENTS } from './rules/agents.js';
30
28
  import { composeActiveRules } from './rules/composer.js';
31
29
  import { distributeRules, listIndirectAgents, listPerFileAgents, listUnsupportedAgents, } from './rules/distribution.js';
32
30
  import { buildRuleInventory } from './rules/inventory.js';
@@ -38,6 +36,8 @@ import { buildSkillInventory } from './skills/inventory.js';
38
36
  import { distributeSubagents } from './subagents/distribution.js';
39
37
  import { importSubagentFromFile } from './subagents/importer.js';
40
38
  import { buildSubagentInventory } from './subagents/inventory.js';
39
+ import { initTargets } from './targets/init.js';
40
+ import { getTargetById, getTargetsForSection } from './targets/registry.js';
41
41
  import { showCommandSelector } from './ui/command-ui.js';
42
42
  import { showHookSelector } from './ui/hook-ui.js';
43
43
  import { showMcpServerUI } from './ui/mcp-ui.js';
@@ -75,6 +75,7 @@ program
75
75
  const scope = resolveScope(options);
76
76
  const loadOptions = scopeToLoadOptions(scope);
77
77
  const { config, layers } = loadSwitchboardConfigWithLayers(loadOptions);
78
+ await initTargets(config);
78
79
  console.log(chalk.yellow('⚠ Sync overwrites agent config without diff.'));
79
80
  console.log();
80
81
  if (options.update !== false) {
@@ -110,17 +111,14 @@ program
110
111
  console.log(chalk.blue('Inventory:'));
111
112
  {
112
113
  const sections = ['mcp', 'rules', 'commands', 'agents', 'skills', 'hooks'];
113
- // Keep in sync with platform lists in each distribution module
114
- const sectionPlatforms = {
115
- mcp: ['claude-code', 'claude-desktop', 'codex', 'cursor', 'gemini', 'opencode'],
116
- rules: ['claude-code', 'codex', 'cursor', 'gemini', 'opencode'],
117
- commands: ['claude-code', 'codex', 'cursor', 'gemini', 'opencode'],
118
- agents: ['claude-code', 'opencode', 'cursor'],
119
- skills: cursorSkillsDeduped
120
- ? ['claude-code', 'codex', 'gemini', 'opencode']
121
- : ['claude-code', 'codex', 'gemini', 'opencode', 'cursor'],
122
- hooks: ['claude-code'],
123
- };
114
+ const sectionPlatforms = {};
115
+ for (const s of sections) {
116
+ let ids = getTargetsForSection(s).map((t) => t.id);
117
+ if (s === 'skills' && cursorSkillsDeduped) {
118
+ ids = ids.filter((id) => id !== 'cursor');
119
+ }
120
+ sectionPlatforms[s] = ids;
121
+ }
124
122
  const termWidth = process.stdout.columns || 80;
125
123
  const maxSectionLen = Math.max(...sections.map((s) => s.length));
126
124
  const maxCountLen = Math.max(...sections.map((s) => `(${config[s].enabled.length})`.length));
@@ -185,9 +183,7 @@ program
185
183
  // Show enabled plugins summary
186
184
  {
187
185
  const pluginIndex = buildPluginIndex();
188
- const enabledPluginRefs = Object.entries(config.plugins.enabled)
189
- .filter(([, v]) => v === true)
190
- .map(([k]) => k);
186
+ const enabledPluginRefs = config.plugins.enabled;
191
187
  if (enabledPluginRefs.length > 0) {
192
188
  const names = enabledPluginRefs
193
189
  .map((pid) => {
@@ -286,22 +282,6 @@ program
286
282
  process.exit(1);
287
283
  }
288
284
  });
289
- function isDir(p) {
290
- try {
291
- return fs.existsSync(p) && fs.statSync(p).isDirectory();
292
- }
293
- catch {
294
- return false;
295
- }
296
- }
297
- function isFile(p) {
298
- try {
299
- return fs.existsSync(p) && fs.statSync(p).isFile();
300
- }
301
- catch {
302
- return false;
303
- }
304
- }
305
285
  function resolveScope(input) {
306
286
  if (!input)
307
287
  return undefined;
@@ -368,26 +348,6 @@ function defaultSkillSourceDir(platform) {
368
348
  return path.join(getCursorDir(), 'skills');
369
349
  }
370
350
  }
371
- function listFilesRecursively(root, filterExts) {
372
- const out = [];
373
- const exts = new Set(filterExts.map((e) => e.toLowerCase()));
374
- const walk = (dir) => {
375
- const entries = fs.readdirSync(dir, { withFileTypes: true });
376
- for (const entry of entries) {
377
- const abs = path.join(dir, entry.name);
378
- if (entry.isDirectory()) {
379
- walk(abs);
380
- }
381
- else if (entry.isFile()) {
382
- const ext = path.extname(entry.name).toLowerCase();
383
- if (exts.has(ext))
384
- out.push(abs);
385
- }
386
- }
387
- };
388
- walk(root);
389
- return out;
390
- }
391
351
  async function confirmOverwrite(filePath, force) {
392
352
  if (!fs.existsSync(filePath))
393
353
  return true;
@@ -395,29 +355,6 @@ async function confirmOverwrite(filePath, force) {
395
355
  return true;
396
356
  return await confirm({ message: `File exists: ${filePath}. Overwrite?`, default: false });
397
357
  }
398
- function copyDirRecursive(src, dest) {
399
- fs.mkdirSync(dest, { recursive: true });
400
- const entries = fs.readdirSync(src, { withFileTypes: true });
401
- for (const entry of entries) {
402
- const srcPath = path.join(src, entry.name);
403
- const destPath = path.join(dest, entry.name);
404
- if (entry.isDirectory()) {
405
- copyDirRecursive(srcPath, destPath);
406
- }
407
- else {
408
- fs.copyFileSync(srcPath, destPath);
409
- // Preserve executable permissions
410
- try {
411
- const mode = fs.statSync(srcPath).mode;
412
- if (mode & 0o111)
413
- fs.chmodSync(destPath, mode & 0o777);
414
- }
415
- catch {
416
- // Ignore
417
- }
418
- }
419
- }
420
- }
421
358
  /**
422
359
  * Extract hooks from Claude Code's ~/.claude/settings.json and import as a
423
360
  * bundle into ~/.asb/hooks/. Copies referenced script files if they exist
@@ -653,7 +590,7 @@ ruleCommand
653
590
  console.log();
654
591
  printAgentSyncStatus({
655
592
  agentSync: inventory.state.agentSync,
656
- agents: RULE_SUPPORTED_AGENTS,
593
+ agents: getTargetsForSection('rules').map((t) => t.id),
657
594
  });
658
595
  const unsupportedAgents = listUnsupportedAgents();
659
596
  if (unsupportedAgents.length > 0) {
@@ -680,6 +617,7 @@ ruleCommand.action(async (options) => {
680
617
  try {
681
618
  const scope = resolveScope(options);
682
619
  const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
620
+ await initTargets(config);
683
621
  const selection = await showRuleSelector({ scope, pageSize: config.ui.page_size });
684
622
  if (!selection) {
685
623
  return;
@@ -768,6 +706,7 @@ commandRoot.action(async (options) => {
768
706
  try {
769
707
  const scope = resolveScope(options);
770
708
  const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
709
+ await initTargets(config);
771
710
  const selection = await showCommandSelector({ scope, pageSize: config.ui.page_size });
772
711
  if (!selection)
773
712
  return;
@@ -917,6 +856,7 @@ agentRoot.action(async (options) => {
917
856
  try {
918
857
  const scope = resolveScope(options);
919
858
  const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
859
+ await initTargets(config);
920
860
  const selection = await showSubagentSelector({ scope, pageSize: config.ui.page_size });
921
861
  if (!selection)
922
862
  return;
@@ -1064,6 +1004,7 @@ skillRoot.action(async (options) => {
1064
1004
  try {
1065
1005
  const scope = resolveScope(options);
1066
1006
  const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
1007
+ await initTargets(config);
1067
1008
  const selection = await showSkillSelector({ scope, pageSize: config.ui.page_size });
1068
1009
  if (!selection)
1069
1010
  return;
@@ -1365,6 +1306,7 @@ hookRoot
1365
1306
  async function applyToAgents(scope, enabledServerNames, options) {
1366
1307
  const mcpConfig = loadMcpConfigWithPlugins();
1367
1308
  const switchboardConfig = loadSwitchboardConfig(scopeToLoadOptions(scope));
1309
+ await initTargets(switchboardConfig);
1368
1310
  const useSpinner = options?.useSpinner ?? true;
1369
1311
  const results = [];
1370
1312
  if (switchboardConfig.applications.active.length === 0) {
@@ -1395,7 +1337,18 @@ async function applyToAgents(scope, enabledServerNames, options) {
1395
1337
  const activeSet = new Set(agentActiveServers);
1396
1338
  const enabledServers = Object.fromEntries(Object.entries(mcpConfig.mcpServers).filter(([name]) => activeSet.has(name)));
1397
1339
  const configToApply = { mcpServers: enabledServers };
1398
- const agent = getAgentById(agentId);
1340
+ const target = getTargetById(agentId);
1341
+ if (!target?.mcp) {
1342
+ persist(chalk.yellow('⚠'), `${chalk.cyan(agentId)} - no MCP handler (skipped)`);
1343
+ results.push({
1344
+ application: agentId,
1345
+ filePath: '(unknown)',
1346
+ status: 'skipped',
1347
+ reason: 'no MCP handler',
1348
+ });
1349
+ continue;
1350
+ }
1351
+ const mcpHandler = target.mcp;
1399
1352
  const readFileSafe = (p) => {
1400
1353
  try {
1401
1354
  return fs.readFileSync(p, 'utf-8');
@@ -1404,11 +1357,10 @@ async function applyToAgents(scope, enabledServerNames, options) {
1404
1357
  return null;
1405
1358
  }
1406
1359
  };
1407
- // Use project-level config when --project is specified
1408
- if (scope?.project && agent.applyProjectConfig) {
1409
- const projectPath = agent.projectConfigPath?.(scope.project) ?? 'project config';
1360
+ if (scope?.project && mcpHandler.applyProjectConfig) {
1361
+ const projectPath = mcpHandler.projectConfigPath?.(scope.project) ?? 'project config';
1410
1362
  const before = readFileSafe(projectPath);
1411
- agent.applyProjectConfig(scope.project, configToApply);
1363
+ mcpHandler.applyProjectConfig(scope.project, configToApply);
1412
1364
  const after = readFileSafe(projectPath);
1413
1365
  const changed = before !== after;
1414
1366
  persist(chalk.green('✓'), `${chalk.cyan(agentId)} ${chalk.dim(shortenPath(projectPath))}`);
@@ -1420,9 +1372,9 @@ async function applyToAgents(scope, enabledServerNames, options) {
1420
1372
  });
1421
1373
  }
1422
1374
  else {
1423
- const configPath = agent.configPath();
1375
+ const configPath = mcpHandler.configPath();
1424
1376
  const before = readFileSafe(configPath);
1425
- agent.applyConfig(configToApply);
1377
+ mcpHandler.applyConfig(configToApply);
1426
1378
  const after = readFileSafe(configPath);
1427
1379
  const changed = before !== after;
1428
1380
  persist(chalk.green('✓'), `${chalk.cyan(agentId)} ${chalk.dim(shortenPath(configPath))}`);
@@ -1518,21 +1470,22 @@ pluginRoot
1518
1470
  const index = buildPluginIndex();
1519
1471
  const scope = resolveScope(options);
1520
1472
  const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
1521
- const enabledMap = config.plugins.enabled;
1473
+ const enabledList = config.plugins.enabled;
1474
+ const enabledSet = new Set(enabledList);
1522
1475
  if (options.json) {
1523
1476
  console.log(JSON.stringify(index.plugins.map((p) => {
1524
1477
  const ref = p.meta.sourceKind === 'marketplace' ? `${p.id}@${p.meta.sourceName}` : p.id;
1525
1478
  return {
1526
1479
  id: p.id,
1527
1480
  ref,
1528
- enabled: enabledMap[ref] ?? null,
1481
+ enabled: enabledSet.has(ref),
1529
1482
  ...p.meta,
1530
1483
  components: Object.fromEntries(Object.entries(p.components).map(([k, v]) => [k, v.length])),
1531
1484
  };
1532
1485
  }), null, 2));
1533
1486
  return;
1534
1487
  }
1535
- printPluginList(index.plugins, enabledMap);
1488
+ printPluginList(index.plugins, enabledList);
1536
1489
  }
1537
1490
  catch (error) {
1538
1491
  if (error instanceof Error) {
@@ -1569,7 +1522,7 @@ function pluginEnableAction(id, options) {
1569
1522
  try {
1570
1523
  const scope = resolveScope(options);
1571
1524
  const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
1572
- if (config.plugins.enabled[id] === true) {
1525
+ if (config.plugins.enabled.includes(id)) {
1573
1526
  console.log(chalk.yellow(`⚠ Plugin "${id}" is already enabled.`));
1574
1527
  return;
1575
1528
  }
@@ -1583,7 +1536,7 @@ function pluginEnableAction(id, options) {
1583
1536
  ...layer,
1584
1537
  plugins: {
1585
1538
  ...(layer.plugins ?? {}),
1586
- enabled: { ...(layer.plugins?.enabled ?? {}), [id]: true },
1539
+ enabled: [...(layer.plugins?.enabled ?? []), id],
1587
1540
  },
1588
1541
  }), scopeToLoadOptions(scope));
1589
1542
  console.log(chalk.green(`✓ Plugin "${id}" enabled.`));
@@ -1599,19 +1552,15 @@ function pluginDisableAction(id, options) {
1599
1552
  try {
1600
1553
  const scope = resolveScope(options);
1601
1554
  const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
1602
- if (config.plugins.enabled[id] === undefined) {
1603
- console.log(chalk.yellow(`⚠ Plugin "${id}" is not installed.`));
1604
- return;
1605
- }
1606
- if (config.plugins.enabled[id] === false) {
1607
- console.log(chalk.yellow(`⚠ Plugin "${id}" is already disabled.`));
1555
+ if (!config.plugins.enabled.includes(id)) {
1556
+ console.log(chalk.yellow(`⚠ Plugin "${id}" is not enabled.`));
1608
1557
  return;
1609
1558
  }
1610
1559
  updateConfigLayer((layer) => ({
1611
1560
  ...layer,
1612
1561
  plugins: {
1613
1562
  ...(layer.plugins ?? {}),
1614
- enabled: { ...(layer.plugins?.enabled ?? {}), [id]: false },
1563
+ enabled: (layer.plugins?.enabled ?? []).filter((x) => x !== id),
1615
1564
  },
1616
1565
  }), scopeToLoadOptions(scope));
1617
1566
  console.log(chalk.green(`✓ Plugin "${id}" disabled.`));
@@ -1627,18 +1576,17 @@ function pluginUninstallAction(id, options) {
1627
1576
  try {
1628
1577
  const scope = resolveScope(options);
1629
1578
  const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
1630
- if (config.plugins.enabled[id] === undefined) {
1631
- console.log(chalk.yellow(`⚠ Plugin "${id}" is not installed.`));
1579
+ if (!config.plugins.enabled.includes(id)) {
1580
+ console.log(chalk.yellow(`⚠ Plugin "${id}" is not enabled.`));
1632
1581
  return;
1633
1582
  }
1634
- updateConfigLayer((layer) => {
1635
- const updated = { ...(layer.plugins?.enabled ?? {}) };
1636
- delete updated[id];
1637
- return {
1638
- ...layer,
1639
- plugins: { ...(layer.plugins ?? {}), enabled: updated },
1640
- };
1641
- }, scopeToLoadOptions(scope));
1583
+ updateConfigLayer((layer) => ({
1584
+ ...layer,
1585
+ plugins: {
1586
+ ...(layer.plugins ?? {}),
1587
+ enabled: (layer.plugins?.enabled ?? []).filter((x) => x !== id),
1588
+ },
1589
+ }), scopeToLoadOptions(scope));
1642
1590
  console.log(chalk.green(`✓ Plugin "${id}" uninstalled.`));
1643
1591
  }
1644
1592
  catch (error) {
@@ -1652,27 +1600,25 @@ const pluginScopeOpts = [
1652
1600
  ['-p, --profile <name>', 'Profile configuration to use'],
1653
1601
  ['--project <path>', 'Project directory containing .asb.toml'],
1654
1602
  ];
1655
- const enableCmd = pluginRoot
1656
- .command('enable <id>')
1657
- .description('Enable a plugin (set plugins.enabled to true)');
1603
+ const enableCmd = pluginRoot.command('enable <id>').description('Add a plugin to the enabled list');
1658
1604
  for (const [flag, desc] of pluginScopeOpts)
1659
1605
  enableCmd.option(flag, desc);
1660
1606
  enableCmd.action(pluginEnableAction);
1661
1607
  const installCmd = pluginRoot
1662
1608
  .command('install <id>')
1663
- .description('Enable a plugin (alias for enable)');
1609
+ .description('Add a plugin to the enabled list (alias for enable)');
1664
1610
  for (const [flag, desc] of pluginScopeOpts)
1665
1611
  installCmd.option(flag, desc);
1666
1612
  installCmd.action(pluginEnableAction);
1667
1613
  const disableCmd = pluginRoot
1668
1614
  .command('disable <id>')
1669
- .description('Disable a plugin (set plugins.enabled to false)');
1615
+ .description('Remove a plugin from the enabled list');
1670
1616
  for (const [flag, desc] of pluginScopeOpts)
1671
1617
  disableCmd.option(flag, desc);
1672
1618
  disableCmd.action(pluginDisableAction);
1673
1619
  const uninstallCmd = pluginRoot
1674
1620
  .command('uninstall <id>')
1675
- .description('Remove a plugin from plugins.enabled');
1621
+ .description('Remove a plugin from the enabled list (alias for disable)');
1676
1622
  for (const [flag, desc] of pluginScopeOpts)
1677
1623
  uninstallCmd.option(flag, desc);
1678
1624
  uninstallCmd.action(pluginUninstallAction);
@@ -1906,7 +1852,7 @@ program
1906
1852
  .action(() => {
1907
1853
  console.error(chalk.red('✗ `asb source` has been removed.\n' +
1908
1854
  ' Sources are now managed under `asb plugin marketplace`.\n' +
1909
- ' Config has moved from [library.sources] to [plugins.sources].\n' +
1855
+ ' Config has moved from [library.sources] to [plugins].\n' +
1910
1856
  ' Run `asb plugin marketplace --help` for usage.'));
1911
1857
  process.exit(1);
1912
1858
  });