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.
- package/README.md +91 -72
- package/bin/cli.mjs +3 -2
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +149 -17
- package/dist/commands/add.d.ts +7 -0
- package/dist/commands/add.js +122 -31
- package/dist/commands/agent.d.ts +2 -0
- package/dist/commands/agent.js +85 -0
- package/dist/commands/command.d.ts +2 -0
- package/dist/commands/command.js +98 -0
- package/dist/commands/delete.d.ts +9 -0
- package/dist/commands/delete.js +444 -0
- package/dist/commands/entity-utils.d.ts +13 -0
- package/dist/commands/entity-utils.js +58 -0
- package/dist/commands/find.d.ts +21 -0
- package/dist/commands/find.js +944 -0
- package/dist/commands/mcp.js +133 -55
- package/dist/commands/skills.d.ts +2 -1
- package/dist/commands/skills.js +105 -9
- package/dist/commands/sync.d.ts +6 -0
- package/dist/commands/sync.js +12 -10
- package/dist/commands/update.d.ts +7 -0
- package/dist/commands/update.js +286 -21
- package/dist/core/argv.d.ts +2 -1
- package/dist/core/argv.js +42 -2
- package/dist/core/commands.d.ts +13 -0
- package/dist/core/commands.js +65 -0
- package/dist/core/copy.d.ts +6 -0
- package/dist/core/copy.js +126 -65
- package/dist/core/importer.d.ts +28 -1
- package/dist/core/importer.js +1104 -41
- package/dist/core/lockfile.js +86 -3
- package/dist/core/manage-agents-bootstrap.d.ts +10 -0
- package/dist/core/manage-agents-bootstrap.js +40 -0
- package/dist/core/manifest.js +7 -1
- package/dist/core/router.d.ts +16 -0
- package/dist/core/router.js +66 -0
- package/dist/core/scope.d.ts +1 -1
- package/dist/core/scope.js +12 -8
- package/dist/core/settings.d.ts +4 -3
- package/dist/core/settings.js +10 -8
- package/dist/core/skills.d.ts +23 -0
- package/dist/core/skills.js +328 -0
- package/dist/core/sources.d.ts +3 -1
- package/dist/core/sources.js +31 -1
- package/dist/core/telemetry.d.ts +26 -0
- package/dist/core/telemetry.js +124 -0
- package/dist/sync/index.d.ts +7 -1
- package/dist/sync/index.js +395 -131
- package/dist/types.d.ts +16 -1
- 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
|
-
###
|
|
41
|
-
Pass-through wrapper to `npx skills ...` from
|
|
42
|
-
[`vercel-labs/skills`](https://github.com/vercel-labs/skills).
|
|
52
|
+
### Aggregate verbs
|
|
43
53
|
|
|
44
|
-
|
|
45
|
-
|
|
54
|
+
- `agentloom add <source>`
|
|
55
|
+
- `agentloom find <query>`
|
|
56
|
+
- `agentloom update [source]`
|
|
57
|
+
- `agentloom sync`
|
|
58
|
+
- `agentloom delete <source|name>`
|
|
46
59
|
|
|
47
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
###
|
|
96
|
-
Manage canonical MCP servers in `.agents/mcp.json`.
|
|
74
|
+
### Entity verbs
|
|
97
75
|
|
|
98
|
-
`
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
110
|
-
- `--local | --global`: choose canonical scope
|
|
92
|
+
### MCP manual server mode
|
|
111
93
|
|
|
112
|
-
`mcp
|
|
94
|
+
Source-based MCP import lives under `agentloom mcp add ...`.
|
|
95
|
+
Manual server management is under:
|
|
113
96
|
|
|
114
|
-
-
|
|
115
|
-
-
|
|
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
|
|
121
|
-
agentloom
|
|
122
|
-
agentloom
|
|
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
|
-
-
|
|
223
|
-
-
|
|
224
|
-
-
|
|
225
|
-
-
|
|
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
|
-
-
|
|
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
|
-
|
|
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
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 {
|
|
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
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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 "
|
|
44
|
-
await
|
|
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
|
|
54
|
-
|
|
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
|
-
|
|
189
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
190
|
+
console.error(formatCliErrorMessage(message));
|
|
59
191
|
process.exit(1);
|
|
60
192
|
});
|
|
61
193
|
}
|
package/dist/commands/add.d.ts
CHANGED
|
@@ -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>;
|
package/dist/commands/add.js
CHANGED
|
@@ -1,56 +1,117 @@
|
|
|
1
|
-
import {
|
|
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 {
|
|
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
|
-
|
|
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:
|
|
17
|
-
example:
|
|
32
|
+
usage: buildAddUsage(options.target),
|
|
33
|
+
example: buildAddExample(options.target),
|
|
18
34
|
}));
|
|
19
35
|
}
|
|
20
|
-
const nonInteractive =
|
|
21
|
-
const paths = await
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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"
|
|
32
|
-
|
|
33
|
-
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
+
}
|