agent-switchboard 0.2.3 → 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 (104) hide show
  1. package/README.md +29 -28
  2. package/dist/agents/registry.d.ts +0 -6
  3. package/dist/agents/registry.js +0 -13
  4. package/dist/agents/registry.js.map +1 -1
  5. package/dist/commands/distribution.d.ts +3 -4
  6. package/dist/commands/distribution.js +18 -116
  7. package/dist/commands/distribution.js.map +1 -1
  8. package/dist/config/application-config.d.ts +1 -1
  9. package/dist/config/application-config.js +2 -10
  10. package/dist/config/application-config.js.map +1 -1
  11. package/dist/config/mcp-config.js +1 -3
  12. package/dist/config/mcp-config.js.map +1 -1
  13. package/dist/config/paths.d.ts +9 -3
  14. package/dist/config/paths.js +24 -5
  15. package/dist/config/paths.js.map +1 -1
  16. package/dist/config/schemas.d.ts +331 -43
  17. package/dist/config/schemas.js +109 -15
  18. package/dist/config/schemas.js.map +1 -1
  19. package/dist/config/switchboard-config.js +0 -1
  20. package/dist/config/switchboard-config.js.map +1 -1
  21. package/dist/extensions/api.d.ts +49 -0
  22. package/dist/extensions/api.js +41 -0
  23. package/dist/extensions/api.js.map +1 -0
  24. package/dist/extensions/loader.d.ts +17 -0
  25. package/dist/extensions/loader.js +73 -0
  26. package/dist/extensions/loader.js.map +1 -0
  27. package/dist/hooks/distribution.js +1 -16
  28. package/dist/hooks/distribution.js.map +1 -1
  29. package/dist/index.js +59 -122
  30. package/dist/index.js.map +1 -1
  31. package/dist/library/distribute-bundle.js +1 -19
  32. package/dist/library/distribute-bundle.js.map +1 -1
  33. package/dist/library/fs.d.ts +12 -0
  34. package/dist/library/fs.js +81 -0
  35. package/dist/library/fs.js.map +1 -1
  36. package/dist/library/sources.d.ts +6 -1
  37. package/dist/library/sources.js +73 -16
  38. package/dist/library/sources.js.map +1 -1
  39. package/dist/rules/agents.d.ts +0 -4
  40. package/dist/rules/agents.js +0 -10
  41. package/dist/rules/agents.js.map +1 -1
  42. package/dist/rules/distribution.d.ts +1 -2
  43. package/dist/rules/distribution.js +20 -79
  44. package/dist/rules/distribution.js.map +1 -1
  45. package/dist/skills/distribution.d.ts +0 -22
  46. package/dist/skills/distribution.js +70 -185
  47. package/dist/skills/distribution.js.map +1 -1
  48. package/dist/skills/importer.js +2 -33
  49. package/dist/skills/importer.js.map +1 -1
  50. package/dist/subagents/codex-distribute.d.ts +13 -0
  51. package/dist/subagents/codex-distribute.js +273 -0
  52. package/dist/subagents/codex-distribute.js.map +1 -0
  53. package/dist/subagents/distribution.d.ts +3 -4
  54. package/dist/subagents/distribution.js +30 -410
  55. package/dist/subagents/distribution.js.map +1 -1
  56. package/dist/targets/builtin/claude-code.d.ts +2 -0
  57. package/dist/targets/builtin/claude-code.js +73 -0
  58. package/dist/targets/builtin/claude-code.js.map +1 -0
  59. package/dist/targets/builtin/claude-desktop.d.ts +2 -0
  60. package/dist/targets/builtin/claude-desktop.js +10 -0
  61. package/dist/targets/builtin/claude-desktop.js.map +1 -0
  62. package/dist/targets/builtin/codex.d.ts +3 -0
  63. package/dist/targets/builtin/codex.js +57 -0
  64. package/dist/targets/builtin/codex.js.map +1 -0
  65. package/dist/targets/builtin/common.d.ts +22 -0
  66. package/dist/targets/builtin/common.js +55 -0
  67. package/dist/targets/builtin/common.js.map +1 -0
  68. package/dist/targets/builtin/cursor.d.ts +2 -0
  69. package/dist/targets/builtin/cursor.js +95 -0
  70. package/dist/targets/builtin/cursor.js.map +1 -0
  71. package/dist/targets/builtin/gemini.d.ts +2 -0
  72. package/dist/targets/builtin/gemini.js +62 -0
  73. package/dist/targets/builtin/gemini.js.map +1 -0
  74. package/dist/targets/builtin/index.d.ts +10 -0
  75. package/dist/targets/builtin/index.js +19 -0
  76. package/dist/targets/builtin/index.js.map +1 -0
  77. package/dist/targets/builtin/opencode.d.ts +2 -0
  78. package/dist/targets/builtin/opencode.js +67 -0
  79. package/dist/targets/builtin/opencode.js.map +1 -0
  80. package/dist/targets/builtin/trae.d.ts +3 -0
  81. package/dist/targets/builtin/trae.js +54 -0
  82. package/dist/targets/builtin/trae.js.map +1 -0
  83. package/dist/targets/dsl/compiler.d.ts +13 -0
  84. package/dist/targets/dsl/compiler.js +215 -0
  85. package/dist/targets/dsl/compiler.js.map +1 -0
  86. package/dist/targets/dsl/index.d.ts +2 -0
  87. package/dist/targets/dsl/index.js +3 -0
  88. package/dist/targets/dsl/index.js.map +1 -0
  89. package/dist/targets/dsl/transforms.d.ts +77 -0
  90. package/dist/targets/dsl/transforms.js +159 -0
  91. package/dist/targets/dsl/transforms.js.map +1 -0
  92. package/dist/targets/init.d.ts +14 -0
  93. package/dist/targets/init.js +28 -0
  94. package/dist/targets/init.js.map +1 -0
  95. package/dist/targets/registry.d.ts +36 -0
  96. package/dist/targets/registry.js +97 -0
  97. package/dist/targets/registry.js.map +1 -0
  98. package/dist/targets/types.d.ts +91 -0
  99. package/dist/targets/types.js +28 -0
  100. package/dist/targets/types.js.map +1 -0
  101. package/dist/ui/plugin-ui.d.ts +1 -1
  102. package/dist/ui/plugin-ui.js +5 -12
  103. package/dist/ui/plugin-ui.js.map +1 -1
  104. 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,26 +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: [
116
- 'claude-code',
117
- 'claude-desktop',
118
- 'codex',
119
- 'cursor',
120
- 'gemini',
121
- 'opencode',
122
- 'trae',
123
- 'trae-cn',
124
- ],
125
- rules: ['claude-code', 'codex', 'cursor', 'gemini', 'opencode', 'trae', 'trae-cn'],
126
- commands: ['claude-code', 'codex', 'cursor', 'gemini', 'opencode'],
127
- agents: ['claude-code', 'opencode', 'cursor'],
128
- skills: cursorSkillsDeduped
129
- ? ['claude-code', 'codex', 'gemini', 'opencode', 'trae', 'trae-cn']
130
- : ['claude-code', 'codex', 'gemini', 'opencode', 'cursor', 'trae', 'trae-cn'],
131
- hooks: ['claude-code'],
132
- };
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
+ }
133
122
  const termWidth = process.stdout.columns || 80;
134
123
  const maxSectionLen = Math.max(...sections.map((s) => s.length));
135
124
  const maxCountLen = Math.max(...sections.map((s) => `(${config[s].enabled.length})`.length));
@@ -194,9 +183,7 @@ program
194
183
  // Show enabled plugins summary
195
184
  {
196
185
  const pluginIndex = buildPluginIndex();
197
- const enabledPluginRefs = Object.entries(config.plugins.enabled)
198
- .filter(([, v]) => v === true)
199
- .map(([k]) => k);
186
+ const enabledPluginRefs = config.plugins.enabled;
200
187
  if (enabledPluginRefs.length > 0) {
201
188
  const names = enabledPluginRefs
202
189
  .map((pid) => {
@@ -295,22 +282,6 @@ program
295
282
  process.exit(1);
296
283
  }
297
284
  });
298
- function isDir(p) {
299
- try {
300
- return fs.existsSync(p) && fs.statSync(p).isDirectory();
301
- }
302
- catch {
303
- return false;
304
- }
305
- }
306
- function isFile(p) {
307
- try {
308
- return fs.existsSync(p) && fs.statSync(p).isFile();
309
- }
310
- catch {
311
- return false;
312
- }
313
- }
314
285
  function resolveScope(input) {
315
286
  if (!input)
316
287
  return undefined;
@@ -377,26 +348,6 @@ function defaultSkillSourceDir(platform) {
377
348
  return path.join(getCursorDir(), 'skills');
378
349
  }
379
350
  }
380
- function listFilesRecursively(root, filterExts) {
381
- const out = [];
382
- const exts = new Set(filterExts.map((e) => e.toLowerCase()));
383
- const walk = (dir) => {
384
- const entries = fs.readdirSync(dir, { withFileTypes: true });
385
- for (const entry of entries) {
386
- const abs = path.join(dir, entry.name);
387
- if (entry.isDirectory()) {
388
- walk(abs);
389
- }
390
- else if (entry.isFile()) {
391
- const ext = path.extname(entry.name).toLowerCase();
392
- if (exts.has(ext))
393
- out.push(abs);
394
- }
395
- }
396
- };
397
- walk(root);
398
- return out;
399
- }
400
351
  async function confirmOverwrite(filePath, force) {
401
352
  if (!fs.existsSync(filePath))
402
353
  return true;
@@ -404,29 +355,6 @@ async function confirmOverwrite(filePath, force) {
404
355
  return true;
405
356
  return await confirm({ message: `File exists: ${filePath}. Overwrite?`, default: false });
406
357
  }
407
- function copyDirRecursive(src, dest) {
408
- fs.mkdirSync(dest, { recursive: true });
409
- const entries = fs.readdirSync(src, { withFileTypes: true });
410
- for (const entry of entries) {
411
- const srcPath = path.join(src, entry.name);
412
- const destPath = path.join(dest, entry.name);
413
- if (entry.isDirectory()) {
414
- copyDirRecursive(srcPath, destPath);
415
- }
416
- else {
417
- fs.copyFileSync(srcPath, destPath);
418
- // Preserve executable permissions
419
- try {
420
- const mode = fs.statSync(srcPath).mode;
421
- if (mode & 0o111)
422
- fs.chmodSync(destPath, mode & 0o777);
423
- }
424
- catch {
425
- // Ignore
426
- }
427
- }
428
- }
429
- }
430
358
  /**
431
359
  * Extract hooks from Claude Code's ~/.claude/settings.json and import as a
432
360
  * bundle into ~/.asb/hooks/. Copies referenced script files if they exist
@@ -662,7 +590,7 @@ ruleCommand
662
590
  console.log();
663
591
  printAgentSyncStatus({
664
592
  agentSync: inventory.state.agentSync,
665
- agents: RULE_SUPPORTED_AGENTS,
593
+ agents: getTargetsForSection('rules').map((t) => t.id),
666
594
  });
667
595
  const unsupportedAgents = listUnsupportedAgents();
668
596
  if (unsupportedAgents.length > 0) {
@@ -689,6 +617,7 @@ ruleCommand.action(async (options) => {
689
617
  try {
690
618
  const scope = resolveScope(options);
691
619
  const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
620
+ await initTargets(config);
692
621
  const selection = await showRuleSelector({ scope, pageSize: config.ui.page_size });
693
622
  if (!selection) {
694
623
  return;
@@ -777,6 +706,7 @@ commandRoot.action(async (options) => {
777
706
  try {
778
707
  const scope = resolveScope(options);
779
708
  const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
709
+ await initTargets(config);
780
710
  const selection = await showCommandSelector({ scope, pageSize: config.ui.page_size });
781
711
  if (!selection)
782
712
  return;
@@ -926,6 +856,7 @@ agentRoot.action(async (options) => {
926
856
  try {
927
857
  const scope = resolveScope(options);
928
858
  const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
859
+ await initTargets(config);
929
860
  const selection = await showSubagentSelector({ scope, pageSize: config.ui.page_size });
930
861
  if (!selection)
931
862
  return;
@@ -1073,6 +1004,7 @@ skillRoot.action(async (options) => {
1073
1004
  try {
1074
1005
  const scope = resolveScope(options);
1075
1006
  const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
1007
+ await initTargets(config);
1076
1008
  const selection = await showSkillSelector({ scope, pageSize: config.ui.page_size });
1077
1009
  if (!selection)
1078
1010
  return;
@@ -1374,6 +1306,7 @@ hookRoot
1374
1306
  async function applyToAgents(scope, enabledServerNames, options) {
1375
1307
  const mcpConfig = loadMcpConfigWithPlugins();
1376
1308
  const switchboardConfig = loadSwitchboardConfig(scopeToLoadOptions(scope));
1309
+ await initTargets(switchboardConfig);
1377
1310
  const useSpinner = options?.useSpinner ?? true;
1378
1311
  const results = [];
1379
1312
  if (switchboardConfig.applications.active.length === 0) {
@@ -1404,7 +1337,18 @@ async function applyToAgents(scope, enabledServerNames, options) {
1404
1337
  const activeSet = new Set(agentActiveServers);
1405
1338
  const enabledServers = Object.fromEntries(Object.entries(mcpConfig.mcpServers).filter(([name]) => activeSet.has(name)));
1406
1339
  const configToApply = { mcpServers: enabledServers };
1407
- 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;
1408
1352
  const readFileSafe = (p) => {
1409
1353
  try {
1410
1354
  return fs.readFileSync(p, 'utf-8');
@@ -1413,11 +1357,10 @@ async function applyToAgents(scope, enabledServerNames, options) {
1413
1357
  return null;
1414
1358
  }
1415
1359
  };
1416
- // Use project-level config when --project is specified
1417
- if (scope?.project && agent.applyProjectConfig) {
1418
- const projectPath = agent.projectConfigPath?.(scope.project) ?? 'project config';
1360
+ if (scope?.project && mcpHandler.applyProjectConfig) {
1361
+ const projectPath = mcpHandler.projectConfigPath?.(scope.project) ?? 'project config';
1419
1362
  const before = readFileSafe(projectPath);
1420
- agent.applyProjectConfig(scope.project, configToApply);
1363
+ mcpHandler.applyProjectConfig(scope.project, configToApply);
1421
1364
  const after = readFileSafe(projectPath);
1422
1365
  const changed = before !== after;
1423
1366
  persist(chalk.green('✓'), `${chalk.cyan(agentId)} ${chalk.dim(shortenPath(projectPath))}`);
@@ -1429,9 +1372,9 @@ async function applyToAgents(scope, enabledServerNames, options) {
1429
1372
  });
1430
1373
  }
1431
1374
  else {
1432
- const configPath = agent.configPath();
1375
+ const configPath = mcpHandler.configPath();
1433
1376
  const before = readFileSafe(configPath);
1434
- agent.applyConfig(configToApply);
1377
+ mcpHandler.applyConfig(configToApply);
1435
1378
  const after = readFileSafe(configPath);
1436
1379
  const changed = before !== after;
1437
1380
  persist(chalk.green('✓'), `${chalk.cyan(agentId)} ${chalk.dim(shortenPath(configPath))}`);
@@ -1527,21 +1470,22 @@ pluginRoot
1527
1470
  const index = buildPluginIndex();
1528
1471
  const scope = resolveScope(options);
1529
1472
  const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
1530
- const enabledMap = config.plugins.enabled;
1473
+ const enabledList = config.plugins.enabled;
1474
+ const enabledSet = new Set(enabledList);
1531
1475
  if (options.json) {
1532
1476
  console.log(JSON.stringify(index.plugins.map((p) => {
1533
1477
  const ref = p.meta.sourceKind === 'marketplace' ? `${p.id}@${p.meta.sourceName}` : p.id;
1534
1478
  return {
1535
1479
  id: p.id,
1536
1480
  ref,
1537
- enabled: enabledMap[ref] ?? null,
1481
+ enabled: enabledSet.has(ref),
1538
1482
  ...p.meta,
1539
1483
  components: Object.fromEntries(Object.entries(p.components).map(([k, v]) => [k, v.length])),
1540
1484
  };
1541
1485
  }), null, 2));
1542
1486
  return;
1543
1487
  }
1544
- printPluginList(index.plugins, enabledMap);
1488
+ printPluginList(index.plugins, enabledList);
1545
1489
  }
1546
1490
  catch (error) {
1547
1491
  if (error instanceof Error) {
@@ -1578,7 +1522,7 @@ function pluginEnableAction(id, options) {
1578
1522
  try {
1579
1523
  const scope = resolveScope(options);
1580
1524
  const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
1581
- if (config.plugins.enabled[id] === true) {
1525
+ if (config.plugins.enabled.includes(id)) {
1582
1526
  console.log(chalk.yellow(`⚠ Plugin "${id}" is already enabled.`));
1583
1527
  return;
1584
1528
  }
@@ -1592,7 +1536,7 @@ function pluginEnableAction(id, options) {
1592
1536
  ...layer,
1593
1537
  plugins: {
1594
1538
  ...(layer.plugins ?? {}),
1595
- enabled: { ...(layer.plugins?.enabled ?? {}), [id]: true },
1539
+ enabled: [...(layer.plugins?.enabled ?? []), id],
1596
1540
  },
1597
1541
  }), scopeToLoadOptions(scope));
1598
1542
  console.log(chalk.green(`✓ Plugin "${id}" enabled.`));
@@ -1608,19 +1552,15 @@ function pluginDisableAction(id, options) {
1608
1552
  try {
1609
1553
  const scope = resolveScope(options);
1610
1554
  const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
1611
- if (config.plugins.enabled[id] === undefined) {
1612
- console.log(chalk.yellow(`⚠ Plugin "${id}" is not installed.`));
1613
- return;
1614
- }
1615
- if (config.plugins.enabled[id] === false) {
1616
- 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.`));
1617
1557
  return;
1618
1558
  }
1619
1559
  updateConfigLayer((layer) => ({
1620
1560
  ...layer,
1621
1561
  plugins: {
1622
1562
  ...(layer.plugins ?? {}),
1623
- enabled: { ...(layer.plugins?.enabled ?? {}), [id]: false },
1563
+ enabled: (layer.plugins?.enabled ?? []).filter((x) => x !== id),
1624
1564
  },
1625
1565
  }), scopeToLoadOptions(scope));
1626
1566
  console.log(chalk.green(`✓ Plugin "${id}" disabled.`));
@@ -1636,18 +1576,17 @@ function pluginUninstallAction(id, options) {
1636
1576
  try {
1637
1577
  const scope = resolveScope(options);
1638
1578
  const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
1639
- if (config.plugins.enabled[id] === undefined) {
1640
- 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.`));
1641
1581
  return;
1642
1582
  }
1643
- updateConfigLayer((layer) => {
1644
- const updated = { ...(layer.plugins?.enabled ?? {}) };
1645
- delete updated[id];
1646
- return {
1647
- ...layer,
1648
- plugins: { ...(layer.plugins ?? {}), enabled: updated },
1649
- };
1650
- }, 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));
1651
1590
  console.log(chalk.green(`✓ Plugin "${id}" uninstalled.`));
1652
1591
  }
1653
1592
  catch (error) {
@@ -1661,27 +1600,25 @@ const pluginScopeOpts = [
1661
1600
  ['-p, --profile <name>', 'Profile configuration to use'],
1662
1601
  ['--project <path>', 'Project directory containing .asb.toml'],
1663
1602
  ];
1664
- const enableCmd = pluginRoot
1665
- .command('enable <id>')
1666
- .description('Enable a plugin (set plugins.enabled to true)');
1603
+ const enableCmd = pluginRoot.command('enable <id>').description('Add a plugin to the enabled list');
1667
1604
  for (const [flag, desc] of pluginScopeOpts)
1668
1605
  enableCmd.option(flag, desc);
1669
1606
  enableCmd.action(pluginEnableAction);
1670
1607
  const installCmd = pluginRoot
1671
1608
  .command('install <id>')
1672
- .description('Enable a plugin (alias for enable)');
1609
+ .description('Add a plugin to the enabled list (alias for enable)');
1673
1610
  for (const [flag, desc] of pluginScopeOpts)
1674
1611
  installCmd.option(flag, desc);
1675
1612
  installCmd.action(pluginEnableAction);
1676
1613
  const disableCmd = pluginRoot
1677
1614
  .command('disable <id>')
1678
- .description('Disable a plugin (set plugins.enabled to false)');
1615
+ .description('Remove a plugin from the enabled list');
1679
1616
  for (const [flag, desc] of pluginScopeOpts)
1680
1617
  disableCmd.option(flag, desc);
1681
1618
  disableCmd.action(pluginDisableAction);
1682
1619
  const uninstallCmd = pluginRoot
1683
1620
  .command('uninstall <id>')
1684
- .description('Remove a plugin from plugins.enabled');
1621
+ .description('Remove a plugin from the enabled list (alias for disable)');
1685
1622
  for (const [flag, desc] of pluginScopeOpts)
1686
1623
  uninstallCmd.option(flag, desc);
1687
1624
  uninstallCmd.action(pluginUninstallAction);
@@ -1915,7 +1852,7 @@ program
1915
1852
  .action(() => {
1916
1853
  console.error(chalk.red('✗ `asb source` has been removed.\n' +
1917
1854
  ' Sources are now managed under `asb plugin marketplace`.\n' +
1918
- ' Config has moved from [library.sources] to [plugins.sources].\n' +
1855
+ ' Config has moved from [library.sources] to [plugins].\n' +
1919
1856
  ' Run `asb plugin marketplace --help` for usage.'));
1920
1857
  process.exit(1);
1921
1858
  });