agentloom 0.1.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 (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +234 -0
  3. package/ThirdPartyNoticeText.txt +3 -0
  4. package/bin/cli.mjs +8 -0
  5. package/dist/cli.d.ts +1 -0
  6. package/dist/cli.js +61 -0
  7. package/dist/commands/add.d.ts +2 -0
  8. package/dist/commands/add.js +62 -0
  9. package/dist/commands/mcp.d.ts +2 -0
  10. package/dist/commands/mcp.js +188 -0
  11. package/dist/commands/skills.d.ts +1 -0
  12. package/dist/commands/skills.js +11 -0
  13. package/dist/commands/sync.d.ts +2 -0
  14. package/dist/commands/sync.js +25 -0
  15. package/dist/commands/update.d.ts +2 -0
  16. package/dist/commands/update.js +71 -0
  17. package/dist/core/agents.d.ts +7 -0
  18. package/dist/core/agents.js +67 -0
  19. package/dist/core/argv.d.ts +5 -0
  20. package/dist/core/argv.js +52 -0
  21. package/dist/core/copy.d.ts +16 -0
  22. package/dist/core/copy.js +167 -0
  23. package/dist/core/fs.d.ts +13 -0
  24. package/dist/core/fs.js +70 -0
  25. package/dist/core/importer.d.ts +21 -0
  26. package/dist/core/importer.js +201 -0
  27. package/dist/core/lockfile.d.ts +4 -0
  28. package/dist/core/lockfile.js +25 -0
  29. package/dist/core/manifest.d.ts +3 -0
  30. package/dist/core/manifest.js +17 -0
  31. package/dist/core/mcp.d.ts +4 -0
  32. package/dist/core/mcp.js +73 -0
  33. package/dist/core/scope.d.ts +9 -0
  34. package/dist/core/scope.js +64 -0
  35. package/dist/core/settings.d.ts +6 -0
  36. package/dist/core/settings.js +54 -0
  37. package/dist/core/sources.d.ts +20 -0
  38. package/dist/core/sources.js +162 -0
  39. package/dist/core/version-notifier.d.ts +8 -0
  40. package/dist/core/version-notifier.js +142 -0
  41. package/dist/core/version.d.ts +1 -0
  42. package/dist/core/version.js +25 -0
  43. package/dist/sync/index.d.ts +15 -0
  44. package/dist/sync/index.js +482 -0
  45. package/dist/types.d.ts +73 -0
  46. package/dist/types.js +8 -0
  47. package/package.json +60 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 agentloom contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,234 @@
1
+ # agentloom
2
+
3
+ `agentloom` is a unified CLI for managing agent definitions and MCP configuration across multiple AI coding tools.
4
+
5
+ It uses `.agents` as the canonical source of truth and syncs provider-native files for:
6
+
7
+ - Cursor
8
+ - Claude
9
+ - Codex
10
+ - OpenCode
11
+ - Gemini
12
+ - Copilot
13
+
14
+ ## Install
15
+
16
+ ```bash
17
+ npm i -g agentloom
18
+ # or
19
+ npx agentloom --help
20
+ ```
21
+
22
+ ## Canonical layout
23
+
24
+ Project scope:
25
+
26
+ ```text
27
+ .agents/
28
+ agents/
29
+ reviewer.md
30
+ debugger.md
31
+ mcp.json
32
+ agents.lock.json
33
+ settings.local.json
34
+ ```
35
+
36
+ Global scope uses `~/.agents` with the same file layout.
37
+
38
+ ## Commands
39
+
40
+ ### `agentloom skills ...`
41
+ Pass-through wrapper to `npx skills ...` from
42
+ [`vercel-labs/skills`](https://github.com/vercel-labs/skills).
43
+
44
+ ### `agentloom add <source>`
45
+ Import canonical agents/MCP from:
46
+
47
+ - local repo path
48
+ - GitHub slug (`owner/repo`)
49
+ - generic git URL
50
+
51
+ Options:
52
+
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
61
+
62
+ Example:
63
+
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
+ ```
94
+
95
+ ### `agentloom mcp add|list|delete`
96
+ Manage canonical MCP servers in `.agents/mcp.json`.
97
+
98
+ `mcp add` options:
99
+
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
106
+
107
+ `mcp list` options:
108
+
109
+ - `--json`: print raw canonical JSON
110
+ - `--local | --global`: choose canonical scope
111
+
112
+ `mcp delete` options:
113
+
114
+ - `--local | --global`: choose canonical scope
115
+ - `--no-sync`: skip post-change sync
116
+
117
+ Examples:
118
+
119
+ ```bash
120
+ agentloom mcp add browser-tools --command npx --arg browser-tools-mcp
121
+ agentloom mcp list
122
+ agentloom mcp delete browser-tools
123
+ ```
124
+
125
+ ### Top-level help
126
+
127
+ ```bash
128
+ agentloom --help
129
+ agentloom add --help
130
+ agentloom update --help
131
+ agentloom sync --help
132
+ agentloom mcp --help
133
+ agentloom mcp add --help
134
+ ```
135
+
136
+ ### Version update notice
137
+
138
+ `agentloom` now performs a best-effort npm version check and shows an update hint when a newer release is available.
139
+
140
+ - check is cached (`~/.agents/.agentloom-version-cache.json`)
141
+ - check runs at most once every 12 hours
142
+ - check is skipped in non-interactive sessions
143
+ - disable via:
144
+
145
+ ```bash
146
+ AGENTLOOM_DISABLE_UPDATE_NOTIFIER=1
147
+ ```
148
+
149
+ ### Scope resolution
150
+
151
+ If neither `--local` nor `--global` is provided:
152
+
153
+ - if `.agents/` exists in current directory, `agentloom` prompts for scope in interactive terminals
154
+ - in non-interactive mode, local scope is selected when `.agents/` exists
155
+ - otherwise global scope (`~/.agents`) is used
156
+
157
+ ## Agent schema
158
+
159
+ Canonical agents are markdown files with YAML frontmatter.
160
+
161
+ ```md
162
+ ---
163
+ name: code-reviewer
164
+ description: Review changes and report issues.
165
+ claude:
166
+ model: sonnet
167
+ codex:
168
+ model: gpt-5.3-codex
169
+ reasoningEffort: low
170
+ webSearch: true
171
+ ---
172
+
173
+ You are a strict reviewer...
174
+ ```
175
+
176
+ ## MCP schema
177
+
178
+ Canonical MCP file format:
179
+
180
+ ```json
181
+ {
182
+ "version": 1,
183
+ "mcpServers": {
184
+ "browser": {
185
+ "base": {
186
+ "command": "npx",
187
+ "args": ["browser-tools-mcp"]
188
+ },
189
+ "providers": {
190
+ "codex": {
191
+ "args": ["browser-tools-mcp", "--codex"]
192
+ },
193
+ "gemini": false
194
+ }
195
+ }
196
+ }
197
+ }
198
+ ```
199
+
200
+ ## Codex multi-agent output
201
+
202
+ For Codex, `agentloom sync` writes role-based multi-agent config:
203
+
204
+ - `.codex/config.toml` (`[features].multi_agent = true`, `[agents.<role>]`)
205
+ - `.codex/agents/<role>.toml`
206
+ - `.codex/agents/<role>.instructions.md`
207
+
208
+ This follows official Codex multi-agent guidance.
209
+
210
+ ## Development
211
+
212
+ ```bash
213
+ pnpm install
214
+ pnpm check
215
+ pnpm build
216
+ ```
217
+
218
+ ## Release and publish
219
+
220
+ The GitHub Actions publish workflow is defined in `.github/workflows/release.yml`.
221
+
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.
226
+
227
+ Required GitHub configuration:
228
+
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).
231
+
232
+ ## License
233
+
234
+ MIT
@@ -0,0 +1,3 @@
1
+ This project depends on third-party open source packages.
2
+
3
+ See package.json and lockfile for full dependency list and licenses.
package/bin/cli.mjs ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { runCli } from '../dist/cli.js';
4
+
5
+ runCli(process.argv.slice(2)).catch((err) => {
6
+ console.error(err instanceof Error ? err.message : String(err));
7
+ process.exit(1);
8
+ });
package/dist/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function runCli(argv: string[]): Promise<void>;
package/dist/cli.js ADDED
@@ -0,0 +1,61 @@
1
+ import { parseArgs } from "./core/argv.js";
2
+ import { runAddCommand } from "./commands/add.js";
3
+ import { runMcpCommand } from "./commands/mcp.js";
4
+ import { runSkillsPassthrough } from "./commands/skills.js";
5
+ import { runSyncCommand } from "./commands/sync.js";
6
+ import { runUpdateCommand } from "./commands/update.js";
7
+ import { formatUnknownCommandError, getRootHelpText } from "./core/copy.js";
8
+ import { maybeNotifyVersionUpdate } from "./core/version-notifier.js";
9
+ import { getCliVersion } from "./core/version.js";
10
+ export async function runCli(argv) {
11
+ const command = argv[0];
12
+ const version = getCliVersion();
13
+ if (!command ||
14
+ command === "help" ||
15
+ command === "--help" ||
16
+ command === "-h") {
17
+ printHelp();
18
+ return;
19
+ }
20
+ if (command === "--version" || command === "-v" || command === "version") {
21
+ console.log(version);
22
+ return;
23
+ }
24
+ if (command === "skills") {
25
+ runSkillsPassthrough(argv.slice(1));
26
+ return;
27
+ }
28
+ const parsed = parseArgs(argv);
29
+ const cwd = process.cwd();
30
+ if (!parsed.help) {
31
+ await maybeNotifyVersionUpdate({
32
+ command,
33
+ currentVersion: version,
34
+ });
35
+ }
36
+ switch (command) {
37
+ case "add":
38
+ await runAddCommand(parsed, cwd);
39
+ return;
40
+ case "update":
41
+ await runUpdateCommand(parsed, cwd);
42
+ return;
43
+ case "sync":
44
+ await runSyncCommand(parsed, cwd);
45
+ return;
46
+ case "mcp":
47
+ await runMcpCommand(parsed, cwd);
48
+ return;
49
+ default:
50
+ throw new Error(formatUnknownCommandError(command));
51
+ }
52
+ }
53
+ function printHelp() {
54
+ console.log(getRootHelpText());
55
+ }
56
+ if (import.meta.url === `file://${process.argv[1]}`) {
57
+ runCli(process.argv.slice(2)).catch((err) => {
58
+ console.error(err instanceof Error ? err.message : String(err));
59
+ process.exit(1);
60
+ });
61
+ }
@@ -0,0 +1,2 @@
1
+ import type { ParsedArgs } from "minimist";
2
+ export declare function runAddCommand(argv: ParsedArgs, cwd: string): Promise<void>;
@@ -0,0 +1,62 @@
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";
5
+ import { formatUsageError, getAddHelpText } from "../core/copy.js";
6
+ import { formatSyncSummary, syncFromCanonical } from "../sync/index.js";
7
+ export async function runAddCommand(argv, cwd) {
8
+ if (argv.help) {
9
+ console.log(getAddHelpText());
10
+ return;
11
+ }
12
+ const source = argv._[1];
13
+ if (typeof source !== "string" || source.trim() === "") {
14
+ throw new Error(formatUsageError({
15
+ issue: "Missing required <source>.",
16
+ usage: "agentloom add <source> [--ref <ref>] [--subdir <path>] [options]",
17
+ example: "agentloom add vercel-labs/skills --subdir skills",
18
+ }));
19
+ }
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
+ });
27
+ try {
28
+ const summary = await importSource({
29
+ 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),
34
+ nonInteractive,
35
+ paths,
36
+ });
37
+ console.log(`Imported source: ${summary.source}`);
38
+ console.log(`Source type: ${summary.sourceType}`);
39
+ console.log(`Resolved commit: ${summary.resolvedCommit}`);
40
+ console.log(`Imported agents: ${summary.importedAgents.length}`);
41
+ 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
+ }
54
+ }
55
+ catch (err) {
56
+ if (err instanceof NonInteractiveConflictError) {
57
+ console.error(err.message);
58
+ process.exit(2);
59
+ }
60
+ throw err;
61
+ }
62
+ }
@@ -0,0 +1,2 @@
1
+ import type { ParsedArgs } from "minimist";
2
+ export declare function runMcpCommand(argv: ParsedArgs, cwd: string): Promise<void>;
@@ -0,0 +1,188 @@
1
+ import { getStringArrayFlag, parseProvidersFlag } from "../core/argv.js";
2
+ import { formatUsageError, getMcpAddHelpText, getMcpDeleteHelpText, getMcpHelpText, getMcpListHelpText, } from "../core/copy.js";
3
+ import { readCanonicalMcp, writeCanonicalMcp } from "../core/mcp.js";
4
+ import { resolveScope } from "../core/scope.js";
5
+ import { formatSyncSummary, syncFromCanonical } from "../sync/index.js";
6
+ export async function runMcpCommand(argv, cwd) {
7
+ const action = argv._[1];
8
+ if (argv.help) {
9
+ if (action === "add") {
10
+ console.log(getMcpAddHelpText());
11
+ return;
12
+ }
13
+ if (action === "list") {
14
+ console.log(getMcpListHelpText());
15
+ return;
16
+ }
17
+ if (action === "delete") {
18
+ console.log(getMcpDeleteHelpText());
19
+ return;
20
+ }
21
+ console.log(getMcpHelpText());
22
+ return;
23
+ }
24
+ if (action !== "add" && action !== "list" && action !== "delete") {
25
+ throw new Error(formatUsageError({
26
+ issue: "Invalid mcp command.",
27
+ usage: "agentloom mcp <add|list|delete> [options]",
28
+ example: "agentloom mcp add browser --command npx --arg browser-tools-mcp",
29
+ }));
30
+ }
31
+ const nonInteractive = !(process.stdin.isTTY && process.stdout.isTTY);
32
+ const paths = await resolveScope({
33
+ cwd,
34
+ global: Boolean(argv.global),
35
+ local: Boolean(argv.local),
36
+ interactive: !nonInteractive,
37
+ });
38
+ if (action === "list") {
39
+ runMcpList(paths, Boolean(argv.json));
40
+ return;
41
+ }
42
+ if (action === "add") {
43
+ const name = argv._[2];
44
+ if (typeof name !== "string" || !name.trim()) {
45
+ throw new Error(formatUsageError({
46
+ issue: "Missing required MCP server name.",
47
+ usage: "agentloom mcp add <name> (--url <url> | --command <cmd>) [options]",
48
+ example: "agentloom mcp add browser --command npx --arg browser-tools-mcp",
49
+ }));
50
+ }
51
+ runMcpAdd(paths, argv, name.trim());
52
+ if (!argv["no-sync"]) {
53
+ const summary = await syncFromCanonical({
54
+ paths,
55
+ providers: parseProvidersFlag(argv.providers),
56
+ yes: Boolean(argv.yes),
57
+ nonInteractive,
58
+ });
59
+ console.log("");
60
+ console.log(formatSyncSummary(summary, paths.agentsRoot));
61
+ }
62
+ return;
63
+ }
64
+ if (action === "delete") {
65
+ const name = argv._[2];
66
+ if (typeof name !== "string" || !name.trim()) {
67
+ throw new Error(formatUsageError({
68
+ issue: "Missing required MCP server name.",
69
+ usage: "agentloom mcp delete <name> [options]",
70
+ example: "agentloom mcp delete browser",
71
+ }));
72
+ }
73
+ const mcp = readCanonicalMcp(paths);
74
+ if (!(name in mcp.mcpServers)) {
75
+ throw new Error(formatUsageError({
76
+ issue: `MCP server "${name}" was not found in canonical config.`,
77
+ usage: "agentloom mcp list [--json] [--local|--global]",
78
+ example: "agentloom mcp list --json",
79
+ }));
80
+ }
81
+ delete mcp.mcpServers[name];
82
+ writeCanonicalMcp(paths, mcp);
83
+ console.log(`Deleted MCP server: ${name}`);
84
+ if (!argv["no-sync"]) {
85
+ const summary = await syncFromCanonical({
86
+ paths,
87
+ providers: parseProvidersFlag(argv.providers),
88
+ yes: Boolean(argv.yes),
89
+ nonInteractive,
90
+ });
91
+ console.log("");
92
+ console.log(formatSyncSummary(summary, paths.agentsRoot));
93
+ }
94
+ }
95
+ }
96
+ function runMcpList(paths, asJson) {
97
+ const mcp = readCanonicalMcp(paths);
98
+ const names = Object.keys(mcp.mcpServers).sort();
99
+ if (asJson) {
100
+ console.log(JSON.stringify(mcp, null, 2));
101
+ return;
102
+ }
103
+ if (names.length === 0) {
104
+ console.log("No MCP servers configured.");
105
+ return;
106
+ }
107
+ for (const name of names) {
108
+ const server = mcp.mcpServers[name];
109
+ const transport = server.base && typeof server.base === "object"
110
+ ? server.base.url
111
+ ? "http"
112
+ : server.base.command
113
+ ? "stdio"
114
+ : "custom"
115
+ : server.url
116
+ ? "http"
117
+ : server.command
118
+ ? "stdio"
119
+ : "custom";
120
+ console.log(`${name} (${transport})`);
121
+ }
122
+ }
123
+ function runMcpAdd(paths, argv, name) {
124
+ const mcp = readCanonicalMcp(paths);
125
+ const baseConfig = {};
126
+ if (typeof argv.url === "string" && argv.url.trim()) {
127
+ baseConfig.url = argv.url.trim();
128
+ }
129
+ if (typeof argv.command === "string" && argv.command.trim()) {
130
+ baseConfig.command = argv.command.trim();
131
+ }
132
+ if (!baseConfig.url && !baseConfig.command) {
133
+ throw new Error(formatUsageError({
134
+ issue: "Missing MCP transport. Use --url or --command.",
135
+ usage: "agentloom mcp add <name> (--url <url> | --command <cmd>) [options]",
136
+ example: "agentloom mcp add browser --command npx --arg browser-tools-mcp",
137
+ }));
138
+ }
139
+ const args = getStringArrayFlag(argv.arg);
140
+ if (args.length > 0) {
141
+ baseConfig.args = args;
142
+ }
143
+ const envPairs = getStringArrayFlag(argv.env);
144
+ if (envPairs.length > 0) {
145
+ const env = {};
146
+ for (const pair of envPairs) {
147
+ const separator = pair.indexOf("=");
148
+ if (separator <= 0) {
149
+ throw new Error(formatUsageError({
150
+ issue: `Invalid --env value "${pair}".`,
151
+ usage: "agentloom mcp add <name> ... --env KEY=VALUE [--env KEY2=VALUE2]",
152
+ example: "agentloom mcp add browser --command npx --env API_KEY=secret",
153
+ }));
154
+ }
155
+ const key = pair.slice(0, separator).trim();
156
+ const value = pair.slice(separator + 1);
157
+ env[key] = value;
158
+ }
159
+ baseConfig.env = env;
160
+ }
161
+ const providers = parseProvidersFlag(argv.providers);
162
+ if (!providers || providers.length === 0) {
163
+ mcp.mcpServers[name] = {
164
+ base: baseConfig,
165
+ };
166
+ }
167
+ else {
168
+ const providerMap = {};
169
+ const allProviders = [
170
+ "cursor",
171
+ "claude",
172
+ "codex",
173
+ "opencode",
174
+ "gemini",
175
+ "copilot",
176
+ ];
177
+ for (const provider of allProviders) {
178
+ providerMap[provider] = providers.includes(provider)
179
+ ? { ...baseConfig }
180
+ : false;
181
+ }
182
+ mcp.mcpServers[name] = {
183
+ providers: providerMap,
184
+ };
185
+ }
186
+ writeCanonicalMcp(paths, mcp);
187
+ console.log(`Added MCP server: ${name}`);
188
+ }
@@ -0,0 +1 @@
1
+ export declare function runSkillsPassthrough(args: string[]): never;
@@ -0,0 +1,11 @@
1
+ import { spawnSync } from "node:child_process";
2
+ export function runSkillsPassthrough(args) {
3
+ const child = spawnSync("npx", ["skills", ...args], {
4
+ stdio: "inherit",
5
+ shell: false,
6
+ });
7
+ if (child.error) {
8
+ throw child.error;
9
+ }
10
+ process.exit(child.status ?? 1);
11
+ }
@@ -0,0 +1,2 @@
1
+ import type { ParsedArgs } from "minimist";
2
+ export declare function runSyncCommand(argv: ParsedArgs, cwd: string): Promise<void>;
@@ -0,0 +1,25 @@
1
+ import { parseProvidersFlag } from "../core/argv.js";
2
+ import { getSyncHelpText } from "../core/copy.js";
3
+ import { resolveScope } from "../core/scope.js";
4
+ import { formatSyncSummary, syncFromCanonical } from "../sync/index.js";
5
+ export async function runSyncCommand(argv, cwd) {
6
+ if (argv.help) {
7
+ console.log(getSyncHelpText());
8
+ return;
9
+ }
10
+ const nonInteractive = !(process.stdin.isTTY && process.stdout.isTTY);
11
+ const paths = await resolveScope({
12
+ cwd,
13
+ global: Boolean(argv.global),
14
+ local: Boolean(argv.local),
15
+ interactive: !nonInteractive,
16
+ });
17
+ const summary = await syncFromCanonical({
18
+ paths,
19
+ providers: parseProvidersFlag(argv.providers),
20
+ yes: Boolean(argv.yes),
21
+ nonInteractive,
22
+ dryRun: Boolean(argv["dry-run"]),
23
+ });
24
+ console.log(formatSyncSummary(summary, paths.agentsRoot));
25
+ }
@@ -0,0 +1,2 @@
1
+ import type { ParsedArgs } from "minimist";
2
+ export declare function runUpdateCommand(argv: ParsedArgs, cwd: string): Promise<void>;