allagents 0.8.7 → 0.10.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 +412 -105
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -12955,9 +12955,9 @@ function conciseSubcommands(config) {
12955
12955
  var import_cmd_ts2 = __toESM(require_cjs(), 1);
12956
12956
 
12957
12957
  // src/core/workspace.ts
12958
- import { mkdir as mkdir5, readFile as readFile8, writeFile as writeFile4, copyFile as copyFile2 } from "node:fs/promises";
12959
- import { existsSync as existsSync8 } from "node:fs";
12960
- import { join as join9, resolve as resolve6, dirname as dirname5, relative as relative2, sep, isAbsolute as isAbsolute2 } from "node:path";
12958
+ import { mkdir as mkdir6, readFile as readFile9, writeFile as writeFile5, copyFile as copyFile2 } from "node:fs/promises";
12959
+ import { existsSync as existsSync9 } from "node:fs";
12960
+ import { join as join10, resolve as resolve6, dirname as dirname5, relative as relative2, sep, isAbsolute as isAbsolute2 } from "node:path";
12961
12961
  import { fileURLToPath as fileURLToPath2 } from "node:url";
12962
12962
 
12963
12963
  // node_modules/js-yaml/dist/js-yaml.mjs
@@ -15608,9 +15608,9 @@ var safeLoadAll = renamed("safeLoadAll", "loadAll");
15608
15608
  var safeDump = renamed("safeDump", "dump");
15609
15609
 
15610
15610
  // src/core/sync.ts
15611
- import { existsSync as existsSync7 } from "node:fs";
15611
+ import { existsSync as existsSync8 } from "node:fs";
15612
15612
  import { rm, unlink, rmdir, copyFile } from "node:fs/promises";
15613
- import { join as join8, resolve as resolve5, dirname as dirname4, relative } from "node:path";
15613
+ import { join as join9, resolve as resolve5, dirname as dirname4, relative } from "node:path";
15614
15614
 
15615
15615
  // src/constants.ts
15616
15616
  var CONFIG_DIR = ".allagents";
@@ -21675,6 +21675,46 @@ var CLIENT_MAPPINGS = {
21675
21675
  agentFile: "AGENTS.md"
21676
21676
  }
21677
21677
  };
21678
+ var USER_CLIENT_MAPPINGS = {
21679
+ claude: {
21680
+ commandsPath: ".claude/commands/",
21681
+ skillsPath: ".claude/skills/",
21682
+ agentsPath: ".claude/agents/",
21683
+ agentFile: "CLAUDE.md",
21684
+ agentFileFallback: "AGENTS.md",
21685
+ hooksPath: ".claude/hooks/"
21686
+ },
21687
+ copilot: {
21688
+ skillsPath: ".copilot/skills/",
21689
+ agentFile: "AGENTS.md"
21690
+ },
21691
+ codex: {
21692
+ skillsPath: ".codex/skills/",
21693
+ agentFile: "AGENTS.md"
21694
+ },
21695
+ cursor: {
21696
+ skillsPath: ".cursor/skills/",
21697
+ agentFile: "AGENTS.md"
21698
+ },
21699
+ opencode: {
21700
+ skillsPath: ".config/opencode/skills/",
21701
+ agentFile: "AGENTS.md"
21702
+ },
21703
+ gemini: {
21704
+ skillsPath: ".gemini/skills/",
21705
+ agentFile: "GEMINI.md",
21706
+ agentFileFallback: "AGENTS.md"
21707
+ },
21708
+ factory: {
21709
+ skillsPath: ".factory/skills/",
21710
+ agentFile: "AGENTS.md",
21711
+ hooksPath: ".factory/hooks/"
21712
+ },
21713
+ ampcode: {
21714
+ skillsPath: ".config/amp/skills/",
21715
+ agentFile: "AGENTS.md"
21716
+ }
21717
+ };
21678
21718
 
21679
21719
  // src/validators/skill.ts
21680
21720
  var import_gray_matter = __toESM(require_gray_matter(), 1);
@@ -21763,9 +21803,12 @@ async function ensureWorkspaceRules(filePath, rules) {
21763
21803
  }
21764
21804
  }
21765
21805
  var injectWorkspaceRules = ensureWorkspaceRules;
21806
+ function getMapping(client, options2) {
21807
+ return options2?.clientMappings?.[client] ?? CLIENT_MAPPINGS[client];
21808
+ }
21766
21809
  async function copyCommands(pluginPath, workspacePath, client, options2 = {}) {
21767
21810
  const { dryRun = false } = options2;
21768
- const mapping = CLIENT_MAPPINGS[client];
21811
+ const mapping = getMapping(client, options2);
21769
21812
  const results = [];
21770
21813
  if (!mapping.commandsPath) {
21771
21814
  return results;
@@ -21803,7 +21846,7 @@ async function copyCommands(pluginPath, workspacePath, client, options2 = {}) {
21803
21846
  }
21804
21847
  async function copySkills(pluginPath, workspacePath, client, options2 = {}) {
21805
21848
  const { dryRun = false, skillNameMap } = options2;
21806
- const mapping = CLIENT_MAPPINGS[client];
21849
+ const mapping = getMapping(client, options2);
21807
21850
  const results = [];
21808
21851
  if (!mapping.skillsPath) {
21809
21852
  return results;
@@ -21872,7 +21915,7 @@ async function collectPluginSkills(pluginPath, pluginSource) {
21872
21915
  }
21873
21916
  async function copyHooks(pluginPath, workspacePath, client, options2 = {}) {
21874
21917
  const { dryRun = false } = options2;
21875
- const mapping = CLIENT_MAPPINGS[client];
21918
+ const mapping = getMapping(client, options2);
21876
21919
  const results = [];
21877
21920
  if (!mapping.hooksPath) {
21878
21921
  return results;
@@ -21902,7 +21945,7 @@ async function copyHooks(pluginPath, workspacePath, client, options2 = {}) {
21902
21945
  }
21903
21946
  async function copyAgents(pluginPath, workspacePath, client, options2 = {}) {
21904
21947
  const { dryRun = false } = options2;
21905
- const mapping = CLIENT_MAPPINGS[client];
21948
+ const mapping = getMapping(client, options2);
21906
21949
  const results = [];
21907
21950
  if (!mapping.agentsPath) {
21908
21951
  return results;
@@ -22967,6 +23010,117 @@ function getPreviouslySyncedFiles(state, client) {
22967
23010
  return state.files[client] ?? [];
22968
23011
  }
22969
23012
 
23013
+ // src/core/user-workspace.ts
23014
+ import { readFile as readFile8, writeFile as writeFile4, mkdir as mkdir5 } from "node:fs/promises";
23015
+ import { existsSync as existsSync7 } from "node:fs";
23016
+ import { join as join8 } from "node:path";
23017
+ var ALL_CLIENTS = [
23018
+ "claude",
23019
+ "copilot",
23020
+ "codex",
23021
+ "cursor",
23022
+ "opencode",
23023
+ "gemini",
23024
+ "factory",
23025
+ "ampcode"
23026
+ ];
23027
+ function getUserWorkspaceConfigPath() {
23028
+ return join8(getAllagentsDir(), WORKSPACE_CONFIG_FILE);
23029
+ }
23030
+ async function ensureUserWorkspace() {
23031
+ const configPath = getUserWorkspaceConfigPath();
23032
+ if (existsSync7(configPath))
23033
+ return;
23034
+ const defaultConfig = {
23035
+ repositories: [],
23036
+ plugins: [],
23037
+ clients: [...ALL_CLIENTS]
23038
+ };
23039
+ await mkdir5(getAllagentsDir(), { recursive: true });
23040
+ await writeFile4(configPath, dump(defaultConfig, { lineWidth: -1 }), "utf-8");
23041
+ }
23042
+ async function getUserWorkspaceConfig() {
23043
+ const configPath = getUserWorkspaceConfigPath();
23044
+ if (!existsSync7(configPath))
23045
+ return null;
23046
+ try {
23047
+ const content = await readFile8(configPath, "utf-8");
23048
+ return load(content);
23049
+ } catch {
23050
+ return null;
23051
+ }
23052
+ }
23053
+ async function addUserPlugin(plugin) {
23054
+ await ensureUserWorkspace();
23055
+ const configPath = getUserWorkspaceConfigPath();
23056
+ if (isPluginSpec(plugin)) {
23057
+ const resolved = await resolvePluginSpecWithAutoRegister(plugin);
23058
+ if (!resolved.success) {
23059
+ return { success: false, error: resolved.error || "Unknown error" };
23060
+ }
23061
+ const normalizedPlugin = resolved.registeredAs ? plugin.replace(/@[^@]+$/, `@${resolved.registeredAs}`) : plugin;
23062
+ return addPluginToUserConfig(normalizedPlugin, configPath, resolved.registeredAs);
23063
+ }
23064
+ if (isGitHubUrl(plugin)) {
23065
+ const validation = validatePluginSource(plugin);
23066
+ if (!validation.valid) {
23067
+ return { success: false, error: validation.error || "Invalid GitHub URL" };
23068
+ }
23069
+ const verifyResult = await verifyGitHubUrlExists(plugin);
23070
+ if (!verifyResult.exists) {
23071
+ return { success: false, error: verifyResult.error || `GitHub URL not found: ${plugin}` };
23072
+ }
23073
+ } else {
23074
+ if (!existsSync7(plugin)) {
23075
+ return {
23076
+ success: false,
23077
+ error: `Plugin not found at ${plugin}`
23078
+ };
23079
+ }
23080
+ }
23081
+ return addPluginToUserConfig(plugin, configPath);
23082
+ }
23083
+ async function removeUserPlugin(plugin) {
23084
+ await ensureUserWorkspace();
23085
+ const configPath = getUserWorkspaceConfigPath();
23086
+ try {
23087
+ const content = await readFile8(configPath, "utf-8");
23088
+ const config = load(content);
23089
+ let index = config.plugins.indexOf(plugin);
23090
+ if (index === -1) {
23091
+ index = config.plugins.findIndex((p) => p.startsWith(`${plugin}@`) || p === plugin);
23092
+ }
23093
+ if (index === -1) {
23094
+ return { success: false, error: `Plugin not found in user config: ${plugin}` };
23095
+ }
23096
+ config.plugins.splice(index, 1);
23097
+ await writeFile4(configPath, dump(config, { lineWidth: -1 }), "utf-8");
23098
+ return { success: true };
23099
+ } catch (error) {
23100
+ return {
23101
+ success: false,
23102
+ error: error instanceof Error ? error.message : String(error)
23103
+ };
23104
+ }
23105
+ }
23106
+ async function addPluginToUserConfig(plugin, configPath, autoRegistered) {
23107
+ try {
23108
+ const content = await readFile8(configPath, "utf-8");
23109
+ const config = load(content);
23110
+ if (config.plugins.includes(plugin)) {
23111
+ return { success: false, error: `Plugin already exists in user config: ${plugin}` };
23112
+ }
23113
+ config.plugins.push(plugin);
23114
+ await writeFile4(configPath, dump(config, { lineWidth: -1 }), "utf-8");
23115
+ return { success: true, ...autoRegistered && { autoRegistered } };
23116
+ } catch (error) {
23117
+ return {
23118
+ success: false,
23119
+ error: error instanceof Error ? error.message : String(error)
23120
+ };
23121
+ }
23122
+ }
23123
+
22970
23124
  // src/core/sync.ts
22971
23125
  async function selectivePurgeWorkspace(workspacePath, state, clients, options2) {
22972
23126
  if (!state) {
@@ -22979,8 +23133,8 @@ async function selectivePurgeWorkspace(workspacePath, state, clients, options2)
22979
23133
  const previousFiles = getPreviouslySyncedFiles(state, client);
22980
23134
  const purgedPaths = [];
22981
23135
  for (const filePath of previousFiles) {
22982
- const fullPath = join8(workspacePath, filePath);
22983
- if (!existsSync7(fullPath)) {
23136
+ const fullPath = join9(workspacePath, filePath);
23137
+ if (!existsSync8(fullPath)) {
22984
23138
  continue;
22985
23139
  }
22986
23140
  try {
@@ -23002,8 +23156,8 @@ async function selectivePurgeWorkspace(workspacePath, state, clients, options2)
23002
23156
  async function cleanupEmptyParents(workspacePath, filePath) {
23003
23157
  let parentPath = dirname4(filePath);
23004
23158
  while (parentPath && parentPath !== "." && parentPath !== "/") {
23005
- const fullParentPath = join8(workspacePath, parentPath);
23006
- if (!existsSync7(fullParentPath)) {
23159
+ const fullParentPath = join9(workspacePath, parentPath);
23160
+ if (!existsSync8(fullParentPath)) {
23007
23161
  parentPath = dirname4(parentPath);
23008
23162
  continue;
23009
23163
  }
@@ -23088,8 +23242,8 @@ function validateFileSources(files, defaultSourcePath, githubCache) {
23088
23242
  errors2.push(`Cannot resolve file '${file}' - no workspace.source configured`);
23089
23243
  continue;
23090
23244
  }
23091
- const fullPath = join8(defaultSourcePath, file);
23092
- if (!existsSync7(fullPath)) {
23245
+ const fullPath = join9(defaultSourcePath, file);
23246
+ if (!existsSync8(fullPath)) {
23093
23247
  errors2.push(`File source not found: ${fullPath}`);
23094
23248
  }
23095
23249
  continue;
@@ -23107,8 +23261,8 @@ function validateFileSources(files, defaultSourcePath, githubCache) {
23107
23261
  errors2.push(`GitHub cache not found for ${cacheKey}`);
23108
23262
  continue;
23109
23263
  }
23110
- const fullPath = join8(cachePath, parsed.filePath);
23111
- if (!existsSync7(fullPath)) {
23264
+ const fullPath = join9(cachePath, parsed.filePath);
23265
+ if (!existsSync8(fullPath)) {
23112
23266
  errors2.push(`Path not found in repository: ${cacheKey}/${parsed.filePath}`);
23113
23267
  }
23114
23268
  } else {
@@ -23118,11 +23272,11 @@ function validateFileSources(files, defaultSourcePath, githubCache) {
23118
23272
  } else if (file.source.startsWith("../")) {
23119
23273
  fullPath = resolve5(file.source);
23120
23274
  } else if (defaultSourcePath) {
23121
- fullPath = join8(defaultSourcePath, file.source);
23275
+ fullPath = join9(defaultSourcePath, file.source);
23122
23276
  } else {
23123
23277
  fullPath = resolve5(file.source);
23124
23278
  }
23125
- if (!existsSync7(fullPath)) {
23279
+ if (!existsSync8(fullPath)) {
23126
23280
  errors2.push(`File source not found: ${fullPath}`);
23127
23281
  }
23128
23282
  }
@@ -23131,15 +23285,15 @@ function validateFileSources(files, defaultSourcePath, githubCache) {
23131
23285
  errors2.push(`Cannot resolve file '${file.dest}' - no workspace.source configured and no explicit source provided`);
23132
23286
  continue;
23133
23287
  }
23134
- const fullPath = join8(defaultSourcePath, file.dest ?? "");
23135
- if (!existsSync7(fullPath)) {
23288
+ const fullPath = join9(defaultSourcePath, file.dest ?? "");
23289
+ if (!existsSync8(fullPath)) {
23136
23290
  errors2.push(`File source not found: ${fullPath}`);
23137
23291
  }
23138
23292
  }
23139
23293
  }
23140
23294
  return errors2;
23141
23295
  }
23142
- function collectSyncedPaths(copyResults, workspacePath, clients) {
23296
+ function collectSyncedPaths(copyResults, workspacePath, clients, clientMappings) {
23143
23297
  const result = {};
23144
23298
  for (const client of clients) {
23145
23299
  result[client] = [];
@@ -23150,7 +23304,7 @@ function collectSyncedPaths(copyResults, workspacePath, clients) {
23150
23304
  }
23151
23305
  const relativePath = relative(workspacePath, copyResult.destination).replace(/\\/g, "/");
23152
23306
  for (const client of clients) {
23153
- const mapping = CLIENT_MAPPINGS[client];
23307
+ const mapping = clientMappings?.[client] ?? CLIENT_MAPPINGS[client];
23154
23308
  if (mapping.skillsPath && relativePath.startsWith(mapping.skillsPath)) {
23155
23309
  const skillName = relativePath.slice(mapping.skillsPath.length);
23156
23310
  if (!skillName.includes("/")) {
@@ -23198,7 +23352,7 @@ async function validatePlugin(pluginSource, workspacePath, offline) {
23198
23352
  ...fetchResult.error && { error: fetchResult.error }
23199
23353
  };
23200
23354
  }
23201
- const resolvedPath2 = parsed?.subpath ? join8(fetchResult.cachePath, parsed.subpath) : fetchResult.cachePath;
23355
+ const resolvedPath2 = parsed?.subpath ? join9(fetchResult.cachePath, parsed.subpath) : fetchResult.cachePath;
23202
23356
  return {
23203
23357
  plugin: pluginSource,
23204
23358
  resolved: resolvedPath2,
@@ -23206,7 +23360,7 @@ async function validatePlugin(pluginSource, workspacePath, offline) {
23206
23360
  };
23207
23361
  }
23208
23362
  const resolvedPath = resolve5(workspacePath, pluginSource);
23209
- if (!existsSync7(resolvedPath)) {
23363
+ if (!existsSync8(resolvedPath)) {
23210
23364
  return {
23211
23365
  plugin: pluginSource,
23212
23366
  resolved: resolvedPath,
@@ -23223,10 +23377,10 @@ async function validatePlugin(pluginSource, workspacePath, offline) {
23223
23377
  async function validateAllPlugins(plugins, workspacePath, offline) {
23224
23378
  return Promise.all(plugins.map((plugin) => validatePlugin(plugin, workspacePath, offline)));
23225
23379
  }
23226
- async function copyValidatedPlugin(validatedPlugin, workspacePath, clients, dryRun, skillNameMap) {
23380
+ async function copyValidatedPlugin(validatedPlugin, workspacePath, clients, dryRun, skillNameMap, clientMappings) {
23227
23381
  const copyResults = [];
23228
23382
  for (const client of clients) {
23229
- const results = await copyPluginToWorkspace(validatedPlugin.resolved, workspacePath, client, { dryRun, ...skillNameMap && { skillNameMap } });
23383
+ const results = await copyPluginToWorkspace(validatedPlugin.resolved, workspacePath, client, { dryRun, ...skillNameMap && { skillNameMap }, ...clientMappings && { clientMappings } });
23230
23384
  copyResults.push(...results);
23231
23385
  }
23232
23386
  const hasFailures = copyResults.some((r) => r.action === "failed");
@@ -23280,9 +23434,9 @@ function buildPluginSkillNameMaps(allSkills) {
23280
23434
  }
23281
23435
  async function syncWorkspace(workspacePath = process.cwd(), options2 = {}) {
23282
23436
  const { offline = false, dryRun = false, workspaceSourceBase } = options2;
23283
- const configDir = join8(workspacePath, CONFIG_DIR);
23284
- const configPath = join8(configDir, WORKSPACE_CONFIG_FILE);
23285
- if (!existsSync7(configPath)) {
23437
+ const configDir = join9(workspacePath, CONFIG_DIR);
23438
+ const configPath = join9(configDir, WORKSPACE_CONFIG_FILE);
23439
+ if (!existsSync8(configPath)) {
23286
23440
  return {
23287
23441
  success: false,
23288
23442
  pluginResults: [],
@@ -23384,8 +23538,8 @@ ${errors2}`
23384
23538
  const filesToCopy = [...config.workspace.files];
23385
23539
  if (sourcePath) {
23386
23540
  for (const agentFile of AGENT_FILES) {
23387
- const agentPath = join8(sourcePath, agentFile);
23388
- if (existsSync7(agentPath) && !filesToCopy.includes(agentFile)) {
23541
+ const agentPath = join9(sourcePath, agentFile);
23542
+ if (existsSync8(agentPath) && !filesToCopy.includes(agentFile)) {
23389
23543
  filesToCopy.push(agentFile);
23390
23544
  }
23391
23545
  }
@@ -23425,10 +23579,10 @@ ${fileValidationErrors.map((e) => ` - ${e}`).join(`
23425
23579
  }
23426
23580
  workspaceFileResults = await copyWorkspaceFiles(sourcePath, workspacePath, filesToCopy, { dryRun, githubCache });
23427
23581
  if (!dryRun && clients.includes("claude") && sourcePath) {
23428
- const claudePath = join8(workspacePath, "CLAUDE.md");
23429
- const agentsPath = join8(workspacePath, "AGENTS.md");
23430
- const claudeExistsInSource = existsSync7(join8(sourcePath, "CLAUDE.md"));
23431
- if (!claudeExistsInSource && existsSync7(agentsPath) && !existsSync7(claudePath)) {
23582
+ const claudePath = join9(workspacePath, "CLAUDE.md");
23583
+ const agentsPath = join9(workspacePath, "AGENTS.md");
23584
+ const claudeExistsInSource = existsSync8(join9(sourcePath, "CLAUDE.md"));
23585
+ if (!claudeExistsInSource && existsSync8(agentsPath) && !existsSync8(claudePath)) {
23432
23586
  await copyFile(agentsPath, claudePath);
23433
23587
  }
23434
23588
  }
@@ -23494,6 +23648,89 @@ ${fileValidationErrors.map((e) => ` - ${e}`).join(`
23494
23648
  purgedPaths
23495
23649
  };
23496
23650
  }
23651
+ async function syncUserWorkspace(options2 = {}) {
23652
+ const homeDir = resolve5(process.env.HOME || process.env.USERPROFILE || "~");
23653
+ const config = await getUserWorkspaceConfig();
23654
+ if (!config) {
23655
+ return {
23656
+ success: true,
23657
+ pluginResults: [],
23658
+ totalCopied: 0,
23659
+ totalFailed: 0,
23660
+ totalSkipped: 0,
23661
+ totalGenerated: 0
23662
+ };
23663
+ }
23664
+ const clients = config.clients;
23665
+ const { offline = false, dryRun = false } = options2;
23666
+ const validatedPlugins = await validateAllPlugins(config.plugins, homeDir, offline);
23667
+ const failedValidations = validatedPlugins.filter((v) => !v.success);
23668
+ if (failedValidations.length > 0) {
23669
+ const errors2 = failedValidations.map((v) => ` - ${v.plugin}: ${v.error}`).join(`
23670
+ `);
23671
+ return {
23672
+ success: false,
23673
+ pluginResults: failedValidations.map((v) => ({
23674
+ plugin: v.plugin,
23675
+ resolved: v.resolved,
23676
+ success: false,
23677
+ copyResults: [],
23678
+ ...v.error && { error: v.error }
23679
+ })),
23680
+ totalCopied: 0,
23681
+ totalFailed: failedValidations.length,
23682
+ totalSkipped: 0,
23683
+ totalGenerated: 0,
23684
+ error: `Plugin validation failed:
23685
+ ${errors2}`
23686
+ };
23687
+ }
23688
+ const previousState = await loadSyncState(homeDir);
23689
+ if (!dryRun) {
23690
+ await selectivePurgeWorkspace(homeDir, previousState, clients);
23691
+ }
23692
+ const allSkills = await collectAllSkills(validatedPlugins);
23693
+ const pluginSkillMaps = buildPluginSkillNameMaps(allSkills);
23694
+ const pluginResults = await Promise.all(validatedPlugins.map((vp) => {
23695
+ const skillNameMap = pluginSkillMaps.get(vp.resolved);
23696
+ return copyValidatedPlugin(vp, homeDir, clients, dryRun, skillNameMap, USER_CLIENT_MAPPINGS);
23697
+ }));
23698
+ let totalCopied = 0;
23699
+ let totalFailed = 0;
23700
+ let totalSkipped = 0;
23701
+ let totalGenerated = 0;
23702
+ for (const pluginResult of pluginResults) {
23703
+ for (const copyResult of pluginResult.copyResults) {
23704
+ switch (copyResult.action) {
23705
+ case "copied":
23706
+ totalCopied++;
23707
+ break;
23708
+ case "failed":
23709
+ totalFailed++;
23710
+ break;
23711
+ case "skipped":
23712
+ totalSkipped++;
23713
+ break;
23714
+ case "generated":
23715
+ totalGenerated++;
23716
+ break;
23717
+ }
23718
+ }
23719
+ }
23720
+ if (!dryRun) {
23721
+ const allCopyResults = pluginResults.flatMap((r) => r.copyResults);
23722
+ const syncedFiles = collectSyncedPaths(allCopyResults, homeDir, clients, USER_CLIENT_MAPPINGS);
23723
+ await saveSyncState(homeDir, syncedFiles);
23724
+ }
23725
+ return {
23726
+ success: totalFailed === 0,
23727
+ pluginResults,
23728
+ totalCopied,
23729
+ totalFailed,
23730
+ totalSkipped,
23731
+ totalGenerated
23732
+ };
23733
+ }
23497
23734
 
23498
23735
  // src/core/github-fetch.ts
23499
23736
  async function resolveBranchAndSubpath(owner, repo, pathAfterTree) {
@@ -23622,19 +23859,19 @@ async function fetchWorkspaceFromGitHub(url) {
23622
23859
  // src/core/workspace.ts
23623
23860
  async function initWorkspace(targetPath = ".", options2 = {}) {
23624
23861
  const absoluteTarget = resolve6(targetPath);
23625
- const configDir = join9(absoluteTarget, CONFIG_DIR);
23626
- const configPath = join9(configDir, WORKSPACE_CONFIG_FILE);
23627
- if (existsSync8(configPath)) {
23862
+ const configDir = join10(absoluteTarget, CONFIG_DIR);
23863
+ const configPath = join10(configDir, WORKSPACE_CONFIG_FILE);
23864
+ if (existsSync9(configPath)) {
23628
23865
  throw new Error(`Workspace already exists: ${absoluteTarget}
23629
23866
  Found existing ${CONFIG_DIR}/${WORKSPACE_CONFIG_FILE}`);
23630
23867
  }
23631
23868
  const currentFilePath = fileURLToPath2(import.meta.url);
23632
23869
  const currentFileDir = dirname5(currentFilePath);
23633
23870
  const isProduction = currentFilePath.includes(`${sep}dist${sep}`);
23634
- const defaultTemplatePath = isProduction ? join9(currentFileDir, "templates", "default") : join9(currentFileDir, "..", "templates", "default");
23871
+ const defaultTemplatePath = isProduction ? join10(currentFileDir, "templates", "default") : join10(currentFileDir, "..", "templates", "default");
23635
23872
  try {
23636
- await mkdir5(absoluteTarget, { recursive: true });
23637
- await mkdir5(configDir, { recursive: true });
23873
+ await mkdir6(absoluteTarget, { recursive: true });
23874
+ await mkdir6(configDir, { recursive: true });
23638
23875
  let workspaceYamlContent;
23639
23876
  let sourceDir;
23640
23877
  if (options2.from) {
@@ -23663,19 +23900,19 @@ async function initWorkspace(targetPath = ".", options2 = {}) {
23663
23900
  console.log(`✓ Using workspace.yaml from: ${options2.from}`);
23664
23901
  } else {
23665
23902
  const fromPath = resolve6(options2.from);
23666
- if (!existsSync8(fromPath)) {
23903
+ if (!existsSync9(fromPath)) {
23667
23904
  throw new Error(`Template not found: ${fromPath}`);
23668
23905
  }
23669
23906
  const { stat: stat2 } = await import("node:fs/promises");
23670
23907
  const fromStat = await stat2(fromPath);
23671
23908
  let sourceYamlPath;
23672
23909
  if (fromStat.isDirectory()) {
23673
- const nestedPath = join9(fromPath, CONFIG_DIR, WORKSPACE_CONFIG_FILE);
23674
- const rootPath = join9(fromPath, WORKSPACE_CONFIG_FILE);
23675
- if (existsSync8(nestedPath)) {
23910
+ const nestedPath = join10(fromPath, CONFIG_DIR, WORKSPACE_CONFIG_FILE);
23911
+ const rootPath = join10(fromPath, WORKSPACE_CONFIG_FILE);
23912
+ if (existsSync9(nestedPath)) {
23676
23913
  sourceYamlPath = nestedPath;
23677
23914
  sourceDir = fromPath;
23678
- } else if (existsSync8(rootPath)) {
23915
+ } else if (existsSync9(rootPath)) {
23679
23916
  sourceYamlPath = rootPath;
23680
23917
  sourceDir = fromPath;
23681
23918
  } else {
@@ -23691,7 +23928,7 @@ async function initWorkspace(targetPath = ".", options2 = {}) {
23691
23928
  sourceDir = parentDir;
23692
23929
  }
23693
23930
  }
23694
- workspaceYamlContent = await readFile8(sourceYamlPath, "utf-8");
23931
+ workspaceYamlContent = await readFile9(sourceYamlPath, "utf-8");
23695
23932
  if (sourceDir) {
23696
23933
  const parsed2 = load(workspaceYamlContent);
23697
23934
  const workspace = parsed2?.workspace;
@@ -23706,13 +23943,13 @@ async function initWorkspace(targetPath = ".", options2 = {}) {
23706
23943
  console.log(`✓ Using workspace.yaml from: ${sourceYamlPath}`);
23707
23944
  }
23708
23945
  } else {
23709
- const defaultYamlPath = join9(defaultTemplatePath, CONFIG_DIR, WORKSPACE_CONFIG_FILE);
23710
- if (!existsSync8(defaultYamlPath)) {
23946
+ const defaultYamlPath = join10(defaultTemplatePath, CONFIG_DIR, WORKSPACE_CONFIG_FILE);
23947
+ if (!existsSync9(defaultYamlPath)) {
23711
23948
  throw new Error(`Default template not found at: ${defaultTemplatePath}`);
23712
23949
  }
23713
- workspaceYamlContent = await readFile8(defaultYamlPath, "utf-8");
23950
+ workspaceYamlContent = await readFile9(defaultYamlPath, "utf-8");
23714
23951
  }
23715
- await writeFile4(configPath, workspaceYamlContent, "utf-8");
23952
+ await writeFile5(configPath, workspaceYamlContent, "utf-8");
23716
23953
  const copiedAgentFiles = [];
23717
23954
  if (options2.from && isGitHubUrl(options2.from)) {
23718
23955
  const parsedUrl = parseGitHubUrl(options2.from);
@@ -23722,7 +23959,7 @@ async function initWorkspace(targetPath = ".", options2 = {}) {
23722
23959
  const filePath = basePath ? `${basePath}/${agentFile}` : agentFile;
23723
23960
  const content = await fetchFileFromGitHub(parsedUrl.owner, parsedUrl.repo, filePath, parsedUrl.branch);
23724
23961
  if (content) {
23725
- await writeFile4(join9(absoluteTarget, agentFile), content, "utf-8");
23962
+ await writeFile5(join10(absoluteTarget, agentFile), content, "utf-8");
23726
23963
  copiedAgentFiles.push(agentFile);
23727
23964
  }
23728
23965
  }
@@ -23730,27 +23967,27 @@ async function initWorkspace(targetPath = ".", options2 = {}) {
23730
23967
  } else {
23731
23968
  const effectiveSourceDir = sourceDir ?? defaultTemplatePath;
23732
23969
  for (const agentFile of AGENT_FILES) {
23733
- const sourcePath = join9(effectiveSourceDir, agentFile);
23734
- if (existsSync8(sourcePath)) {
23735
- const content = await readFile8(sourcePath, "utf-8");
23736
- await writeFile4(join9(absoluteTarget, agentFile), content, "utf-8");
23970
+ const sourcePath = join10(effectiveSourceDir, agentFile);
23971
+ if (existsSync9(sourcePath)) {
23972
+ const content = await readFile9(sourcePath, "utf-8");
23973
+ await writeFile5(join10(absoluteTarget, agentFile), content, "utf-8");
23737
23974
  copiedAgentFiles.push(agentFile);
23738
23975
  }
23739
23976
  }
23740
23977
  }
23741
23978
  if (copiedAgentFiles.length === 0) {
23742
- await ensureWorkspaceRules(join9(absoluteTarget, "AGENTS.md"));
23979
+ await ensureWorkspaceRules(join10(absoluteTarget, "AGENTS.md"));
23743
23980
  copiedAgentFiles.push("AGENTS.md");
23744
23981
  } else {
23745
23982
  for (const agentFile of copiedAgentFiles) {
23746
- await ensureWorkspaceRules(join9(absoluteTarget, agentFile));
23983
+ await ensureWorkspaceRules(join10(absoluteTarget, agentFile));
23747
23984
  }
23748
23985
  }
23749
23986
  const parsed = load(workspaceYamlContent);
23750
23987
  const clients = parsed?.clients ?? [];
23751
23988
  if (clients.includes("claude") && !copiedAgentFiles.includes("CLAUDE.md") && copiedAgentFiles.includes("AGENTS.md")) {
23752
- const agentsPath = join9(absoluteTarget, "AGENTS.md");
23753
- const claudePath = join9(absoluteTarget, "CLAUDE.md");
23989
+ const agentsPath = join10(absoluteTarget, "AGENTS.md");
23990
+ const claudePath = join10(absoluteTarget, "CLAUDE.md");
23754
23991
  await copyFile2(agentsPath, claudePath);
23755
23992
  }
23756
23993
  console.log(`✓ Workspace created at: ${absoluteTarget}`);
@@ -23784,11 +24021,11 @@ Next steps:`);
23784
24021
  }
23785
24022
 
23786
24023
  // src/core/status.ts
23787
- import { existsSync as existsSync9 } from "node:fs";
23788
- import { join as join10 } from "node:path";
24024
+ import { existsSync as existsSync10 } from "node:fs";
24025
+ import { join as join11 } from "node:path";
23789
24026
  async function getWorkspaceStatus(workspacePath = process.cwd()) {
23790
- const configPath = join10(workspacePath, CONFIG_DIR, WORKSPACE_CONFIG_FILE);
23791
- if (!existsSync9(configPath)) {
24027
+ const configPath = join11(workspacePath, CONFIG_DIR, WORKSPACE_CONFIG_FILE);
24028
+ if (!existsSync10(configPath)) {
23792
24029
  return {
23793
24030
  success: false,
23794
24031
  error: `${CONFIG_DIR}/${WORKSPACE_CONFIG_FILE} not found in ${workspacePath}
@@ -23827,7 +24064,7 @@ async function getWorkspaceStatus(workspacePath = process.cwd()) {
23827
24064
  function getPluginStatus(parsed) {
23828
24065
  if (parsed.type === "github") {
23829
24066
  const cachePath = parsed.owner && parsed.repo ? getPluginCachePath(parsed.owner, parsed.repo) : "";
23830
- const available2 = cachePath ? existsSync9(cachePath) : false;
24067
+ const available2 = cachePath ? existsSync10(cachePath) : false;
23831
24068
  return {
23832
24069
  source: parsed.original,
23833
24070
  type: "github",
@@ -23837,7 +24074,7 @@ function getPluginStatus(parsed) {
23837
24074
  ...parsed.repo && { repo: parsed.repo }
23838
24075
  };
23839
24076
  }
23840
- const available = existsSync9(parsed.normalized);
24077
+ const available = existsSync10(parsed.normalized);
23841
24078
  return {
23842
24079
  source: parsed.original,
23843
24080
  type: "local",
@@ -23909,13 +24146,15 @@ var syncMeta = {
23909
24146
  "allagents workspace sync",
23910
24147
  "allagents workspace sync --dry-run",
23911
24148
  "allagents workspace sync --client claude",
23912
- "allagents workspace sync --offline"
24149
+ "allagents workspace sync --offline",
24150
+ "allagents workspace sync --scope user"
23913
24151
  ],
23914
24152
  expectedOutput: "Lists synced files with status per plugin. Exit 0 on success, exit 1 if any files failed.",
23915
24153
  options: [
23916
24154
  { flag: "--offline", type: "boolean", description: "Use cached plugins without fetching latest from remote" },
23917
24155
  { flag: "--dry-run", short: "-n", type: "boolean", description: "Simulate sync without making changes" },
23918
- { flag: "--client", short: "-c", type: "string", description: "Sync only the specified client (e.g., opencode, claude)" }
24156
+ { flag: "--client", short: "-c", type: "string", description: "Sync only the specified client (e.g., opencode, claude)" },
24157
+ { flag: "--scope", short: "-s", type: "string", description: 'Sync scope: "project" (default) or "user"' }
23919
24158
  ],
23920
24159
  outputSchema: {
23921
24160
  copied: "number",
@@ -24016,10 +24255,12 @@ var syncCmd = import_cmd_ts2.command({
24016
24255
  args: {
24017
24256
  offline: import_cmd_ts2.flag({ long: "offline", description: "Use cached plugins without fetching latest from remote" }),
24018
24257
  dryRun: import_cmd_ts2.flag({ long: "dry-run", short: "n", description: "Simulate sync without making changes" }),
24019
- client: import_cmd_ts2.option({ type: import_cmd_ts2.optional(import_cmd_ts2.string), long: "client", short: "c", description: "Sync only the specified client (e.g., opencode, claude)" })
24258
+ client: import_cmd_ts2.option({ type: import_cmd_ts2.optional(import_cmd_ts2.string), long: "client", short: "c", description: "Sync only the specified client (e.g., opencode, claude)" }),
24259
+ scope: import_cmd_ts2.option({ type: import_cmd_ts2.optional(import_cmd_ts2.string), long: "scope", short: "s", description: 'Sync scope: "project" (default) or "user"' })
24020
24260
  },
24021
- handler: async ({ offline, dryRun, client }) => {
24261
+ handler: async ({ offline, dryRun, client, scope }) => {
24022
24262
  try {
24263
+ const isUser = scope === "user";
24023
24264
  if (!isJsonMode()) {
24024
24265
  if (dryRun) {
24025
24266
  console.log(`Dry run mode - no changes will be made
@@ -24029,10 +24270,10 @@ var syncCmd = import_cmd_ts2.command({
24029
24270
  console.log(`Syncing client: ${client}
24030
24271
  `);
24031
24272
  }
24032
- console.log(`Syncing workspace...
24273
+ console.log(`Syncing ${isUser ? "user" : ""} workspace...
24033
24274
  `);
24034
24275
  }
24035
- const result = await syncWorkspace(process.cwd(), {
24276
+ const result = isUser ? await syncUserWorkspace({ offline, dryRun }) : await syncWorkspace(process.cwd(), {
24036
24277
  offline,
24037
24278
  dryRun,
24038
24279
  ...client && { clients: [client] }
@@ -24194,12 +24435,12 @@ var workspaceCmd = conciseSubcommands({
24194
24435
  var import_cmd_ts3 = __toESM(require_cjs(), 1);
24195
24436
 
24196
24437
  // src/core/workspace-modify.ts
24197
- import { readFile as readFile9, writeFile as writeFile5 } from "node:fs/promises";
24198
- import { existsSync as existsSync10 } from "node:fs";
24199
- import { join as join11 } from "node:path";
24438
+ import { readFile as readFile10, writeFile as writeFile6 } from "node:fs/promises";
24439
+ import { existsSync as existsSync11 } from "node:fs";
24440
+ import { join as join12 } from "node:path";
24200
24441
  async function addPlugin(plugin, workspacePath = process.cwd()) {
24201
- const configPath = join11(workspacePath, CONFIG_DIR, WORKSPACE_CONFIG_FILE);
24202
- if (!existsSync10(configPath)) {
24442
+ const configPath = join12(workspacePath, CONFIG_DIR, WORKSPACE_CONFIG_FILE);
24443
+ if (!existsSync11(configPath)) {
24203
24444
  return {
24204
24445
  success: false,
24205
24446
  error: `${CONFIG_DIR}/${WORKSPACE_CONFIG_FILE} not found in ${workspacePath}
@@ -24232,8 +24473,8 @@ async function addPlugin(plugin, workspacePath = process.cwd()) {
24232
24473
  };
24233
24474
  }
24234
24475
  } else {
24235
- const fullPath = join11(workspacePath, plugin);
24236
- if (!existsSync10(fullPath) && !existsSync10(plugin)) {
24476
+ const fullPath = join12(workspacePath, plugin);
24477
+ if (!existsSync11(fullPath) && !existsSync11(plugin)) {
24237
24478
  return {
24238
24479
  success: false,
24239
24480
  error: `Plugin not found at ${plugin}`
@@ -24244,7 +24485,7 @@ async function addPlugin(plugin, workspacePath = process.cwd()) {
24244
24485
  }
24245
24486
  async function addPluginToConfig(plugin, configPath, autoRegistered) {
24246
24487
  try {
24247
- const content = await readFile9(configPath, "utf-8");
24488
+ const content = await readFile10(configPath, "utf-8");
24248
24489
  const config = load(content);
24249
24490
  if (config.plugins.includes(plugin)) {
24250
24491
  return {
@@ -24254,7 +24495,7 @@ async function addPluginToConfig(plugin, configPath, autoRegistered) {
24254
24495
  }
24255
24496
  config.plugins.push(plugin);
24256
24497
  const newContent = dump(config, { lineWidth: -1 });
24257
- await writeFile5(configPath, newContent, "utf-8");
24498
+ await writeFile6(configPath, newContent, "utf-8");
24258
24499
  return {
24259
24500
  success: true,
24260
24501
  ...autoRegistered && { autoRegistered }
@@ -24267,8 +24508,8 @@ async function addPluginToConfig(plugin, configPath, autoRegistered) {
24267
24508
  }
24268
24509
  }
24269
24510
  async function removePlugin(plugin, workspacePath = process.cwd()) {
24270
- const configPath = join11(workspacePath, CONFIG_DIR, WORKSPACE_CONFIG_FILE);
24271
- if (!existsSync10(configPath)) {
24511
+ const configPath = join12(workspacePath, CONFIG_DIR, WORKSPACE_CONFIG_FILE);
24512
+ if (!existsSync11(configPath)) {
24272
24513
  return {
24273
24514
  success: false,
24274
24515
  error: `${CONFIG_DIR}/${WORKSPACE_CONFIG_FILE} not found in ${workspacePath}
@@ -24276,7 +24517,7 @@ async function removePlugin(plugin, workspacePath = process.cwd()) {
24276
24517
  };
24277
24518
  }
24278
24519
  try {
24279
- const content = await readFile9(configPath, "utf-8");
24520
+ const content = await readFile10(configPath, "utf-8");
24280
24521
  const config = load(content);
24281
24522
  let index = config.plugins.indexOf(plugin);
24282
24523
  if (index === -1 && isPluginSpec(plugin) === false) {
@@ -24290,7 +24531,7 @@ async function removePlugin(plugin, workspacePath = process.cwd()) {
24290
24531
  }
24291
24532
  config.plugins.splice(index, 1);
24292
24533
  const newContent = dump(config, { lineWidth: -1 });
24293
- await writeFile5(configPath, newContent, "utf-8");
24534
+ await writeFile6(configPath, newContent, "utf-8");
24294
24535
  return { success: true };
24295
24536
  } catch (error) {
24296
24537
  return {
@@ -24406,19 +24647,24 @@ var pluginValidateMeta = {
24406
24647
  };
24407
24648
  var pluginInstallMeta = {
24408
24649
  command: "plugin install",
24409
- description: "Install plugin to .allagents/workspace.yaml (supports plugin@marketplace, GitHub URL, or local path)",
24410
- whenToUse: "To add a new plugin to your workspace and immediately sync it",
24650
+ description: "Install plugin to workspace (supports plugin@marketplace, GitHub URL, or local path). Use --scope user for user-level install.",
24651
+ whenToUse: "To add a new plugin to your workspace (or user-level config with --scope user) and immediately sync it",
24411
24652
  examples: [
24412
24653
  "allagents plugin install my-plugin@official",
24413
24654
  "allagents plugin install https://github.com/user/plugin",
24414
- "allagents plugin install ../local-plugin"
24655
+ "allagents plugin install ../local-plugin",
24656
+ "allagents plugin install my-plugin@official --scope user"
24415
24657
  ],
24416
24658
  expectedOutput: "Confirms the plugin was added, then runs sync. Shows sync results. Exit 0 on success, exit 1 on failure.",
24417
24659
  positionals: [
24418
24660
  { name: "plugin", type: "string", required: true, description: "Plugin identifier (plugin@marketplace, GitHub URL, or local path)" }
24419
24661
  ],
24662
+ options: [
24663
+ { flag: "--scope", short: "-s", type: "string", description: 'Installation scope: "project" (default) or "user"' }
24664
+ ],
24420
24665
  outputSchema: {
24421
24666
  plugin: "string",
24667
+ scope: "string",
24422
24668
  autoRegistered: "string | null",
24423
24669
  syncResult: {
24424
24670
  copied: "number",
@@ -24431,18 +24677,23 @@ var pluginInstallMeta = {
24431
24677
  };
24432
24678
  var pluginUninstallMeta = {
24433
24679
  command: "plugin uninstall",
24434
- description: "Uninstall plugin from .allagents/workspace.yaml",
24435
- whenToUse: "To remove a plugin from your workspace config and re-sync",
24680
+ description: "Uninstall plugin from workspace config. Use --scope user for user-level uninstall.",
24681
+ whenToUse: "To remove a plugin from your workspace (or user-level config with --scope user) and re-sync",
24436
24682
  examples: [
24437
24683
  "allagents plugin uninstall my-plugin@official",
24438
- "allagents plugin uninstall https://github.com/user/plugin"
24684
+ "allagents plugin uninstall https://github.com/user/plugin",
24685
+ "allagents plugin uninstall my-plugin@official --scope user"
24439
24686
  ],
24440
24687
  expectedOutput: "Confirms the plugin was removed, then runs sync to clean up. Exit 0 on success, exit 1 on failure.",
24441
24688
  positionals: [
24442
24689
  { name: "plugin", type: "string", required: true, description: "Plugin identifier to uninstall" }
24443
24690
  ],
24691
+ options: [
24692
+ { flag: "--scope", short: "-s", type: "string", description: 'Installation scope: "project" (default) or "user"' }
24693
+ ],
24444
24694
  outputSchema: {
24445
24695
  plugin: "string",
24696
+ scope: "string",
24446
24697
  syncResult: {
24447
24698
  copied: "number",
24448
24699
  generated: "number",
@@ -24522,6 +24773,56 @@ Sync complete:`);
24522
24773
  }
24523
24774
  return { ok: result.success && result.totalFailed === 0, syncData };
24524
24775
  }
24776
+ async function runUserSyncAndPrint() {
24777
+ if (!isJsonMode()) {
24778
+ console.log(`
24779
+ Syncing user workspace...
24780
+ `);
24781
+ }
24782
+ const result = await syncUserWorkspace();
24783
+ if (!result.success && result.error) {
24784
+ if (!isJsonMode()) {
24785
+ console.error(`Sync error: ${result.error}`);
24786
+ }
24787
+ return { ok: false, syncData: null };
24788
+ }
24789
+ const syncData = buildSyncData2(result);
24790
+ if (!isJsonMode()) {
24791
+ for (const pluginResult of result.pluginResults) {
24792
+ const status = pluginResult.success ? "✓" : "✗";
24793
+ console.log(`${status} Plugin: ${pluginResult.plugin}`);
24794
+ if (pluginResult.error) {
24795
+ console.log(` Error: ${pluginResult.error}`);
24796
+ }
24797
+ const copied = pluginResult.copyResults.filter((r) => r.action === "copied").length;
24798
+ const generated = pluginResult.copyResults.filter((r) => r.action === "generated").length;
24799
+ const failed = pluginResult.copyResults.filter((r) => r.action === "failed").length;
24800
+ if (copied > 0)
24801
+ console.log(` Copied: ${copied} files`);
24802
+ if (generated > 0)
24803
+ console.log(` Generated: ${generated} files`);
24804
+ if (failed > 0) {
24805
+ console.log(` Failed: ${failed} files`);
24806
+ for (const failedResult of pluginResult.copyResults.filter((r) => r.action === "failed")) {
24807
+ console.log(` - ${failedResult.destination}: ${failedResult.error}`);
24808
+ }
24809
+ }
24810
+ }
24811
+ console.log(`
24812
+ User sync complete:`);
24813
+ console.log(` Total copied: ${result.totalCopied}`);
24814
+ if (result.totalGenerated > 0) {
24815
+ console.log(` Total generated: ${result.totalGenerated}`);
24816
+ }
24817
+ if (result.totalFailed > 0) {
24818
+ console.log(` Total failed: ${result.totalFailed}`);
24819
+ }
24820
+ if (result.totalSkipped > 0) {
24821
+ console.log(` Total skipped: ${result.totalSkipped}`);
24822
+ }
24823
+ }
24824
+ return { ok: result.success && result.totalFailed === 0, syncData };
24825
+ }
24525
24826
  var marketplaceListCmd = import_cmd_ts3.command({
24526
24827
  name: "list",
24527
24828
  description: buildDescription(marketplaceListMeta),
@@ -24855,11 +25156,13 @@ var pluginInstallCmd = import_cmd_ts3.command({
24855
25156
  name: "install",
24856
25157
  description: buildDescription(pluginInstallMeta),
24857
25158
  args: {
24858
- plugin: import_cmd_ts3.positional({ type: import_cmd_ts3.string, displayName: "plugin" })
25159
+ plugin: import_cmd_ts3.positional({ type: import_cmd_ts3.string, displayName: "plugin" }),
25160
+ 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"' })
24859
25161
  },
24860
- handler: async ({ plugin }) => {
25162
+ handler: async ({ plugin, scope }) => {
24861
25163
  try {
24862
- const result = await addPlugin(plugin);
25164
+ const isUser = scope === "user";
25165
+ const result = isUser ? await addUserPlugin(plugin) : await addPlugin(plugin);
24863
25166
  if (!result.success) {
24864
25167
  if (isJsonMode()) {
24865
25168
  jsonOutput({ success: false, command: "plugin install", error: result.error ?? "Unknown error" });
@@ -24869,12 +25172,13 @@ var pluginInstallCmd = import_cmd_ts3.command({
24869
25172
  process.exit(1);
24870
25173
  }
24871
25174
  if (isJsonMode()) {
24872
- const { ok, syncData } = await runSyncAndPrint();
25175
+ const { ok, syncData } = isUser ? await runUserSyncAndPrint() : await runSyncAndPrint();
24873
25176
  jsonOutput({
24874
25177
  success: ok,
24875
25178
  command: "plugin install",
24876
25179
  data: {
24877
25180
  plugin,
25181
+ scope: isUser ? "user" : "project",
24878
25182
  autoRegistered: result.autoRegistered ?? null,
24879
25183
  syncResult: syncData
24880
25184
  },
@@ -24888,8 +25192,8 @@ var pluginInstallCmd = import_cmd_ts3.command({
24888
25192
  if (result.autoRegistered) {
24889
25193
  console.log(`✓ Auto-registered marketplace: ${result.autoRegistered}`);
24890
25194
  }
24891
- console.log(`✓ Installed plugin: ${plugin}`);
24892
- const { ok: syncOk } = await runSyncAndPrint();
25195
+ console.log(`✓ Installed plugin${isUser ? " (user scope)" : ""}: ${plugin}`);
25196
+ const { ok: syncOk } = isUser ? await runUserSyncAndPrint() : await runSyncAndPrint();
24893
25197
  if (!syncOk) {
24894
25198
  process.exit(1);
24895
25199
  }
@@ -24911,11 +25215,13 @@ var pluginUninstallCmd = import_cmd_ts3.command({
24911
25215
  description: buildDescription(pluginUninstallMeta),
24912
25216
  aliases: ["remove"],
24913
25217
  args: {
24914
- plugin: import_cmd_ts3.positional({ type: import_cmd_ts3.string, displayName: "plugin" })
25218
+ plugin: import_cmd_ts3.positional({ type: import_cmd_ts3.string, displayName: "plugin" }),
25219
+ 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"' })
24915
25220
  },
24916
- handler: async ({ plugin }) => {
25221
+ handler: async ({ plugin, scope }) => {
24917
25222
  try {
24918
- const result = await removePlugin(plugin);
25223
+ const isUser = scope === "user";
25224
+ const result = isUser ? await removeUserPlugin(plugin) : await removePlugin(plugin);
24919
25225
  if (!result.success) {
24920
25226
  if (isJsonMode()) {
24921
25227
  jsonOutput({ success: false, command: "plugin uninstall", error: result.error ?? "Unknown error" });
@@ -24925,12 +25231,13 @@ var pluginUninstallCmd = import_cmd_ts3.command({
24925
25231
  process.exit(1);
24926
25232
  }
24927
25233
  if (isJsonMode()) {
24928
- const { ok, syncData } = await runSyncAndPrint();
25234
+ const { ok, syncData } = isUser ? await runUserSyncAndPrint() : await runSyncAndPrint();
24929
25235
  jsonOutput({
24930
25236
  success: ok,
24931
25237
  command: "plugin uninstall",
24932
25238
  data: {
24933
25239
  plugin,
25240
+ scope: isUser ? "user" : "project",
24934
25241
  syncResult: syncData
24935
25242
  },
24936
25243
  ...!ok && { error: "Sync completed with failures" }
@@ -24940,8 +25247,8 @@ var pluginUninstallCmd = import_cmd_ts3.command({
24940
25247
  }
24941
25248
  return;
24942
25249
  }
24943
- console.log(`✓ Uninstalled plugin: ${plugin}`);
24944
- const { ok: syncOk } = await runSyncAndPrint();
25250
+ console.log(`✓ Uninstalled plugin${isUser ? " (user scope)" : ""}: ${plugin}`);
25251
+ const { ok: syncOk } = isUser ? await runUserSyncAndPrint() : await runSyncAndPrint();
24945
25252
  if (!syncOk) {
24946
25253
  process.exit(1);
24947
25254
  }
@@ -24997,7 +25304,7 @@ var updateMeta = {
24997
25304
  // package.json
24998
25305
  var package_default = {
24999
25306
  name: "allagents",
25000
- version: "0.8.7",
25307
+ version: "0.10.0",
25001
25308
  description: "CLI tool for managing multi-repo AI agent workspaces with plugin synchronization",
25002
25309
  type: "module",
25003
25310
  bin: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "allagents",
3
- "version": "0.8.7",
3
+ "version": "0.10.0",
4
4
  "description": "CLI tool for managing multi-repo AI agent workspaces with plugin synchronization",
5
5
  "type": "module",
6
6
  "bin": {