allagents 0.19.1 → 0.20.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 (2) hide show
  1. package/dist/index.js +736 -132
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -11424,7 +11424,8 @@ var init_workspace_config = __esm(() => {
11424
11424
  plugins: exports_external.array(PluginSourceSchema),
11425
11425
  clients: exports_external.array(ClientTypeSchema),
11426
11426
  vscode: VscodeConfigSchema.optional(),
11427
- syncMode: SyncModeSchema.optional()
11427
+ syncMode: SyncModeSchema.optional(),
11428
+ disabledSkills: exports_external.array(exports_external.string()).optional()
11428
11429
  });
11429
11430
  });
11430
11431
 
@@ -25006,7 +25007,10 @@ async function copySkills(pluginPath, workspacePath, client, options2 = {}) {
25006
25007
  await mkdir3(destDir, { recursive: true });
25007
25008
  }
25008
25009
  const entries = await readdir2(sourceDir, { withFileTypes: true });
25009
- const skillDirs = entries.filter((e) => e.isDirectory());
25010
+ let skillDirs = entries.filter((e) => e.isDirectory());
25011
+ if (skillNameMap) {
25012
+ skillDirs = skillDirs.filter((e) => skillNameMap.has(e.name));
25013
+ }
25010
25014
  const useSymlinks = syncMode === "symlink" && !isUniversalClient(client) && canonicalSkillsPath;
25011
25015
  const copyPromises = skillDirs.map(async (entry) => {
25012
25016
  const skillSourcePath = join6(sourceDir, entry.name);
@@ -25057,14 +25061,15 @@ async function copySkills(pluginPath, workspacePath, client, options2 = {}) {
25057
25061
  });
25058
25062
  return Promise.all(copyPromises);
25059
25063
  }
25060
- async function collectPluginSkills(pluginPath, pluginSource) {
25064
+ async function collectPluginSkills(pluginPath, pluginSource, disabledSkills, pluginName) {
25061
25065
  const skillsDir = join6(pluginPath, "skills");
25062
25066
  if (!existsSync4(skillsDir)) {
25063
25067
  return [];
25064
25068
  }
25065
25069
  const entries = await readdir2(skillsDir, { withFileTypes: true });
25066
25070
  const skillDirs = entries.filter((e) => e.isDirectory());
25067
- return skillDirs.map((entry) => ({
25071
+ const filteredDirs = disabledSkills && pluginName ? skillDirs.filter((e) => !disabledSkills.has(`${pluginName}:${e.name}`)) : skillDirs;
25072
+ return filteredDirs.map((entry) => ({
25068
25073
  folderName: entry.name,
25069
25074
  skillPath: join6(skillsDir, entry.name),
25070
25075
  pluginPath,
@@ -25553,15 +25558,18 @@ __export(exports_user_workspace, {
25553
25558
  resolveGitHubIdentity: () => resolveGitHubIdentity,
25554
25559
  removeUserPluginsForMarketplace: () => removeUserPluginsForMarketplace,
25555
25560
  removeUserPlugin: () => removeUserPlugin,
25561
+ removeUserDisabledSkill: () => removeUserDisabledSkill,
25556
25562
  isUserConfigPath: () => isUserConfigPath,
25557
25563
  hasUserPlugin: () => hasUserPlugin,
25558
25564
  getUserWorkspaceConfigPath: () => getUserWorkspaceConfigPath,
25559
25565
  getUserWorkspaceConfig: () => getUserWorkspaceConfig,
25560
25566
  getUserPluginsForMarketplace: () => getUserPluginsForMarketplace,
25567
+ getUserDisabledSkills: () => getUserDisabledSkills,
25561
25568
  getInstalledUserPlugins: () => getInstalledUserPlugins,
25562
25569
  getInstalledProjectPlugins: () => getInstalledProjectPlugins,
25563
25570
  ensureUserWorkspace: () => ensureUserWorkspace,
25564
- addUserPlugin: () => addUserPlugin
25571
+ addUserPlugin: () => addUserPlugin,
25572
+ addUserDisabledSkill: () => addUserDisabledSkill
25565
25573
  });
25566
25574
  import { readFile as readFile6, writeFile as writeFile2, mkdir as mkdir4 } from "node:fs/promises";
25567
25575
  import { existsSync as existsSync6 } from "node:fs";
@@ -25749,6 +25757,53 @@ async function addPluginToUserConfig(plugin, configPath, autoRegistered) {
25749
25757
  };
25750
25758
  }
25751
25759
  }
25760
+ async function getUserDisabledSkills() {
25761
+ const config = await getUserWorkspaceConfig();
25762
+ return config?.disabledSkills ?? [];
25763
+ }
25764
+ async function addUserDisabledSkill(skillKey) {
25765
+ await ensureUserWorkspace();
25766
+ const configPath = getUserWorkspaceConfigPath();
25767
+ try {
25768
+ const content = await readFile6(configPath, "utf-8");
25769
+ const config = load(content);
25770
+ const disabledSkills = config.disabledSkills ?? [];
25771
+ if (disabledSkills.includes(skillKey)) {
25772
+ return { success: false, error: `Skill '${skillKey}' is already disabled` };
25773
+ }
25774
+ config.disabledSkills = [...disabledSkills, skillKey];
25775
+ await writeFile2(configPath, dump(config, { lineWidth: -1 }), "utf-8");
25776
+ return { success: true };
25777
+ } catch (error) {
25778
+ return {
25779
+ success: false,
25780
+ error: error instanceof Error ? error.message : String(error)
25781
+ };
25782
+ }
25783
+ }
25784
+ async function removeUserDisabledSkill(skillKey) {
25785
+ await ensureUserWorkspace();
25786
+ const configPath = getUserWorkspaceConfigPath();
25787
+ try {
25788
+ const content = await readFile6(configPath, "utf-8");
25789
+ const config = load(content);
25790
+ const disabledSkills = config.disabledSkills ?? [];
25791
+ if (!disabledSkills.includes(skillKey)) {
25792
+ return { success: false, error: `Skill '${skillKey}' is already enabled` };
25793
+ }
25794
+ config.disabledSkills = disabledSkills.filter((s) => s !== skillKey);
25795
+ if (config.disabledSkills.length === 0) {
25796
+ config.disabledSkills = undefined;
25797
+ }
25798
+ await writeFile2(configPath, dump(config, { lineWidth: -1 }), "utf-8");
25799
+ return { success: true };
25800
+ } catch (error) {
25801
+ return {
25802
+ success: false,
25803
+ error: error instanceof Error ? error.message : String(error)
25804
+ };
25805
+ }
25806
+ }
25752
25807
  async function getInstalledUserPlugins() {
25753
25808
  const config = await getUserWorkspaceConfig();
25754
25809
  if (!config)
@@ -25851,14 +25906,22 @@ async function saveRegistry(registry) {
25851
25906
  await writeFile3(registryPath, `${JSON.stringify(registry, null, 2)}
25852
25907
  `);
25853
25908
  }
25854
- function parseMarketplaceSource(source) {
25855
- if (WELL_KNOWN_MARKETPLACES[source]) {
25856
- return {
25857
- type: "github",
25858
- location: WELL_KNOWN_MARKETPLACES[source],
25859
- name: source
25860
- };
25909
+ function getSourceLocationKey(source) {
25910
+ if (source.type === "github") {
25911
+ const { owner, repo } = parseLocation(source.location);
25912
+ return `${owner}/${repo}`;
25861
25913
  }
25914
+ return source.location;
25915
+ }
25916
+ function findBySourceLocation(registry, sourceLocation) {
25917
+ for (const entry of Object.values(registry.marketplaces)) {
25918
+ if (getSourceLocationKey(entry.source) === sourceLocation) {
25919
+ return entry;
25920
+ }
25921
+ }
25922
+ return null;
25923
+ }
25924
+ function parseMarketplaceSource(source) {
25862
25925
  if (source.startsWith("https://github.com/")) {
25863
25926
  const match = source.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?(?:\/tree\/(.+))?$/);
25864
25927
  if (match) {
@@ -25902,7 +25965,7 @@ async function addMarketplace(source, customName, branch) {
25902
25965
  return {
25903
25966
  success: false,
25904
25967
  error: `Invalid marketplace source: ${source}
25905
- Use: GitHub URL, owner/repo, local path, or well-known name`
25968
+ Use: GitHub URL, owner/repo, or local path`
25906
25969
  };
25907
25970
  }
25908
25971
  const effectiveBranch = branch || parsed.branch;
@@ -25930,6 +25993,11 @@ async function addMarketplace(source, customName, branch) {
25930
25993
  error: `Marketplace '${name}' already exists. Use 'update' to refresh it.`
25931
25994
  };
25932
25995
  }
25996
+ const sourceLocation = parsed.type === "github" ? `${parseLocation(parsed.location).owner}/${parseLocation(parsed.location).repo}` : parsed.location;
25997
+ const existingBySource = findBySourceLocation(registry, sourceLocation);
25998
+ if (existingBySource) {
25999
+ return { success: true, marketplace: existingBySource };
26000
+ }
25933
26001
  let marketplacePath;
25934
26002
  if (parsed.type === "github") {
25935
26003
  marketplacePath = join9(getMarketplacesDir(), name);
@@ -26049,11 +26117,7 @@ async function findMarketplace(name, sourceLocation) {
26049
26117
  return registry.marketplaces[name];
26050
26118
  }
26051
26119
  if (sourceLocation) {
26052
- for (const entry of Object.values(registry.marketplaces)) {
26053
- if (entry.source.location === sourceLocation) {
26054
- return entry;
26055
- }
26056
- }
26120
+ return findBySourceLocation(registry, sourceLocation);
26057
26121
  }
26058
26122
  return null;
26059
26123
  }
@@ -26335,35 +26399,22 @@ async function resolvePluginSpecWithAutoRegister(spec, options2 = {}) {
26335
26399
  ...marketplace.name !== marketplaceName && { registeredAs: marketplace.name }
26336
26400
  };
26337
26401
  }
26338
- async function autoRegisterMarketplace(name) {
26339
- const wellKnown = getWellKnownMarketplaces();
26340
- if (wellKnown[name]) {
26341
- console.log(`Auto-registering well-known marketplace: ${name}`);
26342
- const result = await addMarketplace(name);
26343
- if (!result.success) {
26344
- return { success: false, error: result.error || "Unknown error" };
26345
- }
26346
- return { success: true, name };
26347
- }
26348
- if (name.includes("/") && !name.includes("://")) {
26349
- const parts = name.split("/");
26402
+ async function autoRegisterMarketplace(source) {
26403
+ if (source.includes("/") && !source.includes("://")) {
26404
+ const parts = source.split("/");
26350
26405
  if (parts.length === 2 && parts[0] && parts[1]) {
26351
- console.log(`Auto-registering GitHub marketplace: ${name}`);
26352
- const result = await addMarketplace(name);
26406
+ console.log(`Auto-registering GitHub marketplace: ${source}`);
26407
+ const result = await addMarketplace(source);
26353
26408
  if (!result.success) {
26354
26409
  return { success: false, error: result.error || "Unknown error" };
26355
26410
  }
26356
- const registeredName = result.marketplace?.name ?? parts[1];
26357
- return { success: true, name: registeredName };
26411
+ return { success: true, name: result.marketplace?.name ?? parts[1] };
26358
26412
  }
26359
26413
  }
26360
26414
  return {
26361
26415
  success: false,
26362
- error: `Marketplace '${name}' not found.
26363
- Options:
26364
- 1. Use fully qualified name: plugin@owner/repo
26365
- 2. Register first: allagents plugin marketplace add <source>
26366
- 3. Well-known marketplaces: ${Object.keys(wellKnown).join(", ")}`
26416
+ error: `Marketplace '${source}' not found.
26417
+ Use fully qualified format: plugin@owner/repo`
26367
26418
  };
26368
26419
  }
26369
26420
  function isPluginSpec(spec) {
@@ -26373,8 +26424,35 @@ function isPluginSpec(spec) {
26373
26424
  }
26374
26425
  return true;
26375
26426
  }
26376
- function getWellKnownMarketplaces() {
26377
- return { ...WELL_KNOWN_MARKETPLACES };
26427
+ function extractUniqueMarketplaceSources(plugins) {
26428
+ const sources = new Set;
26429
+ for (const plugin of plugins) {
26430
+ if (!isPluginSpec(plugin))
26431
+ continue;
26432
+ const parsed = parsePluginSpec(plugin);
26433
+ if (!parsed)
26434
+ continue;
26435
+ if (parsed.owner && parsed.repo) {
26436
+ sources.add(`${parsed.owner}/${parsed.repo}`);
26437
+ }
26438
+ }
26439
+ return Array.from(sources);
26440
+ }
26441
+ async function ensureMarketplacesRegistered(plugins) {
26442
+ const sources = extractUniqueMarketplaceSources(plugins);
26443
+ const results = [];
26444
+ for (const source of sources) {
26445
+ const parts = source.split("/");
26446
+ const sourceLocation = source;
26447
+ const existing = await findMarketplace(parts[1] ?? "", sourceLocation);
26448
+ if (existing) {
26449
+ results.push({ source, success: true, name: existing.name });
26450
+ continue;
26451
+ }
26452
+ const result = await autoRegisterMarketplace(source);
26453
+ results.push({ source, ...result });
26454
+ }
26455
+ return results;
26378
26456
  }
26379
26457
  async function getMarketplaceVersion(marketplacePath) {
26380
26458
  if (!existsSync7(marketplacePath)) {
@@ -26388,7 +26466,6 @@ async function getMarketplaceVersion(marketplacePath) {
26388
26466
  return null;
26389
26467
  }
26390
26468
  }
26391
- var WELL_KNOWN_MARKETPLACES;
26392
26469
  var init_marketplace = __esm(() => {
26393
26470
  init_esm();
26394
26471
  init_git();
@@ -26396,9 +26473,6 @@ var init_marketplace = __esm(() => {
26396
26473
  init_plugin();
26397
26474
  init_plugin_path();
26398
26475
  init_constants();
26399
- WELL_KNOWN_MARKETPLACES = {
26400
- "claude-plugins-official": "anthropics/claude-plugins-official"
26401
- };
26402
26476
  });
26403
26477
 
26404
26478
  // src/core/workspace-modify.ts
@@ -26552,6 +26626,65 @@ async function removePlugin(plugin, workspacePath = process.cwd()) {
26552
26626
  };
26553
26627
  }
26554
26628
  }
26629
+ async function addDisabledSkill(skillKey, workspacePath = process.cwd()) {
26630
+ const configPath = join10(workspacePath, CONFIG_DIR, WORKSPACE_CONFIG_FILE);
26631
+ if (!existsSync8(configPath)) {
26632
+ return {
26633
+ success: false,
26634
+ error: `${CONFIG_DIR}/${WORKSPACE_CONFIG_FILE} not found in ${workspacePath}`
26635
+ };
26636
+ }
26637
+ try {
26638
+ const content = await readFile8(configPath, "utf-8");
26639
+ const config = load(content);
26640
+ const disabledSkills = config.disabledSkills ?? [];
26641
+ if (disabledSkills.includes(skillKey)) {
26642
+ return {
26643
+ success: false,
26644
+ error: `Skill '${skillKey}' is already disabled`
26645
+ };
26646
+ }
26647
+ config.disabledSkills = [...disabledSkills, skillKey];
26648
+ await writeFile4(configPath, dump(config, { lineWidth: -1 }), "utf-8");
26649
+ return { success: true };
26650
+ } catch (error) {
26651
+ return {
26652
+ success: false,
26653
+ error: error instanceof Error ? error.message : String(error)
26654
+ };
26655
+ }
26656
+ }
26657
+ async function removeDisabledSkill(skillKey, workspacePath = process.cwd()) {
26658
+ const configPath = join10(workspacePath, CONFIG_DIR, WORKSPACE_CONFIG_FILE);
26659
+ if (!existsSync8(configPath)) {
26660
+ return {
26661
+ success: false,
26662
+ error: `${CONFIG_DIR}/${WORKSPACE_CONFIG_FILE} not found in ${workspacePath}`
26663
+ };
26664
+ }
26665
+ try {
26666
+ const content = await readFile8(configPath, "utf-8");
26667
+ const config = load(content);
26668
+ const disabledSkills = config.disabledSkills ?? [];
26669
+ if (!disabledSkills.includes(skillKey)) {
26670
+ return {
26671
+ success: false,
26672
+ error: `Skill '${skillKey}' is already enabled`
26673
+ };
26674
+ }
26675
+ config.disabledSkills = disabledSkills.filter((s) => s !== skillKey);
26676
+ if (config.disabledSkills.length === 0) {
26677
+ config.disabledSkills = undefined;
26678
+ }
26679
+ await writeFile4(configPath, dump(config, { lineWidth: -1 }), "utf-8");
26680
+ return { success: true };
26681
+ } catch (error) {
26682
+ return {
26683
+ success: false,
26684
+ error: error instanceof Error ? error.message : String(error)
26685
+ };
26686
+ }
26687
+ }
26555
26688
  var DEFAULT_PROJECT_CLIENTS;
26556
26689
  var init_workspace_modify = __esm(() => {
26557
26690
  init_js_yaml();
@@ -27345,11 +27478,11 @@ async function copyValidatedPlugin(validatedPlugin, workspacePath, clients, dryR
27345
27478
  copyResults
27346
27479
  };
27347
27480
  }
27348
- async function collectAllSkills(validatedPlugins) {
27481
+ async function collectAllSkills(validatedPlugins, disabledSkills) {
27349
27482
  const allSkills = [];
27350
27483
  for (const plugin of validatedPlugins) {
27351
27484
  const pluginName = plugin.pluginName ?? await getPluginName(plugin.resolved);
27352
- const skills = await collectPluginSkills(plugin.resolved, plugin.plugin);
27485
+ const skills = await collectPluginSkills(plugin.resolved, plugin.plugin, disabledSkills, pluginName);
27353
27486
  for (const skill of skills) {
27354
27487
  allSkills.push({
27355
27488
  folderName: skill.folderName,
@@ -27453,6 +27586,7 @@ async function syncWorkspace(workspacePath = process.cwd(), options2 = {}) {
27453
27586
  };
27454
27587
  }
27455
27588
  }
27589
+ await ensureMarketplacesRegistered(config.plugins);
27456
27590
  const validatedPlugins = await validateAllPlugins(config.plugins, workspacePath, offline);
27457
27591
  let validatedWorkspaceSource = null;
27458
27592
  if (config.workspace?.source) {
@@ -27497,7 +27631,8 @@ ${failedValidations.map((v) => ` - ${v.plugin}: ${v.error}`).join(`
27497
27631
  partialSync: !!options2.clients
27498
27632
  });
27499
27633
  }
27500
- const allSkills = await collectAllSkills(validPlugins);
27634
+ const disabledSkillsSet = new Set(config.disabledSkills ?? []);
27635
+ const allSkills = await collectAllSkills(validPlugins, disabledSkillsSet);
27501
27636
  const pluginSkillMaps = buildPluginSkillNameMaps(allSkills);
27502
27637
  const syncMode = config.syncMode ?? "symlink";
27503
27638
  const pluginResults = await Promise.all(validPlugins.map((validatedPlugin) => {
@@ -27642,6 +27777,7 @@ async function syncUserWorkspace(options2 = {}) {
27642
27777
  }
27643
27778
  const clients = config.clients;
27644
27779
  const { offline = false, dryRun = false } = options2;
27780
+ await ensureMarketplacesRegistered(config.plugins);
27645
27781
  const validatedPlugins = await validateAllPlugins(config.plugins, homeDir, offline);
27646
27782
  const failedValidations = validatedPlugins.filter((v) => !v.success);
27647
27783
  const validPlugins = validatedPlugins.filter((v) => v.success);
@@ -27664,7 +27800,8 @@ ${failedValidations.map((v) => ` - ${v.plugin}: ${v.error}`).join(`
27664
27800
  if (!dryRun) {
27665
27801
  await selectivePurgeWorkspace(homeDir, previousState, clients);
27666
27802
  }
27667
- const allSkills = await collectAllSkills(validPlugins);
27803
+ const disabledSkillsSet = new Set(config.disabledSkills ?? []);
27804
+ const allSkills = await collectAllSkills(validPlugins, disabledSkillsSet);
27668
27805
  const pluginSkillMaps = buildPluginSkillNameMaps(allSkills);
27669
27806
  const syncMode = config.syncMode ?? "symlink";
27670
27807
  const pluginResults = await Promise.all(validPlugins.map((vp) => {
@@ -28237,12 +28374,12 @@ var require_isexe = __commonJS((exports, module) => {
28237
28374
  if (typeof Promise !== "function") {
28238
28375
  throw new TypeError("callback not provided");
28239
28376
  }
28240
- return new Promise(function(resolve12, reject) {
28377
+ return new Promise(function(resolve13, reject) {
28241
28378
  isexe(path, options2 || {}, function(er, is) {
28242
28379
  if (er) {
28243
28380
  reject(er);
28244
28381
  } else {
28245
- resolve12(is);
28382
+ resolve13(is);
28246
28383
  }
28247
28384
  });
28248
28385
  });
@@ -28304,27 +28441,27 @@ var require_which = __commonJS((exports, module) => {
28304
28441
  opt = {};
28305
28442
  const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
28306
28443
  const found = [];
28307
- const step = (i2) => new Promise((resolve12, reject) => {
28444
+ const step = (i2) => new Promise((resolve13, reject) => {
28308
28445
  if (i2 === pathEnv.length)
28309
- return opt.all && found.length ? resolve12(found) : reject(getNotFoundError(cmd));
28446
+ return opt.all && found.length ? resolve13(found) : reject(getNotFoundError(cmd));
28310
28447
  const ppRaw = pathEnv[i2];
28311
28448
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
28312
28449
  const pCmd = path.join(pathPart, cmd);
28313
28450
  const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
28314
- resolve12(subStep(p, i2, 0));
28451
+ resolve13(subStep(p, i2, 0));
28315
28452
  });
28316
- const subStep = (p, i2, ii) => new Promise((resolve12, reject) => {
28453
+ const subStep = (p, i2, ii) => new Promise((resolve13, reject) => {
28317
28454
  if (ii === pathExt.length)
28318
- return resolve12(step(i2 + 1));
28455
+ return resolve13(step(i2 + 1));
28319
28456
  const ext = pathExt[ii];
28320
28457
  isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
28321
28458
  if (!er && is) {
28322
28459
  if (opt.all)
28323
28460
  found.push(p + ext);
28324
28461
  else
28325
- return resolve12(p + ext);
28462
+ return resolve13(p + ext);
28326
28463
  }
28327
- return resolve12(subStep(p, i2, ii + 1));
28464
+ return resolve13(subStep(p, i2, ii + 1));
28328
28465
  });
28329
28466
  });
28330
28467
  return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
@@ -28442,8 +28579,8 @@ var require_shebang_regex = __commonJS((exports, module) => {
28442
28579
  // node_modules/shebang-command/index.js
28443
28580
  var require_shebang_command = __commonJS((exports, module) => {
28444
28581
  var shebangRegex = require_shebang_regex();
28445
- module.exports = (string3 = "") => {
28446
- const match = string3.match(shebangRegex);
28582
+ module.exports = (string4 = "") => {
28583
+ const match = string4.match(shebangRegex);
28447
28584
  if (!match) {
28448
28585
  return null;
28449
28586
  }
@@ -28460,12 +28597,12 @@ var require_shebang_command = __commonJS((exports, module) => {
28460
28597
  var require_readShebang = __commonJS((exports, module) => {
28461
28598
  var fs = __require("fs");
28462
28599
  var shebangCommand = require_shebang_command();
28463
- function readShebang(command3) {
28600
+ function readShebang(command4) {
28464
28601
  const size = 150;
28465
28602
  const buffer = Buffer.alloc(size);
28466
28603
  let fd;
28467
28604
  try {
28468
- fd = fs.openSync(command3, "r");
28605
+ fd = fs.openSync(command4, "r");
28469
28606
  fs.readSync(fd, buffer, 0, size, 0);
28470
28607
  fs.closeSync(fd);
28471
28608
  } catch (e) {}
@@ -28511,7 +28648,7 @@ var require_parse5 = __commonJS((exports, module) => {
28511
28648
  }
28512
28649
  return parsed;
28513
28650
  }
28514
- function parse2(command3, args, options2) {
28651
+ function parse2(command4, args, options2) {
28515
28652
  if (args && !Array.isArray(args)) {
28516
28653
  options2 = args;
28517
28654
  args = null;
@@ -28519,12 +28656,12 @@ var require_parse5 = __commonJS((exports, module) => {
28519
28656
  args = args ? args.slice(0) : [];
28520
28657
  options2 = Object.assign({}, options2);
28521
28658
  const parsed = {
28522
- command: command3,
28659
+ command: command4,
28523
28660
  args,
28524
28661
  options: options2,
28525
28662
  file: undefined,
28526
28663
  original: {
28527
- command: command3,
28664
+ command: command4,
28528
28665
  args
28529
28666
  }
28530
28667
  };
@@ -28585,14 +28722,14 @@ var require_cross_spawn = __commonJS((exports, module) => {
28585
28722
  var cp2 = __require("child_process");
28586
28723
  var parse2 = require_parse5();
28587
28724
  var enoent = require_enoent();
28588
- function spawn2(command3, args, options2) {
28589
- const parsed = parse2(command3, args, options2);
28725
+ function spawn2(command4, args, options2) {
28726
+ const parsed = parse2(command4, args, options2);
28590
28727
  const spawned = cp2.spawn(parsed.command, parsed.args, parsed.options);
28591
28728
  enoent.hookChildProcess(spawned, parsed);
28592
28729
  return spawned;
28593
28730
  }
28594
- function spawnSync(command3, args, options2) {
28595
- const parsed = parse2(command3, args, options2);
28731
+ function spawnSync(command4, args, options2) {
28732
+ const parsed = parse2(command4, args, options2);
28596
28733
  const result = cp2.spawnSync(parsed.command, parsed.args, parsed.options);
28597
28734
  result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
28598
28735
  return result;
@@ -29135,7 +29272,7 @@ var getErrorPrefix = ({ timedOut, timeout, errorCode, signal, signalDescription,
29135
29272
  error,
29136
29273
  signal,
29137
29274
  exitCode,
29138
- command: command3,
29275
+ command: command4,
29139
29276
  escapedCommand,
29140
29277
  timedOut,
29141
29278
  isCanceled,
@@ -29147,7 +29284,7 @@ var getErrorPrefix = ({ timedOut, timeout, errorCode, signal, signalDescription,
29147
29284
  const signalDescription = signal === undefined ? undefined : signalsByName[signal].description;
29148
29285
  const errorCode = error && error.code;
29149
29286
  const prefix = getErrorPrefix({ timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled });
29150
- const execaMessage = `Command ${prefix}: ${command3}`;
29287
+ const execaMessage = `Command ${prefix}: ${command4}`;
29151
29288
  const isError = Object.prototype.toString.call(error) === "[object Error]";
29152
29289
  const shortMessage = isError ? `${execaMessage}
29153
29290
  ${error.message}` : execaMessage;
@@ -29160,7 +29297,7 @@ ${error.message}` : execaMessage;
29160
29297
  error = new Error(message);
29161
29298
  }
29162
29299
  error.shortMessage = shortMessage;
29163
- error.command = command3;
29300
+ error.command = command4;
29164
29301
  error.escapedCommand = escapedCommand;
29165
29302
  error.exitCode = exitCode;
29166
29303
  error.signal = signal;
@@ -29457,7 +29594,7 @@ var DEFAULT_FORCE_KILL_TIMEOUT, spawnedKill = (kill, signal = "SIGTERM", options
29457
29594
  return spawnedPromise;
29458
29595
  }
29459
29596
  let timeoutId;
29460
- const timeoutPromise = new Promise((resolve12, reject) => {
29597
+ const timeoutPromise = new Promise((resolve13, reject) => {
29461
29598
  timeoutId = setTimeout(() => {
29462
29599
  timeoutKill(spawned, killSignal, reject);
29463
29600
  }, timeout);
@@ -29847,9 +29984,9 @@ var nativePromisePrototype, descriptors, mergePromise = (spawned, promise) => {
29847
29984
  const value = typeof promise === "function" ? (...args) => Reflect.apply(descriptor.value, promise(), args) : descriptor.value.bind(promise);
29848
29985
  Reflect.defineProperty(spawned, property, { ...descriptor, value });
29849
29986
  }
29850
- }, getSpawnedPromise = (spawned) => new Promise((resolve12, reject) => {
29987
+ }, getSpawnedPromise = (spawned) => new Promise((resolve13, reject) => {
29851
29988
  spawned.on("exit", (exitCode, signal) => {
29852
- resolve12({ exitCode, signal });
29989
+ resolve13({ exitCode, signal });
29853
29990
  });
29854
29991
  spawned.on("error", (error) => {
29855
29992
  reject(error);
@@ -29950,7 +30087,7 @@ import childProcess from "node:child_process";
29950
30087
  import process7 from "node:process";
29951
30088
  function execa(file, args, options2) {
29952
30089
  const parsed = handleArguments(file, args, options2);
29953
- const command3 = joinCommand(file, args);
30090
+ const command4 = joinCommand(file, args);
29954
30091
  const escapedCommand = getEscapedCommand(file, args);
29955
30092
  logCommand(escapedCommand, parsed.options);
29956
30093
  validateTimeout(parsed.options);
@@ -29964,7 +30101,7 @@ function execa(file, args, options2) {
29964
30101
  stdout: "",
29965
30102
  stderr: "",
29966
30103
  all: "",
29967
- command: command3,
30104
+ command: command4,
29968
30105
  escapedCommand,
29969
30106
  parsed,
29970
30107
  timedOut: false,
@@ -29993,7 +30130,7 @@ function execa(file, args, options2) {
29993
30130
  stdout,
29994
30131
  stderr,
29995
30132
  all,
29996
- command: command3,
30133
+ command: command4,
29997
30134
  escapedCommand,
29998
30135
  parsed,
29999
30136
  timedOut,
@@ -30006,7 +30143,7 @@ function execa(file, args, options2) {
30006
30143
  throw returnedError;
30007
30144
  }
30008
30145
  return {
30009
- command: command3,
30146
+ command: command4,
30010
30147
  escapedCommand,
30011
30148
  exitCode: 0,
30012
30149
  stdout,
@@ -30027,7 +30164,7 @@ function execa(file, args, options2) {
30027
30164
  }
30028
30165
  function execaSync(file, args, options2) {
30029
30166
  const parsed = handleArguments(file, args, options2);
30030
- const command3 = joinCommand(file, args);
30167
+ const command4 = joinCommand(file, args);
30031
30168
  const escapedCommand = getEscapedCommand(file, args);
30032
30169
  logCommand(escapedCommand, parsed.options);
30033
30170
  const input = handleInputSync(parsed.options);
@@ -30040,7 +30177,7 @@ function execaSync(file, args, options2) {
30040
30177
  stdout: "",
30041
30178
  stderr: "",
30042
30179
  all: "",
30043
- command: command3,
30180
+ command: command4,
30044
30181
  escapedCommand,
30045
30182
  parsed,
30046
30183
  timedOut: false,
@@ -30057,7 +30194,7 @@ function execaSync(file, args, options2) {
30057
30194
  error: result.error,
30058
30195
  signal: result.signal,
30059
30196
  exitCode: result.status,
30060
- command: command3,
30197
+ command: command4,
30061
30198
  escapedCommand,
30062
30199
  parsed,
30063
30200
  timedOut: result.error && result.error.code === "ETIMEDOUT",
@@ -30070,7 +30207,7 @@ function execaSync(file, args, options2) {
30070
30207
  throw error;
30071
30208
  }
30072
30209
  return {
30073
- command: command3,
30210
+ command: command4,
30074
30211
  escapedCommand,
30075
30212
  exitCode: 0,
30076
30213
  stdout,
@@ -30165,7 +30302,7 @@ var package_default;
30165
30302
  var init_package = __esm(() => {
30166
30303
  package_default = {
30167
30304
  name: "allagents",
30168
- version: "0.19.1",
30305
+ version: "0.20.0",
30169
30306
  description: "CLI tool for managing multi-repo AI agent workspaces with plugin synchronization",
30170
30307
  type: "module",
30171
30308
  bin: {
@@ -30234,13 +30371,13 @@ var init_package = __esm(() => {
30234
30371
  });
30235
30372
 
30236
30373
  // src/cli/update-check.ts
30237
- import { readFile as readFile13 } from "node:fs/promises";
30238
- import { join as join19 } from "node:path";
30374
+ import { readFile as readFile14 } from "node:fs/promises";
30375
+ import { join as join20 } from "node:path";
30239
30376
  import { spawn as spawn2 } from "node:child_process";
30240
30377
  async function getCachedUpdateInfo(path3) {
30241
- const filePath = path3 ?? join19(getHomeDir(), CONFIG_DIR, CACHE_FILE);
30378
+ const filePath = path3 ?? join20(getHomeDir(), CONFIG_DIR, CACHE_FILE);
30242
30379
  try {
30243
- const raw = await readFile13(filePath, "utf-8");
30380
+ const raw = await readFile14(filePath, "utf-8");
30244
30381
  const data = JSON.parse(raw);
30245
30382
  if (typeof data.latestVersion === "string" && typeof data.lastCheckedAt === "string") {
30246
30383
  return data;
@@ -30276,8 +30413,8 @@ function buildNotice(currentVersion, latestVersion) {
30276
30413
  Run \`allagents self update\` to upgrade.`;
30277
30414
  }
30278
30415
  function backgroundUpdateCheck() {
30279
- const dir = join19(getHomeDir(), CONFIG_DIR);
30280
- const filePath = join19(dir, CACHE_FILE);
30416
+ const dir = join20(getHomeDir(), CONFIG_DIR);
30417
+ const filePath = join20(dir, CACHE_FILE);
30281
30418
  const script = `
30282
30419
  const https = require('https');
30283
30420
  const fs = require('fs');
@@ -30328,17 +30465,17 @@ var require_picocolors = __commonJS((exports, module) => {
30328
30465
  var env2 = p.env || {};
30329
30466
  var isColorSupported = !(!!env2.NO_COLOR || argv.includes("--no-color")) && (!!env2.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env2.TERM !== "dumb" || !!env2.CI);
30330
30467
  var formatter = (open, close, replace = open) => (input) => {
30331
- let string3 = "" + input, index = string3.indexOf(close, open.length);
30332
- return ~index ? open + replaceClose(string3, close, replace, index) + close : open + string3 + close;
30468
+ let string4 = "" + input, index = string4.indexOf(close, open.length);
30469
+ return ~index ? open + replaceClose(string4, close, replace, index) + close : open + string4 + close;
30333
30470
  };
30334
- var replaceClose = (string3, close, replace, index) => {
30471
+ var replaceClose = (string4, close, replace, index) => {
30335
30472
  let result = "", cursor = 0;
30336
30473
  do {
30337
- result += string3.substring(cursor, index) + replace;
30474
+ result += string4.substring(cursor, index) + replace;
30338
30475
  cursor = index + close.length;
30339
- index = string3.indexOf(close, cursor);
30476
+ index = string4.indexOf(close, cursor);
30340
30477
  } while (~index);
30341
- return result + string3.substring(cursor);
30478
+ return result + string4.substring(cursor);
30342
30479
  };
30343
30480
  var createColors = (enabled = isColorSupported) => {
30344
30481
  let f = enabled ? formatter : () => String;
@@ -32113,15 +32250,15 @@ class TuiCache {
32113
32250
  }
32114
32251
 
32115
32252
  // src/cli/tui/context.ts
32116
- import { existsSync as existsSync17 } from "node:fs";
32117
- import { join as join20 } from "node:path";
32253
+ import { existsSync as existsSync18 } from "node:fs";
32254
+ import { join as join21 } from "node:path";
32118
32255
  async function getTuiContext(cwd = process.cwd(), cache2) {
32119
32256
  const cachedContext = cache2?.getContext();
32120
32257
  if (cachedContext) {
32121
32258
  return cachedContext;
32122
32259
  }
32123
- const configPath = join20(cwd, CONFIG_DIR, WORKSPACE_CONFIG_FILE);
32124
- const hasWorkspace = existsSync17(configPath) && !isUserConfigPath(cwd);
32260
+ const configPath = join21(cwd, CONFIG_DIR, WORKSPACE_CONFIG_FILE);
32261
+ const hasWorkspace = existsSync18(configPath) && !isUserConfigPath(cwd);
32125
32262
  let projectPluginCount = 0;
32126
32263
  if (hasWorkspace) {
32127
32264
  try {
@@ -32878,7 +33015,7 @@ var init_wizard = __esm(() => {
32878
33015
  });
32879
33016
 
32880
33017
  // src/cli/index.ts
32881
- var import_cmd_ts5 = __toESM(require_cjs(), 1);
33018
+ var import_cmd_ts6 = __toESM(require_cjs(), 1);
32882
33019
 
32883
33020
  // src/cli/help.ts
32884
33021
  var import_cmd_ts = __toESM(require_cjs(), 1);
@@ -33651,7 +33788,7 @@ init_marketplace();
33651
33788
  init_sync();
33652
33789
  init_workspace_modify();
33653
33790
  init_user_workspace();
33654
- var import_cmd_ts3 = __toESM(require_cjs(), 1);
33791
+ var import_cmd_ts4 = __toESM(require_cjs(), 1);
33655
33792
 
33656
33793
  // src/cli/metadata/plugin.ts
33657
33794
  var marketplaceListMeta = {
@@ -33818,6 +33955,474 @@ var pluginUninstallMeta = {
33818
33955
  }
33819
33956
  };
33820
33957
 
33958
+ // src/cli/commands/plugin-skills.ts
33959
+ init_sync();
33960
+ init_workspace_modify();
33961
+ init_user_workspace();
33962
+ var import_cmd_ts3 = __toESM(require_cjs(), 1);
33963
+
33964
+ // src/core/skills.ts
33965
+ init_js_yaml();
33966
+ init_constants();
33967
+ init_plugin();
33968
+ init_plugin_path();
33969
+ init_marketplace();
33970
+ import { existsSync as existsSync17 } from "node:fs";
33971
+ import { readFile as readFile13, readdir as readdir4 } from "node:fs/promises";
33972
+ import { join as join19, resolve as resolve12 } from "node:path";
33973
+ async function resolvePluginPath(pluginSource, workspacePath) {
33974
+ if (isPluginSpec(pluginSource)) {
33975
+ const resolved2 = await resolvePluginSpecWithAutoRegister(pluginSource);
33976
+ return resolved2.success ? resolved2.path ?? null : null;
33977
+ }
33978
+ if (isGitHubUrl(pluginSource)) {
33979
+ const parsed = parseGitHubUrl(pluginSource);
33980
+ const result = await fetchPlugin(pluginSource, {
33981
+ offline: true,
33982
+ ...parsed?.branch && { branch: parsed.branch }
33983
+ });
33984
+ if (!result.success)
33985
+ return null;
33986
+ return parsed?.subpath ? join19(result.cachePath, parsed.subpath) : result.cachePath;
33987
+ }
33988
+ const resolved = resolve12(workspacePath, pluginSource);
33989
+ return existsSync17(resolved) ? resolved : null;
33990
+ }
33991
+ async function getAllSkillsFromPlugins(workspacePath = process.cwd()) {
33992
+ const configPath = join19(workspacePath, CONFIG_DIR, WORKSPACE_CONFIG_FILE);
33993
+ if (!existsSync17(configPath)) {
33994
+ return [];
33995
+ }
33996
+ const content = await readFile13(configPath, "utf-8");
33997
+ const config = load(content);
33998
+ const disabledSkills = new Set(config.disabledSkills ?? []);
33999
+ const skills = [];
34000
+ for (const pluginSource of config.plugins) {
34001
+ const pluginPath = await resolvePluginPath(pluginSource, workspacePath);
34002
+ if (!pluginPath)
34003
+ continue;
34004
+ const pluginName = await getPluginName(pluginPath);
34005
+ const skillsDir = join19(pluginPath, "skills");
34006
+ if (!existsSync17(skillsDir))
34007
+ continue;
34008
+ const entries = await readdir4(skillsDir, { withFileTypes: true });
34009
+ const skillDirs = entries.filter((e) => e.isDirectory());
34010
+ for (const entry of skillDirs) {
34011
+ const skillKey = `${pluginName}:${entry.name}`;
34012
+ skills.push({
34013
+ name: entry.name,
34014
+ pluginName,
34015
+ pluginSource,
34016
+ path: join19(skillsDir, entry.name),
34017
+ disabled: disabledSkills.has(skillKey)
34018
+ });
34019
+ }
34020
+ }
34021
+ return skills;
34022
+ }
34023
+ async function findSkillByName(skillName, workspacePath = process.cwd()) {
34024
+ const allSkills = await getAllSkillsFromPlugins(workspacePath);
34025
+ return allSkills.filter((s) => s.name === skillName);
34026
+ }
34027
+
34028
+ // src/cli/metadata/plugin-skills.ts
34029
+ var skillsListMeta = {
34030
+ command: "plugin skills list",
34031
+ description: "List all skills from installed plugins",
34032
+ whenToUse: "To see available skills and their enabled/disabled status",
34033
+ examples: [
34034
+ "allagents plugin skills list",
34035
+ "allagents plugin skills list --scope user"
34036
+ ],
34037
+ expectedOutput: "Lists skills grouped by plugin with enabled/disabled status",
34038
+ options: [
34039
+ { flag: "--scope", short: "-s", type: "string", description: 'Scope: "project" (default) or "user"' }
34040
+ ],
34041
+ outputSchema: {
34042
+ skills: [{ name: "string", plugin: "string", disabled: "boolean" }]
34043
+ }
34044
+ };
34045
+ var skillsRemoveMeta = {
34046
+ command: "plugin skills remove",
34047
+ description: "Disable a skill (exclude from sync)",
34048
+ whenToUse: "To prevent a specific skill from being synced to your workspace",
34049
+ examples: [
34050
+ "allagents plugin skills remove brainstorming",
34051
+ "allagents plugin skills remove brainstorming --plugin superpowers",
34052
+ "allagents plugin skills remove brainstorming --scope user"
34053
+ ],
34054
+ expectedOutput: "Confirms skill was disabled and runs sync",
34055
+ positionals: [
34056
+ { name: "skill", type: "string", required: true, description: "Skill name to disable" }
34057
+ ],
34058
+ options: [
34059
+ { flag: "--scope", short: "-s", type: "string", description: 'Scope: "project" (default) or "user"' },
34060
+ { flag: "--plugin", short: "-p", type: "string", description: "Plugin name (required if skill exists in multiple plugins)" }
34061
+ ],
34062
+ outputSchema: {
34063
+ skill: "string",
34064
+ plugin: "string",
34065
+ syncResult: { copied: "number", failed: "number" }
34066
+ }
34067
+ };
34068
+ var skillsAddMeta = {
34069
+ command: "plugin skills add",
34070
+ description: "Re-enable a previously disabled skill",
34071
+ whenToUse: "To re-enable a skill that was previously disabled",
34072
+ examples: [
34073
+ "allagents plugin skills add brainstorming",
34074
+ "allagents plugin skills add brainstorming --plugin superpowers"
34075
+ ],
34076
+ expectedOutput: "Confirms skill was enabled and runs sync",
34077
+ positionals: [
34078
+ { name: "skill", type: "string", required: true, description: "Skill name to enable" }
34079
+ ],
34080
+ options: [
34081
+ { flag: "--scope", short: "-s", type: "string", description: 'Scope: "project" (default) or "user"' },
34082
+ { flag: "--plugin", short: "-p", type: "string", description: "Plugin name (required if skill exists in multiple plugins)" }
34083
+ ],
34084
+ outputSchema: {
34085
+ skill: "string",
34086
+ plugin: "string",
34087
+ syncResult: { copied: "number", failed: "number" }
34088
+ }
34089
+ };
34090
+
34091
+ // src/cli/commands/plugin-skills.ts
34092
+ init_constants();
34093
+ function groupSkillsByPlugin(skills) {
34094
+ const grouped = new Map;
34095
+ for (const skill of skills) {
34096
+ const existing = grouped.get(skill.pluginName);
34097
+ if (existing) {
34098
+ existing.skills.push({ name: skill.name, disabled: skill.disabled });
34099
+ } else {
34100
+ grouped.set(skill.pluginName, {
34101
+ source: skill.pluginSource,
34102
+ skills: [{ name: skill.name, disabled: skill.disabled }]
34103
+ });
34104
+ }
34105
+ }
34106
+ return grouped;
34107
+ }
34108
+ var listCmd = import_cmd_ts3.command({
34109
+ name: "list",
34110
+ description: buildDescription(skillsListMeta),
34111
+ args: {
34112
+ scope: import_cmd_ts3.option({
34113
+ type: import_cmd_ts3.optional(import_cmd_ts3.string),
34114
+ long: "scope",
34115
+ short: "s",
34116
+ description: 'Scope: "project" (default) or "user"'
34117
+ })
34118
+ },
34119
+ handler: async ({ scope }) => {
34120
+ try {
34121
+ const isUser = scope === "user" || !scope && isUserConfigPath(process.cwd());
34122
+ const workspacePath = isUser ? getHomeDir() : process.cwd();
34123
+ const skills = await getAllSkillsFromPlugins(workspacePath);
34124
+ if (isJsonMode()) {
34125
+ jsonOutput({
34126
+ success: true,
34127
+ command: "plugin skills list",
34128
+ data: {
34129
+ scope: isUser ? "user" : "project",
34130
+ skills: skills.map((s) => ({
34131
+ name: s.name,
34132
+ plugin: s.pluginName,
34133
+ disabled: s.disabled
34134
+ }))
34135
+ }
34136
+ });
34137
+ return;
34138
+ }
34139
+ if (skills.length === 0) {
34140
+ console.log("No skills found. Install a plugin first with:");
34141
+ console.log(" allagents plugin install <plugin>");
34142
+ return;
34143
+ }
34144
+ const grouped = groupSkillsByPlugin(skills);
34145
+ for (const [pluginName, data] of grouped) {
34146
+ console.log(`
34147
+ ${pluginName} (${data.source}):`);
34148
+ for (const skill of data.skills) {
34149
+ const icon = skill.disabled ? "✗" : "✓";
34150
+ const status = skill.disabled ? " (disabled)" : "";
34151
+ console.log(` ${icon} ${skill.name}${status}`);
34152
+ }
34153
+ }
34154
+ console.log();
34155
+ } catch (error) {
34156
+ if (error instanceof Error) {
34157
+ if (isJsonMode()) {
34158
+ jsonOutput({ success: false, command: "plugin skills list", error: error.message });
34159
+ process.exit(1);
34160
+ }
34161
+ console.error(`Error: ${error.message}`);
34162
+ process.exit(1);
34163
+ }
34164
+ throw error;
34165
+ }
34166
+ }
34167
+ });
34168
+ var removeCmd = import_cmd_ts3.command({
34169
+ name: "remove",
34170
+ description: buildDescription(skillsRemoveMeta),
34171
+ args: {
34172
+ skill: import_cmd_ts3.positional({ type: import_cmd_ts3.string, displayName: "skill" }),
34173
+ scope: import_cmd_ts3.option({
34174
+ type: import_cmd_ts3.optional(import_cmd_ts3.string),
34175
+ long: "scope",
34176
+ short: "s",
34177
+ description: 'Scope: "project" (default) or "user"'
34178
+ }),
34179
+ plugin: import_cmd_ts3.option({
34180
+ type: import_cmd_ts3.optional(import_cmd_ts3.string),
34181
+ long: "plugin",
34182
+ short: "p",
34183
+ description: "Plugin name (required if skill exists in multiple plugins)"
34184
+ })
34185
+ },
34186
+ handler: async ({ skill, scope, plugin }) => {
34187
+ try {
34188
+ const isUser = scope === "user" || !scope && isUserConfigPath(process.cwd());
34189
+ const workspacePath = isUser ? getHomeDir() : process.cwd();
34190
+ const matches = await findSkillByName(skill, workspacePath);
34191
+ if (matches.length === 0) {
34192
+ const allSkills = await getAllSkillsFromPlugins(workspacePath);
34193
+ const skillNames = [...new Set(allSkills.map((s) => s.name))].join(", ");
34194
+ const error = `Skill '${skill}' not found in any installed plugin.
34195
+
34196
+ Available skills: ${skillNames || "none"}`;
34197
+ if (isJsonMode()) {
34198
+ jsonOutput({ success: false, command: "plugin skills remove", error });
34199
+ process.exit(1);
34200
+ }
34201
+ console.error(`Error: ${error}`);
34202
+ process.exit(1);
34203
+ }
34204
+ let targetSkill = matches[0];
34205
+ if (!targetSkill) {
34206
+ throw new Error("Unexpected empty matches array");
34207
+ }
34208
+ if (matches.length > 1) {
34209
+ if (!plugin) {
34210
+ const pluginList = matches.map((m) => ` - ${m.pluginName} (${m.pluginSource})`).join(`
34211
+ `);
34212
+ const error = `'${skill}' exists in multiple plugins:
34213
+ ${pluginList}
34214
+
34215
+ Use --plugin to specify: allagents plugin skills remove ${skill} --plugin <name>`;
34216
+ if (isJsonMode()) {
34217
+ jsonOutput({ success: false, command: "plugin skills remove", error });
34218
+ process.exit(1);
34219
+ }
34220
+ console.error(`Error: ${error}`);
34221
+ process.exit(1);
34222
+ }
34223
+ const filtered = matches.find((m) => m.pluginName === plugin);
34224
+ if (!filtered) {
34225
+ const error = `Plugin '${plugin}' not found. Installed plugins: ${matches.map((m) => m.pluginName).join(", ")}`;
34226
+ if (isJsonMode()) {
34227
+ jsonOutput({ success: false, command: "plugin skills remove", error });
34228
+ process.exit(1);
34229
+ }
34230
+ console.error(`Error: ${error}`);
34231
+ process.exit(1);
34232
+ }
34233
+ targetSkill = filtered;
34234
+ }
34235
+ if (targetSkill.disabled) {
34236
+ const msg = `Skill '${skill}' is already disabled.`;
34237
+ if (isJsonMode()) {
34238
+ jsonOutput({ success: false, command: "plugin skills remove", error: msg });
34239
+ process.exit(1);
34240
+ }
34241
+ console.log(msg);
34242
+ return;
34243
+ }
34244
+ const skillKey = `${targetSkill.pluginName}:${skill}`;
34245
+ const result = isUser ? await addUserDisabledSkill(skillKey) : await addDisabledSkill(skillKey, workspacePath);
34246
+ if (!result.success) {
34247
+ if (isJsonMode()) {
34248
+ jsonOutput({ success: false, command: "plugin skills remove", error: result.error ?? "Unknown error" });
34249
+ process.exit(1);
34250
+ }
34251
+ console.error(`Error: ${result.error}`);
34252
+ process.exit(1);
34253
+ }
34254
+ if (!isJsonMode()) {
34255
+ console.log(`✓ Disabled skill: ${skill} (${targetSkill.pluginName})`);
34256
+ console.log(`
34257
+ Syncing workspace...
34258
+ `);
34259
+ }
34260
+ const syncResult = isUser ? await syncUserWorkspace() : await syncWorkspace(workspacePath);
34261
+ if (isJsonMode()) {
34262
+ jsonOutput({
34263
+ success: syncResult.success,
34264
+ command: "plugin skills remove",
34265
+ data: {
34266
+ skill,
34267
+ plugin: targetSkill.pluginName,
34268
+ syncResult: {
34269
+ copied: syncResult.totalCopied,
34270
+ failed: syncResult.totalFailed
34271
+ }
34272
+ }
34273
+ });
34274
+ if (!syncResult.success)
34275
+ process.exit(1);
34276
+ return;
34277
+ }
34278
+ console.log("Sync complete.");
34279
+ } catch (error) {
34280
+ if (error instanceof Error) {
34281
+ if (isJsonMode()) {
34282
+ jsonOutput({ success: false, command: "plugin skills remove", error: error.message });
34283
+ process.exit(1);
34284
+ }
34285
+ console.error(`Error: ${error.message}`);
34286
+ process.exit(1);
34287
+ }
34288
+ throw error;
34289
+ }
34290
+ }
34291
+ });
34292
+ var addCmd = import_cmd_ts3.command({
34293
+ name: "add",
34294
+ description: buildDescription(skillsAddMeta),
34295
+ args: {
34296
+ skill: import_cmd_ts3.positional({ type: import_cmd_ts3.string, displayName: "skill" }),
34297
+ scope: import_cmd_ts3.option({
34298
+ type: import_cmd_ts3.optional(import_cmd_ts3.string),
34299
+ long: "scope",
34300
+ short: "s",
34301
+ description: 'Scope: "project" (default) or "user"'
34302
+ }),
34303
+ plugin: import_cmd_ts3.option({
34304
+ type: import_cmd_ts3.optional(import_cmd_ts3.string),
34305
+ long: "plugin",
34306
+ short: "p",
34307
+ description: "Plugin name (required if skill exists in multiple plugins)"
34308
+ })
34309
+ },
34310
+ handler: async ({ skill, scope, plugin }) => {
34311
+ try {
34312
+ const isUser = scope === "user" || !scope && isUserConfigPath(process.cwd());
34313
+ const workspacePath = isUser ? getHomeDir() : process.cwd();
34314
+ const matches = await findSkillByName(skill, workspacePath);
34315
+ if (matches.length === 0) {
34316
+ const allSkills = await getAllSkillsFromPlugins(workspacePath);
34317
+ const skillNames = [...new Set(allSkills.map((s) => s.name))].join(", ");
34318
+ const error = `Skill '${skill}' not found in any installed plugin.
34319
+
34320
+ Available skills: ${skillNames || "none"}`;
34321
+ if (isJsonMode()) {
34322
+ jsonOutput({ success: false, command: "plugin skills add", error });
34323
+ process.exit(1);
34324
+ }
34325
+ console.error(`Error: ${error}`);
34326
+ process.exit(1);
34327
+ }
34328
+ let targetSkill = matches[0];
34329
+ if (!targetSkill) {
34330
+ throw new Error("Unexpected empty matches array");
34331
+ }
34332
+ if (matches.length > 1) {
34333
+ if (!plugin) {
34334
+ const pluginList = matches.map((m) => ` - ${m.pluginName} (${m.pluginSource})`).join(`
34335
+ `);
34336
+ const error = `'${skill}' exists in multiple plugins:
34337
+ ${pluginList}
34338
+
34339
+ Use --plugin to specify: allagents plugin skills add ${skill} --plugin <name>`;
34340
+ if (isJsonMode()) {
34341
+ jsonOutput({ success: false, command: "plugin skills add", error });
34342
+ process.exit(1);
34343
+ }
34344
+ console.error(`Error: ${error}`);
34345
+ process.exit(1);
34346
+ }
34347
+ const filtered = matches.find((m) => m.pluginName === plugin);
34348
+ if (!filtered) {
34349
+ const error = `Plugin '${plugin}' not found. Installed plugins: ${matches.map((m) => m.pluginName).join(", ")}`;
34350
+ if (isJsonMode()) {
34351
+ jsonOutput({ success: false, command: "plugin skills add", error });
34352
+ process.exit(1);
34353
+ }
34354
+ console.error(`Error: ${error}`);
34355
+ process.exit(1);
34356
+ }
34357
+ targetSkill = filtered;
34358
+ }
34359
+ if (!targetSkill.disabled) {
34360
+ const msg = `Skill '${skill}' is already enabled.`;
34361
+ if (isJsonMode()) {
34362
+ jsonOutput({ success: false, command: "plugin skills add", error: msg });
34363
+ process.exit(1);
34364
+ }
34365
+ console.log(msg);
34366
+ return;
34367
+ }
34368
+ const skillKey = `${targetSkill.pluginName}:${skill}`;
34369
+ const result = isUser ? await removeUserDisabledSkill(skillKey) : await removeDisabledSkill(skillKey, workspacePath);
34370
+ if (!result.success) {
34371
+ if (isJsonMode()) {
34372
+ jsonOutput({ success: false, command: "plugin skills add", error: result.error ?? "Unknown error" });
34373
+ process.exit(1);
34374
+ }
34375
+ console.error(`Error: ${result.error}`);
34376
+ process.exit(1);
34377
+ }
34378
+ if (!isJsonMode()) {
34379
+ console.log(`✓ Enabled skill: ${skill} (${targetSkill.pluginName})`);
34380
+ console.log(`
34381
+ Syncing workspace...
34382
+ `);
34383
+ }
34384
+ const syncResult = isUser ? await syncUserWorkspace() : await syncWorkspace(workspacePath);
34385
+ if (isJsonMode()) {
34386
+ jsonOutput({
34387
+ success: syncResult.success,
34388
+ command: "plugin skills add",
34389
+ data: {
34390
+ skill,
34391
+ plugin: targetSkill.pluginName,
34392
+ syncResult: {
34393
+ copied: syncResult.totalCopied,
34394
+ failed: syncResult.totalFailed
34395
+ }
34396
+ }
34397
+ });
34398
+ if (!syncResult.success)
34399
+ process.exit(1);
34400
+ return;
34401
+ }
34402
+ console.log("Sync complete.");
34403
+ } catch (error) {
34404
+ if (error instanceof Error) {
34405
+ if (isJsonMode()) {
34406
+ jsonOutput({ success: false, command: "plugin skills add", error: error.message });
34407
+ process.exit(1);
34408
+ }
34409
+ console.error(`Error: ${error.message}`);
34410
+ process.exit(1);
34411
+ }
34412
+ throw error;
34413
+ }
34414
+ }
34415
+ });
34416
+ var skillsCmd = conciseSubcommands({
34417
+ name: "skills",
34418
+ description: "Manage individual skills from plugins",
34419
+ cmds: {
34420
+ list: listCmd,
34421
+ remove: removeCmd,
34422
+ add: addCmd
34423
+ }
34424
+ });
34425
+
33821
34426
  // src/cli/commands/plugin.ts
33822
34427
  function buildSyncData2(result) {
33823
34428
  return {
@@ -33937,7 +34542,7 @@ User sync complete:`);
33937
34542
  }
33938
34543
  return { ok: result.success && result.totalFailed === 0, syncData };
33939
34544
  }
33940
- var marketplaceListCmd = import_cmd_ts3.command({
34545
+ var marketplaceListCmd = import_cmd_ts4.command({
33941
34546
  name: "list",
33942
34547
  description: buildDescription(marketplaceListMeta),
33943
34548
  args: {},
@@ -33958,11 +34563,9 @@ var marketplaceListCmd = import_cmd_ts3.command({
33958
34563
  console.log("Add a marketplace with:");
33959
34564
  console.log(` allagents plugin marketplace add <source>
33960
34565
  `);
33961
- console.log("Well-known marketplaces:");
33962
- const wellKnown = getWellKnownMarketplaces();
33963
- for (const [name, repo] of Object.entries(wellKnown)) {
33964
- console.log(` ${name} → ${repo}`);
33965
- }
34566
+ console.log("Examples:");
34567
+ console.log(" allagents plugin marketplace add owner/repo");
34568
+ console.log(" allagents plugin marketplace add https://github.com/owner/repo");
33966
34569
  return;
33967
34570
  }
33968
34571
  console.log(`Registered marketplaces:
@@ -33990,13 +34593,13 @@ var marketplaceListCmd = import_cmd_ts3.command({
33990
34593
  }
33991
34594
  }
33992
34595
  });
33993
- var marketplaceAddCmd = import_cmd_ts3.command({
34596
+ var marketplaceAddCmd = import_cmd_ts4.command({
33994
34597
  name: "add",
33995
34598
  description: buildDescription(marketplaceAddMeta),
33996
34599
  args: {
33997
- source: import_cmd_ts3.positional({ type: import_cmd_ts3.string, displayName: "source" }),
33998
- name: import_cmd_ts3.option({ type: import_cmd_ts3.optional(import_cmd_ts3.string), long: "name", short: "n", description: "Custom name for the marketplace" }),
33999
- branch: import_cmd_ts3.option({ type: import_cmd_ts3.optional(import_cmd_ts3.string), long: "branch", short: "b", description: "Branch to checkout after cloning" })
34600
+ source: import_cmd_ts4.positional({ type: import_cmd_ts4.string, displayName: "source" }),
34601
+ name: import_cmd_ts4.option({ type: import_cmd_ts4.optional(import_cmd_ts4.string), long: "name", short: "n", description: "Custom name for the marketplace" }),
34602
+ branch: import_cmd_ts4.option({ type: import_cmd_ts4.optional(import_cmd_ts4.string), long: "branch", short: "b", description: "Branch to checkout after cloning" })
34000
34603
  },
34001
34604
  handler: async ({ source, name, branch }) => {
34002
34605
  try {
@@ -34041,11 +34644,11 @@ Error: ${result.error}`);
34041
34644
  }
34042
34645
  }
34043
34646
  });
34044
- var marketplaceRemoveCmd = import_cmd_ts3.command({
34647
+ var marketplaceRemoveCmd = import_cmd_ts4.command({
34045
34648
  name: "remove",
34046
34649
  description: buildDescription(marketplaceRemoveMeta),
34047
34650
  args: {
34048
- name: import_cmd_ts3.positional({ type: import_cmd_ts3.string, displayName: "name" })
34651
+ name: import_cmd_ts4.positional({ type: import_cmd_ts4.string, displayName: "name" })
34049
34652
  },
34050
34653
  handler: async ({ name }) => {
34051
34654
  try {
@@ -34089,11 +34692,11 @@ var marketplaceRemoveCmd = import_cmd_ts3.command({
34089
34692
  }
34090
34693
  }
34091
34694
  });
34092
- var marketplaceUpdateCmd = import_cmd_ts3.command({
34695
+ var marketplaceUpdateCmd = import_cmd_ts4.command({
34093
34696
  name: "update",
34094
34697
  description: buildDescription(marketplaceUpdateMeta),
34095
34698
  args: {
34096
- name: import_cmd_ts3.positional({ type: import_cmd_ts3.optional(import_cmd_ts3.string), displayName: "name" })
34699
+ name: import_cmd_ts4.positional({ type: import_cmd_ts4.optional(import_cmd_ts4.string), displayName: "name" })
34097
34700
  },
34098
34701
  handler: async ({ name }) => {
34099
34702
  try {
@@ -34159,11 +34762,11 @@ var marketplaceCmd = conciseSubcommands({
34159
34762
  update: marketplaceUpdateCmd
34160
34763
  }
34161
34764
  });
34162
- var pluginListCmd = import_cmd_ts3.command({
34765
+ var pluginListCmd = import_cmd_ts4.command({
34163
34766
  name: "list",
34164
34767
  description: buildDescription(pluginListMeta),
34165
34768
  args: {
34166
- marketplace: import_cmd_ts3.positional({ type: import_cmd_ts3.optional(import_cmd_ts3.string), displayName: "marketplace" })
34769
+ marketplace: import_cmd_ts4.positional({ type: import_cmd_ts4.optional(import_cmd_ts4.string), displayName: "marketplace" })
34167
34770
  },
34168
34771
  handler: async ({ marketplace }) => {
34169
34772
  try {
@@ -34299,11 +34902,11 @@ var pluginListCmd = import_cmd_ts3.command({
34299
34902
  }
34300
34903
  }
34301
34904
  });
34302
- var pluginValidateCmd = import_cmd_ts3.command({
34905
+ var pluginValidateCmd = import_cmd_ts4.command({
34303
34906
  name: "validate",
34304
34907
  description: buildDescription(pluginValidateMeta),
34305
34908
  args: {
34306
- path: import_cmd_ts3.positional({ type: import_cmd_ts3.string, displayName: "path" })
34909
+ path: import_cmd_ts4.positional({ type: import_cmd_ts4.string, displayName: "path" })
34307
34910
  },
34308
34911
  handler: async ({ path }) => {
34309
34912
  if (isJsonMode()) {
@@ -34318,12 +34921,12 @@ var pluginValidateCmd = import_cmd_ts3.command({
34318
34921
  console.log("(validation not yet implemented)");
34319
34922
  }
34320
34923
  });
34321
- var pluginInstallCmd = import_cmd_ts3.command({
34924
+ var pluginInstallCmd = import_cmd_ts4.command({
34322
34925
  name: "install",
34323
34926
  description: buildDescription(pluginInstallMeta),
34324
34927
  args: {
34325
- plugin: import_cmd_ts3.positional({ type: import_cmd_ts3.string, displayName: "plugin" }),
34326
- scope: import_cmd_ts3.option({ type: import_cmd_ts3.optional(import_cmd_ts3.string), long: "scope", short: "s", description: 'Installation scope: "project" (default) or "user"' })
34928
+ plugin: import_cmd_ts4.positional({ type: import_cmd_ts4.string, displayName: "plugin" }),
34929
+ scope: import_cmd_ts4.option({ type: import_cmd_ts4.optional(import_cmd_ts4.string), long: "scope", short: "s", description: 'Installation scope: "project" (default) or "user"' })
34327
34930
  },
34328
34931
  handler: async ({ plugin, scope }) => {
34329
34932
  try {
@@ -34376,13 +34979,13 @@ var pluginInstallCmd = import_cmd_ts3.command({
34376
34979
  }
34377
34980
  }
34378
34981
  });
34379
- var pluginUninstallCmd = import_cmd_ts3.command({
34982
+ var pluginUninstallCmd = import_cmd_ts4.command({
34380
34983
  name: "uninstall",
34381
34984
  description: buildDescription(pluginUninstallMeta),
34382
34985
  aliases: ["remove"],
34383
34986
  args: {
34384
- plugin: import_cmd_ts3.positional({ type: import_cmd_ts3.string, displayName: "plugin" }),
34385
- scope: import_cmd_ts3.option({ type: import_cmd_ts3.optional(import_cmd_ts3.string), long: "scope", short: "s", description: 'Installation scope: "project" (default) or "user"' })
34987
+ plugin: import_cmd_ts4.positional({ type: import_cmd_ts4.string, displayName: "plugin" }),
34988
+ scope: import_cmd_ts4.option({ type: import_cmd_ts4.optional(import_cmd_ts4.string), long: "scope", short: "s", description: 'Installation scope: "project" (default) or "user"' })
34386
34989
  },
34387
34990
  handler: async ({ plugin, scope }) => {
34388
34991
  try {
@@ -34512,13 +35115,14 @@ var pluginCmd = conciseSubcommands({
34512
35115
  uninstall: pluginUninstallCmd,
34513
35116
  marketplace: marketplaceCmd,
34514
35117
  list: pluginListCmd,
34515
- validate: pluginValidateCmd
35118
+ validate: pluginValidateCmd,
35119
+ skills: skillsCmd
34516
35120
  }
34517
35121
  });
34518
35122
 
34519
35123
  // src/cli/commands/self.ts
34520
35124
  init_execa();
34521
- var import_cmd_ts4 = __toESM(require_cjs(), 1);
35125
+ var import_cmd_ts5 = __toESM(require_cjs(), 1);
34522
35126
 
34523
35127
  // src/cli/metadata/self.ts
34524
35128
  var updateMeta = {
@@ -34556,12 +35160,12 @@ function detectPackageManager() {
34556
35160
  function getCurrentVersion() {
34557
35161
  return package_default.version;
34558
35162
  }
34559
- var updateCmd = import_cmd_ts4.command({
35163
+ var updateCmd = import_cmd_ts5.command({
34560
35164
  name: "update",
34561
35165
  description: buildDescription(updateMeta),
34562
35166
  args: {
34563
- npm: import_cmd_ts4.flag({ long: "npm", description: "Force update using npm" }),
34564
- bun: import_cmd_ts4.flag({ long: "bun", description: "Force update using bun" })
35167
+ npm: import_cmd_ts5.flag({ long: "npm", description: "Force update using npm" }),
35168
+ bun: import_cmd_ts5.flag({ long: "bun", description: "Force update using bun" })
34565
35169
  },
34566
35170
  handler: async ({ npm, bun }) => {
34567
35171
  try {
@@ -34762,5 +35366,5 @@ if (agentHelp) {
34762
35366
  const { runWizard: runWizard2 } = await Promise.resolve().then(() => (init_wizard(), exports_wizard));
34763
35367
  await runWizard2();
34764
35368
  } else {
34765
- import_cmd_ts5.run(app, finalArgs);
35369
+ import_cmd_ts6.run(app, finalArgs);
34766
35370
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "allagents",
3
- "version": "0.19.1",
3
+ "version": "0.20.0",
4
4
  "description": "CLI tool for managing multi-repo AI agent workspaces with plugin synchronization",
5
5
  "type": "module",
6
6
  "bin": {