agentloom 0.1.0 → 0.1.1

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 (51) hide show
  1. package/README.md +91 -72
  2. package/bin/cli.mjs +3 -2
  3. package/dist/cli.d.ts +1 -0
  4. package/dist/cli.js +149 -17
  5. package/dist/commands/add.d.ts +7 -0
  6. package/dist/commands/add.js +122 -31
  7. package/dist/commands/agent.d.ts +2 -0
  8. package/dist/commands/agent.js +85 -0
  9. package/dist/commands/command.d.ts +2 -0
  10. package/dist/commands/command.js +98 -0
  11. package/dist/commands/delete.d.ts +9 -0
  12. package/dist/commands/delete.js +444 -0
  13. package/dist/commands/entity-utils.d.ts +13 -0
  14. package/dist/commands/entity-utils.js +58 -0
  15. package/dist/commands/find.d.ts +21 -0
  16. package/dist/commands/find.js +944 -0
  17. package/dist/commands/mcp.js +133 -55
  18. package/dist/commands/skills.d.ts +2 -1
  19. package/dist/commands/skills.js +105 -9
  20. package/dist/commands/sync.d.ts +6 -0
  21. package/dist/commands/sync.js +12 -10
  22. package/dist/commands/update.d.ts +7 -0
  23. package/dist/commands/update.js +286 -21
  24. package/dist/core/argv.d.ts +2 -1
  25. package/dist/core/argv.js +42 -2
  26. package/dist/core/commands.d.ts +13 -0
  27. package/dist/core/commands.js +65 -0
  28. package/dist/core/copy.d.ts +6 -0
  29. package/dist/core/copy.js +126 -65
  30. package/dist/core/importer.d.ts +28 -1
  31. package/dist/core/importer.js +1104 -41
  32. package/dist/core/lockfile.js +86 -3
  33. package/dist/core/manage-agents-bootstrap.d.ts +10 -0
  34. package/dist/core/manage-agents-bootstrap.js +40 -0
  35. package/dist/core/manifest.js +7 -1
  36. package/dist/core/router.d.ts +16 -0
  37. package/dist/core/router.js +66 -0
  38. package/dist/core/scope.d.ts +1 -1
  39. package/dist/core/scope.js +12 -8
  40. package/dist/core/settings.d.ts +4 -3
  41. package/dist/core/settings.js +10 -8
  42. package/dist/core/skills.d.ts +23 -0
  43. package/dist/core/skills.js +328 -0
  44. package/dist/core/sources.d.ts +3 -1
  45. package/dist/core/sources.js +31 -1
  46. package/dist/core/telemetry.d.ts +26 -0
  47. package/dist/core/telemetry.js +124 -0
  48. package/dist/sync/index.d.ts +7 -1
  49. package/dist/sync/index.js +395 -131
  50. package/dist/types.d.ts +16 -1
  51. package/package.json +5 -4
package/README.md CHANGED
@@ -28,6 +28,18 @@ Project scope:
28
28
  agents/
29
29
  reviewer.md
30
30
  debugger.md
31
+ commands/
32
+ review.md
33
+ ship.md
34
+ skills/
35
+ reviewing/
36
+ SKILL.md
37
+ references/
38
+ assets/
39
+ debugging/
40
+ SKILL.md
41
+ references/
42
+ assets/
31
43
  mcp.json
32
44
  agents.lock.json
33
45
  settings.local.json
@@ -37,100 +49,83 @@ Global scope uses `~/.agents` with the same file layout.
37
49
 
38
50
  ## Commands
39
51
 
40
- ### `agentloom skills ...`
41
- Pass-through wrapper to `npx skills ...` from
42
- [`vercel-labs/skills`](https://github.com/vercel-labs/skills).
52
+ ### Aggregate verbs
43
53
 
44
- ### `agentloom add <source>`
45
- Import canonical agents/MCP from:
54
+ - `agentloom add <source>`
55
+ - `agentloom find <query>`
56
+ - `agentloom update [source]`
57
+ - `agentloom sync`
58
+ - `agentloom delete <source|name>`
46
59
 
47
- - local repo path
48
- - GitHub slug (`owner/repo`)
49
- - generic git URL
60
+ Aggregate `add` imports discoverable entities from a source (agents, commands, MCP servers, skills). In interactive sessions, each entity supports two tracking modes:
50
61
 
51
- Options:
62
+ - `Sync everything from source` (default): updates include newly added source items.
63
+ - `Use custom selection`: updates stay pinned to the selected items, even if all current items were selected.
52
64
 
53
- - `--ref <ref>`: git ref (branch/tag/commit) for remote sources
54
- - `--subdir <path>`: subdirectory inside source repo
55
- - `--rename <name>`: rename imported agent when importing a single agent
56
- - `--local | --global`: choose destination scope
57
- - `--yes`: skip interactive conflict prompts
58
- - `--no-sync`: skip post-import sync
59
- - `--providers <csv>`: limit post-import sync providers
60
- - `--dry-run`: show sync changes without writing provider files
65
+ Source path resolution is additive and priority-ordered:
61
66
 
62
- Example:
67
+ - Agents: `.agents/agents` -> `agents`
68
+ - Commands: `.agents/commands` -> `commands` -> `prompts`
69
+ - Skills: `.agents/skills` -> `skills` -> root `SKILL.md` fallback
70
+ - MCP: `.agents/mcp.json` -> `mcp.json`
63
71
 
64
- ```bash
65
- agentloom add vercel-labs/skills --subdir skills
66
- ```
67
-
68
- ### `agentloom update`
69
- Refresh lockfile sources (`agents.lock.json`) and re-import changed revisions.
70
-
71
- Options:
72
-
73
- - `--local | --global`: choose lockfile scope
74
- - `--yes`: skip conflict prompts during re-import
75
- - `--no-sync`: skip post-update sync
76
- - `--providers <csv>`: limit post-update sync providers
77
- - `--dry-run`: show sync changes without writing provider files
78
-
79
- ### `agentloom sync`
80
- Generate provider-specific outputs from canonical `.agents` data.
81
-
82
- Options:
83
-
84
- - `--local | --global`: choose canonical scope
85
- - `--providers <csv>`: limit sync providers
86
- - `--yes`: auto-delete stale generated files
87
- - `--dry-run`: show planned changes without writing files
88
-
89
- Example:
90
-
91
- ```bash
92
- agentloom sync --providers codex,claude,cursor
93
- ```
72
+ Aggregate `agentloom add <source>` can import command/skill/MCP-only repositories even when no `agents/` directory exists.
94
73
 
95
- ### `agentloom mcp add|list|delete`
96
- Manage canonical MCP servers in `.agents/mcp.json`.
74
+ ### Entity verbs
97
75
 
98
- `mcp add` options:
76
+ - `agentloom agent <add|list|delete|find|update|sync>`
77
+ - `agentloom command <add|list|delete|find|update|sync>`
78
+ - `agentloom mcp <add|list|delete|find|update|sync>`
79
+ - `agentloom skill <add|list|delete|find|update|sync>`
99
80
 
100
- - `--url <url>` or `--command <cmd>`: required transport config
101
- - `--arg <value>`: repeatable command arg
102
- - `--env KEY=VALUE`: repeatable environment variable
103
- - `--providers <csv>`: provider-specific assignment
104
- - `--local | --global`: choose canonical scope
105
- - `--no-sync`: skip post-change sync
81
+ ### Selector flags
106
82
 
107
- `mcp list` options:
83
+ - `--agents <csv>`
84
+ - `--commands <csv>`
85
+ - `--mcps <csv>`
86
+ - `--skills <csv>`
87
+ - `--selection-mode <all|sync-all|custom>`
88
+ - `--source <value>`
89
+ - `--name <value>`
90
+ - `--entity <agent|command|mcp|skill>`
108
91
 
109
- - `--json`: print raw canonical JSON
110
- - `--local | --global`: choose canonical scope
92
+ ### MCP manual server mode
111
93
 
112
- `mcp delete` options:
94
+ Source-based MCP import lives under `agentloom mcp add ...`.
95
+ Manual server management is under:
113
96
 
114
- - `--local | --global`: choose canonical scope
115
- - `--no-sync`: skip post-change sync
97
+ - `agentloom mcp server add <name> (--url <url> | --command <cmd>)`
98
+ - `agentloom mcp server list`
99
+ - `agentloom mcp server delete <name>`
116
100
 
117
101
  Examples:
118
102
 
119
103
  ```bash
120
- agentloom mcp add browser-tools --command npx --arg browser-tools-mcp
121
- agentloom mcp list
122
- agentloom mcp delete browser-tools
104
+ agentloom add farnoodma/agents
105
+ agentloom agent add farnoodma/agents --agents issue-creator
106
+ agentloom command add farnoodma/agents --commands review
107
+ agentloom mcp add farnoodma/agents --mcps browser
108
+ agentloom skill add farnoodma/agents --skills pr-review
109
+ agentloom delete farnoodma/agents
110
+ agentloom mcp server add browser-tools --command npx --arg browser-tools-mcp
123
111
  ```
124
112
 
125
113
  ### Top-level help
126
114
 
127
115
  ```bash
128
116
  agentloom --help
117
+ agentloom find --help
129
118
  agentloom add --help
130
119
  agentloom update --help
131
120
  agentloom sync --help
121
+ agentloom delete --help
122
+ agentloom agent --help
123
+ agentloom skill --help
124
+ agentloom command --help
125
+ agentloom command add --help
132
126
  agentloom mcp --help
133
127
  agentloom mcp add --help
128
+ agentloom mcp server --help
134
129
  ```
135
130
 
136
131
  ### Version update notice
@@ -146,6 +141,27 @@ agentloom mcp add --help
146
141
  AGENTLOOM_DISABLE_UPDATE_NOTIFIER=1
147
142
  ```
148
143
 
144
+ ### Manage-agents bootstrap prompt
145
+
146
+ In interactive sessions, `agentloom` checks for:
147
+
148
+ - `~/.agents/skills/manage-agents/SKILL.md`
149
+ - `.agents/skills/manage-agents/SKILL.md` (in the current workspace)
150
+
151
+ If missing in both locations, it offers to bootstrap `manage-agents` because that skill helps agents reliably manage Agentloom resources (find/create/import/update/sync/delete).
152
+
153
+ The install runs after the requested command completes so scope/provider selections from that command can be reused.
154
+
155
+ - disable this prompt via `AGENTLOOM_DISABLE_MANAGE_AGENTS_PROMPT=1`
156
+
157
+ ### Telemetry
158
+
159
+ Successful GitHub-based `agentloom add` imports can send anonymous telemetry
160
+ to the Agentloom directory API.
161
+
162
+ - disable telemetry via `AGENTLOOM_DISABLE_TELEMETRY=1`
163
+ - override endpoint via `AGENTLOOM_TELEMETRY_ENDPOINT`
164
+
149
165
  ### Scope resolution
150
166
 
151
167
  If neither `--local` nor `--global` is provided:
@@ -207,6 +223,10 @@ For Codex, `agentloom sync` writes role-based multi-agent config:
207
223
 
208
224
  This follows official Codex multi-agent guidance.
209
225
 
226
+ For canonical commands (`.agents/commands`), Codex output is always written to
227
+ global prompts under `~/.codex/prompts` (Codex prompts are global-only), even
228
+ when syncing local scope.
229
+
210
230
  ## Development
211
231
 
212
232
  ```bash
@@ -219,15 +239,14 @@ pnpm build
219
239
 
220
240
  The GitHub Actions publish workflow is defined in `.github/workflows/release.yml`.
221
241
 
222
- - Push to `main` with `[patch]` or `[minor]` in commit subjects to trigger an automated npm release.
223
- - Run the workflow manually (`workflow_dispatch`) and choose `patch` or `minor` to force a release.
224
- - Push a `v*` tag (for example `v0.2.0`) to publish an already-versioned commit without bumping.
225
- - Automated bump releases create a `vX.Y.Z` commit/tag via `npm version`, push both to GitHub, then publish to npm with provenance.
242
+ - Publish runs only when a GitHub Release is published (`release.published` event).
243
+ - Release tags must use stable semver (`vX.Y.Z`).
244
+ - The release tag version must match `packages/cli/package.json`.
245
+ - The workflow publishes only the CLI package to npm with provenance.
226
246
 
227
247
  Required GitHub configuration:
228
248
 
229
- - Secret: `NPM_TOKEN` (automation token from the npm account that should own `agentloom`).
230
- - Repository setting: `Actions -> General -> Workflow permissions -> Read and write permissions` (required so CI can push version commits/tags).
249
+ - npm Trusted Publisher configured for this repo/workflow (`farnoodma/agentloom`, workflow file `release.yml`).
231
250
 
232
251
  ## License
233
252
 
package/bin/cli.mjs CHANGED
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { runCli } from '../dist/cli.js';
3
+ import { formatCliErrorMessage, runCli } from '../dist/cli.js';
4
4
 
5
5
  runCli(process.argv.slice(2)).catch((err) => {
6
- console.error(err instanceof Error ? err.message : String(err));
6
+ const message = err instanceof Error ? err.message : String(err);
7
+ console.error(formatCliErrorMessage(message));
7
8
  process.exit(1);
8
9
  });
package/dist/cli.d.ts CHANGED
@@ -1 +1,2 @@
1
1
  export declare function runCli(argv: string[]): Promise<void>;
2
+ export declare function formatCliErrorMessage(message: string): string;
package/dist/cli.js CHANGED
@@ -1,14 +1,26 @@
1
1
  import { parseArgs } from "./core/argv.js";
2
+ import { parseProvidersFlag } from "./core/argv.js";
3
+ import { runAgentCommand } from "./commands/agent.js";
2
4
  import { runAddCommand } from "./commands/add.js";
5
+ import { runCommandCommand } from "./commands/command.js";
6
+ import { runDeleteCommand } from "./commands/delete.js";
7
+ import { runFindCommand } from "./commands/find.js";
3
8
  import { runMcpCommand } from "./commands/mcp.js";
4
- import { runSkillsPassthrough } from "./commands/skills.js";
9
+ import { runSkillCommand } from "./commands/skills.js";
5
10
  import { runSyncCommand } from "./commands/sync.js";
6
11
  import { runUpdateCommand } from "./commands/update.js";
7
12
  import { formatUnknownCommandError, getRootHelpText } from "./core/copy.js";
13
+ import { maybePromptManageAgentsBootstrap } from "./core/manage-agents-bootstrap.js";
14
+ import { parseCommandRoute } from "./core/router.js";
15
+ import { buildScopePaths } from "./core/scope.js";
16
+ import { getGlobalSettingsPath, readSettings } from "./core/settings.js";
8
17
  import { maybeNotifyVersionUpdate } from "./core/version-notifier.js";
9
18
  import { getCliVersion } from "./core/version.js";
19
+ import { ALL_PROVIDERS } from "./types.js";
20
+ const MANAGE_AGENTS_SOURCE = "farnoodma/agentloom";
21
+ const MANAGE_AGENTS_SELECTOR = "manage-agents";
10
22
  export async function runCli(argv) {
11
- const command = argv[0];
23
+ const command = argv[0] ?? "";
12
24
  const version = getCliVersion();
13
25
  if (!command ||
14
26
  command === "help" ||
@@ -21,41 +33,161 @@ export async function runCli(argv) {
21
33
  console.log(version);
22
34
  return;
23
35
  }
24
- if (command === "skills") {
25
- runSkillsPassthrough(argv.slice(1));
26
- return;
27
- }
28
36
  const parsed = parseArgs(argv);
29
37
  const cwd = process.cwd();
38
+ const shouldBootstrapManageAgents = await maybePromptManageAgentsBootstrap({
39
+ command,
40
+ help: Boolean(parsed.help),
41
+ yes: Boolean(parsed.yes),
42
+ cwd,
43
+ });
44
+ const route = parseCommandRoute(argv);
30
45
  if (!parsed.help) {
31
46
  await maybeNotifyVersionUpdate({
32
47
  command,
33
48
  currentVersion: version,
34
49
  });
35
50
  }
36
- switch (command) {
37
- case "add":
38
- await runAddCommand(parsed, cwd);
39
- return;
40
- case "update":
41
- await runUpdateCommand(parsed, cwd);
51
+ if (!route) {
52
+ throw new Error(formatUnknownCommandError(command));
53
+ }
54
+ await runRoutedCommand(route, parsed, cwd, command);
55
+ if (shouldBootstrapManageAgents) {
56
+ const bootstrapArgs = buildManageAgentsBootstrapArgs(parsed, cwd);
57
+ await runAddCommand(parseArgs(bootstrapArgs), cwd);
58
+ }
59
+ }
60
+ function printHelp() {
61
+ console.log(getRootHelpText());
62
+ }
63
+ async function runRoutedCommand(route, parsed, cwd, command) {
64
+ if (!route) {
65
+ throw new Error(formatUnknownCommandError(command));
66
+ }
67
+ if (route.mode === "aggregate") {
68
+ switch (route.verb) {
69
+ case "add":
70
+ await runAddCommand(parsed, cwd);
71
+ return;
72
+ case "find":
73
+ await runFindCommand(parsed);
74
+ return;
75
+ case "update":
76
+ await runUpdateCommand(parsed, cwd);
77
+ return;
78
+ case "sync":
79
+ await runSyncCommand(parsed, cwd);
80
+ return;
81
+ case "delete":
82
+ await runDeleteCommand(parsed, cwd);
83
+ return;
84
+ default:
85
+ throw new Error(formatUnknownCommandError(command));
86
+ }
87
+ }
88
+ if (route.mode === "mcp-server") {
89
+ await runMcpCommand(parsed, cwd);
90
+ return;
91
+ }
92
+ switch (route.entity) {
93
+ case "agent":
94
+ await runAgentCommand(parsed, cwd);
42
95
  return;
43
- case "sync":
44
- await runSyncCommand(parsed, cwd);
96
+ case "command":
97
+ await runCommandCommand(parsed, cwd);
45
98
  return;
46
99
  case "mcp":
47
100
  await runMcpCommand(parsed, cwd);
48
101
  return;
102
+ case "skill":
103
+ await runSkillCommand(parsed, cwd);
104
+ return;
49
105
  default:
50
106
  throw new Error(formatUnknownCommandError(command));
51
107
  }
52
108
  }
53
- function printHelp() {
54
- console.log(getRootHelpText());
109
+ function buildManageAgentsBootstrapArgs(parsed, cwd) {
110
+ const scope = resolveBootstrapScope(parsed);
111
+ const providers = resolveBootstrapProviders(parsed, cwd, scope);
112
+ const args = [
113
+ "skill",
114
+ "add",
115
+ MANAGE_AGENTS_SOURCE,
116
+ "--skills",
117
+ MANAGE_AGENTS_SELECTOR,
118
+ ];
119
+ if (scope === "local")
120
+ args.push("--local");
121
+ if (scope === "global")
122
+ args.push("--global");
123
+ if (typeof parsed["selection-mode"] === "string" &&
124
+ parsed["selection-mode"].trim().length > 0) {
125
+ args.push("--selection-mode", parsed["selection-mode"].trim());
126
+ }
127
+ if (parsed["no-sync"])
128
+ args.push("--no-sync");
129
+ if (parsed["dry-run"])
130
+ args.push("--dry-run");
131
+ if (providers && providers.length > 0) {
132
+ args.push("--providers", providers.join(","));
133
+ }
134
+ return args;
135
+ }
136
+ function resolveBootstrapScope(parsed) {
137
+ if (parsed.local)
138
+ return "local";
139
+ if (parsed.global)
140
+ return "global";
141
+ const globalSettings = readSettings(getGlobalSettingsPath());
142
+ if (globalSettings.lastScope === "local" ||
143
+ globalSettings.lastScope === "global") {
144
+ return globalSettings.lastScope;
145
+ }
146
+ return undefined;
147
+ }
148
+ function resolveBootstrapProviders(parsed, cwd, scope) {
149
+ const explicitProviders = parseProvidersFlag(parsed.providers);
150
+ if (explicitProviders && explicitProviders.length > 0) {
151
+ return explicitProviders;
152
+ }
153
+ if (!scope)
154
+ return undefined;
155
+ const settingsPath = buildScopePaths(cwd, scope).settingsPath;
156
+ const scopeSettings = readSettings(settingsPath);
157
+ return normalizeProviders(scopeSettings.defaultProviders);
158
+ }
159
+ function normalizeProviders(providers) {
160
+ const selected = new Set();
161
+ for (const provider of providers ?? []) {
162
+ const normalized = provider.trim().toLowerCase();
163
+ if (ALL_PROVIDERS.includes(normalized)) {
164
+ selected.add(normalized);
165
+ }
166
+ }
167
+ return [...selected];
168
+ }
169
+ function colorRed(text) {
170
+ return process.stderr.isTTY ? `\u001b[31m${text}\u001b[0m` : text;
171
+ }
172
+ export function formatCliErrorMessage(message) {
173
+ const trimmed = message.trim();
174
+ if (trimmed.length === 0) {
175
+ return `\n${colorRed("✖")} Error`;
176
+ }
177
+ const lines = trimmed.split("\n");
178
+ const firstLine = lines.shift();
179
+ if (!firstLine) {
180
+ return `\n${colorRed("✖")} Error`;
181
+ }
182
+ const formatted = `${colorRed("✖")} ${firstLine}`;
183
+ return lines.length > 0
184
+ ? `\n${formatted}\n${lines.join("\n")}`
185
+ : `\n${formatted}`;
55
186
  }
56
187
  if (import.meta.url === `file://${process.argv[1]}`) {
57
188
  runCli(process.argv.slice(2)).catch((err) => {
58
- console.error(err instanceof Error ? err.message : String(err));
189
+ const message = err instanceof Error ? err.message : String(err);
190
+ console.error(formatCliErrorMessage(message));
59
191
  process.exit(1);
60
192
  });
61
193
  }
@@ -1,2 +1,9 @@
1
1
  import type { ParsedArgs } from "minimist";
2
+ import type { EntityType } from "../types.js";
2
3
  export declare function runAddCommand(argv: ParsedArgs, cwd: string): Promise<void>;
4
+ export declare function runScopedAddCommand(options: {
5
+ argv: ParsedArgs;
6
+ cwd: string;
7
+ entity: EntityType;
8
+ sourceIndex: number;
9
+ }): Promise<void>;
@@ -1,56 +1,117 @@
1
- import { importSource, NonInteractiveConflictError } from "../core/importer.js";
2
- import { resolveScope } from "../core/scope.js";
3
- import { updateLastScope } from "../core/settings.js";
4
- import { parseProvidersFlag } from "../core/argv.js";
1
+ import { parseProvidersFlag, parseSelectionModeFlag } from "../core/argv.js";
5
2
  import { formatUsageError, getAddHelpText } from "../core/copy.js";
6
- import { formatSyncSummary, syncFromCanonical } from "../sync/index.js";
3
+ import { importSource, NonInteractiveConflictError } from "../core/importer.js";
4
+ import { sendAddTelemetryEvent } from "../core/telemetry.js";
5
+ import { resolveProvidersForSync } from "../sync/index.js";
6
+ import { getEntitySelectors, getNonInteractiveMode, resolvePathsForCommand, runPostMutationSync, } from "./entity-utils.js";
7
7
  export async function runAddCommand(argv, cwd) {
8
8
  if (argv.help) {
9
9
  console.log(getAddHelpText());
10
10
  return;
11
11
  }
12
- const source = argv._[1];
12
+ await runEntityAwareAdd({
13
+ argv,
14
+ cwd,
15
+ target: "all",
16
+ sourceIndex: 1,
17
+ });
18
+ }
19
+ export async function runScopedAddCommand(options) {
20
+ await runEntityAwareAdd({
21
+ argv: options.argv,
22
+ cwd: options.cwd,
23
+ target: options.entity,
24
+ sourceIndex: options.sourceIndex,
25
+ });
26
+ }
27
+ async function runEntityAwareAdd(options) {
28
+ const source = options.argv._[options.sourceIndex];
13
29
  if (typeof source !== "string" || source.trim() === "") {
14
30
  throw new Error(formatUsageError({
15
31
  issue: "Missing required <source>.",
16
- usage: "agentloom add <source> [--ref <ref>] [--subdir <path>] [options]",
17
- example: "agentloom add vercel-labs/skills --subdir skills",
32
+ usage: buildAddUsage(options.target),
33
+ example: buildAddExample(options.target),
18
34
  }));
19
35
  }
20
- const nonInteractive = !(process.stdin.isTTY && process.stdout.isTTY);
21
- const paths = await resolveScope({
22
- cwd,
23
- global: Boolean(argv.global),
24
- local: Boolean(argv.local),
25
- interactive: !nonInteractive,
26
- });
36
+ const nonInteractive = getNonInteractiveMode(options.argv);
37
+ const paths = await resolvePathsForCommand(options.argv, options.cwd);
38
+ const explicitProviders = parseProvidersFlag(options.argv.providers);
39
+ const selectionMode = parseSelectionModeFlag(options.argv["selection-mode"]);
40
+ const importAgents = options.target === "all" || options.target === "agent";
41
+ const importCommands = options.target === "all" || options.target === "command";
42
+ const importMcp = options.target === "all" || options.target === "mcp";
43
+ const importSkills = options.target === "all" || options.target === "skill";
44
+ const agentSelectors = getEntitySelectors(options.argv, "agent");
45
+ const commandSelectors = getEntitySelectors(options.argv, "command");
46
+ const mcpSelectors = getEntitySelectors(options.argv, "mcp");
47
+ const skillSelectors = getEntitySelectors(options.argv, "skill");
48
+ let resolvedSkillProviders;
49
+ const resolveProvidersForSkills = async () => {
50
+ if (explicitProviders && explicitProviders.length > 0) {
51
+ return explicitProviders;
52
+ }
53
+ if (resolvedSkillProviders && resolvedSkillProviders.length > 0) {
54
+ return resolvedSkillProviders;
55
+ }
56
+ resolvedSkillProviders = await resolveProvidersForSync({
57
+ paths,
58
+ explicitProviders,
59
+ nonInteractive,
60
+ });
61
+ return resolvedSkillProviders;
62
+ };
27
63
  try {
28
64
  const summary = await importSource({
29
65
  source,
30
- ref: typeof argv.ref === "string" ? argv.ref : undefined,
31
- subdir: typeof argv.subdir === "string" ? argv.subdir : undefined,
32
- rename: typeof argv.rename === "string" ? argv.rename : undefined,
33
- yes: Boolean(argv.yes),
66
+ ref: typeof options.argv.ref === "string" ? options.argv.ref : undefined,
67
+ subdir: typeof options.argv.subdir === "string"
68
+ ? options.argv.subdir
69
+ : undefined,
70
+ rename: typeof options.argv.rename === "string"
71
+ ? options.argv.rename
72
+ : undefined,
73
+ agents: agentSelectors,
74
+ yes: Boolean(options.argv.yes),
34
75
  nonInteractive,
35
76
  paths,
77
+ importAgents,
78
+ requireAgents: options.target === "agent",
79
+ importCommands,
80
+ requireCommands: options.target === "command",
81
+ importMcp,
82
+ requireMcp: options.target === "mcp",
83
+ mcpSelectors,
84
+ promptForMcp: mcpSelectors.length === 0,
85
+ importSkills,
86
+ requireSkills: options.target === "skill",
87
+ skillSelectors,
88
+ promptForSkills: skillSelectors.length === 0,
89
+ skillsProviders: explicitProviders,
90
+ resolveSkillsProviders: importSkills && !explicitProviders
91
+ ? resolveProvidersForSkills
92
+ : undefined,
93
+ commandSelectors,
94
+ promptForCommands: commandSelectors.length === 0,
95
+ promptForAgentSelection: agentSelectors.length === 0,
96
+ selectionMode,
36
97
  });
37
98
  console.log(`Imported source: ${summary.source}`);
38
99
  console.log(`Source type: ${summary.sourceType}`);
39
100
  console.log(`Resolved commit: ${summary.resolvedCommit}`);
40
101
  console.log(`Imported agents: ${summary.importedAgents.length}`);
102
+ console.log(`Imported commands: ${summary.importedCommands.length}`);
41
103
  console.log(`Imported MCP servers: ${summary.importedMcpServers.length}`);
42
- updateLastScope(paths.settingsPath, paths.scope);
43
- if (!argv["no-sync"]) {
44
- const syncSummary = await syncFromCanonical({
45
- paths,
46
- providers: parseProvidersFlag(argv.providers),
47
- yes: Boolean(argv.yes),
48
- nonInteractive,
49
- dryRun: Boolean(argv["dry-run"]),
50
- });
51
- console.log("");
52
- console.log(formatSyncSummary(syncSummary, paths.agentsRoot));
53
- }
104
+ console.log(`Imported skills: ${summary.importedSkills.length}`);
105
+ await sendAddTelemetryEvent({
106
+ rawSource: source,
107
+ summary,
108
+ });
109
+ await runPostMutationSync({
110
+ argv: options.argv,
111
+ paths,
112
+ target: options.target,
113
+ providers: explicitProviders ?? resolvedSkillProviders,
114
+ });
54
115
  }
55
116
  catch (err) {
56
117
  if (err instanceof NonInteractiveConflictError) {
@@ -60,3 +121,33 @@ export async function runAddCommand(argv, cwd) {
60
121
  throw err;
61
122
  }
62
123
  }
124
+ function buildAddUsage(target) {
125
+ if (target === "agent") {
126
+ return "agentloom agent add <source> [--ref <ref>] [--subdir <path>] [--agents <name>] [options]";
127
+ }
128
+ if (target === "command") {
129
+ return "agentloom command add <source> [--ref <ref>] [--subdir <path>] [--commands <name>] [options]";
130
+ }
131
+ if (target === "mcp") {
132
+ return "agentloom mcp add <source> [--ref <ref>] [--subdir <path>] [--mcps <name>] [options]";
133
+ }
134
+ if (target === "skill") {
135
+ return "agentloom skill add <source> [--ref <ref>] [--subdir <path>] [--skills <name>] [options]";
136
+ }
137
+ return "agentloom add <source> [--ref <ref>] [--subdir <path>] [options]";
138
+ }
139
+ function buildAddExample(target) {
140
+ if (target === "agent") {
141
+ return "agentloom agent add farnoodma/agents --agents issue-creator";
142
+ }
143
+ if (target === "command") {
144
+ return "agentloom command add farnoodma/agents --commands review";
145
+ }
146
+ if (target === "mcp") {
147
+ return "agentloom mcp add farnoodma/agents --mcps browser";
148
+ }
149
+ if (target === "skill") {
150
+ return "agentloom skill add farnoodma/agents --skills code-review";
151
+ }
152
+ return "agentloom add farnoodma/agents --providers codex,claude";
153
+ }
@@ -0,0 +1,2 @@
1
+ import type { ParsedArgs } from "minimist";
2
+ export declare function runAgentCommand(argv: ParsedArgs, cwd: string): Promise<void>;