@swarmify/agents-cli 1.5.7 → 1.5.8
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.
- package/dist/index.js +151 -61
- package/dist/index.js.map +1 -1
- package/dist/lib/agents.d.ts +12 -12
- package/dist/lib/agents.d.ts.map +1 -1
- package/dist/lib/agents.js +34 -36
- package/dist/lib/agents.js.map +1 -1
- package/dist/lib/commands.d.ts +5 -0
- package/dist/lib/commands.d.ts.map +1 -1
- package/dist/lib/commands.js +32 -0
- package/dist/lib/commands.js.map +1 -1
- package/dist/lib/hooks.d.ts +15 -0
- package/dist/lib/hooks.d.ts.map +1 -1
- package/dist/lib/hooks.js +66 -0
- package/dist/lib/hooks.js.map +1 -1
- package/dist/lib/skills.d.ts +5 -0
- package/dist/lib/skills.d.ts.map +1 -1
- package/dist/lib/skills.js +61 -0
- package/dist/lib/skills.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -21,9 +21,9 @@ import { readManifest, writeManifest, createDefaultManifest, MANIFEST_FILENAME,
|
|
|
21
21
|
import { readState, ensureAgentsDir, getRepoLocalPath, getScope, setScope, removeScope, getScopesByPriority, getScopePriority, } from './lib/state.js';
|
|
22
22
|
import { SCOPE_PRIORITIES, DEFAULT_SYSTEM_REPO } from './lib/types.js';
|
|
23
23
|
import { cloneRepo, parseSource } from './lib/git.js';
|
|
24
|
-
import { discoverCommands, resolveCommandSource, installCommand, uninstallCommand, listInstalledCommandsWithScope, promoteCommandToUser, commandExists, } from './lib/commands.js';
|
|
25
|
-
import { discoverHooksFromRepo, installHooks, listInstalledHooksWithScope, promoteHookToUser, removeHook, hookExists, } from './lib/hooks.js';
|
|
26
|
-
import { discoverSkillsFromRepo, installSkill, uninstallSkill, listInstalledSkillsWithScope, promoteSkillToUser, getSkillInfo, getSkillRules, skillExists, } from './lib/skills.js';
|
|
24
|
+
import { discoverCommands, resolveCommandSource, installCommand, uninstallCommand, listInstalledCommandsWithScope, promoteCommandToUser, commandExists, commandContentMatches, } from './lib/commands.js';
|
|
25
|
+
import { discoverHooksFromRepo, installHooks, listInstalledHooksWithScope, promoteHookToUser, removeHook, hookExists, hookContentMatches, getSourceHookEntry, } from './lib/hooks.js';
|
|
26
|
+
import { discoverSkillsFromRepo, installSkill, uninstallSkill, listInstalledSkillsWithScope, promoteSkillToUser, getSkillInfo, getSkillRules, skillExists, skillContentMatches, } from './lib/skills.js';
|
|
27
27
|
import { DEFAULT_REGISTRIES } from './lib/types.js';
|
|
28
28
|
import { search as searchRegistries, getRegistries, setRegistry, removeRegistry, resolvePackage, } from './lib/registry.js';
|
|
29
29
|
const program = new Command();
|
|
@@ -95,10 +95,12 @@ async function checkForUpdates() {
|
|
|
95
95
|
});
|
|
96
96
|
if (answer === 'now') {
|
|
97
97
|
// Run upgrade
|
|
98
|
-
const {
|
|
98
|
+
const { exec } = await import('child_process');
|
|
99
|
+
const { promisify } = await import('util');
|
|
100
|
+
const execAsync = promisify(exec);
|
|
99
101
|
const spinner = ora('Upgrading...').start();
|
|
100
102
|
try {
|
|
101
|
-
|
|
103
|
+
await execAsync('npm install -g @swarmify/agents-cli@latest');
|
|
102
104
|
spinner.succeed(`Upgraded to ${latestVersion}`);
|
|
103
105
|
await showWhatsNew(VERSION, latestVersion);
|
|
104
106
|
}
|
|
@@ -155,7 +157,7 @@ program
|
|
|
155
157
|
}
|
|
156
158
|
}
|
|
157
159
|
const cwd = process.cwd();
|
|
158
|
-
const cliStates = getAllCliStates();
|
|
160
|
+
const cliStates = await getAllCliStates();
|
|
159
161
|
const agentsToShow = filterAgentId ? [filterAgentId] : ALL_AGENT_IDS;
|
|
160
162
|
const skillAgentsToShow = filterAgentId
|
|
161
163
|
? SKILLS_CAPABLE_AGENTS.filter((id) => id === filterAgentId)
|
|
@@ -172,9 +174,8 @@ program
|
|
|
172
174
|
agent: AGENTS[agentId],
|
|
173
175
|
skills: listInstalledSkillsWithScope(agentId, cwd),
|
|
174
176
|
}));
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
.map((agentId) => ({
|
|
177
|
+
const installedMcpAgents = mcpAgentsToShow.filter((agentId) => cliStates[agentId]?.installed);
|
|
178
|
+
const mcpsData = installedMcpAgents.map((agentId) => ({
|
|
178
179
|
agent: AGENTS[agentId],
|
|
179
180
|
mcps: listInstalledMcpsWithScope(agentId, cwd),
|
|
180
181
|
}));
|
|
@@ -364,6 +365,7 @@ program
|
|
|
364
365
|
const allSkills = discoverSkillsFromRepo(localPath);
|
|
365
366
|
const discoveredHooks = discoverHooksFromRepo(localPath);
|
|
366
367
|
// Determine which agents to sync
|
|
368
|
+
const cliStates = await getAllCliStates();
|
|
367
369
|
let selectedAgents;
|
|
368
370
|
if (agentFilter) {
|
|
369
371
|
// Single agent filter
|
|
@@ -374,7 +376,7 @@ program
|
|
|
374
376
|
selectedAgents = (manifest?.defaults?.agents || ['claude', 'codex', 'gemini']);
|
|
375
377
|
}
|
|
376
378
|
else {
|
|
377
|
-
const installedAgents = ALL_AGENT_IDS.filter((id) =>
|
|
379
|
+
const installedAgents = ALL_AGENT_IDS.filter((id) => cliStates[id]?.installed || id === 'cursor');
|
|
378
380
|
selectedAgents = await checkbox({
|
|
379
381
|
message: 'Select agents to sync:',
|
|
380
382
|
choices: installedAgents.map((id) => ({
|
|
@@ -385,7 +387,7 @@ program
|
|
|
385
387
|
});
|
|
386
388
|
}
|
|
387
389
|
// Filter agents to only installed ones (plus cursor which doesn't need CLI)
|
|
388
|
-
selectedAgents = selectedAgents.filter((id) =>
|
|
390
|
+
selectedAgents = selectedAgents.filter((id) => cliStates[id]?.installed || id === 'cursor');
|
|
389
391
|
if (selectedAgents.length === 0) {
|
|
390
392
|
console.log(chalk.yellow('\nNo agents selected or installed. Nothing to sync.'));
|
|
391
393
|
return;
|
|
@@ -393,6 +395,7 @@ program
|
|
|
393
395
|
// Build resource items with conflict detection
|
|
394
396
|
const newItems = [];
|
|
395
397
|
const existingItems = [];
|
|
398
|
+
const upToDateItems = [];
|
|
396
399
|
// Process commands
|
|
397
400
|
for (const command of allCommands) {
|
|
398
401
|
const applicableAgents = selectedAgents.filter((agentId) => {
|
|
@@ -401,29 +404,55 @@ program
|
|
|
401
404
|
});
|
|
402
405
|
if (applicableAgents.length === 0)
|
|
403
406
|
continue;
|
|
404
|
-
const conflictingAgents = applicableAgents.filter((agentId) => commandExists(agentId, command.name));
|
|
405
407
|
const newAgents = applicableAgents.filter((agentId) => !commandExists(agentId, command.name));
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
408
|
+
const upToDateAgents = applicableAgents.filter((agentId) => {
|
|
409
|
+
if (!commandExists(agentId, command.name))
|
|
410
|
+
return false;
|
|
411
|
+
const sourcePath = resolveCommandSource(localPath, command.name, agentId);
|
|
412
|
+
return sourcePath && commandContentMatches(agentId, command.name, sourcePath);
|
|
413
|
+
});
|
|
414
|
+
const conflictingAgents = applicableAgents.filter((agentId) => {
|
|
415
|
+
if (!commandExists(agentId, command.name))
|
|
416
|
+
return false;
|
|
417
|
+
const sourcePath = resolveCommandSource(localPath, command.name, agentId);
|
|
418
|
+
return sourcePath && !commandContentMatches(agentId, command.name, sourcePath);
|
|
419
|
+
});
|
|
409
420
|
if (newAgents.length > 0) {
|
|
410
421
|
newItems.push({ type: 'command', name: command.name, agents: newAgents, isNew: true });
|
|
411
422
|
}
|
|
423
|
+
if (upToDateAgents.length > 0) {
|
|
424
|
+
upToDateItems.push({ type: 'command', name: command.name, agents: upToDateAgents, isNew: false });
|
|
425
|
+
}
|
|
426
|
+
if (conflictingAgents.length > 0) {
|
|
427
|
+
existingItems.push({ type: 'command', name: command.name, agents: conflictingAgents, isNew: false });
|
|
428
|
+
}
|
|
412
429
|
}
|
|
413
430
|
// Process skills
|
|
414
431
|
const skillAgents = SKILLS_CAPABLE_AGENTS.filter((id) => selectedAgents.includes(id));
|
|
415
432
|
for (const skill of allSkills) {
|
|
416
|
-
const conflictingAgents = skillAgents.filter((agentId) => skillExists(agentId, skill.name));
|
|
417
433
|
const newAgents = skillAgents.filter((agentId) => !skillExists(agentId, skill.name));
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
434
|
+
const upToDateAgents = skillAgents.filter((agentId) => {
|
|
435
|
+
if (!skillExists(agentId, skill.name))
|
|
436
|
+
return false;
|
|
437
|
+
return skillContentMatches(agentId, skill.name, skill.path);
|
|
438
|
+
});
|
|
439
|
+
const conflictingAgents = skillAgents.filter((agentId) => {
|
|
440
|
+
if (!skillExists(agentId, skill.name))
|
|
441
|
+
return false;
|
|
442
|
+
return !skillContentMatches(agentId, skill.name, skill.path);
|
|
443
|
+
});
|
|
421
444
|
if (newAgents.length > 0) {
|
|
422
445
|
newItems.push({ type: 'skill', name: skill.name, agents: newAgents, isNew: true });
|
|
423
446
|
}
|
|
447
|
+
if (upToDateAgents.length > 0) {
|
|
448
|
+
upToDateItems.push({ type: 'skill', name: skill.name, agents: upToDateAgents, isNew: false });
|
|
449
|
+
}
|
|
450
|
+
if (conflictingAgents.length > 0) {
|
|
451
|
+
existingItems.push({ type: 'skill', name: skill.name, agents: conflictingAgents, isNew: false });
|
|
452
|
+
}
|
|
424
453
|
}
|
|
425
454
|
// Process hooks
|
|
426
|
-
const hookAgents = selectedAgents.filter((id) => HOOKS_CAPABLE_AGENTS.includes(id) &&
|
|
455
|
+
const hookAgents = selectedAgents.filter((id) => HOOKS_CAPABLE_AGENTS.includes(id) && cliStates[id]?.installed);
|
|
427
456
|
const allHookNames = [
|
|
428
457
|
...discoveredHooks.shared,
|
|
429
458
|
...Object.entries(discoveredHooks.agentSpecific)
|
|
@@ -432,25 +461,43 @@ program
|
|
|
432
461
|
];
|
|
433
462
|
const uniqueHookNames = [...new Set(allHookNames)];
|
|
434
463
|
for (const hookName of uniqueHookNames) {
|
|
435
|
-
const conflictingAgents = hookAgents.filter((agentId) => hookExists(agentId, hookName));
|
|
436
464
|
const newAgents = hookAgents.filter((agentId) => !hookExists(agentId, hookName));
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
465
|
+
const upToDateAgents = hookAgents.filter((agentId) => {
|
|
466
|
+
if (!hookExists(agentId, hookName))
|
|
467
|
+
return false;
|
|
468
|
+
const sourceEntry = getSourceHookEntry(localPath, agentId, hookName);
|
|
469
|
+
return sourceEntry && hookContentMatches(agentId, hookName, sourceEntry);
|
|
470
|
+
});
|
|
471
|
+
const conflictingAgents = hookAgents.filter((agentId) => {
|
|
472
|
+
if (!hookExists(agentId, hookName))
|
|
473
|
+
return false;
|
|
474
|
+
const sourceEntry = getSourceHookEntry(localPath, agentId, hookName);
|
|
475
|
+
return !sourceEntry || !hookContentMatches(agentId, hookName, sourceEntry);
|
|
476
|
+
});
|
|
440
477
|
if (newAgents.length > 0) {
|
|
441
478
|
newItems.push({ type: 'hook', name: hookName, agents: newAgents, isNew: true });
|
|
442
479
|
}
|
|
480
|
+
if (upToDateAgents.length > 0) {
|
|
481
|
+
upToDateItems.push({ type: 'hook', name: hookName, agents: upToDateAgents, isNew: false });
|
|
482
|
+
}
|
|
483
|
+
if (conflictingAgents.length > 0) {
|
|
484
|
+
existingItems.push({ type: 'hook', name: hookName, agents: conflictingAgents, isNew: false });
|
|
485
|
+
}
|
|
443
486
|
}
|
|
444
|
-
// Process MCPs
|
|
487
|
+
// Process MCPs (no content comparison - just existence check)
|
|
445
488
|
if (!options.skipMcp && manifest?.mcp) {
|
|
446
489
|
for (const [name, config] of Object.entries(manifest.mcp)) {
|
|
447
490
|
if (config.transport === 'http' || !config.command)
|
|
448
491
|
continue;
|
|
449
|
-
const mcpAgents = config.agents.filter((agentId) => selectedAgents.includes(agentId) &&
|
|
492
|
+
const mcpAgents = config.agents.filter((agentId) => selectedAgents.includes(agentId) && cliStates[agentId]?.installed);
|
|
450
493
|
if (mcpAgents.length === 0)
|
|
451
494
|
continue;
|
|
452
|
-
const
|
|
453
|
-
|
|
495
|
+
const registrationChecks = await Promise.all(mcpAgents.map(async (agentId) => ({
|
|
496
|
+
agentId,
|
|
497
|
+
isRegistered: await isMcpRegistered(agentId, name),
|
|
498
|
+
})));
|
|
499
|
+
const conflictingAgents = registrationChecks.filter((r) => r.isRegistered).map((r) => r.agentId);
|
|
500
|
+
const newAgents = registrationChecks.filter((r) => !r.isRegistered).map((r) => r.agentId);
|
|
454
501
|
if (conflictingAgents.length > 0) {
|
|
455
502
|
existingItems.push({ type: 'mcp', name, agents: conflictingAgents, isNew: false });
|
|
456
503
|
}
|
|
@@ -493,6 +540,31 @@ program
|
|
|
493
540
|
}
|
|
494
541
|
console.log();
|
|
495
542
|
}
|
|
543
|
+
if (upToDateItems.length > 0) {
|
|
544
|
+
console.log(chalk.gray(' UP TO DATE (no changes):\n'));
|
|
545
|
+
const byType = { command: [], skill: [], hook: [], mcp: [] };
|
|
546
|
+
for (const item of upToDateItems)
|
|
547
|
+
byType[item.type].push(item);
|
|
548
|
+
if (byType.command.length > 0) {
|
|
549
|
+
console.log(` Commands:`);
|
|
550
|
+
for (const item of byType.command) {
|
|
551
|
+
console.log(` ${chalk.dim(item.name.padEnd(20))} ${chalk.dim(formatAgentList(item.agents))}`);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
if (byType.skill.length > 0) {
|
|
555
|
+
console.log(` Skills:`);
|
|
556
|
+
for (const item of byType.skill) {
|
|
557
|
+
console.log(` ${chalk.dim(item.name.padEnd(20))} ${chalk.dim(formatAgentList(item.agents))}`);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
if (byType.hook.length > 0) {
|
|
561
|
+
console.log(` Hooks:`);
|
|
562
|
+
for (const item of byType.hook) {
|
|
563
|
+
console.log(` ${chalk.dim(item.name.padEnd(20))} ${chalk.dim(formatAgentList(item.agents))}`);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
console.log();
|
|
567
|
+
}
|
|
496
568
|
if (existingItems.length > 0) {
|
|
497
569
|
console.log(chalk.yellow(' EXISTING (conflicts):\n'));
|
|
498
570
|
const byType = { command: [], skill: [], hook: [], mcp: [] };
|
|
@@ -525,7 +597,7 @@ program
|
|
|
525
597
|
console.log();
|
|
526
598
|
}
|
|
527
599
|
if (newItems.length === 0 && existingItems.length === 0) {
|
|
528
|
-
console.log(chalk.gray('
|
|
600
|
+
console.log(chalk.gray(' Already up to date.\n'));
|
|
529
601
|
return;
|
|
530
602
|
}
|
|
531
603
|
if (options.dryRun) {
|
|
@@ -670,9 +742,9 @@ program
|
|
|
670
742
|
continue;
|
|
671
743
|
for (const agentId of item.agents) {
|
|
672
744
|
if (!item.isNew) {
|
|
673
|
-
unregisterMcp(agentId, item.name);
|
|
745
|
+
await unregisterMcp(agentId, item.name);
|
|
674
746
|
}
|
|
675
|
-
const result = registerMcp(agentId, item.name, config.command, config.scope);
|
|
747
|
+
const result = await registerMcp(agentId, item.name, config.command, config.scope);
|
|
676
748
|
if (result.success)
|
|
677
749
|
installed.mcps++;
|
|
678
750
|
}
|
|
@@ -698,7 +770,7 @@ program
|
|
|
698
770
|
const agent = AGENTS[agentId];
|
|
699
771
|
if (!agent || !cliConfig.package)
|
|
700
772
|
continue;
|
|
701
|
-
const currentVersion = getCliVersion(agentId);
|
|
773
|
+
const currentVersion = await getCliVersion(agentId);
|
|
702
774
|
const targetVersion = cliConfig.version;
|
|
703
775
|
if (currentVersion === targetVersion)
|
|
704
776
|
continue;
|
|
@@ -765,7 +837,7 @@ program
|
|
|
765
837
|
const localPath = getRepoLocalPath(scope.source);
|
|
766
838
|
const manifest = readManifest(localPath) || createDefaultManifest();
|
|
767
839
|
console.log(chalk.bold('\nExporting local configuration...\n'));
|
|
768
|
-
const cliStates = getAllCliStates();
|
|
840
|
+
const cliStates = await getAllCliStates();
|
|
769
841
|
let exported = 0;
|
|
770
842
|
for (const agentId of ALL_AGENT_IDS) {
|
|
771
843
|
const agent = AGENTS[agentId];
|
|
@@ -872,10 +944,11 @@ commandsCmd
|
|
|
872
944
|
const agents = options.agents
|
|
873
945
|
? options.agents.split(',')
|
|
874
946
|
: ['claude', 'codex', 'gemini'];
|
|
947
|
+
const cliStates = await getAllCliStates();
|
|
875
948
|
for (const command of commands) {
|
|
876
949
|
console.log(`\n ${chalk.cyan(command.name)}: ${command.description}`);
|
|
877
950
|
for (const agentId of agents) {
|
|
878
|
-
if (!
|
|
951
|
+
if (!cliStates[agentId]?.installed && agentId !== 'cursor')
|
|
879
952
|
continue;
|
|
880
953
|
const sourcePath = resolveCommandSource(localPath, command.name, agentId);
|
|
881
954
|
if (sourcePath) {
|
|
@@ -918,14 +991,15 @@ commandsCmd
|
|
|
918
991
|
.command('push <name>')
|
|
919
992
|
.description('Save project-scoped command to user scope')
|
|
920
993
|
.option('-a, --agents <list>', 'Comma-separated agents to push for')
|
|
921
|
-
.action((name, options) => {
|
|
994
|
+
.action(async (name, options) => {
|
|
922
995
|
const cwd = process.cwd();
|
|
923
996
|
const agents = options.agents
|
|
924
997
|
? options.agents.split(',')
|
|
925
998
|
: ALL_AGENT_IDS;
|
|
999
|
+
const cliStates = await getAllCliStates();
|
|
926
1000
|
let pushed = 0;
|
|
927
1001
|
for (const agentId of agents) {
|
|
928
|
-
if (!
|
|
1002
|
+
if (!cliStates[agentId]?.installed && agentId !== 'cursor')
|
|
929
1003
|
continue;
|
|
930
1004
|
const result = promoteCommandToUser(agentId, name, cwd);
|
|
931
1005
|
if (result.success) {
|
|
@@ -1185,11 +1259,12 @@ skillsCmd
|
|
|
1185
1259
|
console.log(` ${chalk.gray(`${skill.ruleCount} rules`)}`);
|
|
1186
1260
|
}
|
|
1187
1261
|
}
|
|
1262
|
+
const cliStates = await getAllCliStates();
|
|
1188
1263
|
const agents = options.agents
|
|
1189
1264
|
? options.agents.split(',')
|
|
1190
1265
|
: await checkbox({
|
|
1191
1266
|
message: 'Select agents to install skills to:',
|
|
1192
|
-
choices: SKILLS_CAPABLE_AGENTS.filter((id) =>
|
|
1267
|
+
choices: SKILLS_CAPABLE_AGENTS.filter((id) => cliStates[id]?.installed || id === 'cursor').map((id) => ({
|
|
1193
1268
|
name: AGENTS[id].name,
|
|
1194
1269
|
value: id,
|
|
1195
1270
|
checked: ['claude', 'codex', 'gemini'].includes(id),
|
|
@@ -1368,12 +1443,14 @@ mcpCmd
|
|
|
1368
1443
|
const agents = options.agent
|
|
1369
1444
|
? [options.agent]
|
|
1370
1445
|
: MCP_CAPABLE_AGENTS;
|
|
1446
|
+
// Collect all data while spinner is active
|
|
1447
|
+
const cliStates = await getAllCliStates();
|
|
1371
1448
|
const agentMcps = agents.map((agentId) => {
|
|
1372
1449
|
const agent = AGENTS[agentId];
|
|
1373
1450
|
if (!agent.capabilities.mcp) {
|
|
1374
1451
|
return { agent, mcps: null };
|
|
1375
1452
|
}
|
|
1376
|
-
if (!
|
|
1453
|
+
if (!cliStates[agentId]?.installed) {
|
|
1377
1454
|
return { agent, mcps: null, notInstalled: true };
|
|
1378
1455
|
}
|
|
1379
1456
|
return {
|
|
@@ -1474,15 +1551,16 @@ mcpCmd
|
|
|
1474
1551
|
.command('remove <name>')
|
|
1475
1552
|
.description('Remove MCP server from agents')
|
|
1476
1553
|
.option('-a, --agents <list>', 'Comma-separated agents')
|
|
1477
|
-
.action((name, options) => {
|
|
1554
|
+
.action(async (name, options) => {
|
|
1478
1555
|
const agents = options.agents
|
|
1479
1556
|
? options.agents.split(',')
|
|
1480
1557
|
: MCP_CAPABLE_AGENTS;
|
|
1558
|
+
const cliStates = await getAllCliStates();
|
|
1481
1559
|
let removed = 0;
|
|
1482
1560
|
for (const agentId of agents) {
|
|
1483
|
-
if (!
|
|
1561
|
+
if (!cliStates[agentId]?.installed)
|
|
1484
1562
|
continue;
|
|
1485
|
-
const result = unregisterMcp(agentId, name);
|
|
1563
|
+
const result = await unregisterMcp(agentId, name);
|
|
1486
1564
|
if (result.success) {
|
|
1487
1565
|
console.log(` ${chalk.red('-')} ${AGENTS[agentId].name}`);
|
|
1488
1566
|
removed++;
|
|
@@ -1508,6 +1586,7 @@ mcpCmd
|
|
|
1508
1586
|
console.log(chalk.yellow('No MCP servers in manifest'));
|
|
1509
1587
|
return;
|
|
1510
1588
|
}
|
|
1589
|
+
const cliStates = await getAllCliStates();
|
|
1511
1590
|
for (const [mcpName, config] of Object.entries(manifest.mcp)) {
|
|
1512
1591
|
// Skip HTTP transport MCPs for now (need different registration)
|
|
1513
1592
|
if (config.transport === 'http' || !config.command) {
|
|
@@ -1516,9 +1595,9 @@ mcpCmd
|
|
|
1516
1595
|
}
|
|
1517
1596
|
console.log(`\n ${chalk.cyan(mcpName)}:`);
|
|
1518
1597
|
for (const agentId of config.agents) {
|
|
1519
|
-
if (!
|
|
1598
|
+
if (!cliStates[agentId]?.installed)
|
|
1520
1599
|
continue;
|
|
1521
|
-
const result = registerMcp(agentId, mcpName, config.command, config.scope);
|
|
1600
|
+
const result = await registerMcp(agentId, mcpName, config.command, config.scope);
|
|
1522
1601
|
if (result.success) {
|
|
1523
1602
|
console.log(` ${chalk.green('+')} ${AGENTS[agentId].name}`);
|
|
1524
1603
|
}
|
|
@@ -1535,16 +1614,17 @@ mcpCmd
|
|
|
1535
1614
|
.command('push <name>')
|
|
1536
1615
|
.description('Save project-scoped MCP to user scope')
|
|
1537
1616
|
.option('-a, --agents <list>', 'Comma-separated agents to push for')
|
|
1538
|
-
.action((name, options) => {
|
|
1617
|
+
.action(async (name, options) => {
|
|
1539
1618
|
const cwd = process.cwd();
|
|
1540
1619
|
const agents = options.agents
|
|
1541
1620
|
? options.agents.split(',')
|
|
1542
1621
|
: MCP_CAPABLE_AGENTS;
|
|
1622
|
+
const cliStates = await getAllCliStates();
|
|
1543
1623
|
let pushed = 0;
|
|
1544
1624
|
for (const agentId of agents) {
|
|
1545
|
-
if (!
|
|
1625
|
+
if (!cliStates[agentId]?.installed)
|
|
1546
1626
|
continue;
|
|
1547
|
-
const result = promoteMcpToUser(agentId, name, cwd);
|
|
1627
|
+
const result = await promoteMcpToUser(agentId, name, cwd);
|
|
1548
1628
|
if (result.success) {
|
|
1549
1629
|
console.log(` ${chalk.green('+')} ${AGENTS[agentId].name}`);
|
|
1550
1630
|
pushed++;
|
|
@@ -1571,7 +1651,7 @@ cliCmd
|
|
|
1571
1651
|
.description('List installed agent CLIs')
|
|
1572
1652
|
.action(async () => {
|
|
1573
1653
|
const spinner = ora('Checking installed CLIs...').start();
|
|
1574
|
-
const states = getAllCliStates();
|
|
1654
|
+
const states = await getAllCliStates();
|
|
1575
1655
|
spinner.stop();
|
|
1576
1656
|
console.log(chalk.bold('Agent CLIs\n'));
|
|
1577
1657
|
for (const agentId of ALL_AGENT_IDS) {
|
|
@@ -1609,10 +1689,12 @@ cliCmd
|
|
|
1609
1689
|
console.log(chalk.yellow(`${agentConfig.name} has no npm package. Install manually.`));
|
|
1610
1690
|
}
|
|
1611
1691
|
else {
|
|
1612
|
-
const {
|
|
1692
|
+
const { exec } = await import('child_process');
|
|
1693
|
+
const { promisify } = await import('util');
|
|
1694
|
+
const execAsync = promisify(exec);
|
|
1613
1695
|
const spinner = ora(`Installing ${agentConfig.name}@${version}...`).start();
|
|
1614
1696
|
try {
|
|
1615
|
-
|
|
1697
|
+
await execAsync(`npm install -g ${pkg}@${version}`);
|
|
1616
1698
|
spinner.succeed(`Installed ${agentConfig.name}@${version}`);
|
|
1617
1699
|
}
|
|
1618
1700
|
catch (err) {
|
|
@@ -1652,14 +1734,16 @@ cliCmd
|
|
|
1652
1734
|
if (!pkg) {
|
|
1653
1735
|
console.log(chalk.yellow(`${agentConfig.name} has no npm package.`));
|
|
1654
1736
|
}
|
|
1655
|
-
else if (!isCliInstalled(agentId)) {
|
|
1737
|
+
else if (!(await isCliInstalled(agentId))) {
|
|
1656
1738
|
console.log(chalk.gray(`${agentConfig.name} is not installed`));
|
|
1657
1739
|
}
|
|
1658
1740
|
else {
|
|
1659
|
-
const {
|
|
1741
|
+
const { exec } = await import('child_process');
|
|
1742
|
+
const { promisify } = await import('util');
|
|
1743
|
+
const execAsync = promisify(exec);
|
|
1660
1744
|
const spinner = ora(`Uninstalling ${agentConfig.name}...`).start();
|
|
1661
1745
|
try {
|
|
1662
|
-
|
|
1746
|
+
await execAsync(`npm uninstall -g ${pkg}`);
|
|
1663
1747
|
spinner.succeed(`Uninstalled ${agentConfig.name}`);
|
|
1664
1748
|
}
|
|
1665
1749
|
catch (err) {
|
|
@@ -1695,7 +1779,9 @@ cliCmd
|
|
|
1695
1779
|
console.log(chalk.yellow('No CLIs to upgrade. Add CLIs to manifest or use --latest'));
|
|
1696
1780
|
return;
|
|
1697
1781
|
}
|
|
1698
|
-
const {
|
|
1782
|
+
const { exec } = await import('child_process');
|
|
1783
|
+
const { promisify } = await import('util');
|
|
1784
|
+
const execAsync = promisify(exec);
|
|
1699
1785
|
for (const agentId of agentsToUpgrade) {
|
|
1700
1786
|
const agentConfig = AGENTS[agentId];
|
|
1701
1787
|
if (!agentConfig) {
|
|
@@ -1707,7 +1793,7 @@ cliCmd
|
|
|
1707
1793
|
const pkg = cliConfig?.package || agentConfig.npmPackage;
|
|
1708
1794
|
const spinner = ora(`Upgrading ${agentConfig.name} to ${version}...`).start();
|
|
1709
1795
|
try {
|
|
1710
|
-
|
|
1796
|
+
await execAsync(`npm install -g ${pkg}@${version}`);
|
|
1711
1797
|
spinner.succeed(`${agentConfig.name} upgraded to ${version}`);
|
|
1712
1798
|
}
|
|
1713
1799
|
catch (err) {
|
|
@@ -2122,18 +2208,19 @@ program
|
|
|
2122
2208
|
else {
|
|
2123
2209
|
command = pkg.name || pkg.registry_name;
|
|
2124
2210
|
}
|
|
2211
|
+
const cliStates = await getAllCliStates();
|
|
2125
2212
|
const agents = options.agents
|
|
2126
2213
|
? options.agents.split(',')
|
|
2127
|
-
: MCP_CAPABLE_AGENTS.filter((id) =>
|
|
2214
|
+
: MCP_CAPABLE_AGENTS.filter((id) => cliStates[id]?.installed);
|
|
2128
2215
|
if (agents.length === 0) {
|
|
2129
2216
|
console.log(chalk.yellow('\nNo MCP-capable agents installed.'));
|
|
2130
2217
|
process.exit(1);
|
|
2131
2218
|
}
|
|
2132
2219
|
console.log(chalk.bold('\nInstalling to agents...'));
|
|
2133
2220
|
for (const agentId of agents) {
|
|
2134
|
-
if (!
|
|
2221
|
+
if (!cliStates[agentId]?.installed)
|
|
2135
2222
|
continue;
|
|
2136
|
-
const result = registerMcp(agentId, entry.name, command, 'user');
|
|
2223
|
+
const result = await registerMcp(agentId, entry.name, command, 'user');
|
|
2137
2224
|
if (result.success) {
|
|
2138
2225
|
console.log(` ${chalk.green('+')} ${AGENTS[agentId].name}`);
|
|
2139
2226
|
}
|
|
@@ -2168,13 +2255,14 @@ program
|
|
|
2168
2255
|
const agents = options.agents
|
|
2169
2256
|
? options.agents.split(',')
|
|
2170
2257
|
: ['claude', 'codex', 'gemini'];
|
|
2258
|
+
const gitCliStates = await getAllCliStates();
|
|
2171
2259
|
// Install commands
|
|
2172
2260
|
if (hasCommands) {
|
|
2173
2261
|
console.log(chalk.bold('\nInstalling commands...'));
|
|
2174
2262
|
let installed = 0;
|
|
2175
2263
|
for (const command of commands) {
|
|
2176
2264
|
for (const agentId of agents) {
|
|
2177
|
-
if (!
|
|
2265
|
+
if (!gitCliStates[agentId]?.installed && agentId !== 'cursor')
|
|
2178
2266
|
continue;
|
|
2179
2267
|
const sourcePath = resolveCommandSource(localPath, command.name, agentId);
|
|
2180
2268
|
if (sourcePath) {
|
|
@@ -2236,7 +2324,9 @@ program
|
|
|
2236
2324
|
}
|
|
2237
2325
|
spinner.text = `Upgrading to ${latestVersion}...`;
|
|
2238
2326
|
// Detect package manager
|
|
2239
|
-
const { execSync } = await import('child_process');
|
|
2327
|
+
const { execSync, exec } = await import('child_process');
|
|
2328
|
+
const { promisify } = await import('util');
|
|
2329
|
+
const execAsync = promisify(exec);
|
|
2240
2330
|
let cmd;
|
|
2241
2331
|
// Check if installed globally via npm, bun, or other
|
|
2242
2332
|
try {
|
|
@@ -2263,8 +2353,8 @@ program
|
|
|
2263
2353
|
cmd = 'npm install -g @swarmify/agents-cli@latest';
|
|
2264
2354
|
}
|
|
2265
2355
|
}
|
|
2266
|
-
// Run silently (suppress npm/bun output)
|
|
2267
|
-
|
|
2356
|
+
// Run silently (suppress npm/bun output) - use async to allow spinner to animate
|
|
2357
|
+
await execAsync(cmd);
|
|
2268
2358
|
spinner.succeed(`Upgraded to ${latestVersion}`);
|
|
2269
2359
|
// Show what's new from changelog
|
|
2270
2360
|
await showWhatsNew(currentVersion, latestVersion);
|