allagents 0.22.1 → 0.22.3

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 (3) hide show
  1. package/README.md +17 -13
  2. package/dist/index.js +383 -169
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -298,18 +298,19 @@ These marketplace names auto-resolve to their GitHub repos:
298
298
 
299
299
  ### Supported Clients
300
300
 
301
- | Client | Skills | Agent File | Hooks | Commands |
302
- |--------|--------|------------|-------|----------|
303
- | claude | `.claude/skills/` | `CLAUDE.md` | `.claude/hooks/` | `.claude/commands/` |
304
- | copilot | `.agents/skills/` | `AGENTS.md` | No | No |
305
- | codex | `.agents/skills/` | `AGENTS.md` | No | No |
306
- | cursor | `.cursor/skills/` | `AGENTS.md` | No | No |
307
- | opencode | `.agents/skills/` | `AGENTS.md` | No | No |
308
- | gemini | `.agents/skills/` | `GEMINI.md` | No | No |
309
- | factory | `.factory/skills/` | `AGENTS.md` | `.factory/hooks/` | No |
310
- | ampcode | `.agents/skills/` | `AGENTS.md` | No | No |
311
-
312
- > **Note:** Clients supporting the universal `.agents/` folder (copilot, codex, opencode, gemini, ampcode) share the same skills directory. Commands are a Claude-specific feature.
301
+ | Client | Skills | Agent File | Hooks | Commands | GitHub Overrides |
302
+ |--------|--------|------------|-------|----------|------------------|
303
+ | claude | `.claude/skills/` | `CLAUDE.md` | `.claude/hooks/` | `.claude/commands/` | No |
304
+ | copilot | `.agents/skills/` | `AGENTS.md` | No | No | `.github/` |
305
+ | codex | `.agents/skills/` | `AGENTS.md` | No | No | No |
306
+ | cursor | `.cursor/skills/` | `AGENTS.md` | No | No | No |
307
+ | opencode | `.agents/skills/` | `AGENTS.md` | No | `.opencode/commands/` | No |
308
+ | gemini | `.agents/skills/` | `GEMINI.md` | No | No | No |
309
+ | factory | `.factory/skills/` | `AGENTS.md` | `.factory/hooks/` | No | No |
310
+ | ampcode | `.agents/skills/` | `AGENTS.md` | No | No | No |
311
+ | vscode | `.agents/skills/` | `AGENTS.md` | No | No | `.github/` |
312
+
313
+ > **Note:** Clients supporting the universal `.agents/` folder (copilot, codex, opencode, gemini, ampcode, vscode) share the same skills directory. GitHub overrides (`.github/prompts/`, `copilot-instructions.md`) are copied to Copilot/VSCode's `.github/` folder.
313
314
 
314
315
  ## Marketplace Structure
315
316
 
@@ -337,9 +338,12 @@ my-plugin/
337
338
  ├── skills/ # Skill directories with SKILL.md (all clients)
338
339
  │ └── debugging/
339
340
  │ └── SKILL.md
340
- ├── commands/ # Command files (.md) - Claude only
341
+ ├── commands/ # Command files (.md) - Claude, OpenCode
341
342
  │ ├── build.md
342
343
  │ └── deploy.md
344
+ ├── .github/ # GitHub overrides (Copilot, VSCode)
345
+ │ └── prompts/
346
+ │ └── review.md
343
347
  ├── hooks/ # Hook files (Claude/Factory only)
344
348
  │ └── pre-commit.md
345
349
  └── AGENTS.md # Agent configuration (optional)
package/dist/index.js CHANGED
@@ -16000,7 +16000,8 @@ async function updatePlugin(pluginSpec, deps) {
16000
16000
  action: "skipped"
16001
16001
  };
16002
16002
  }
16003
- const marketplace = await deps.getMarketplace(parsed.marketplaceName);
16003
+ const sourceLocation = parsed.owner && parsed.repo ? `${parsed.owner}/${parsed.repo}` : undefined;
16004
+ const marketplace = await deps.getMarketplace(parsed.marketplaceName, sourceLocation);
16004
16005
  if (!marketplace) {
16005
16006
  return {
16006
16007
  plugin: pluginSpec,
@@ -16009,9 +16010,10 @@ async function updatePlugin(pluginSpec, deps) {
16009
16010
  error: `Marketplace not found: ${parsed.marketplaceName}`
16010
16011
  };
16011
16012
  }
16013
+ const marketplaceName = marketplace.name;
16012
16014
  const manifestResult = await deps.parseMarketplaceManifest(marketplace.path);
16013
16015
  if (!manifestResult.success || !manifestResult.data) {
16014
- const updateResults = await deps.updateMarketplace(parsed.marketplaceName);
16016
+ const updateResults = await deps.updateMarketplace(marketplaceName);
16015
16017
  const result = updateResults[0];
16016
16018
  return {
16017
16019
  plugin: pluginSpec,
@@ -16022,7 +16024,7 @@ async function updatePlugin(pluginSpec, deps) {
16022
16024
  }
16023
16025
  const pluginEntry = manifestResult.data.plugins.find((p) => p.name === parsed.plugin);
16024
16026
  if (!pluginEntry) {
16025
- const updateResults = await deps.updateMarketplace(parsed.marketplaceName);
16027
+ const updateResults = await deps.updateMarketplace(marketplaceName);
16026
16028
  const result = updateResults[0];
16027
16029
  return {
16028
16030
  plugin: pluginSpec,
@@ -16032,7 +16034,7 @@ async function updatePlugin(pluginSpec, deps) {
16032
16034
  };
16033
16035
  }
16034
16036
  if (typeof pluginEntry.source === "string") {
16035
- const updateResults = await deps.updateMarketplace(parsed.marketplaceName);
16037
+ const updateResults = await deps.updateMarketplace(marketplaceName);
16036
16038
  const result = updateResults[0];
16037
16039
  return {
16038
16040
  plugin: pluginSpec,
@@ -16043,7 +16045,7 @@ async function updatePlugin(pluginSpec, deps) {
16043
16045
  }
16044
16046
  const url = pluginEntry.source.url;
16045
16047
  if (marketplace.source.type === "github") {
16046
- await deps.updateMarketplace(parsed.marketplaceName);
16048
+ await deps.updateMarketplace(marketplaceName);
16047
16049
  }
16048
16050
  const fetchResult = await fetchFn(url);
16049
16051
  return {
@@ -21397,6 +21399,7 @@ var init_client_mapping = __esm(() => {
21397
21399
  agentFile: "AGENTS.md"
21398
21400
  },
21399
21401
  opencode: {
21402
+ commandsPath: ".opencode/commands/",
21400
21403
  skillsPath: ".agents/skills/",
21401
21404
  agentFile: "AGENTS.md"
21402
21405
  },
@@ -21443,6 +21446,7 @@ var init_client_mapping = __esm(() => {
21443
21446
  agentFile: "AGENTS.md"
21444
21447
  },
21445
21448
  opencode: {
21449
+ commandsPath: ".opencode/commands/",
21446
21450
  skillsPath: ".agents/skills/",
21447
21451
  agentFile: "AGENTS.md"
21448
21452
  },
@@ -26188,7 +26192,8 @@ var init_user_workspace = __esm(() => {
26188
26192
  "opencode",
26189
26193
  "gemini",
26190
26194
  "factory",
26191
- "ampcode"
26195
+ "ampcode",
26196
+ "vscode"
26192
26197
  ];
26193
26198
  });
26194
26199
 
@@ -27337,7 +27342,8 @@ var init_sync_state = __esm(() => {
27337
27342
  SyncStateSchema = exports_external.object({
27338
27343
  version: exports_external.literal(1),
27339
27344
  lastSync: exports_external.string(),
27340
- files: exports_external.record(ClientTypeSchema, exports_external.array(exports_external.string()))
27345
+ files: exports_external.record(ClientTypeSchema, exports_external.array(exports_external.string())),
27346
+ mcpServers: exports_external.record(exports_external.string(), exports_external.array(exports_external.string())).optional()
27341
27347
  });
27342
27348
  });
27343
27349
 
@@ -27365,12 +27371,14 @@ async function loadSyncState(workspacePath) {
27365
27371
  return null;
27366
27372
  }
27367
27373
  }
27368
- async function saveSyncState(workspacePath, files) {
27374
+ async function saveSyncState(workspacePath, data) {
27369
27375
  const statePath = getSyncStatePath(workspacePath);
27376
+ const normalizedData = "files" in data ? data : { files: data };
27370
27377
  const state = {
27371
27378
  version: 1,
27372
27379
  lastSync: new Date().toISOString(),
27373
- files
27380
+ files: normalizedData.files,
27381
+ ...normalizedData.mcpServers && { mcpServers: normalizedData.mcpServers }
27374
27382
  };
27375
27383
  await mkdir7(dirname5(statePath), { recursive: true });
27376
27384
  await writeFile6(statePath, JSON.stringify(state, null, 2), "utf-8");
@@ -27381,6 +27389,12 @@ function getPreviouslySyncedFiles(state, client) {
27381
27389
  }
27382
27390
  return state.files[client] ?? [];
27383
27391
  }
27392
+ function getPreviouslySyncedMcpServers(state, scope) {
27393
+ if (!state?.mcpServers) {
27394
+ return [];
27395
+ }
27396
+ return state.mcpServers[scope] ?? [];
27397
+ }
27384
27398
  var init_sync_state2 = __esm(() => {
27385
27399
  init_constants();
27386
27400
  init_sync_state();
@@ -27556,19 +27570,21 @@ function syncVscodeMcpConfig(validatedPlugins, options2) {
27556
27570
  const dryRun = options2?.dryRun ?? false;
27557
27571
  const force = options2?.force ?? false;
27558
27572
  const configPath = options2?.configPath ?? getVscodeMcpConfigPath();
27573
+ const previouslyTracked = new Set(options2?.trackedServers ?? []);
27574
+ const hasTracking = options2?.trackedServers !== undefined;
27559
27575
  const { servers: pluginServers, warnings } = collectMcpServers(validatedPlugins);
27560
27576
  const result = {
27561
27577
  added: 0,
27562
27578
  skipped: 0,
27563
27579
  overwritten: 0,
27580
+ removed: 0,
27564
27581
  warnings: [...warnings],
27565
27582
  addedServers: [],
27566
27583
  skippedServers: [],
27567
- overwrittenServers: []
27584
+ overwrittenServers: [],
27585
+ removedServers: [],
27586
+ trackedServers: []
27568
27587
  };
27569
- if (pluginServers.size === 0) {
27570
- return result;
27571
- }
27572
27588
  let existingConfig = {};
27573
27589
  if (existsSync11(configPath)) {
27574
27590
  try {
@@ -27583,22 +27599,42 @@ function syncVscodeMcpConfig(validatedPlugins, options2) {
27583
27599
  for (const [name, config] of pluginServers) {
27584
27600
  if (name in existingServers) {
27585
27601
  if (!deepEqual(existingServers[name], config)) {
27586
- if (force) {
27602
+ if (hasTracking && previouslyTracked.has(name)) {
27603
+ existingServers[name] = config;
27604
+ result.overwritten++;
27605
+ result.overwrittenServers.push(name);
27606
+ result.trackedServers.push(name);
27607
+ } else if (force) {
27587
27608
  existingServers[name] = config;
27588
27609
  result.overwritten++;
27589
27610
  result.overwrittenServers.push(name);
27611
+ result.trackedServers.push(name);
27590
27612
  } else {
27591
27613
  result.skipped++;
27592
27614
  result.skippedServers.push(name);
27593
27615
  }
27616
+ } else if (hasTracking && previouslyTracked.has(name)) {
27617
+ result.trackedServers.push(name);
27594
27618
  }
27595
27619
  } else {
27596
27620
  existingServers[name] = config;
27597
27621
  result.added++;
27598
27622
  result.addedServers.push(name);
27623
+ result.trackedServers.push(name);
27599
27624
  }
27600
27625
  }
27601
- if ((result.added > 0 || result.overwritten > 0) && !dryRun) {
27626
+ if (hasTracking) {
27627
+ const currentServerNames = new Set(pluginServers.keys());
27628
+ for (const trackedName of previouslyTracked) {
27629
+ if (!currentServerNames.has(trackedName) && trackedName in existingServers) {
27630
+ delete existingServers[trackedName];
27631
+ result.removed++;
27632
+ result.removedServers.push(trackedName);
27633
+ }
27634
+ }
27635
+ }
27636
+ const hasChanges = result.added > 0 || result.overwritten > 0 || result.removed > 0;
27637
+ if (hasChanges && !dryRun) {
27602
27638
  existingConfig.servers = existingServers;
27603
27639
  const dir = dirname6(configPath);
27604
27640
  if (!existsSync11(dir)) {
@@ -27606,6 +27642,26 @@ function syncVscodeMcpConfig(validatedPlugins, options2) {
27606
27642
  }
27607
27643
  writeFileSync(configPath, `${JSON.stringify(existingConfig, null, 2)}
27608
27644
  `, "utf-8");
27645
+ result.configPath = configPath;
27646
+ }
27647
+ if (pluginServers.size === 0 && hasTracking && previouslyTracked.size > 0) {
27648
+ for (const trackedName of previouslyTracked) {
27649
+ if (trackedName in existingServers) {
27650
+ delete existingServers[trackedName];
27651
+ result.removed++;
27652
+ result.removedServers.push(trackedName);
27653
+ }
27654
+ }
27655
+ if (result.removed > 0 && !dryRun) {
27656
+ existingConfig.servers = existingServers;
27657
+ const dir = dirname6(configPath);
27658
+ if (!existsSync11(dir)) {
27659
+ mkdirSync(dir, { recursive: true });
27660
+ }
27661
+ writeFileSync(configPath, `${JSON.stringify(existingConfig, null, 2)}
27662
+ `, "utf-8");
27663
+ result.configPath = configPath;
27664
+ }
27609
27665
  }
27610
27666
  return result;
27611
27667
  }
@@ -28325,18 +28381,22 @@ ${failedValidations.map((v) => ` - ${v.plugin}: ${v.error}`).join(`
28325
28381
  }
28326
28382
  }
28327
28383
  }
28328
- if (!dryRun) {
28329
- const allCopyResults = pluginResults.flatMap((r) => r.copyResults);
28330
- const syncedFiles = collectSyncedPaths(allCopyResults, homeDir, clients, USER_CLIENT_MAPPINGS);
28331
- await saveSyncState(homeDir, syncedFiles);
28332
- }
28333
28384
  let mcpResult;
28334
- if (clients.includes("vscode") && validPlugins.length > 0) {
28335
- mcpResult = syncVscodeMcpConfig(validPlugins, { dryRun, force });
28385
+ if (clients.includes("vscode")) {
28386
+ const trackedMcpServers = getPreviouslySyncedMcpServers(previousState, "vscode");
28387
+ mcpResult = syncVscodeMcpConfig(validPlugins, { dryRun, force, trackedServers: trackedMcpServers });
28336
28388
  if (mcpResult.warnings.length > 0) {
28337
28389
  warnings.push(...mcpResult.warnings);
28338
28390
  }
28339
28391
  }
28392
+ if (!dryRun) {
28393
+ const allCopyResults = pluginResults.flatMap((r) => r.copyResults);
28394
+ const syncedFiles = collectSyncedPaths(allCopyResults, homeDir, clients, USER_CLIENT_MAPPINGS);
28395
+ await saveSyncState(homeDir, {
28396
+ files: syncedFiles,
28397
+ ...mcpResult && { mcpServers: { vscode: mcpResult.trackedServers } }
28398
+ });
28399
+ }
28340
28400
  return {
28341
28401
  success: totalFailed === 0,
28342
28402
  pluginResults,
@@ -28789,6 +28849,67 @@ var init_status2 = __esm(() => {
28789
28849
  init_user_workspace();
28790
28850
  });
28791
28851
 
28852
+ // src/cli/format-sync.ts
28853
+ function formatMcpResult(mcpResult) {
28854
+ const { added, overwritten, removed, skipped } = mcpResult;
28855
+ if (added === 0 && overwritten === 0 && removed === 0 && skipped === 0) {
28856
+ return [];
28857
+ }
28858
+ const lines = [];
28859
+ const parts = [`${added} added`];
28860
+ if (overwritten > 0)
28861
+ parts.push(`${overwritten} updated`);
28862
+ if (removed > 0)
28863
+ parts.push(`${removed} removed`);
28864
+ if (skipped > 0)
28865
+ parts.push(`${skipped} skipped`);
28866
+ lines.push(`MCP servers: ${parts.join(", ")}`);
28867
+ for (const name of mcpResult.addedServers) {
28868
+ lines.push(` + ${name}`);
28869
+ }
28870
+ for (const name of mcpResult.overwrittenServers) {
28871
+ lines.push(` ~ ${name}`);
28872
+ }
28873
+ for (const name of mcpResult.removedServers) {
28874
+ lines.push(` - ${name}`);
28875
+ }
28876
+ if (mcpResult.configPath) {
28877
+ lines.push(`File modified: ${mcpResult.configPath}`);
28878
+ }
28879
+ return lines;
28880
+ }
28881
+ function buildSyncData(result) {
28882
+ return {
28883
+ copied: result.totalCopied,
28884
+ generated: result.totalGenerated,
28885
+ failed: result.totalFailed,
28886
+ skipped: result.totalSkipped,
28887
+ plugins: result.pluginResults.map((pr) => ({
28888
+ plugin: pr.plugin,
28889
+ success: pr.success,
28890
+ error: pr.error,
28891
+ copied: pr.copyResults.filter((r) => r.action === "copied").length,
28892
+ generated: pr.copyResults.filter((r) => r.action === "generated").length,
28893
+ failed: pr.copyResults.filter((r) => r.action === "failed").length,
28894
+ copyResults: pr.copyResults
28895
+ })),
28896
+ purgedPaths: result.purgedPaths ?? [],
28897
+ ...result.mcpResult && {
28898
+ mcpServers: {
28899
+ added: result.mcpResult.added,
28900
+ skipped: result.mcpResult.skipped,
28901
+ overwritten: result.mcpResult.overwritten,
28902
+ removed: result.mcpResult.removed,
28903
+ addedServers: result.mcpResult.addedServers,
28904
+ skippedServers: result.mcpResult.skippedServers,
28905
+ overwrittenServers: result.mcpResult.overwrittenServers,
28906
+ removedServers: result.mcpResult.removedServers,
28907
+ ...result.mcpResult.configPath && { configPath: result.mcpResult.configPath }
28908
+ }
28909
+ }
28910
+ };
28911
+ }
28912
+
28792
28913
  // src/core/skills.ts
28793
28914
  import { existsSync as existsSync18 } from "node:fs";
28794
28915
  import { readFile as readFile13, readdir as readdir4 } from "node:fs/promises";
@@ -29355,7 +29476,7 @@ var package_default;
29355
29476
  var init_package = __esm(() => {
29356
29477
  package_default = {
29357
29478
  name: "allagents",
29358
- version: "0.22.1",
29479
+ version: "0.22.3",
29359
29480
  description: "CLI tool for managing multi-repo AI agent workspaces with plugin synchronization",
29360
29481
  type: "module",
29361
29482
  bin: {
@@ -31404,13 +31525,8 @@ async function runSync(context) {
31404
31525
  const lines = userResult.pluginResults.map((pr) => `${pr.success ? "✓" : "✗"} ${pr.plugin}`);
31405
31526
  lines.push("");
31406
31527
  lines.push(`Copied: ${userResult.totalCopied} Failed: ${userResult.totalFailed} Skipped: ${userResult.totalSkipped}`);
31407
- if (userResult.mcpResult && (userResult.mcpResult.added > 0 || userResult.mcpResult.skipped > 0 || userResult.mcpResult.overwritten > 0)) {
31408
- const parts = [`${userResult.mcpResult.added} added`];
31409
- if (userResult.mcpResult.overwritten > 0)
31410
- parts.push(`${userResult.mcpResult.overwritten} overwritten`);
31411
- if (userResult.mcpResult.skipped > 0)
31412
- parts.push(`${userResult.mcpResult.skipped} skipped`);
31413
- lines.push(`MCP servers: ${parts.join(", ")}`);
31528
+ if (userResult.mcpResult) {
31529
+ lines.push(...formatMcpResult(userResult.mcpResult));
31414
31530
  }
31415
31531
  kt2(lines.join(`
31416
31532
  `), "User Sync");
@@ -31489,78 +31605,25 @@ var init_init2 = __esm(() => {
31489
31605
  ({ text, multiselect } = exports_dist);
31490
31606
  });
31491
31607
 
31492
- // src/cli/tui/actions/status.ts
31493
- async function runStatus(context, cache2) {
31494
- try {
31495
- let status = cache2?.getStatus();
31496
- if (!status) {
31497
- status = await getWorkspaceStatus(context.workspacePath ?? undefined);
31498
- cache2?.setStatus(status);
31499
- }
31500
- if (!status.success) {
31501
- kt2(status.error ?? "Unknown error", "Status Error");
31502
- return;
31503
- }
31504
- const lines = [];
31505
- if (context.hasWorkspace) {
31506
- lines.push(`Workspace: ${context.workspacePath}`);
31507
- } else {
31508
- lines.push("No workspace detected");
31509
- }
31510
- lines.push("");
31511
- const userPlugins = status.userPlugins ?? [];
31512
- const hasProjectPlugins = status.plugins.length > 0;
31513
- const hasUserPlugins = userPlugins.length > 0;
31514
- if (!hasProjectPlugins && !hasUserPlugins) {
31515
- lines.push("No plugins configured");
31516
- }
31517
- if (hasProjectPlugins) {
31518
- lines.push("Project plugins:");
31519
- for (const plugin of status.plugins) {
31520
- const icon = plugin.available ? "✓" : "✗";
31521
- lines.push(` ${icon} ${plugin.source} (${plugin.type})`);
31608
+ // src/cli/tui/actions/plugins.ts
31609
+ function createUpdateDeps() {
31610
+ const updatedMarketplaces = new Set;
31611
+ return {
31612
+ parsePluginSpec,
31613
+ getMarketplace: (name, sourceLocation) => findMarketplace(name, sourceLocation),
31614
+ parseMarketplaceManifest,
31615
+ updateMarketplace: async (name) => {
31616
+ if (updatedMarketplaces.has(name)) {
31617
+ return [{ name, success: true }];
31522
31618
  }
31523
- }
31524
- if (hasUserPlugins) {
31525
- if (hasProjectPlugins)
31526
- lines.push("");
31527
- lines.push("User plugins:");
31528
- for (const plugin of userPlugins) {
31529
- const icon = plugin.available ? "✓" : "✗";
31530
- lines.push(` ${icon} ${plugin.source} (${plugin.type})`);
31531
- }
31532
- }
31533
- lines.push("");
31534
- lines.push(`Clients: ${status.clients.length > 0 ? status.clients.join(", ") : "none"}`);
31535
- kt2(lines.join(`
31536
- `), "Status");
31537
- if (!context.hasWorkspace) {
31538
- const action = await select({
31539
- message: "Options",
31540
- options: [
31541
- { label: "Add workspace", value: "init" },
31542
- { label: "Back", value: "back" }
31543
- ]
31544
- });
31545
- if (!Ct(action) && action === "init") {
31546
- await runInit();
31547
- cache2?.invalidate();
31619
+ const result = await updateMarketplace(name);
31620
+ if (result[0]?.success) {
31621
+ updatedMarketplaces.add(name);
31548
31622
  }
31623
+ return result;
31549
31624
  }
31550
- } catch (error) {
31551
- const message = error instanceof Error ? error.message : String(error);
31552
- kt2(message, "Error");
31553
- }
31625
+ };
31554
31626
  }
31555
- var select;
31556
- var init_status3 = __esm(() => {
31557
- init_dist2();
31558
- init_status2();
31559
- init_init2();
31560
- ({ select } = exports_dist);
31561
- });
31562
-
31563
- // src/cli/tui/actions/plugins.ts
31564
31627
  async function getCachedMarketplaces(cache2) {
31565
31628
  const cached = cache2?.getMarketplaces();
31566
31629
  if (cached)
@@ -31578,7 +31641,7 @@ async function getCachedMarketplacePlugins(name, cache2) {
31578
31641
  return result;
31579
31642
  }
31580
31643
  async function installSelectedPlugin(pluginRef, context, cache2) {
31581
- const scopeChoice = await select2({
31644
+ const scopeChoice = await select({
31582
31645
  message: "Install scope",
31583
31646
  options: [
31584
31647
  { label: "Project (this workspace)", value: "project" },
@@ -31621,6 +31684,102 @@ async function installSelectedPlugin(pluginRef, context, cache2) {
31621
31684
  kt2(`Installed: ${pluginRef}`, "Success");
31622
31685
  return true;
31623
31686
  }
31687
+ async function runUpdatePlugin(pluginSource, scope, context, cache2) {
31688
+ const s = Ie();
31689
+ s.start("Updating plugin...");
31690
+ const result = await updatePlugin(pluginSource, createUpdateDeps());
31691
+ if (!result.success) {
31692
+ s.stop("Update failed");
31693
+ kt2(result.error ?? "Unknown error", "Error");
31694
+ return;
31695
+ }
31696
+ s.stop(result.action === "updated" ? "Plugin updated" : "Already up to date");
31697
+ if (result.action === "updated") {
31698
+ const syncS = Ie();
31699
+ syncS.start("Syncing...");
31700
+ if (scope === "project" && context.workspacePath) {
31701
+ await syncWorkspace(context.workspacePath);
31702
+ } else {
31703
+ await syncUserWorkspace();
31704
+ }
31705
+ syncS.stop("Sync complete");
31706
+ cache2?.invalidate();
31707
+ }
31708
+ const icon = result.action === "updated" ? "✓" : "-";
31709
+ kt2(`${icon} ${pluginSource} (${result.action})`, "Update");
31710
+ }
31711
+ async function runUpdateAllPlugins(context, cache2) {
31712
+ const s = Ie();
31713
+ s.start("Gathering plugins...");
31714
+ const pluginsToUpdate = [];
31715
+ if (context.workspacePath) {
31716
+ const projectPlugins = await getInstalledProjectPlugins(context.workspacePath);
31717
+ for (const plugin of projectPlugins) {
31718
+ pluginsToUpdate.push({ spec: plugin.spec, scope: "project" });
31719
+ }
31720
+ }
31721
+ const userPlugins = await getInstalledUserPlugins();
31722
+ for (const plugin of userPlugins) {
31723
+ if (!pluginsToUpdate.some((existing) => existing.spec === plugin.spec)) {
31724
+ pluginsToUpdate.push({ spec: plugin.spec, scope: "user" });
31725
+ }
31726
+ }
31727
+ if (pluginsToUpdate.length === 0) {
31728
+ s.stop("No plugins to update");
31729
+ return;
31730
+ }
31731
+ s.stop(`Found ${pluginsToUpdate.length} plugin(s)`);
31732
+ const deps = createUpdateDeps();
31733
+ const updateS = Ie();
31734
+ updateS.start("Updating plugins...");
31735
+ const results = [];
31736
+ let needsProjectSync = false;
31737
+ let needsUserSync = false;
31738
+ for (const { spec, scope } of pluginsToUpdate) {
31739
+ const result = await updatePlugin(spec, deps);
31740
+ const entry = {
31741
+ plugin: spec,
31742
+ action: result.action
31743
+ };
31744
+ if (result.error) {
31745
+ entry.error = result.error;
31746
+ }
31747
+ results.push(entry);
31748
+ if (result.action === "updated") {
31749
+ if (scope === "project")
31750
+ needsProjectSync = true;
31751
+ else
31752
+ needsUserSync = true;
31753
+ }
31754
+ }
31755
+ updateS.stop("Update complete");
31756
+ if (needsProjectSync && context.workspacePath) {
31757
+ const syncS = Ie();
31758
+ syncS.start("Syncing project...");
31759
+ await syncWorkspace(context.workspacePath);
31760
+ syncS.stop("Project sync complete");
31761
+ }
31762
+ if (needsUserSync) {
31763
+ const syncS = Ie();
31764
+ syncS.start("Syncing user...");
31765
+ await syncUserWorkspace();
31766
+ syncS.stop("User sync complete");
31767
+ }
31768
+ if (needsProjectSync || needsUserSync) {
31769
+ cache2?.invalidate();
31770
+ }
31771
+ const updated = results.filter((r) => r.action === "updated").length;
31772
+ const skipped = results.filter((r) => r.action === "skipped").length;
31773
+ const failed = results.filter((r) => r.action === "failed").length;
31774
+ const lines = results.map((r) => {
31775
+ const icon = r.action === "updated" ? "✓" : r.action === "skipped" ? "-" : "✗";
31776
+ return `${icon} ${r.plugin} (${r.action})${r.error ? ` - ${r.error}` : ""}`;
31777
+ });
31778
+ lines.push("");
31779
+ lines.push(`Updated: ${updated} Skipped: ${skipped} Failed: ${failed}`);
31780
+ kt2(lines.join(`
31781
+ `), "Update Results");
31782
+ }
31624
31783
  async function runPlugins(context, cache2) {
31625
31784
  try {
31626
31785
  while (true) {
@@ -31632,6 +31791,10 @@ async function runPlugins(context, cache2) {
31632
31791
  status = await getWorkspaceStatus(context.workspacePath ?? undefined);
31633
31792
  cache2?.setStatus(status);
31634
31793
  }
31794
+ const hasPlugins = status.success && ((status.plugins?.length ?? 0) > 0 || (status.userPlugins?.length ?? 0) > 0);
31795
+ if (hasPlugins) {
31796
+ options2.push({ label: "Update all", value: "__update_all__" });
31797
+ }
31635
31798
  if (status.success) {
31636
31799
  for (const plugin of status.plugins) {
31637
31800
  const key = `project:${plugin.source}`;
@@ -31649,7 +31812,7 @@ async function runPlugins(context, cache2) {
31649
31812
  }
31650
31813
  }
31651
31814
  options2.push({ label: "Back", value: "__back__" });
31652
- const selected = await select2({
31815
+ const selected = await select({
31653
31816
  message: "Plugins",
31654
31817
  options: options2
31655
31818
  });
@@ -31660,6 +31823,10 @@ async function runPlugins(context, cache2) {
31660
31823
  await runInstallPlugin(context, cache2);
31661
31824
  continue;
31662
31825
  }
31826
+ if (selected === "__update_all__") {
31827
+ await runUpdateAllPlugins(context, cache2);
31828
+ continue;
31829
+ }
31663
31830
  await runPluginDetail(selected, context, cache2);
31664
31831
  }
31665
31832
  } catch (error) {
@@ -31671,10 +31838,11 @@ async function runPluginDetail(pluginKey, context, cache2) {
31671
31838
  const scope = pluginKey.startsWith("project:") ? "project" : "user";
31672
31839
  const pluginSource = pluginKey.replace(/^(project|user):/, "");
31673
31840
  while (true) {
31674
- const action = await select2({
31841
+ const action = await select({
31675
31842
  message: `Plugin: ${pluginSource} [${scope}]`,
31676
31843
  options: [
31677
31844
  { label: "Browse skills", value: "browse" },
31845
+ { label: "Update", value: "update" },
31678
31846
  { label: "Remove", value: "remove" },
31679
31847
  { label: "Back", value: "back" }
31680
31848
  ]
@@ -31686,6 +31854,10 @@ async function runPluginDetail(pluginKey, context, cache2) {
31686
31854
  await runBrowsePluginSkills(pluginSource, scope, context, cache2);
31687
31855
  continue;
31688
31856
  }
31857
+ if (action === "update") {
31858
+ await runUpdatePlugin(pluginSource, scope, context, cache2);
31859
+ continue;
31860
+ }
31689
31861
  if (action === "remove") {
31690
31862
  const confirmed = await confirm({
31691
31863
  message: `Remove plugin "${pluginSource}"?`
@@ -31822,7 +31994,7 @@ Use "Manage marketplaces" to add one first.`, "Marketplace");
31822
31994
  return;
31823
31995
  }
31824
31996
  allPlugins.push({ label: "Back", value: "__back__" });
31825
- const selected = await select2({
31997
+ const selected = await select({
31826
31998
  message: "Select a plugin to install",
31827
31999
  options: allPlugins
31828
32000
  });
@@ -31847,7 +32019,7 @@ async function runBrowseMarketplaces(context, cache2) {
31847
32019
  })),
31848
32020
  { label: "Back", value: "__back__" }
31849
32021
  ];
31850
- const selected = await select2({
32022
+ const selected = await select({
31851
32023
  message: "Marketplaces",
31852
32024
  options: options2
31853
32025
  });
@@ -31882,7 +32054,7 @@ async function runBrowseMarketplaces(context, cache2) {
31882
32054
  }
31883
32055
  async function runMarketplaceDetail(marketplaceName, context, cache2) {
31884
32056
  while (true) {
31885
- const action = await select2({
32057
+ const action = await select({
31886
32058
  message: `Marketplace: ${marketplaceName}`,
31887
32059
  options: [
31888
32060
  { label: "Browse plugins", value: "browse" },
@@ -31906,7 +32078,7 @@ async function runMarketplaceDetail(marketplaceName, context, cache2) {
31906
32078
  return { label, value: plugin.name };
31907
32079
  });
31908
32080
  pluginOptions.push({ label: "Back", value: "__back__" });
31909
- const selectedPlugin = await select2({
32081
+ const selectedPlugin = await select({
31910
32082
  message: "Select a plugin to install",
31911
32083
  options: pluginOptions
31912
32084
  });
@@ -31962,17 +32134,102 @@ async function runMarketplaceDetail(marketplaceName, context, cache2) {
31962
32134
  }
31963
32135
  }
31964
32136
  }
31965
- var select2, text2, confirm, multiselect2;
32137
+ var select, text2, confirm, multiselect2;
31966
32138
  var init_plugins = __esm(() => {
31967
32139
  init_dist2();
31968
32140
  init_workspace_modify();
31969
32141
  init_user_workspace();
31970
32142
  init_sync();
31971
32143
  init_marketplace();
32144
+ init_plugin();
32145
+ init_marketplace_manifest_parser();
31972
32146
  init_status2();
31973
32147
  init_skills();
31974
32148
  init_constants();
31975
- ({ select: select2, text: text2, confirm, multiselect: multiselect2 } = exports_dist);
32149
+ ({ select, text: text2, confirm, multiselect: multiselect2 } = exports_dist);
32150
+ });
32151
+
32152
+ // src/cli/tui/actions/status.ts
32153
+ async function runStatus(context, cache2) {
32154
+ try {
32155
+ let status = cache2?.getStatus();
32156
+ if (!status) {
32157
+ status = await getWorkspaceStatus(context.workspacePath ?? undefined);
32158
+ cache2?.setStatus(status);
32159
+ }
32160
+ if (!status.success) {
32161
+ kt2(status.error ?? "Unknown error", "Status Error");
32162
+ return;
32163
+ }
32164
+ const lines = [];
32165
+ if (context.hasWorkspace) {
32166
+ lines.push(`Workspace: ${context.workspacePath}`);
32167
+ } else {
32168
+ lines.push("No workspace detected");
32169
+ }
32170
+ lines.push("");
32171
+ const userPlugins = status.userPlugins ?? [];
32172
+ const hasProjectPlugins = status.plugins.length > 0;
32173
+ const hasUserPlugins = userPlugins.length > 0;
32174
+ if (!hasProjectPlugins && !hasUserPlugins) {
32175
+ lines.push("No plugins configured");
32176
+ }
32177
+ if (hasProjectPlugins) {
32178
+ lines.push("Project plugins:");
32179
+ for (const plugin of status.plugins) {
32180
+ const icon = plugin.available ? "✓" : "✗";
32181
+ lines.push(` ${icon} ${plugin.source} (${plugin.type})`);
32182
+ }
32183
+ }
32184
+ if (hasUserPlugins) {
32185
+ if (hasProjectPlugins)
32186
+ lines.push("");
32187
+ lines.push("User plugins:");
32188
+ for (const plugin of userPlugins) {
32189
+ const icon = plugin.available ? "✓" : "✗";
32190
+ lines.push(` ${icon} ${plugin.source} (${plugin.type})`);
32191
+ }
32192
+ }
32193
+ lines.push("");
32194
+ lines.push(`Clients: ${status.clients.length > 0 ? status.clients.join(", ") : "none"}`);
32195
+ kt2(lines.join(`
32196
+ `), "Status");
32197
+ const hasPlugins = context.projectPluginCount > 0 || context.userPluginCount > 0;
32198
+ const options2 = [];
32199
+ if (hasPlugins) {
32200
+ options2.push({ label: "Update all", value: "update_all" });
32201
+ }
32202
+ if (context.hasWorkspace) {
32203
+ options2.push({ label: "Add workspace", value: "init", hint: "in subdirectory" });
32204
+ } else {
32205
+ options2.push({ label: "Add workspace", value: "init" });
32206
+ }
32207
+ options2.push({ label: "Back", value: "back" });
32208
+ const action = await select2({
32209
+ message: "Options",
32210
+ options: options2
32211
+ });
32212
+ if (Ct(action) || action === "back") {
32213
+ return;
32214
+ }
32215
+ if (action === "update_all") {
32216
+ await runUpdateAllPlugins(context, cache2);
32217
+ } else if (action === "init") {
32218
+ await runInit();
32219
+ cache2?.invalidate();
32220
+ }
32221
+ } catch (error) {
32222
+ const message = error instanceof Error ? error.message : String(error);
32223
+ kt2(message, "Error");
32224
+ }
32225
+ }
32226
+ var select2;
32227
+ var init_status3 = __esm(() => {
32228
+ init_dist2();
32229
+ init_status2();
32230
+ init_init2();
32231
+ init_plugins();
32232
+ ({ select: select2 } = exports_dist);
31976
32233
  });
31977
32234
 
31978
32235
  // src/cli/tui/actions/clients.ts
@@ -32551,34 +32808,6 @@ var repoListMeta = {
32551
32808
  };
32552
32809
 
32553
32810
  // src/cli/commands/workspace.ts
32554
- function buildSyncData(result) {
32555
- return {
32556
- copied: result.totalCopied,
32557
- generated: result.totalGenerated,
32558
- failed: result.totalFailed,
32559
- skipped: result.totalSkipped,
32560
- plugins: result.pluginResults.map((pr) => ({
32561
- plugin: pr.plugin,
32562
- success: pr.success,
32563
- error: pr.error,
32564
- copied: pr.copyResults.filter((r) => r.action === "copied").length,
32565
- generated: pr.copyResults.filter((r) => r.action === "generated").length,
32566
- failed: pr.copyResults.filter((r) => r.action === "failed").length,
32567
- copyResults: pr.copyResults
32568
- })),
32569
- purgedPaths: result.purgedPaths ?? [],
32570
- ...result.mcpResult && {
32571
- mcpServers: {
32572
- added: result.mcpResult.added,
32573
- skipped: result.mcpResult.skipped,
32574
- overwritten: result.mcpResult.overwritten,
32575
- addedServers: result.mcpResult.addedServers,
32576
- skippedServers: result.mcpResult.skippedServers,
32577
- overwrittenServers: result.mcpResult.overwrittenServers
32578
- }
32579
- }
32580
- };
32581
- }
32582
32811
  var initCmd = import_cmd_ts2.command({
32583
32812
  name: "init",
32584
32813
  description: buildDescription(initMeta),
@@ -32748,19 +32977,13 @@ Warnings:`);
32748
32977
  console.log(` ⚠ ${warning}`);
32749
32978
  }
32750
32979
  }
32751
- if (result.mcpResult && (result.mcpResult.added > 0 || result.mcpResult.skipped > 0 || result.mcpResult.overwritten > 0)) {
32752
- const parts = [`${result.mcpResult.added} added`];
32753
- if (result.mcpResult.overwritten > 0)
32754
- parts.push(`${result.mcpResult.overwritten} overwritten`);
32755
- if (result.mcpResult.skipped > 0)
32756
- parts.push(`${result.mcpResult.skipped} skipped`);
32757
- console.log(`
32758
- MCP servers: ${parts.join(", ")}`);
32759
- for (const name of result.mcpResult.addedServers) {
32760
- console.log(` + ${name}`);
32761
- }
32762
- for (const name of result.mcpResult.overwrittenServers) {
32763
- console.log(` ~ ${name}`);
32980
+ if (result.mcpResult) {
32981
+ const mcpLines = formatMcpResult(result.mcpResult);
32982
+ if (mcpLines.length > 0) {
32983
+ console.log("");
32984
+ for (const line of mcpLines) {
32985
+ console.log(line);
32986
+ }
32764
32987
  }
32765
32988
  }
32766
32989
  console.log(`
@@ -33723,24 +33946,6 @@ var skillsCmd = conciseSubcommands({
33723
33946
  });
33724
33947
 
33725
33948
  // src/cli/commands/plugin.ts
33726
- function buildSyncData2(result) {
33727
- return {
33728
- copied: result.totalCopied,
33729
- generated: result.totalGenerated,
33730
- failed: result.totalFailed,
33731
- skipped: result.totalSkipped,
33732
- plugins: result.pluginResults.map((pr) => ({
33733
- plugin: pr.plugin,
33734
- success: pr.success,
33735
- error: pr.error,
33736
- copied: pr.copyResults.filter((r) => r.action === "copied").length,
33737
- generated: pr.copyResults.filter((r) => r.action === "generated").length,
33738
- failed: pr.copyResults.filter((r) => r.action === "failed").length,
33739
- copyResults: pr.copyResults
33740
- })),
33741
- purgedPaths: result.purgedPaths ?? []
33742
- };
33743
- }
33744
33949
  async function runSyncAndPrint(options2) {
33745
33950
  if (!isJsonMode()) {
33746
33951
  console.log(`
@@ -33754,7 +33959,7 @@ Syncing workspace...
33754
33959
  }
33755
33960
  return { ok: false, syncData: null };
33756
33961
  }
33757
- const syncData = buildSyncData2(result);
33962
+ const syncData = buildSyncData(result);
33758
33963
  if (!isJsonMode()) {
33759
33964
  for (const pluginResult of result.pluginResults) {
33760
33965
  const status = pluginResult.success ? "✓" : "✗";
@@ -33804,7 +34009,7 @@ Syncing user workspace...
33804
34009
  }
33805
34010
  return { ok: false, syncData: null };
33806
34011
  }
33807
- const syncData = buildSyncData2(result);
34012
+ const syncData = buildSyncData(result);
33808
34013
  if (!isJsonMode()) {
33809
34014
  for (const pluginResult of result.pluginResults) {
33810
34015
  const status = pluginResult.success ? "✓" : "✗";
@@ -33826,6 +34031,15 @@ Syncing user workspace...
33826
34031
  }
33827
34032
  }
33828
34033
  }
34034
+ if (result.mcpResult) {
34035
+ const mcpLines = formatMcpResult(result.mcpResult);
34036
+ if (mcpLines.length > 0) {
34037
+ console.log("");
34038
+ for (const line of mcpLines) {
34039
+ console.log(line);
34040
+ }
34041
+ }
34042
+ }
33829
34043
  console.log(`
33830
34044
  User sync complete:`);
33831
34045
  console.log(` Total copied: ${result.totalCopied}`);
@@ -34518,7 +34732,7 @@ var pluginUpdateCmd = import_cmd_ts4.command({
34518
34732
  const updatedMarketplaces = new Set;
34519
34733
  const deps = {
34520
34734
  parsePluginSpec,
34521
- getMarketplace,
34735
+ getMarketplace: (name, sourceLocation) => findMarketplace(name, sourceLocation),
34522
34736
  parseMarketplaceManifest,
34523
34737
  updateMarketplace: async (name) => {
34524
34738
  if (updatedMarketplaces.has(name)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "allagents",
3
- "version": "0.22.1",
3
+ "version": "0.22.3",
4
4
  "description": "CLI tool for managing multi-repo AI agent workspaces with plugin synchronization",
5
5
  "type": "module",
6
6
  "bin": {