@yama662607/agent-config-sync 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.
- package/LICENSE +21 -0
- package/README.md +174 -0
- package/dist/catalog.d.ts +65 -0
- package/dist/catalog.js +328 -0
- package/dist/catalog.js.map +1 -0
- package/dist/cli-catalog.d.ts +70 -0
- package/dist/cli-catalog.js +433 -0
- package/dist/cli-catalog.js.map +1 -0
- package/dist/cli-diagnostics.d.ts +14 -0
- package/dist/cli-diagnostics.js +177 -0
- package/dist/cli-diagnostics.js.map +1 -0
- package/dist/cli-init.d.ts +8 -0
- package/dist/cli-init.js +77 -0
- package/dist/cli-init.js.map +1 -0
- package/dist/cli-mcp.d.ts +38 -0
- package/dist/cli-mcp.js +179 -0
- package/dist/cli-mcp.js.map +1 -0
- package/dist/cli-skill.d.ts +51 -0
- package/dist/cli-skill.js +239 -0
- package/dist/cli-skill.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +868 -0
- package/dist/cli.js.map +1 -0
- package/dist/config-adapters.d.ts +32 -0
- package/dist/config-adapters.js +410 -0
- package/dist/config-adapters.js.map +1 -0
- package/dist/fs.d.ts +2 -0
- package/dist/fs.js +20 -0
- package/dist/fs.js.map +1 -0
- package/dist/project-discovery.d.ts +20 -0
- package/dist/project-discovery.js +79 -0
- package/dist/project-discovery.js.map +1 -0
- package/dist/prompts/confirm-prompt.d.ts +9 -0
- package/dist/prompts/confirm-prompt.js +54 -0
- package/dist/prompts/confirm-prompt.js.map +1 -0
- package/dist/prompts/custom-multiselect.d.ts +9 -0
- package/dist/prompts/custom-multiselect.js +28 -0
- package/dist/prompts/custom-multiselect.js.map +1 -0
- package/dist/prompts/index.d.ts +5 -0
- package/dist/prompts/index.js +6 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/mcp-prompt.d.ts +5 -0
- package/dist/prompts/mcp-prompt.js +57 -0
- package/dist/prompts/mcp-prompt.js.map +1 -0
- package/dist/prompts/skill-prompt.d.ts +5 -0
- package/dist/prompts/skill-prompt.js +57 -0
- package/dist/prompts/skill-prompt.js.map +1 -0
- package/dist/prompts/target-prompt.d.ts +7 -0
- package/dist/prompts/target-prompt.js +47 -0
- package/dist/prompts/target-prompt.js.map +1 -0
- package/dist/registry.d.ts +49 -0
- package/dist/registry.js +121 -0
- package/dist/registry.js.map +1 -0
- package/dist/skill-adapters.d.ts +53 -0
- package/dist/skill-adapters.js +183 -0
- package/dist/skill-adapters.js.map +1 -0
- package/dist/types.d.ts +151 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/package.json +68 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,868 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// CLI command handlers
|
|
3
|
+
import { catalogMcpList, catalogMcpShow, catalogMcpAdd, catalogMcpRemove, } from './cli-catalog.js';
|
|
4
|
+
import { mcpStatus, mcpAdd, mcpRemove, mcpEnable, mcpDisable, } from './cli-mcp.js';
|
|
5
|
+
import { skillStatus, skillAdd, skillRemove, skillEnable, skillDisable, } from './cli-skill.js';
|
|
6
|
+
import { validate, doctor } from './cli-diagnostics.js';
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Constants
|
|
9
|
+
// ============================================================================
|
|
10
|
+
const HELP = `acsync - Agent configuration sync tool
|
|
11
|
+
|
|
12
|
+
USAGE:
|
|
13
|
+
acsync [COMMAND]
|
|
14
|
+
|
|
15
|
+
COMMANDS:
|
|
16
|
+
init Interactive setup for the current project
|
|
17
|
+
catalog Manage reusable MCP and skill definitions in your personal catalog
|
|
18
|
+
mcp Manage MCP servers for the current project
|
|
19
|
+
skill Manage skills for the current project
|
|
20
|
+
validate Validate current project configuration
|
|
21
|
+
doctor Run diagnostics and health checks
|
|
22
|
+
|
|
23
|
+
OPTIONS:
|
|
24
|
+
-h, --help Show this help message
|
|
25
|
+
-V, --version Show version information
|
|
26
|
+
|
|
27
|
+
TARGETS:
|
|
28
|
+
claude Claude Code (.mcp.json, .claude/skills/)
|
|
29
|
+
codex Codex (.codex/config.toml, .codex/skills/)
|
|
30
|
+
gemini Gemini CLI (.gemini/settings.json, .gemini/antigravity/skills/)
|
|
31
|
+
|
|
32
|
+
ABOUT CATALOG:
|
|
33
|
+
Your personal catalog (~/.acsync/) stores reusable MCP and skill definitions.
|
|
34
|
+
Use "acsync catalog" to manage the catalog, then add items to projects.
|
|
35
|
+
|
|
36
|
+
EXAMPLES:
|
|
37
|
+
acsync init Interactive setup for current project
|
|
38
|
+
acsync mcp Show MCP status for current project
|
|
39
|
+
acsync skill Show skill status for current project
|
|
40
|
+
acsync catalog mcp list List all MCPs in your personal catalog
|
|
41
|
+
acsync mcp add github --targets claude Add GitHub MCP to Claude Code
|
|
42
|
+
acsync skill add frontend-design --targets claude Add skill from catalog
|
|
43
|
+
acsync skill install <github-url> --targets claude,codex Install from GitHub
|
|
44
|
+
|
|
45
|
+
For more information, run: acsync <command> --help
|
|
46
|
+
`;
|
|
47
|
+
const CATALOG_HELP = `acsync catalog - Manage reusable MCP and skill definitions
|
|
48
|
+
|
|
49
|
+
USAGE:
|
|
50
|
+
acsync catalog <kind> <subcommand>
|
|
51
|
+
|
|
52
|
+
ABOUT CATALOG:
|
|
53
|
+
Your personal catalog (~/.acsync/catalog.json) stores reusable MCP servers
|
|
54
|
+
and skills. Once added to the catalog, you can easily add them to any project.
|
|
55
|
+
|
|
56
|
+
KINDS:
|
|
57
|
+
mcp Manage MCP definitions
|
|
58
|
+
skill Manage skill definitions
|
|
59
|
+
|
|
60
|
+
MCP SUBCOMMANDS:
|
|
61
|
+
list List all MCP entries in catalog
|
|
62
|
+
show <id> Show details of a specific MCP entry
|
|
63
|
+
add <pkg> Add a new MCP entry to catalog
|
|
64
|
+
remove <id> Remove an MCP entry from catalog
|
|
65
|
+
|
|
66
|
+
SKILL SUBCOMMANDS:
|
|
67
|
+
list List all skill entries in catalog
|
|
68
|
+
show <id> Show details of a specific skill entry
|
|
69
|
+
add <name> Add a new skill entry to catalog from file
|
|
70
|
+
import <path> Import a skill from a local directory
|
|
71
|
+
install <id> Install a skill from skills.directory registry
|
|
72
|
+
search <query> Search the skills.directory registry
|
|
73
|
+
remove <id> Remove a skill entry from catalog
|
|
74
|
+
|
|
75
|
+
OPTIONS (mcp add):
|
|
76
|
+
--url <url> HTTP/SSE URL for the MCP server
|
|
77
|
+
--command <cmd> Command to execute (stdio transport)
|
|
78
|
+
--args <json> Arguments for command (JSON array)
|
|
79
|
+
--cwd <path> Working directory for command
|
|
80
|
+
--display-name <name> Display name for the entry
|
|
81
|
+
--description <desc> Description for the entry
|
|
82
|
+
--env <json> Environment variables (JSON object)
|
|
83
|
+
|
|
84
|
+
OPTIONS (skill install):
|
|
85
|
+
--force Force reinstall if already exists
|
|
86
|
+
|
|
87
|
+
OPTIONS (skill import):
|
|
88
|
+
--name <name> Override skill name
|
|
89
|
+
--display-name <name> Display name for the entry
|
|
90
|
+
--description <desc> Description for the entry
|
|
91
|
+
|
|
92
|
+
EXAMPLES:
|
|
93
|
+
# Catalog operations
|
|
94
|
+
acsync catalog mcp list
|
|
95
|
+
acsync catalog mcp show @modelcontextprotocol/server-github
|
|
96
|
+
acsync catalog mcp add @modelcontextprotocol/server-filesystem
|
|
97
|
+
|
|
98
|
+
# Skill catalog operations
|
|
99
|
+
acsync catalog skill list
|
|
100
|
+
acsync catalog skill install frontend-design
|
|
101
|
+
acsync catalog skill search typescript
|
|
102
|
+
acsync catalog skill import ~/.claude/skills/frontend-design
|
|
103
|
+
acsync catalog skill add my-skill --file ./my-skill/SKILL.md
|
|
104
|
+
|
|
105
|
+
# After adding to catalog, use with project commands:
|
|
106
|
+
acsync mcp add @modelcontextprotocol/server-github --targets claude
|
|
107
|
+
acsync skill add frontend-design --targets claude,codex
|
|
108
|
+
`;
|
|
109
|
+
const MCP_HELP = `acsync mcp - Manage MCP servers for the current project
|
|
110
|
+
|
|
111
|
+
USAGE:
|
|
112
|
+
acsync mcp [subcommand] [options]
|
|
113
|
+
|
|
114
|
+
SUBCOMMANDS:
|
|
115
|
+
status Show MCP status (default)
|
|
116
|
+
add <package> Add an MCP to the project (from catalog or npm)
|
|
117
|
+
remove <server> Remove an MCP from the project
|
|
118
|
+
enable <server> Enable a disabled MCP
|
|
119
|
+
disable <server> Disable an MCP
|
|
120
|
+
|
|
121
|
+
OPTIONS:
|
|
122
|
+
--targets <list> Comma-separated target list (default: claude,codex,gemini)
|
|
123
|
+
--[no-]register Auto-register to catalog (default: yes)
|
|
124
|
+
|
|
125
|
+
TARGETS:
|
|
126
|
+
claude Claude Code (.mcp.json)
|
|
127
|
+
codex Codex (.codex/config.toml)
|
|
128
|
+
gemini Gemini CLI (.gemini/settings.json)
|
|
129
|
+
|
|
130
|
+
EXAMPLES:
|
|
131
|
+
# Show status
|
|
132
|
+
acsync mcp
|
|
133
|
+
acsync mcp status
|
|
134
|
+
|
|
135
|
+
# Add from npm package (auto-registers to catalog)
|
|
136
|
+
acsync mcp add @modelcontextprotocol/server-github --targets claude
|
|
137
|
+
acsync mcp add @modelcontextprotocol/server-filesystem --targets claude,codex
|
|
138
|
+
|
|
139
|
+
# Add with custom configuration
|
|
140
|
+
acsync mcp add custom-mcp --url "https://mcp.example.com" --targets claude
|
|
141
|
+
acsync mcp add local-mcp --command "node" --args '["server.js"]' --targets claude
|
|
142
|
+
|
|
143
|
+
# Enable/disable/remove
|
|
144
|
+
acsync mcp disable github --targets claude
|
|
145
|
+
acsync mcp enable github --targets codex
|
|
146
|
+
acsync mcp remove github
|
|
147
|
+
|
|
148
|
+
# Work with catalog
|
|
149
|
+
acsync catalog mcp list # List catalog entries
|
|
150
|
+
acsync catalog mcp add <package> # Add to catalog first
|
|
151
|
+
`;
|
|
152
|
+
const SKILL_HELP = `acsync skill - Manage skills for the current project
|
|
153
|
+
|
|
154
|
+
USAGE:
|
|
155
|
+
acsync skill [subcommand] [options]
|
|
156
|
+
|
|
157
|
+
SUBCOMMANDS:
|
|
158
|
+
status Show skill status (default)
|
|
159
|
+
add <name> Add a skill to the project from your catalog
|
|
160
|
+
install <github-url> Install a skill directly from GitHub URL
|
|
161
|
+
remove <name> Remove a skill from the project
|
|
162
|
+
enable <name> Enable a skill (skills are always enabled if present)
|
|
163
|
+
disable <name> Disable a skill (equivalent to remove)
|
|
164
|
+
|
|
165
|
+
OPTIONS:
|
|
166
|
+
--targets <list> Comma-separated target list (default: claude,codex,gemini)
|
|
167
|
+
--[no-]register Auto-register to catalog (default: yes)
|
|
168
|
+
|
|
169
|
+
INSTALL OPTIONS (for GitHub install):
|
|
170
|
+
--name <name> Override skill name from GitHub
|
|
171
|
+
--no-catalog Don't add to catalog, only install to project
|
|
172
|
+
|
|
173
|
+
TARGETS:
|
|
174
|
+
claude Claude Code (.claude/skills/)
|
|
175
|
+
codex Codex (.codex/skills/)
|
|
176
|
+
gemini Gemini CLI (.gemini/antigravity/skills/)
|
|
177
|
+
|
|
178
|
+
COMMAND DIFFERENCES:
|
|
179
|
+
add <name> Add from your catalog (must exist in catalog first)
|
|
180
|
+
install <github-url> Install directly from GitHub (adds to catalog + project)
|
|
181
|
+
|
|
182
|
+
EXAMPLES:
|
|
183
|
+
# Show status
|
|
184
|
+
acsync skill
|
|
185
|
+
acsync skill status
|
|
186
|
+
|
|
187
|
+
# Add from catalog (requires catalog entry)
|
|
188
|
+
acsync skill add frontend-design --targets claude
|
|
189
|
+
acsync skill add skill-creator --targets claude,codex
|
|
190
|
+
|
|
191
|
+
# Install directly from GitHub (adds to catalog + project)
|
|
192
|
+
acsync skill install https://github.com/anthropics/skills/tree/main/skill-creator
|
|
193
|
+
acsync skill install https://github.com/user/repo --name my-skill --targets claude
|
|
194
|
+
|
|
195
|
+
# Install without adding to catalog
|
|
196
|
+
acsync skill install <github-url> --no-catalog --targets claude
|
|
197
|
+
|
|
198
|
+
# Remove from project
|
|
199
|
+
acsync skill remove frontend-design
|
|
200
|
+
|
|
201
|
+
# Work with catalog
|
|
202
|
+
acsync catalog skill list # List catalog entries
|
|
203
|
+
acsync catalog skill import <path> # Import local skill to catalog
|
|
204
|
+
acsync catalog skill search <query> # Search skills.directory registry
|
|
205
|
+
`;
|
|
206
|
+
const VALIDATE_HELP = `acsync validate - Validate current project configuration
|
|
207
|
+
|
|
208
|
+
USAGE:
|
|
209
|
+
acsync validate [options]
|
|
210
|
+
|
|
211
|
+
OPTIONS:
|
|
212
|
+
--strict Fail on warnings as well as errors
|
|
213
|
+
|
|
214
|
+
DESCRIPTION:
|
|
215
|
+
Validates MCP and skill configurations across all target agents.
|
|
216
|
+
Checks for missing files, invalid configurations, and common issues.
|
|
217
|
+
|
|
218
|
+
EXAMPLES:
|
|
219
|
+
acsync validate # Show warnings but don't fail
|
|
220
|
+
acsync validate --strict # Fail on any warnings or errors
|
|
221
|
+
`;
|
|
222
|
+
const DOCTOR_HELP = `acsync doctor - Run diagnostics and health checks
|
|
223
|
+
|
|
224
|
+
USAGE:
|
|
225
|
+
acsync doctor [options]
|
|
226
|
+
|
|
227
|
+
OPTIONS:
|
|
228
|
+
--fix Attempt to auto-fix issues
|
|
229
|
+
|
|
230
|
+
DESCRIPTION:
|
|
231
|
+
Runs comprehensive diagnostics on your acsync setup and project configurations.
|
|
232
|
+
Checks catalog integrity, config file validity, and common issues.
|
|
233
|
+
|
|
234
|
+
EXAMPLES:
|
|
235
|
+
acsync doctor # Diagnose issues without fixing
|
|
236
|
+
acsync doctor --fix # Attempt to auto-fix found issues
|
|
237
|
+
`;
|
|
238
|
+
// ============================================================================
|
|
239
|
+
// Main
|
|
240
|
+
// ============================================================================
|
|
241
|
+
async function main() {
|
|
242
|
+
const argv = process.argv.slice(2);
|
|
243
|
+
// Top-level help
|
|
244
|
+
if (argv.length === 0 || argv[0] === '--help' || argv[0] === '-h') {
|
|
245
|
+
process.stdout.write(HELP);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
// Version
|
|
249
|
+
if (argv[0] === '--version' || argv[0] === '-V') {
|
|
250
|
+
const { version } = await getPackageVersion();
|
|
251
|
+
process.stdout.write(`acsync v${version}\n`);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
const command = argv[0];
|
|
255
|
+
switch (command) {
|
|
256
|
+
case 'init':
|
|
257
|
+
await handleInit(argv.slice(1));
|
|
258
|
+
break;
|
|
259
|
+
case 'catalog':
|
|
260
|
+
await handleCatalog(argv.slice(1));
|
|
261
|
+
break;
|
|
262
|
+
case 'mcp':
|
|
263
|
+
await handleMcp(argv.slice(1));
|
|
264
|
+
break;
|
|
265
|
+
case 'skill':
|
|
266
|
+
await handleSkill(argv.slice(1));
|
|
267
|
+
break;
|
|
268
|
+
case 'validate':
|
|
269
|
+
await handleValidate(argv.slice(1));
|
|
270
|
+
break;
|
|
271
|
+
case 'doctor':
|
|
272
|
+
await handleDoctor(argv.slice(1));
|
|
273
|
+
break;
|
|
274
|
+
default:
|
|
275
|
+
process.stderr.write(`Unknown command: ${command}\n\n`);
|
|
276
|
+
process.stderr.write(HELP);
|
|
277
|
+
process.exitCode = 1;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
// ============================================================================
|
|
281
|
+
// Command Handlers
|
|
282
|
+
// ============================================================================
|
|
283
|
+
async function handleCatalog(argv) {
|
|
284
|
+
if (argv.length === 0 || argv[0] === '--help' || argv[0] === '-h') {
|
|
285
|
+
process.stdout.write(CATALOG_HELP);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
const resource = argv[0];
|
|
289
|
+
const subcommand = argv[1];
|
|
290
|
+
const args = argv.slice(2);
|
|
291
|
+
if (resource !== 'mcp' && resource !== 'skill') {
|
|
292
|
+
process.stderr.write(`Unknown catalog resource: ${resource}\n`);
|
|
293
|
+
process.stderr.write('Use "acsync catalog mcp" or "acsync catalog skill" for management.\n');
|
|
294
|
+
process.exitCode = 1;
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
if (subcommand === '--help' || subcommand === '-h') {
|
|
298
|
+
process.stdout.write(CATALOG_HELP);
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
switch (resource) {
|
|
302
|
+
case 'mcp':
|
|
303
|
+
await handleCatalogMcp(subcommand, args);
|
|
304
|
+
break;
|
|
305
|
+
case 'skill':
|
|
306
|
+
await handleCatalogSkill(subcommand, args);
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
async function handleCatalogMcp(subcommand, args) {
|
|
311
|
+
if (!subcommand) {
|
|
312
|
+
process.stderr.write('Usage: acsync catalog mcp <subcommand>\n');
|
|
313
|
+
process.exitCode = 1;
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
switch (subcommand) {
|
|
317
|
+
case 'list':
|
|
318
|
+
await catalogMcpList();
|
|
319
|
+
break;
|
|
320
|
+
case 'show':
|
|
321
|
+
if (args.length === 0) {
|
|
322
|
+
process.stderr.write('Usage: acsync catalog mcp show <id>\n');
|
|
323
|
+
process.exitCode = 1;
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
await catalogMcpShow(args[0]);
|
|
327
|
+
break;
|
|
328
|
+
case 'add':
|
|
329
|
+
await handleCatalogMcpAdd(args);
|
|
330
|
+
break;
|
|
331
|
+
case 'remove':
|
|
332
|
+
if (args.length === 0) {
|
|
333
|
+
process.stderr.write('Usage: acsync catalog mcp remove <id>\n');
|
|
334
|
+
process.exitCode = 1;
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
await catalogMcpRemove(args[0]);
|
|
338
|
+
break;
|
|
339
|
+
default:
|
|
340
|
+
process.stderr.write(`Unknown subcommand: ${subcommand}\n`);
|
|
341
|
+
process.stderr.write(CATALOG_HELP);
|
|
342
|
+
process.exitCode = 1;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
async function handleCatalogMcpAdd(argv) {
|
|
346
|
+
if (argv.length === 0) {
|
|
347
|
+
process.stderr.write('Usage: acsync catalog mcp add <package-id> [options]\n');
|
|
348
|
+
process.exitCode = 1;
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
const packageId = argv[0];
|
|
352
|
+
const options = parseCatalogMcpAddOptions(argv.slice(1));
|
|
353
|
+
await catalogMcpAdd({
|
|
354
|
+
packageId,
|
|
355
|
+
displayName: options.displayName,
|
|
356
|
+
description: options.description,
|
|
357
|
+
command: options.command,
|
|
358
|
+
args: options.args,
|
|
359
|
+
url: options.url,
|
|
360
|
+
cwd: options.cwd,
|
|
361
|
+
env: options.env,
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
async function handleCatalogSkill(subcommand, args) {
|
|
365
|
+
if (!subcommand) {
|
|
366
|
+
process.stderr.write('Usage: acsync catalog skill <subcommand>\n');
|
|
367
|
+
process.exitCode = 1;
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
switch (subcommand) {
|
|
371
|
+
case 'list':
|
|
372
|
+
await (await import('./cli-catalog.js')).catalogSkillList();
|
|
373
|
+
break;
|
|
374
|
+
case 'show':
|
|
375
|
+
if (args.length === 0) {
|
|
376
|
+
process.stderr.write('Usage: acsync catalog skill show <id>\n');
|
|
377
|
+
process.exitCode = 1;
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
await (await import('./cli-catalog.js')).catalogSkillShow(args[0]);
|
|
381
|
+
break;
|
|
382
|
+
case 'add':
|
|
383
|
+
await handleCatalogSkillAdd(args);
|
|
384
|
+
break;
|
|
385
|
+
case 'install':
|
|
386
|
+
await handleCatalogSkillInstall(args);
|
|
387
|
+
break;
|
|
388
|
+
case 'search':
|
|
389
|
+
if (args.length === 0) {
|
|
390
|
+
process.stderr.write('Usage: acsync catalog skill search <query>\n');
|
|
391
|
+
process.exitCode = 1;
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
await (await import('./cli-catalog.js')).catalogSkillSearch(args[0]);
|
|
395
|
+
break;
|
|
396
|
+
case 'import':
|
|
397
|
+
await handleCatalogSkillImport(args);
|
|
398
|
+
break;
|
|
399
|
+
case 'remove':
|
|
400
|
+
if (args.length === 0) {
|
|
401
|
+
process.stderr.write('Usage: acsync catalog skill remove <id>\n');
|
|
402
|
+
process.exitCode = 1;
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
await (await import('./cli-catalog.js')).catalogSkillRemove(args[0]);
|
|
406
|
+
break;
|
|
407
|
+
default:
|
|
408
|
+
process.stderr.write(`Unknown subcommand: ${subcommand}\n`);
|
|
409
|
+
process.stderr.write(CATALOG_HELP);
|
|
410
|
+
process.exitCode = 1;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
async function handleCatalogSkillAdd(argv) {
|
|
414
|
+
if (argv.length === 0) {
|
|
415
|
+
process.stderr.write('Usage: acsync catalog skill add <skill-id> [options]\n');
|
|
416
|
+
process.exitCode = 1;
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
const skillId = argv[0];
|
|
420
|
+
const options = parseCatalogSkillAddOptions(argv.slice(1));
|
|
421
|
+
await (await import('./cli-catalog.js')).catalogSkillAdd({
|
|
422
|
+
skillId,
|
|
423
|
+
file: options.file,
|
|
424
|
+
displayName: options.displayName,
|
|
425
|
+
description: options.description,
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
async function handleCatalogSkillInstall(argv) {
|
|
429
|
+
if (argv.length === 0) {
|
|
430
|
+
process.stderr.write('Usage: acsync catalog skill install <skill-id> [--force]\n');
|
|
431
|
+
process.exitCode = 1;
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
const skillId = argv[0];
|
|
435
|
+
const force = parseFlag(argv, 'force');
|
|
436
|
+
await (await import('./cli-catalog.js')).catalogSkillInstall({ skillId, force });
|
|
437
|
+
}
|
|
438
|
+
async function handleCatalogSkillImport(argv) {
|
|
439
|
+
if (argv.length === 0) {
|
|
440
|
+
process.stderr.write('Usage: acsync catalog skill import <path> [options]\n');
|
|
441
|
+
process.exitCode = 1;
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
const skillPath = argv[0];
|
|
445
|
+
const options = parseCatalogSkillImportOptions(argv.slice(1));
|
|
446
|
+
await (await import('./cli-catalog.js')).catalogSkillImport({
|
|
447
|
+
path: skillPath,
|
|
448
|
+
skillId: options.skillId,
|
|
449
|
+
displayName: options.displayName,
|
|
450
|
+
description: options.description,
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
async function handleMcp(argv) {
|
|
454
|
+
if (argv.length === 0 || argv[0] === '--help' || argv[0] === '-h') {
|
|
455
|
+
process.stdout.write(MCP_HELP);
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
// Check if verbose flag is present
|
|
459
|
+
const verbose = parseFlag(argv, 'verbose', 'v');
|
|
460
|
+
// Remove verbose from argv for further parsing
|
|
461
|
+
const filteredArgs = argv.filter((arg) => arg !== '--verbose' && arg !== '-v');
|
|
462
|
+
const subcommand = filteredArgs[0];
|
|
463
|
+
// Default to status if no subcommand or status
|
|
464
|
+
if (!subcommand || subcommand === 'status') {
|
|
465
|
+
await mcpStatus(verbose);
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
const options = parseMcpOptions(filteredArgs.slice(1), subcommand);
|
|
469
|
+
switch (subcommand) {
|
|
470
|
+
case 'add':
|
|
471
|
+
if (options.packageId === undefined) {
|
|
472
|
+
process.stderr.write('Usage: acsync mcp add <package> [options]\n');
|
|
473
|
+
process.exitCode = 1;
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
await mcpAdd({
|
|
477
|
+
packageId: options.packageId,
|
|
478
|
+
targets: options.targets,
|
|
479
|
+
noRegister: options.noRegister,
|
|
480
|
+
});
|
|
481
|
+
break;
|
|
482
|
+
case 'remove':
|
|
483
|
+
if (options.packageId === undefined) {
|
|
484
|
+
process.stderr.write('Usage: acsync mcp remove <server> [options]\n');
|
|
485
|
+
process.exitCode = 1;
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
await mcpRemove({
|
|
489
|
+
serverName: options.packageId,
|
|
490
|
+
targets: options.targets,
|
|
491
|
+
});
|
|
492
|
+
break;
|
|
493
|
+
case 'enable':
|
|
494
|
+
if (options.packageId === undefined) {
|
|
495
|
+
process.stderr.write('Usage: acsync mcp enable <server> [options]\n');
|
|
496
|
+
process.exitCode = 1;
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
await mcpEnable({
|
|
500
|
+
serverName: options.packageId,
|
|
501
|
+
targets: options.targets,
|
|
502
|
+
});
|
|
503
|
+
break;
|
|
504
|
+
case 'disable':
|
|
505
|
+
if (options.packageId === undefined) {
|
|
506
|
+
process.stderr.write('Usage: acsync mcp disable <server> [options]\n');
|
|
507
|
+
process.exitCode = 1;
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
await mcpDisable({
|
|
511
|
+
serverName: options.packageId,
|
|
512
|
+
targets: options.targets,
|
|
513
|
+
});
|
|
514
|
+
break;
|
|
515
|
+
default:
|
|
516
|
+
process.stderr.write(`Unknown subcommand: ${subcommand}\n`);
|
|
517
|
+
process.stderr.write(MCP_HELP);
|
|
518
|
+
process.exitCode = 1;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
async function handleSkill(argv) {
|
|
522
|
+
if (argv.length === 0 || argv[0] === '--help' || argv[0] === '-h') {
|
|
523
|
+
process.stdout.write(SKILL_HELP);
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
// Check if verbose flag is present
|
|
527
|
+
const verbose = parseFlag(argv, 'verbose', 'v');
|
|
528
|
+
// Remove verbose from argv for further parsing
|
|
529
|
+
const filteredArgs = argv.filter((arg) => arg !== '--verbose' && arg !== '-v');
|
|
530
|
+
const subcommand = filteredArgs[0];
|
|
531
|
+
// Default to status if no subcommand or status
|
|
532
|
+
if (!subcommand || subcommand === 'status') {
|
|
533
|
+
await skillStatus(verbose);
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
const options = parseSkillOptions(filteredArgs.slice(1), subcommand);
|
|
537
|
+
switch (subcommand) {
|
|
538
|
+
case 'add':
|
|
539
|
+
if (options.skillId === undefined) {
|
|
540
|
+
process.stderr.write('Usage: acsync skill add <name> [options]\n');
|
|
541
|
+
process.exitCode = 1;
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
await skillAdd({
|
|
545
|
+
skillId: options.skillId,
|
|
546
|
+
targets: options.targets,
|
|
547
|
+
noRegister: options.noRegister,
|
|
548
|
+
});
|
|
549
|
+
break;
|
|
550
|
+
case 'install':
|
|
551
|
+
if (options.githubUrl === undefined) {
|
|
552
|
+
process.stderr.write('Usage: acsync skill install <github-url> [options]\n');
|
|
553
|
+
process.exitCode = 1;
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
await (await import('./cli-skill.js')).skillInstallFromGitHub({
|
|
557
|
+
githubUrl: options.githubUrl,
|
|
558
|
+
skillName: options.skillName,
|
|
559
|
+
targets: options.targets,
|
|
560
|
+
addToCatalog: options.addToCatalog,
|
|
561
|
+
});
|
|
562
|
+
break;
|
|
563
|
+
case 'remove':
|
|
564
|
+
if (options.skillId === undefined) {
|
|
565
|
+
process.stderr.write('Usage: acsync skill remove <name> [options]\n');
|
|
566
|
+
process.exitCode = 1;
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
569
|
+
await skillRemove({
|
|
570
|
+
skillName: options.skillId,
|
|
571
|
+
targets: options.targets,
|
|
572
|
+
});
|
|
573
|
+
break;
|
|
574
|
+
case 'enable':
|
|
575
|
+
if (options.skillId === undefined) {
|
|
576
|
+
process.stderr.write('Usage: acsync skill enable <name> [options]\n');
|
|
577
|
+
process.exitCode = 1;
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
await skillEnable({
|
|
581
|
+
skillName: options.skillId,
|
|
582
|
+
targets: options.targets,
|
|
583
|
+
});
|
|
584
|
+
break;
|
|
585
|
+
case 'disable':
|
|
586
|
+
if (options.skillId === undefined) {
|
|
587
|
+
process.stderr.write('Usage: acsync skill disable <name> [options]\n');
|
|
588
|
+
process.exitCode = 1;
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
await skillDisable({
|
|
592
|
+
skillName: options.skillId,
|
|
593
|
+
targets: options.targets,
|
|
594
|
+
});
|
|
595
|
+
break;
|
|
596
|
+
default:
|
|
597
|
+
process.stderr.write(`Unknown subcommand: ${subcommand}\n`);
|
|
598
|
+
process.stderr.write(SKILL_HELP);
|
|
599
|
+
process.exitCode = 1;
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
async function handleValidate(argv) {
|
|
603
|
+
if (argv.includes('--help') || argv.includes('-h')) {
|
|
604
|
+
process.stdout.write(VALIDATE_HELP);
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
const strict = parseFlag(argv, 'strict');
|
|
608
|
+
await validate({ strict });
|
|
609
|
+
}
|
|
610
|
+
async function handleDoctor(argv) {
|
|
611
|
+
if (argv.includes('--help') || argv.includes('-h')) {
|
|
612
|
+
process.stdout.write(DOCTOR_HELP);
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
const fix = parseFlag(argv, 'fix');
|
|
616
|
+
await doctor({ fix });
|
|
617
|
+
}
|
|
618
|
+
// ============================================================================
|
|
619
|
+
// Init Command
|
|
620
|
+
// ============================================================================
|
|
621
|
+
const INIT_HELP = `acsync init - Interactive setup for the current project
|
|
622
|
+
|
|
623
|
+
USAGE:
|
|
624
|
+
acsync init [options]
|
|
625
|
+
|
|
626
|
+
OPTIONS:
|
|
627
|
+
--targets <list> Pre-select targets (e.g., claude,codex)
|
|
628
|
+
|
|
629
|
+
DESCRIPTION:
|
|
630
|
+
Interactive setup wizard for configuring your project.
|
|
631
|
+
Guides you through selecting MCP servers and skills from your catalog.
|
|
632
|
+
|
|
633
|
+
EXAMPLES:
|
|
634
|
+
acsync init # Full interactive setup
|
|
635
|
+
acsync init --targets claude # Skip target selection
|
|
636
|
+
`;
|
|
637
|
+
async function handleInit(argv) {
|
|
638
|
+
if (argv.includes('--help') || argv.includes('-h')) {
|
|
639
|
+
process.stdout.write(INIT_HELP);
|
|
640
|
+
return;
|
|
641
|
+
}
|
|
642
|
+
const options = parseInitOptions(argv);
|
|
643
|
+
await init(options);
|
|
644
|
+
}
|
|
645
|
+
function parseInitOptions(argv) {
|
|
646
|
+
const options = {};
|
|
647
|
+
for (let i = 0; i < argv.length; i++) {
|
|
648
|
+
const arg = argv[i];
|
|
649
|
+
switch (arg) {
|
|
650
|
+
case '--targets':
|
|
651
|
+
options.targets = argv[++i].split(',').map(t => t.trim());
|
|
652
|
+
break;
|
|
653
|
+
default:
|
|
654
|
+
process.stderr.write(`Unknown option: ${arg}\n`);
|
|
655
|
+
process.stderr.write(INIT_HELP);
|
|
656
|
+
process.exitCode = 1;
|
|
657
|
+
break;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
return options;
|
|
661
|
+
}
|
|
662
|
+
async function init(options) {
|
|
663
|
+
console.log('🚀 acsync init - Interactive Project Setup\n');
|
|
664
|
+
// Import the interactive init module
|
|
665
|
+
const { runInteractiveInit } = await import('./cli-init.js');
|
|
666
|
+
await runInteractiveInit(options);
|
|
667
|
+
}
|
|
668
|
+
function parseMcpOptions(argv, subcommand) {
|
|
669
|
+
const options = {
|
|
670
|
+
targets: ['claude', 'codex'], // Default targets
|
|
671
|
+
noRegister: false,
|
|
672
|
+
};
|
|
673
|
+
let i = 0;
|
|
674
|
+
while (i < argv.length) {
|
|
675
|
+
const arg = argv[i];
|
|
676
|
+
switch (arg) {
|
|
677
|
+
case '--targets':
|
|
678
|
+
options.targets = parseTargets(argv[++i]);
|
|
679
|
+
break;
|
|
680
|
+
case '--no-register':
|
|
681
|
+
options.noRegister = true;
|
|
682
|
+
break;
|
|
683
|
+
case '--register':
|
|
684
|
+
options.noRegister = false;
|
|
685
|
+
break;
|
|
686
|
+
case '--verbose':
|
|
687
|
+
case '-v':
|
|
688
|
+
options.verbose = true;
|
|
689
|
+
break;
|
|
690
|
+
default:
|
|
691
|
+
// Treat as package/server name (except for status subcommand which doesn't need it)
|
|
692
|
+
if (!options.packageId && subcommand !== 'status') {
|
|
693
|
+
options.packageId = arg;
|
|
694
|
+
}
|
|
695
|
+
break;
|
|
696
|
+
}
|
|
697
|
+
i++;
|
|
698
|
+
}
|
|
699
|
+
return options;
|
|
700
|
+
}
|
|
701
|
+
function parseCatalogMcpAddOptions(argv) {
|
|
702
|
+
const options = {};
|
|
703
|
+
let i = 0;
|
|
704
|
+
while (i < argv.length) {
|
|
705
|
+
const arg = argv[i];
|
|
706
|
+
switch (arg) {
|
|
707
|
+
case '--display-name':
|
|
708
|
+
options.displayName = argv[++i];
|
|
709
|
+
break;
|
|
710
|
+
case '--description':
|
|
711
|
+
options.description = argv[++i];
|
|
712
|
+
break;
|
|
713
|
+
case '--command':
|
|
714
|
+
options.command = argv[++i];
|
|
715
|
+
break;
|
|
716
|
+
case '--args':
|
|
717
|
+
options.args = JSON.parse(argv[++i]);
|
|
718
|
+
break;
|
|
719
|
+
case '--url':
|
|
720
|
+
options.url = argv[++i];
|
|
721
|
+
break;
|
|
722
|
+
case '--cwd':
|
|
723
|
+
options.cwd = argv[++i];
|
|
724
|
+
break;
|
|
725
|
+
case '--env':
|
|
726
|
+
options.env = JSON.parse(argv[++i]);
|
|
727
|
+
break;
|
|
728
|
+
default:
|
|
729
|
+
process.stderr.write(`Unknown option: ${arg}\n`);
|
|
730
|
+
process.exitCode = 1;
|
|
731
|
+
break;
|
|
732
|
+
}
|
|
733
|
+
i++;
|
|
734
|
+
}
|
|
735
|
+
return options;
|
|
736
|
+
}
|
|
737
|
+
function parseCatalogSkillAddOptions(argv) {
|
|
738
|
+
const options = {};
|
|
739
|
+
let i = 0;
|
|
740
|
+
while (i < argv.length) {
|
|
741
|
+
const arg = argv[i];
|
|
742
|
+
switch (arg) {
|
|
743
|
+
case '--file':
|
|
744
|
+
options.file = argv[++i];
|
|
745
|
+
break;
|
|
746
|
+
case '--display-name':
|
|
747
|
+
options.displayName = argv[++i];
|
|
748
|
+
break;
|
|
749
|
+
case '--description':
|
|
750
|
+
options.description = argv[++i];
|
|
751
|
+
break;
|
|
752
|
+
default:
|
|
753
|
+
process.stderr.write(`Unknown option: ${arg}\n`);
|
|
754
|
+
process.exitCode = 1;
|
|
755
|
+
break;
|
|
756
|
+
}
|
|
757
|
+
i++;
|
|
758
|
+
}
|
|
759
|
+
return options;
|
|
760
|
+
}
|
|
761
|
+
function parseCatalogSkillImportOptions(argv) {
|
|
762
|
+
const options = {};
|
|
763
|
+
let i = 0;
|
|
764
|
+
while (i < argv.length) {
|
|
765
|
+
const arg = argv[i];
|
|
766
|
+
switch (arg) {
|
|
767
|
+
case '--name':
|
|
768
|
+
options.skillId = argv[++i];
|
|
769
|
+
break;
|
|
770
|
+
case '--display-name':
|
|
771
|
+
options.displayName = argv[++i];
|
|
772
|
+
break;
|
|
773
|
+
case '--description':
|
|
774
|
+
options.description = argv[++i];
|
|
775
|
+
break;
|
|
776
|
+
default:
|
|
777
|
+
process.stderr.write(`Unknown option: ${arg}\n`);
|
|
778
|
+
process.exitCode = 1;
|
|
779
|
+
break;
|
|
780
|
+
}
|
|
781
|
+
i++;
|
|
782
|
+
}
|
|
783
|
+
return options;
|
|
784
|
+
}
|
|
785
|
+
function parseTargets(input) {
|
|
786
|
+
const validTargets = ['claude', 'codex', 'gemini'];
|
|
787
|
+
const targets = input.split(',').map((t) => t.trim().toLowerCase());
|
|
788
|
+
for (const target of targets) {
|
|
789
|
+
if (!validTargets.includes(target)) {
|
|
790
|
+
process.stderr.write(`Invalid target: ${target}\n`);
|
|
791
|
+
process.stderr.write(`Valid targets: ${validTargets.join(', ')}\n`);
|
|
792
|
+
process.exit(1);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
return targets;
|
|
796
|
+
}
|
|
797
|
+
function parseSkillOptions(argv, subcommand) {
|
|
798
|
+
const options = {
|
|
799
|
+
targets: ['claude', 'codex'], // Default targets
|
|
800
|
+
noRegister: false,
|
|
801
|
+
};
|
|
802
|
+
let i = 0;
|
|
803
|
+
while (i < argv.length) {
|
|
804
|
+
const arg = argv[i];
|
|
805
|
+
switch (arg) {
|
|
806
|
+
case '--targets':
|
|
807
|
+
options.targets = parseTargets(argv[++i]);
|
|
808
|
+
break;
|
|
809
|
+
case '--no-register':
|
|
810
|
+
options.noRegister = true;
|
|
811
|
+
break;
|
|
812
|
+
case '--register':
|
|
813
|
+
options.noRegister = false;
|
|
814
|
+
break;
|
|
815
|
+
case '--verbose':
|
|
816
|
+
case '-v':
|
|
817
|
+
options.verbose = true;
|
|
818
|
+
break;
|
|
819
|
+
case '--from-github':
|
|
820
|
+
case '--github':
|
|
821
|
+
options.githubUrl = argv[++i];
|
|
822
|
+
break;
|
|
823
|
+
case '--name':
|
|
824
|
+
options.skillName = argv[++i];
|
|
825
|
+
break;
|
|
826
|
+
case '--no-catalog':
|
|
827
|
+
options.addToCatalog = false;
|
|
828
|
+
break;
|
|
829
|
+
default:
|
|
830
|
+
// Treat as skill name or GitHub URL (except for status subcommand)
|
|
831
|
+
if (subcommand === 'install' && arg.startsWith('http')) {
|
|
832
|
+
options.githubUrl = arg;
|
|
833
|
+
}
|
|
834
|
+
else if (!options.skillId && subcommand !== 'status') {
|
|
835
|
+
options.skillId = arg;
|
|
836
|
+
}
|
|
837
|
+
break;
|
|
838
|
+
}
|
|
839
|
+
i++;
|
|
840
|
+
}
|
|
841
|
+
return options;
|
|
842
|
+
}
|
|
843
|
+
function parseFlag(argv, longName, shortName) {
|
|
844
|
+
return argv.includes(`--${longName}`) || (shortName ? argv.includes(`-${shortName}`) : false);
|
|
845
|
+
}
|
|
846
|
+
// ============================================================================
|
|
847
|
+
// Utilities
|
|
848
|
+
// ============================================================================
|
|
849
|
+
async function getPackageVersion() {
|
|
850
|
+
// Read package.json dynamically to support global installation
|
|
851
|
+
const { readFile } = await import('node:fs/promises');
|
|
852
|
+
const { dirname, join } = await import('node:path');
|
|
853
|
+
const { fileURLToPath } = await import('node:url');
|
|
854
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
855
|
+
const __dirname = dirname(__filename);
|
|
856
|
+
const pkgPath = join(__dirname, '..', 'package.json');
|
|
857
|
+
const content = await readFile(pkgPath, 'utf8');
|
|
858
|
+
return JSON.parse(content);
|
|
859
|
+
}
|
|
860
|
+
// ============================================================================
|
|
861
|
+
// Error Handling
|
|
862
|
+
// ============================================================================
|
|
863
|
+
main().catch((error) => {
|
|
864
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
865
|
+
process.stderr.write(`Error: ${message}\n`);
|
|
866
|
+
process.exit(1);
|
|
867
|
+
});
|
|
868
|
+
//# sourceMappingURL=cli.js.map
|