@team-semicolon/semo-cli 2.0.5 โ†’ 3.0.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 (2) hide show
  1. package/dist/index.js +91 -37
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -408,6 +408,11 @@ async function setupExtensionSymlinks(cwd, packages) {
408
408
  console.log(chalk_1.default.cyan("\n๐Ÿ”— Extensions ์—ฐ๊ฒฐ"));
409
409
  const claudeDir = path.join(cwd, ".claude");
410
410
  const semoSystemDir = path.join(cwd, "semo-system");
411
+ // .claude/agents, .claude/skills ๋””๋ ‰ํ† ๋ฆฌ ์ƒ์„ฑ (์—†์œผ๋ฉด)
412
+ const claudeAgentsDir = path.join(claudeDir, "agents");
413
+ const claudeSkillsDir = path.join(claudeDir, "skills");
414
+ fs.mkdirSync(claudeAgentsDir, { recursive: true });
415
+ fs.mkdirSync(claudeSkillsDir, { recursive: true });
411
416
  for (const pkg of packages) {
412
417
  const pkgPath = path.join(semoSystemDir, pkg);
413
418
  if (!fs.existsSync(pkgPath))
@@ -416,7 +421,6 @@ async function setupExtensionSymlinks(cwd, packages) {
416
421
  // Extension์˜ agents/skills๋งŒ ๊ฐœ๋ณ„ ๋งํฌํ•˜์—ฌ ๋ณ‘ํ•ฉ
417
422
  // 1. Extension์˜ agents๋ฅผ .claude/agents/์— ๊ฐœ๋ณ„ ๋งํฌ
418
423
  const extAgentsDir = path.join(pkgPath, "agents");
419
- const claudeAgentsDir = path.join(claudeDir, "agents");
420
424
  if (fs.existsSync(extAgentsDir)) {
421
425
  const agents = fs.readdirSync(extAgentsDir).filter(f => fs.statSync(path.join(extAgentsDir, f)).isDirectory());
422
426
  for (const agent of agents) {
@@ -428,9 +432,8 @@ async function setupExtensionSymlinks(cwd, packages) {
428
432
  }
429
433
  }
430
434
  }
431
- // 3. Extension์˜ skills๋ฅผ .claude/skills/์— ๊ฐœ๋ณ„ ๋งํฌ
435
+ // 2. Extension์˜ skills๋ฅผ .claude/skills/์— ๊ฐœ๋ณ„ ๋งํฌ
432
436
  const extSkillsDir = path.join(pkgPath, "skills");
433
- const claudeSkillsDir = path.join(claudeDir, "skills");
434
437
  if (fs.existsSync(extSkillsDir)) {
435
438
  const skills = fs.readdirSync(extSkillsDir).filter(f => fs.statSync(path.join(extSkillsDir, f)).isDirectory());
436
439
  for (const skill of skills) {
@@ -467,28 +470,34 @@ const BASE_MCP_SERVERS = [
467
470
  args: ["-y", "@modelcontextprotocol/server-sequential-thinking"],
468
471
  },
469
472
  ];
473
+ // === Claude MCP ์„œ๋ฒ„ ์กด์žฌ ์—ฌ๋ถ€ ํ™•์ธ ===
474
+ function isMCPServerRegistered(serverName) {
475
+ try {
476
+ const result = (0, child_process_1.execSync)("claude mcp list", { stdio: "pipe", encoding: "utf-8" });
477
+ return result.includes(serverName);
478
+ }
479
+ catch {
480
+ return false;
481
+ }
482
+ }
470
483
  // === Claude MCP ๋“ฑ๋ก ํ•จ์ˆ˜ ===
471
484
  function registerMCPServer(server) {
472
485
  try {
473
- // ํ™˜๊ฒฝ๋ณ€์ˆ˜๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ --env ์˜ต์…˜ ์ถ”๊ฐ€
474
- const envArgs = [];
486
+ // ์ด๋ฏธ ๋“ฑ๋ก๋œ ์„œ๋ฒ„์ธ์ง€ ํ™•์ธ
487
+ if (isMCPServerRegistered(server.name)) {
488
+ return { success: true, skipped: true };
489
+ }
490
+ // claude mcp add ๋ช…๋ น์–ด ๊ตฌ์„ฑ
491
+ // ํ˜•์‹: claude mcp add <name> [-e KEY=value...] -- <command> [args...]
492
+ const args = ["mcp", "add", server.name];
493
+ // ํ™˜๊ฒฝ๋ณ€์ˆ˜๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ -e ์˜ต์…˜ ์ถ”๊ฐ€
475
494
  if (server.env) {
476
495
  for (const [key, value] of Object.entries(server.env)) {
477
- envArgs.push("-e", `${key}=${value}`);
496
+ args.push("-e", `${key}=${value}`);
478
497
  }
479
498
  }
480
- // claude mcp add ๋ช…๋ น์–ด ์‹คํ–‰
481
- const args = [
482
- "mcp", "add",
483
- server.name,
484
- "--",
485
- server.command,
486
- ...server.args,
487
- ];
488
- // ํ™˜๊ฒฝ๋ณ€์ˆ˜๊ฐ€ ์žˆ์œผ๋ฉด ๋ช…๋ น์–ด ์•ž์— ์ถ”๊ฐ€
489
- if (envArgs.length > 0) {
490
- args.splice(2, 0, ...envArgs);
491
- }
499
+ // -- ๊ตฌ๋ถ„์ž ํ›„ ๋ช…๋ น์–ด์™€ ์ธ์ž ์ถ”๊ฐ€
500
+ args.push("--", server.command, ...server.args);
492
501
  (0, child_process_1.execSync)(`claude ${args.join(" ")}`, { stdio: "pipe" });
493
502
  return { success: true };
494
503
  }
@@ -575,13 +584,20 @@ async function setupMCP(cwd, extensions, force) {
575
584
  // Claude Code์— MCP ์„œ๋ฒ„ ๋“ฑ๋ก ์‹œ๋„
576
585
  console.log(chalk_1.default.cyan("\n๐Ÿ”Œ Claude Code์— MCP ์„œ๋ฒ„ ๋“ฑ๋ก ์ค‘..."));
577
586
  const successServers = [];
587
+ const skippedServers = [];
578
588
  const failedServers = [];
579
589
  for (const server of allServers) {
580
590
  const spinner = (0, ora_1.default)(` ${server.name} ๋“ฑ๋ก ์ค‘...`).start();
581
591
  const result = registerMCPServer(server);
582
592
  if (result.success) {
583
- spinner.succeed(` ${server.name} ๋“ฑ๋ก ์™„๋ฃŒ`);
584
- successServers.push(server.name);
593
+ if (result.skipped) {
594
+ spinner.info(` ${server.name} ์ด๋ฏธ ๋“ฑ๋ก๋จ (๊ฑด๋„ˆ๋œ€)`);
595
+ skippedServers.push(server.name);
596
+ }
597
+ else {
598
+ spinner.succeed(` ${server.name} ๋“ฑ๋ก ์™„๋ฃŒ`);
599
+ successServers.push(server.name);
600
+ }
585
601
  }
586
602
  else {
587
603
  spinner.fail(` ${server.name} ๋“ฑ๋ก ์‹คํŒจ`);
@@ -590,7 +606,10 @@ async function setupMCP(cwd, extensions, force) {
590
606
  }
591
607
  // ๊ฒฐ๊ณผ ์š”์•ฝ
592
608
  if (successServers.length > 0) {
593
- console.log(chalk_1.default.green(`\nโœ“ ${successServers.length}๊ฐœ MCP ์„œ๋ฒ„ ์ž๋™ ๋“ฑ๋ก ์™„๋ฃŒ`));
609
+ console.log(chalk_1.default.green(`\nโœ“ ${successServers.length}๊ฐœ MCP ์„œ๋ฒ„ ์ƒˆ๋กœ ๋“ฑ๋ก ์™„๋ฃŒ`));
610
+ }
611
+ if (skippedServers.length > 0) {
612
+ console.log(chalk_1.default.gray(` (${skippedServers.length}๊ฐœ ์ด๋ฏธ ๋“ฑ๋ก๋จ)`));
594
613
  }
595
614
  // ์‹คํŒจํ•œ ์„œ๋ฒ„๊ฐ€ ์žˆ์œผ๋ฉด ์ˆ˜๋™ ๋“ฑ๋ก ์•ˆ๋‚ด
596
615
  if (failedServers.length > 0) {
@@ -665,13 +684,20 @@ async function mergeExtensionSettings(cwd, packages) {
665
684
  if (newServers.length > 0) {
666
685
  console.log(chalk_1.default.cyan("\n๐Ÿ”Œ Claude Code์— MCP ์„œ๋ฒ„ ๋“ฑ๋ก ์ค‘..."));
667
686
  const successServers = [];
687
+ const skippedServers = [];
668
688
  const failedServers = [];
669
689
  for (const server of newServers) {
670
690
  const spinner = (0, ora_1.default)(` ${server.name} ๋“ฑ๋ก ์ค‘...`).start();
671
691
  const result = registerMCPServer(server);
672
692
  if (result.success) {
673
- spinner.succeed(` ${server.name} ๋“ฑ๋ก ์™„๋ฃŒ`);
674
- successServers.push(server.name);
693
+ if (result.skipped) {
694
+ spinner.info(` ${server.name} ์ด๋ฏธ ๋“ฑ๋ก๋จ (๊ฑด๋„ˆ๋œ€)`);
695
+ skippedServers.push(server.name);
696
+ }
697
+ else {
698
+ spinner.succeed(` ${server.name} ๋“ฑ๋ก ์™„๋ฃŒ`);
699
+ successServers.push(server.name);
700
+ }
675
701
  }
676
702
  else {
677
703
  spinner.fail(` ${server.name} ๋“ฑ๋ก ์‹คํŒจ`);
@@ -679,7 +705,10 @@ async function mergeExtensionSettings(cwd, packages) {
679
705
  }
680
706
  }
681
707
  if (successServers.length > 0) {
682
- console.log(chalk_1.default.green(`\nโœ“ ${successServers.length}๊ฐœ MCP ์„œ๋ฒ„ ์ž๋™ ๋“ฑ๋ก ์™„๋ฃŒ`));
708
+ console.log(chalk_1.default.green(`\nโœ“ ${successServers.length}๊ฐœ MCP ์„œ๋ฒ„ ์ƒˆ๋กœ ๋“ฑ๋ก ์™„๋ฃŒ`));
709
+ }
710
+ if (skippedServers.length > 0) {
711
+ console.log(chalk_1.default.gray(` (${skippedServers.length}๊ฐœ ์ด๋ฏธ ๋“ฑ๋ก๋จ)`));
683
712
  }
684
713
  if (failedServers.length > 0) {
685
714
  console.log(chalk_1.default.yellow(`\nโš  ${failedServers.length}๊ฐœ MCP ์„œ๋ฒ„ ์ž๋™ ๋“ฑ๋ก ์‹คํŒจ`));
@@ -978,11 +1007,19 @@ program
978
1007
  console.log(chalk_1.default.red("\nSEMO๊ฐ€ ์„ค์น˜๋˜์–ด ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. 'semo init'์„ ๋จผ์ € ์‹คํ–‰ํ•˜์„ธ์š”.\n"));
979
1008
  process.exit(1);
980
1009
  }
981
- if (!(packageName in EXTENSION_PACKAGES)) {
1010
+ // ๋ ˆ๊ฑฐ์‹œ ํŒจํ‚ค์ง€ ์ด๋ฆ„ โ†’ ์ƒˆ ์ด๋ฆ„ ๋ณ€ํ™˜
1011
+ let resolvedPackage = packageName;
1012
+ if (packageName in LEGACY_MAPPING) {
1013
+ resolvedPackage = LEGACY_MAPPING[packageName];
1014
+ console.log(chalk_1.default.yellow(`\n๐Ÿ’ก '${packageName}' โ†’ '${resolvedPackage}' (v3.0 ๊ตฌ์กฐ)`));
1015
+ }
1016
+ if (!(resolvedPackage in EXTENSION_PACKAGES)) {
982
1017
  console.log(chalk_1.default.red(`\n์•Œ ์ˆ˜ ์—†๋Š” ํŒจํ‚ค์ง€: ${packageName}`));
983
- console.log(chalk_1.default.gray(`์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํŒจํ‚ค์ง€: ${Object.keys(EXTENSION_PACKAGES).join(", ")}\n`));
1018
+ console.log(chalk_1.default.gray(`์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํŒจํ‚ค์ง€: ${Object.keys(EXTENSION_PACKAGES).join(", ")}`));
1019
+ console.log(chalk_1.default.gray(`๋ ˆ๊ฑฐ์‹œ ๋ณ„์นญ: ${Object.keys(LEGACY_MAPPING).join(", ")}\n`));
984
1020
  process.exit(1);
985
1021
  }
1022
+ packageName = resolvedPackage;
986
1023
  const pkgPath = path.join(semoSystemDir, packageName);
987
1024
  if (fs.existsSync(pkgPath) && !options.force) {
988
1025
  console.log(chalk_1.default.yellow(`\n${EXTENSION_PACKAGES[packageName].name} ํŒจํ‚ค์ง€๊ฐ€ ์ด๋ฏธ ์„ค์น˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.`));
@@ -1006,24 +1043,41 @@ program
1006
1043
  .action(() => {
1007
1044
  const cwd = process.cwd();
1008
1045
  const semoSystemDir = path.join(cwd, "semo-system");
1009
- console.log(chalk_1.default.cyan.bold("\n๐Ÿ“ฆ SEMO ํŒจํ‚ค์ง€ ๋ชฉ๋ก\n"));
1046
+ console.log(chalk_1.default.cyan.bold("\n๐Ÿ“ฆ SEMO ํŒจํ‚ค์ง€ ๋ชฉ๋ก (v3.0)\n"));
1010
1047
  // Standard
1011
1048
  console.log(chalk_1.default.white.bold("Standard (ํ•„์ˆ˜)"));
1012
1049
  const coreInstalled = fs.existsSync(path.join(semoSystemDir, "semo-core"));
1013
1050
  const skillsInstalled = fs.existsSync(path.join(semoSystemDir, "semo-skills"));
1014
1051
  console.log(` ${coreInstalled ? chalk_1.default.green("โœ“") : chalk_1.default.gray("โ—‹")} semo-core - ์›์น™, ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ดํ„ฐ`);
1015
- console.log(` ${skillsInstalled ? chalk_1.default.green("โœ“") : chalk_1.default.gray("โ—‹")} semo-skills - 13๊ฐœ ํ†ตํ•ฉ ์Šคํ‚ฌ`);
1052
+ console.log(` ${skillsInstalled ? chalk_1.default.green("โœ“") : chalk_1.default.gray("โ—‹")} semo-skills - ํ†ตํ•ฉ ์Šคํ‚ฌ`);
1016
1053
  console.log();
1017
- // Extensions
1018
- console.log(chalk_1.default.white.bold("Extensions (์„ ํƒ)"));
1019
- for (const [key, pkg] of Object.entries(EXTENSION_PACKAGES)) {
1020
- const isInstalled = fs.existsSync(path.join(semoSystemDir, key));
1021
- const status = isInstalled ? chalk_1.default.green("โœ“") : chalk_1.default.gray("โ—‹");
1022
- console.log(` ${status} ${key} - ${pkg.desc}`);
1054
+ // Extensions - ๋ ˆ์ด์–ด๋ณ„ ๊ทธ๋ฃนํ™”
1055
+ const layers = {
1056
+ biz: { title: "Business Layer", emoji: "๐Ÿ’ผ" },
1057
+ eng: { title: "Engineering Layer", emoji: "โš™๏ธ" },
1058
+ ops: { title: "Operations Layer", emoji: "๐Ÿ“Š" },
1059
+ meta: { title: "Meta", emoji: "๐Ÿ”ง" },
1060
+ };
1061
+ for (const [layerKey, layerInfo] of Object.entries(layers)) {
1062
+ const layerPackages = Object.entries(EXTENSION_PACKAGES).filter(([, pkg]) => pkg.layer === layerKey);
1063
+ if (layerPackages.length === 0)
1064
+ continue;
1065
+ console.log(chalk_1.default.white.bold(`${layerInfo.emoji} ${layerInfo.title}`));
1066
+ for (const [key, pkg] of layerPackages) {
1067
+ const isInstalled = fs.existsSync(path.join(semoSystemDir, key));
1068
+ const status = isInstalled ? chalk_1.default.green("โœ“") : chalk_1.default.gray("โ—‹");
1069
+ const displayKey = key.includes("/") ? key.split("/")[1] : key;
1070
+ console.log(` ${status} ${chalk_1.default.cyan(displayKey)} - ${pkg.desc}`);
1071
+ console.log(chalk_1.default.gray(` semo add ${key}`));
1072
+ }
1073
+ console.log();
1023
1074
  }
1024
- console.log();
1025
- console.log(chalk_1.default.gray("์„ค์น˜: semo add <package>"));
1026
- console.log(chalk_1.default.gray("์˜ˆ์‹œ: semo add next\n"));
1075
+ // ๋ ˆ๊ฑฐ์‹œ ํ˜ธํ™˜์„ฑ ์•ˆ๋‚ด
1076
+ console.log(chalk_1.default.gray("โ”€".repeat(50)));
1077
+ console.log(chalk_1.default.gray("๋ ˆ๊ฑฐ์‹œ ๋ช…๋ น์–ด๋„ ์ง€์›๋ฉ๋‹ˆ๋‹ค:"));
1078
+ console.log(chalk_1.default.gray(" semo add next โ†’ eng/nextjs"));
1079
+ console.log(chalk_1.default.gray(" semo add backend โ†’ eng/spring"));
1080
+ console.log(chalk_1.default.gray(" semo add mvp โ†’ biz/poc\n"));
1027
1081
  });
1028
1082
  // === status ๋ช…๋ น์–ด ===
1029
1083
  program
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@team-semicolon/semo-cli",
3
- "version": "2.0.5",
3
+ "version": "3.0.1",
4
4
  "description": "SEMO CLI - AI Agent Orchestration Framework Installer",
5
5
  "main": "dist/index.js",
6
6
  "bin": {