mimi-seed 0.2.9 → 0.2.10

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 +191 -72
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4,9 +4,9 @@ import {
4
4
  } from "./chunk-Q5YGYAFK.js";
5
5
 
6
6
  // src/index.ts
7
- import os5 from "os";
8
- import fs6 from "fs";
9
- import path6 from "path";
7
+ import os6 from "os";
8
+ import fs7 from "fs";
9
+ import path7 from "path";
10
10
  import kleur9 from "kleur";
11
11
  import open from "open";
12
12
 
@@ -460,8 +460,25 @@ async function cmdCheck(argv) {
460
460
  `);
461
461
  process.stdout.write("\n");
462
462
  }
463
+ const base = `${cfg.webBase}/apps/${appId}`;
464
+ const nextSteps = [];
465
+ if (data.modules) {
466
+ if ((data.modules.integration ?? 25) < 25) nextSteps.push(`\uC5F0\uACB0 \uC9C4\uB2E8 ${base}/integration`);
467
+ if ((data.modules.copy ?? 25) < 25) nextSteps.push(`\uBB38\uAD6C \uBCF4\uAC15 mimi-seed notes \uB610\uB294 ${base}/copy`);
468
+ if ((data.modules.screenshot ?? 25) < 25) nextSteps.push(`\uC2A4\uD06C\uB9B0\uC0F7 ${base}/screenshots`);
469
+ if ((data.modules.checklist ?? 25) < 25) nextSteps.push(`\uCCB4\uD06C\uB9AC\uC2A4\uD2B8 ${base}/launch`);
470
+ }
471
+ if (nextSteps.length) {
472
+ process.stdout.write(kleur2.bold("\u2192 \uB2E4\uC74C \uB2E8\uACC4:\n"));
473
+ for (const s of nextSteps) process.stdout.write(` ${kleur2.cyan("\u2022")} ${s}
474
+ `);
475
+ process.stdout.write(kleur2.dim(` \uBBF8\uB9AC\uBCF4\uAE30: mimi-seed deploy --dry-run
476
+
477
+ `));
478
+ }
463
479
  if (!hasBlocker) {
464
- process.stdout.write(score >= 80 ? kleur2.green("\u2713 \uCD9C\uC2DC \uC900\uBE44 \uC644\uB8CC!\n") : kleur2.yellow("\uC810\uC218\uB97C \uB192\uC774\uB824\uBA74 \uB300\uC2DC\uBCF4\uB4DC\uB97C \uD655\uC778\uD558\uC138\uC694.\n"));
480
+ process.stdout.write(score >= 80 ? kleur2.green("\u2713 \uCD9C\uC2DC \uC900\uBE44 \uC644\uB8CC!\n") : kleur2.yellow(`\uC544\uC9C1 ${score}/100 \u2014 \uC704 \uB2E4\uC74C \uB2E8\uACC4\uB97C \uC9C4\uD589\uD558\uC138\uC694.
481
+ `));
465
482
  }
466
483
  } catch {
467
484
  for (const line of readinessResult.text.split("\n")) process.stdout.write(" " + line + "\n");
@@ -599,6 +616,7 @@ async function cmdNotes(argv) {
599
616
  return;
600
617
  }
601
618
  let selectedText = result.concise;
619
+ let userSelectedTone = false;
602
620
  if (shouldPrompt) {
603
621
  const choice = await promptUser("\uC801\uC6A9\uD560 \uBC84\uC804 [1=\uAC04\uACB0/2=\uC0C1\uC138/3=\uB9C8\uCF00\uD305/Enter=\uAC74\uB108\uB700]: ");
604
622
  if (!choice) {
@@ -607,6 +625,7 @@ async function cmdNotes(argv) {
607
625
  }
608
626
  if (choice === "2") selectedText = result.detailed;
609
627
  else if (choice === "3") selectedText = result.marketing;
628
+ userSelectedTone = true;
610
629
  }
611
630
  const appsResult = await mcpCall(cfg.endpoint, cfg.token, "list_apps", {});
612
631
  if (appsResult.isError) {
@@ -619,13 +638,17 @@ async function cmdNotes(argv) {
619
638
  process.stdout.write(kleur3.yellow("\uB4F1\uB85D\uB41C \uC571\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.\n"));
620
639
  return;
621
640
  }
641
+ if (userSelectedTone && args.locales.length > 1) {
642
+ process.stdout.write(kleur3.dim("\uC120\uD0DD\uD55C \uD1A4\uC744 \uBAA8\uB4E0 \uB85C\uCF00\uC77C\uC5D0 \uC801\uC6A9\uD569\uB2C8\uB2E4 (\uC790\uB3D9 \uBC88\uC5ED \uBBF8\uC801\uC6A9).\n"));
643
+ }
622
644
  process.stdout.write("Play Store\uC5D0 \uC801\uC6A9 \uC911...\n");
623
645
  for (const locale of args.locales) {
646
+ const text = userSelectedTone ? selectedText : result.localized[locale] ?? selectedText;
624
647
  const r = await mcpCall(cfg.endpoint, cfg.token, "apply_release_notes", {
625
648
  app_id: app.id,
626
649
  platform: "android",
627
650
  locale,
628
- text: result.localized[locale] ?? selectedText
651
+ text
629
652
  });
630
653
  process.stdout.write(r.isError ? kleur3.red(`${locale} \uC801\uC6A9 \uC2E4\uD328: ${r.text}
631
654
  `) : kleur3.green(`\u2713 ${locale} \uC801\uC6A9\uB428
@@ -783,30 +806,42 @@ async function cmdReview(argv) {
783
806
 
784
807
  // src/auth.ts
785
808
  import { spawn } from "child_process";
809
+ import fs3 from "fs";
810
+ import os2 from "os";
811
+ import path3 from "path";
786
812
  import kleur5 from "kleur";
787
813
  var MCP_PKG = "@yoonion/mimi-seed-mcp";
814
+ var MIMI_DIR = path3.join(os2.homedir(), ".mimi-seed");
788
815
  function log(msg) {
789
816
  process.stdout.write(msg + "\n");
790
817
  }
791
818
  function printAuthHelp() {
792
- log(`${kleur5.bold("mimi-seed auth")} \u2014 Google OAuth \uC778\uC99D (Firebase / AdMob / Play Store)
819
+ log(`${kleur5.bold("mimi-seed auth")} \u2014 \uB85C\uCEEC \uC790\uACA9\uC99D\uBA85 \uC778\uC99D/\uAD00\uB9AC
820
+
821
+ ${kleur5.bold("Google OAuth (Firebase / AdMob / Play):")}
822
+ ${kleur5.cyan("mimi-seed auth login")} \uBE0C\uB77C\uC6B0\uC800\uB85C \uB85C\uADF8\uC778 (\uC774\uBBF8 \uC788\uC73C\uBA74 \uC790\uB3D9 refresh \uC2DC\uB3C4)
823
+ ${kleur5.cyan("mimi-seed auth status")} \uD604\uC7AC OAuth \uD1A0\uD070 \uC0C1\uD0DC
824
+ ${kleur5.cyan("mimi-seed auth refresh")} refresh_token\uC73C\uB85C \uAC31\uC2E0\uB9CC \uC2DC\uB3C4 (\uBE0C\uB77C\uC6B0\uC800 X)
825
+ ${kleur5.cyan("mimi-seed auth logout")} OAuth \uD1A0\uD070 \uC0AD\uC81C
826
+
827
+ ${kleur5.bold("\uD50C\uB7AB\uD3FC\uBCC4 \uC790\uACA9\uC99D\uBA85:")}
828
+ ${kleur5.cyan("mimi-seed auth appstore")} App Store Connect API \uD0A4 (appstore.json)
829
+ ${kleur5.cyan("mimi-seed auth playstore")} Play \uC11C\uBE44\uC2A4 \uACC4\uC815 JSON \uB4F1\uB85D
830
+ ${kleur5.cyan("mimi-seed auth bigquery")} BigQuery \uC11C\uBE44\uC2A4 \uACC4\uC815 (Crashlytics export \uB4F1)
793
831
 
794
- ${kleur5.bold("\uC11C\uBE0C\uBA85\uB839:")}
795
- ${kleur5.cyan("mimi-seed auth login")} \uBE0C\uB77C\uC6B0\uC800\uB85C \uB85C\uADF8\uC778 (\uC774\uBBF8 \uC788\uC73C\uBA74 \uC790\uB3D9 refresh \uC2DC\uB3C4)
796
- ${kleur5.cyan("mimi-seed auth status")} \uD604\uC7AC \uD1A0\uD070 \uC0C1\uD0DC
797
- ${kleur5.cyan("mimi-seed auth refresh")} refresh_token\uC73C\uB85C \uAC31\uC2E0\uB9CC \uC2DC\uB3C4 (\uBE0C\uB77C\uC6B0\uC800 X)
798
- ${kleur5.cyan("mimi-seed auth logout")} \uD1A0\uD070 \uC0AD\uC81C
832
+ ${kleur5.bold("\uC804\uCCB4 \uC0C1\uD0DC:")}
833
+ ${kleur5.cyan("mimi-seed auth status --all")} 4\uAC1C \uC790\uACA9\uC99D\uBA85 \uBCF4\uC720 \uC5EC\uBD80 \uD55C\uB208\uC5D0
799
834
 
800
835
  ${kleur5.bold("login \uC635\uC158:")}
801
836
  --no-browser URL \uC790\uB3D9 \uC624\uD508 \uC548 \uD568 (\uC9C1\uC811 \uBCF5\uBD99)
802
837
  --timeout <\uCD08> \uCF5C\uBC31 \uB300\uAE30 \uC2DC\uAC04 (\uAE30\uBCF8 600)
803
838
  --force \uAE30\uC874 \uD1A0\uD070 \uBB34\uC2DC\uD558\uACE0 \uAC15\uC81C \uC7AC\uB85C\uADF8\uC778
804
839
 
805
- ${kleur5.dim(`\uB0B4\uBD80\uC801\uC73C\uB85C ${MCP_PKG} \uC758 mimi-seed-auth CLI\uB97C \uD638\uCD9C\uD569\uB2C8\uB2E4.`)}`);
840
+ ${kleur5.dim(`\uB0B4\uBD80\uC801\uC73C\uB85C ${MCP_PKG} \uC758 mimi-seed-*-auth CLI\uB97C \uD638\uCD9C\uD569\uB2C8\uB2E4.`)}`);
806
841
  }
807
- async function runMcpAuth(extraArgs) {
842
+ async function runMcpBin(bin, extraArgs) {
808
843
  return new Promise((resolve) => {
809
- const child = spawn("npx", ["-y", `${MCP_PKG}`, "mimi-seed-auth", ...extraArgs], {
844
+ const child = spawn("npx", ["-y", `${MCP_PKG}`, bin, ...extraArgs], {
810
845
  stdio: "inherit",
811
846
  shell: true
812
847
  });
@@ -819,6 +854,30 @@ async function runMcpAuth(extraArgs) {
819
854
  child.on("exit", (code) => resolve(code ?? 0));
820
855
  });
821
856
  }
857
+ function fileExists(name) {
858
+ return fs3.existsSync(path3.join(MIMI_DIR, name));
859
+ }
860
+ function anyFileStarting(prefix) {
861
+ try {
862
+ return fs3.readdirSync(MIMI_DIR).some((f) => f.startsWith(prefix));
863
+ } catch {
864
+ return false;
865
+ }
866
+ }
867
+ function printAllCredStatus() {
868
+ log(kleur5.bold("\uB85C\uCEEC \uC790\uACA9\uC99D\uBA85 \uC0C1\uD0DC ") + kleur5.dim("(~/.mimi-seed)"));
869
+ const rows = [
870
+ ["Google OAuth (Firebase/AdMob/Play)", fileExists("tokens.json"), "mimi-seed auth login"],
871
+ ["App Store Connect", fileExists("appstore.json"), "mimi-seed auth appstore"],
872
+ ["Play \uC11C\uBE44\uC2A4 \uACC4\uC815", anyFileStarting("play-service-account"), "mimi-seed auth playstore"],
873
+ ["BigQuery \uC11C\uBE44\uC2A4 \uACC4\uC815", anyFileStarting("bigquery"), "mimi-seed auth bigquery"]
874
+ ];
875
+ for (const [label, ok2, cmd] of rows) {
876
+ const mark = ok2 ? kleur5.green("\u2713") : kleur5.red("\u2717");
877
+ const hint = ok2 ? "" : kleur5.dim(` \u2192 ${cmd}`);
878
+ log(` ${mark} ${label}${hint}`);
879
+ }
880
+ }
822
881
  async function cmdAuth(args) {
823
882
  const sub = args[0];
824
883
  const rest = args.slice(1);
@@ -826,6 +885,13 @@ async function cmdAuth(args) {
826
885
  printAuthHelp();
827
886
  return;
828
887
  }
888
+ if (sub === "status" && rest.includes("--all")) {
889
+ printAllCredStatus();
890
+ return;
891
+ }
892
+ if (sub === "appstore") return void exitWith(await runMcpBin("mimi-seed-appstore-auth", rest));
893
+ if (sub === "playstore") return void exitWith(await runMcpBin("mimi-seed-playstore-auth", rest));
894
+ if (sub === "bigquery") return void exitWith(await runMcpBin("mimi-seed-bigquery-auth", rest));
829
895
  let mcpArgs;
830
896
  switch (sub) {
831
897
  case void 0:
@@ -846,7 +912,9 @@ async function cmdAuth(args) {
846
912
  printAuthHelp();
847
913
  process.exit(1);
848
914
  }
849
- const code = await runMcpAuth(mcpArgs);
915
+ exitWith(await runMcpBin("mimi-seed-auth", mcpArgs));
916
+ }
917
+ function exitWith(code) {
850
918
  if (code !== 0) process.exit(code);
851
919
  }
852
920
 
@@ -855,25 +923,25 @@ import kleur6 from "kleur";
855
923
  import * as readline from "readline";
856
924
 
857
925
  // src/ci-providers.ts
858
- import fs3 from "fs";
859
- import path3 from "path";
860
- import os2 from "os";
861
- var CI_CONFIG_PATH = path3.join(os2.homedir(), ".mimi-seed", "ci.json");
926
+ import fs4 from "fs";
927
+ import path4 from "path";
928
+ import os3 from "os";
929
+ var CI_CONFIG_PATH = path4.join(os3.homedir(), ".mimi-seed", "ci.json");
862
930
  function loadCiProviderConfig() {
863
931
  try {
864
- return JSON.parse(fs3.readFileSync(CI_CONFIG_PATH, "utf-8"));
932
+ return JSON.parse(fs4.readFileSync(CI_CONFIG_PATH, "utf-8"));
865
933
  } catch {
866
934
  return null;
867
935
  }
868
936
  }
869
937
  function saveCiProviderConfig(cfg) {
870
- const dir = path3.dirname(CI_CONFIG_PATH);
871
- if (!fs3.existsSync(dir)) {
872
- fs3.mkdirSync(dir, { recursive: true, mode: 448 });
938
+ const dir = path4.dirname(CI_CONFIG_PATH);
939
+ if (!fs4.existsSync(dir)) {
940
+ fs4.mkdirSync(dir, { recursive: true, mode: 448 });
873
941
  }
874
- fs3.writeFileSync(CI_CONFIG_PATH, JSON.stringify(cfg, null, 2));
942
+ fs4.writeFileSync(CI_CONFIG_PATH, JSON.stringify(cfg, null, 2));
875
943
  if (process.platform !== "win32") {
876
- fs3.chmodSync(CI_CONFIG_PATH, 384);
944
+ fs4.chmodSync(CI_CONFIG_PATH, 384);
877
945
  }
878
946
  }
879
947
  function ghBase(cfg) {
@@ -1110,6 +1178,7 @@ function parseArgs4(argv) {
1110
1178
  platform: "android",
1111
1179
  language: "ko-KR",
1112
1180
  dryRun: false,
1181
+ yes: false,
1113
1182
  skipBuild: false,
1114
1183
  setupJenkins: false,
1115
1184
  setupGithub: false,
@@ -1125,6 +1194,7 @@ function parseArgs4(argv) {
1125
1194
  if (argv[i] === "--to" && argv[i + 1]) args.toRef = argv[++i];
1126
1195
  if (argv[i] === "--language" && argv[i + 1]) args.language = argv[++i];
1127
1196
  if (argv[i] === "--dry-run") args.dryRun = true;
1197
+ if (argv[i] === "--yes" || argv[i] === "-y") args.yes = true;
1128
1198
  if (argv[i] === "--skip-build") args.skipBuild = true;
1129
1199
  if (argv[i] === "--ci" && argv[i + 1]) args.ci = argv[++i];
1130
1200
  if (argv[i] === "--workflow" && argv[i + 1]) args.workflow = argv[++i];
@@ -1336,6 +1406,21 @@ async function cmdDeploy(argv) {
1336
1406
  log2(kleur6.red("appId\uB97C \uD655\uC778\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. --app <id> \uB85C \uC9C0\uC815\uD558\uAC70\uB098 `mimi-seed init` \uC73C\uB85C \uC571 \uB4F1\uB85D."));
1337
1407
  process.exit(1);
1338
1408
  }
1409
+ const needsConfirm = !args.dryRun && !args.yes && process.stdout.isTTY && !process.env.MIMI_SEED_TOKEN;
1410
+ if (needsConfirm) {
1411
+ const target = args.platform === "ios" ? "App Store \uC2EC\uC0AC \uC81C\uCD9C" : "Play Store production \uD2B8\uB799";
1412
+ log2("");
1413
+ log2(kleur6.yellow(`\u26A0 \uC2E4\uC81C \uBC30\uD3EC: ${args.platform} \xB7 versionCode ${versionCode} \u2192 ${target}`));
1414
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
1415
+ const answer = await new Promise(
1416
+ (resolve) => rl.question(kleur6.bold("\uACC4\uC18D \uC9C4\uD589\uD560\uAE4C\uC694? [y/N]: "), (a) => resolve(a.trim().toLowerCase()))
1417
+ );
1418
+ rl.close();
1419
+ if (answer !== "y" && answer !== "yes") {
1420
+ log2(kleur6.dim("\uCDE8\uC18C\uB428. (--yes \uB85C \uD655\uC778 \uC0DD\uB7B5 \uAC00\uB2A5)"));
1421
+ return;
1422
+ }
1423
+ }
1339
1424
  log2("");
1340
1425
  log2("\u{1F4E1} \uC11C\uBC84 \uBC30\uD3EC \uD30C\uC774\uD504\uB77C\uC778 \uC2DC\uC791...");
1341
1426
  log2("");
@@ -1357,17 +1442,17 @@ async function cmdDeploy(argv) {
1357
1442
 
1358
1443
  // src/mcp-restart.ts
1359
1444
  import { execSync as execSync2 } from "child_process";
1360
- import fs4 from "fs";
1361
- import os3 from "os";
1362
- import path4 from "path";
1445
+ import fs5 from "fs";
1446
+ import os4 from "os";
1447
+ import path5 from "path";
1363
1448
  import kleur7 from "kleur";
1364
1449
  function log3(msg) {
1365
1450
  process.stdout.write(msg + "\n");
1366
1451
  }
1367
1452
  function readClaudeJson() {
1368
- const p = path4.join(os3.homedir(), ".claude.json");
1453
+ const p = path5.join(os4.homedir(), ".claude.json");
1369
1454
  try {
1370
- return JSON.parse(fs4.readFileSync(p, "utf8"));
1455
+ return JSON.parse(fs5.readFileSync(p, "utf8"));
1371
1456
  } catch {
1372
1457
  return {};
1373
1458
  }
@@ -1383,7 +1468,7 @@ function findProcessMarker(cfg) {
1383
1468
  return meaningful.at(-1) ?? null;
1384
1469
  }
1385
1470
  function killByMarker(marker) {
1386
- const isWin = os3.platform() === "win32";
1471
+ const isWin = os4.platform() === "win32";
1387
1472
  if (isWin) {
1388
1473
  const escaped = marker.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
1389
1474
  let pids = [];
@@ -1454,9 +1539,9 @@ async function cmdRestart(args) {
1454
1539
  }
1455
1540
 
1456
1541
  // src/mcp-config.ts
1457
- import fs5 from "fs/promises";
1458
- import path5 from "path";
1459
- import os4 from "os";
1542
+ import fs6 from "fs/promises";
1543
+ import path6 from "path";
1544
+ import os5 from "os";
1460
1545
  import kleur8 from "kleur";
1461
1546
  var SERVER_NAME = "mimi-seed";
1462
1547
  function tomlString(value) {
@@ -1496,17 +1581,17 @@ function printMcpSetup(cfg) {
1496
1581
  );
1497
1582
  }
1498
1583
  async function writeCodexMcpConfig(cfg) {
1499
- const configDir = path5.join(os4.homedir(), ".codex");
1500
- const configPath = path5.join(configDir, "config.toml");
1501
- await fs5.mkdir(configDir, { recursive: true });
1584
+ const configDir = path6.join(os5.homedir(), ".codex");
1585
+ const configPath = path6.join(configDir, "config.toml");
1586
+ await fs6.mkdir(configDir, { recursive: true });
1502
1587
  let current = "";
1503
1588
  try {
1504
- current = await fs5.readFile(configPath, "utf8");
1589
+ current = await fs6.readFile(configPath, "utf8");
1505
1590
  } catch {
1506
1591
  current = "";
1507
1592
  }
1508
1593
  const next = replaceTomlBlock(current, `mcp_servers.${SERVER_NAME}`, codexBlock(cfg));
1509
- await fs5.writeFile(configPath, next);
1594
+ await fs6.writeFile(configPath, next);
1510
1595
  return configPath;
1511
1596
  }
1512
1597
 
@@ -1551,7 +1636,7 @@ async function cmdInit() {
1551
1636
  return;
1552
1637
  }
1553
1638
  log4("\u{1F510} \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uB85C\uADF8\uC778 \uB300\uAE30...");
1554
- const hostName = os5.hostname().slice(0, 32);
1639
+ const hostName = os6.hostname().slice(0, 32);
1555
1640
  const name = `cli-${hostName}`;
1556
1641
  const { port, promise } = await awaitHandshake(5 * 60 * 1e3);
1557
1642
  const callback = `http://127.0.0.1:${port}/cb`;
@@ -1617,16 +1702,16 @@ async function cmdInit() {
1617
1702
  "- `/mimi-seed:health` \u2014 \uC5F0\uACB0 \uC0C1\uD0DC \uBE60\uB978 \uD655\uC778",
1618
1703
  "- `/mimi-seed:review-inbox` \u2014 \uBBF8\uB2F5\uBCC0 \uB9AC\uBDF0 \uB2F5\uBCC0"
1619
1704
  ].join("\n");
1620
- const claudeDir = path6.join(cwd, ".claude");
1621
- const claudeAgentPath = path6.join(claudeDir, "mimi-seed.md");
1622
- if (!fs6.existsSync(claudeAgentPath)) {
1623
- fs6.mkdirSync(claudeDir, { recursive: true });
1624
- fs6.writeFileSync(claudeAgentPath, agentMd, { mode: 420 });
1705
+ const claudeDir = path7.join(cwd, ".claude");
1706
+ const claudeAgentPath = path7.join(claudeDir, "mimi-seed.md");
1707
+ if (!fs7.existsSync(claudeAgentPath)) {
1708
+ fs7.mkdirSync(claudeDir, { recursive: true });
1709
+ fs7.writeFileSync(claudeAgentPath, agentMd, { mode: 420 });
1625
1710
  log4(kleur9.dim(` Claude \uC5D0\uC774\uC804\uD2B8 \uC124\uC815: .claude/mimi-seed.md`));
1626
1711
  }
1627
- const codexAgentPath = path6.join(cwd, "AGENTS.md");
1628
- if (!fs6.existsSync(codexAgentPath)) {
1629
- fs6.writeFileSync(codexAgentPath, agentMd, { mode: 420 });
1712
+ const codexAgentPath = path7.join(cwd, "AGENTS.md");
1713
+ if (!fs7.existsSync(codexAgentPath)) {
1714
+ fs7.writeFileSync(codexAgentPath, agentMd, { mode: 420 });
1630
1715
  log4(kleur9.dim(` Codex \uC5D0\uC774\uC804\uD2B8 \uC124\uC815: AGENTS.md`));
1631
1716
  }
1632
1717
  log4(kleur9.bold("\u2713 \uC900\uBE44 \uC644\uB8CC."));
@@ -1675,6 +1760,7 @@ async function cmdMcp(args) {
1675
1760
  const configPath = await writeCodexMcpConfig(cfg);
1676
1761
  log4(kleur9.green("\u2713 Codex MCP \uC124\uC815 \uC644\uB8CC"));
1677
1762
  log4(kleur9.dim(` ${configPath}`));
1763
+ log4(kleur9.dim(" \u26A0 config.toml\uC5D0 \uC2E4\uC81C \uD1A0\uD070\uC774 \uD3C9\uBB38\uC73C\uB85C \uC800\uC7A5\uB429\uB2C8\uB2E4 (\uD30C\uC77C \uAD8C\uD55C \uD655\uC778 \uAD8C\uC7A5)."));
1678
1764
  log4("");
1679
1765
  log4("Codex\uB97C \uC0C8\uB85C \uC5F4\uACE0 `/mcp` \uB610\uB294 `codex mcp list`\uB85C \uD655\uC778\uD558\uC138\uC694.");
1680
1766
  return;
@@ -1699,35 +1785,34 @@ http_headers = { Authorization = "Bearer ${cfg.prefix}..." }`);
1699
1785
  }
1700
1786
  printMcpSetup(cfg);
1701
1787
  }
1702
- function printHelp() {
1703
- log4(`${kleur9.bold("mimi-seed")} \u2014 Claude Code/Codex\uC5D0\uC11C \uC571 \uCD9C\uC2DC \uC6B4\uC601
1788
+ var CMD_USAGE = {
1789
+ init: `${kleur9.bold("mimi-seed init")} \u2014 \uD604\uC7AC \uD504\uB85C\uC81D\uD2B8\uB97C Mimi Seed\uC5D0 \uC5F0\uACB0
1704
1790
 
1705
- ${kleur9.bold("\uBA85\uB839\uC5B4:")}
1706
- ${kleur9.cyan("mimi-seed init")} \uD604\uC7AC \uD504\uB85C\uC81D\uD2B8\uB97C Mimi Seed\uC5D0 \uC5F0\uACB0
1707
- ${kleur9.cyan("mimi-seed status")} \uC5F0\uACB0 \uC0C1\uD0DC + \uB4F1\uB85D \uC571 \uBAA9\uB85D
1708
- ${kleur9.cyan("mimi-seed auth")} Google OAuth \uC778\uC99D (Firebase/AdMob/Play). 'mimi-seed auth --help'
1709
- ${kleur9.cyan("mimi-seed doctor")} \uD658\uACBD \uC9C4\uB2E8 (\uD1A0\uD070\xB7Git\xB7\uD504\uB85C\uC81D\uD2B8\xB7CI \uCCB4\uD06C)
1710
- ${kleur9.cyan("mimi-seed check")} \uCD9C\uC2DC \uC804 Readiness \uC810\uAC80
1711
- ${kleur9.cyan("mimi-seed notes")} \uB9B4\uB9AC\uC988 \uB178\uD2B8 \uC0DD\uC131 (git log \u2192 AI \u2192 \uB9C8\uCF13 \uC801\uC6A9)
1712
- ${kleur9.cyan("mimi-seed review")} \uB9AC\uBDF0 \uB2F5\uBCC0 AI \uCD08\uC548 \uC0DD\uC131 \uBC0F Play Store \uAC8C\uC2DC
1713
- ${kleur9.cyan("mimi-seed deploy")} \uC571 \uC790\uB3D9 \uBC30\uD3EC (Jenkins \u2192 Play Store/App Store)
1714
- ${kleur9.cyan("mimi-seed mcp")} Claude/Codex MCP \uC5F0\uACB0 \uC548\uB0B4 \uBC0F Codex \uC124\uC815 \uC4F0\uAE30
1715
- ${kleur9.cyan("mimi-seed restart")} MCP \uC11C\uBC84 \uD504\uB85C\uC138\uC2A4 \uC7AC\uC2DC\uC791 (\uAE30\uBCF8: mimi-seed)
1716
- ${kleur9.cyan("mimi-seed logout")} \uB85C\uCEEC \uC124\uC815 \uC0AD\uC81C
1791
+ \uC571 \uC790\uB3D9 \uAC10\uC9C0(Expo/Gradle/Info.plist/pbxproj) \u2192 \uBE0C\uB77C\uC6B0\uC800 PAT \uBC1C\uAE09 \u2192 \uC571 \uB4F1\uB85D
1792
+ + .claude/mimi-seed.md, AGENTS.md \uC0DD\uC131. \uC635\uC158 \uC5C6\uC74C.`,
1793
+ status: `${kleur9.bold("mimi-seed status")} \u2014 \uC5F0\uACB0 \uC0C1\uD0DC + \uB4F1\uB85D \uC571 \uBAA9\uB85D. \uC635\uC158 \uC5C6\uC74C.`,
1794
+ doctor: `${kleur9.bold("mimi-seed doctor")} \u2014 \uD658\uACBD \uC9C4\uB2E8 (\uD1A0\uD070\xB7Node\xB7Git\xB7\uD504\uB85C\uC81D\uD2B8\xB7CI). \uC635\uC158 \uC5C6\uC74C.`,
1795
+ logout: `${kleur9.bold("mimi-seed logout")} \u2014 \uB85C\uCEEC \uC124\uC815(config.json) \uC0AD\uC81C. \uC635\uC158 \uC5C6\uC74C.`,
1796
+ restart: `${kleur9.bold("mimi-seed restart")} \u2014 MCP \uC11C\uBC84 \uD504\uB85C\uC138\uC2A4 \uC7AC\uC2DC\uC791 (\uAE30\uBCF8: mimi-seed)
1717
1797
 
1718
- ${kleur9.bold("mimi-seed notes \uC635\uC158:")}
1798
+ mimi-seed restart [server-name]`,
1799
+ notes: `${kleur9.bold("mimi-seed notes")} \u2014 \uB9B4\uB9AC\uC988 \uB178\uD2B8 \uC0DD\uC131 (git log \u2192 AI \u2192 \uB9C8\uCF13 \uC801\uC6A9)
1800
+
1801
+ \uC635\uC158:
1719
1802
  --from <ref> \uC2DC\uC791 \uCEE4\uBC0B/\uD0DC\uADF8 (\uAE30\uBCF8: \uCD5C\uC2E0 \uD0DC\uADF8)
1720
1803
  --to <ref> \uB05D \uCEE4\uBC0B (\uAE30\uBCF8: HEAD)
1721
1804
  --locale ko,en-US \uB300\uC0C1 \uB85C\uCF00\uC77C (\uC27C\uD45C \uAD6C\uBD84)
1722
1805
  --apply \uC0DD\uC131 \uD6C4 \uC2A4\uD1A0\uC5B4\uC5D0 \uBC14\uB85C \uC801\uC6A9
1723
1806
  --no-interactive CI \uBAA8\uB4DC (\uD504\uB86C\uD504\uD2B8 \uC5C6\uC74C)
1724
- --limit <n> \uCD5C\uB300 \uCEE4\uBC0B \uC218 (\uAE30\uBCF8: 30)
1807
+ --limit <n> \uCD5C\uB300 \uCEE4\uBC0B \uC218 (\uAE30\uBCF8: 30)`,
1808
+ check: `${kleur9.bold("mimi-seed check")} \u2014 \uCD9C\uC2DC \uC804 Readiness \uC810\uAC80
1725
1809
 
1726
- ${kleur9.bold("mimi-seed check \uC635\uC158:")}
1810
+ \uC635\uC158:
1727
1811
  --app <id> \uC571 ID \uC9C0\uC815
1728
- --fail-on-blocker \uBE14\uB85C\uCEE4 \uC788\uC73C\uBA74 exit 1 (CI\uC6A9)
1812
+ --fail-on-blocker \uBE14\uB85C\uCEE4 \uC788\uC73C\uBA74 exit 1 (CI\uC6A9)`,
1813
+ review: `${kleur9.bold("mimi-seed review")} \u2014 \uB9AC\uBDF0 \uB2F5\uBCC0 AI \uCD08\uC548 \uC0DD\uC131 \uBC0F Play Store \uAC8C\uC2DC
1729
1814
 
1730
- ${kleur9.bold("mimi-seed review \uC635\uC158:")}
1815
+ \uC635\uC158:
1731
1816
  --text <\uB0B4\uC6A9> \uB9AC\uBDF0 \uC6D0\uBB38 (\uBBF8\uC785\uB825 \uC2DC \uB300\uD654\uD615 \uD504\uB86C\uD504\uD2B8)
1732
1817
  --rating <1-5> \uBCC4\uC810
1733
1818
  --tone <tone> friendly / professional / empathetic / brief (\uAE30\uBCF8: friendly)
@@ -1736,9 +1821,10 @@ ${kleur9.bold("mimi-seed review \uC635\uC158:")}
1736
1821
  --apply \uB2F5\uBCC0\uC744 Play Store\uC5D0 \uAC8C\uC2DC
1737
1822
  --review-id <id> \uB9AC\uBDF0 ID (--apply \uC2DC \uD544\uC694)
1738
1823
  --package-name <p> \uD328\uD0A4\uC9C0\uBA85 (--apply \uC2DC \uD544\uC694)
1739
- --no-interactive CI \uBAA8\uB4DC
1824
+ --no-interactive CI \uBAA8\uB4DC`,
1825
+ deploy: `${kleur9.bold("mimi-seed deploy")} \u2014 \uC571 \uC790\uB3D9 \uBC30\uD3EC (CI \uBE4C\uB4DC \u2192 Play Store/App Store)
1740
1826
 
1741
- ${kleur9.bold("mimi-seed deploy \uC635\uC158:")}
1827
+ \uC635\uC158:
1742
1828
  --platform android|ios \uBC30\uD3EC \uD50C\uB7AB\uD3FC (\uAE30\uBCF8: android)
1743
1829
  --app <id> \uC571 ID \uC9C0\uC815
1744
1830
  --version-code <n> \uBE4C\uB4DC \uBC88\uD638 \uC9C1\uC811 \uC9C0\uC815 (--skip-build \uC640 \uD568\uAED8)
@@ -1746,13 +1832,43 @@ ${kleur9.bold("mimi-seed deploy \uC635\uC158:")}
1746
1832
  --to <ref> \uCEE4\uBC0B \uBC94\uC704 \uB05D (\uAE30\uBCF8: HEAD)
1747
1833
  --language <\uCF54\uB4DC> \uB9B4\uB9AC\uC988 \uB178\uD2B8 \uC5B8\uC5B4 (\uAE30\uBCF8: ko-KR)
1748
1834
  --dry-run \uC2E4\uC81C \uBC30\uD3EC \uC5C6\uC774 \uD30C\uC774\uD504\uB77C\uC778 \uD14C\uC2A4\uD2B8
1835
+ --yes, -y \uBC30\uD3EC \uD655\uC778 \uD504\uB86C\uD504\uD2B8 \uC0DD\uB7B5 (\uC2A4\uD06C\uB9BD\uD2B8/\uC790\uB3D9\uD654\uC6A9)
1749
1836
  --skip-build CI \uBE4C\uB4DC \uAC74\uB108\uB700 (--version-code \uD544\uC218)
1750
1837
  --ci jenkins|github|gitlab CI \uAC15\uC81C \uC120\uD0DD (\uAE30\uBCF8: auto)
1751
1838
  --workflow <file> GitHub workflow \uD30C\uC77C (\uC608: deploy.yml)
1752
1839
  --ref <branch|tag> GitHub/GitLab \uBE0C\uB79C\uCE58/\uD0DC\uADF8 (\uAE30\uBCF8: main)
1753
- setup-jenkins Jenkins \uC124\uC815 \uB300\uD654\uD615 \uB4F1\uB85D
1754
- setup-github GitHub Actions \uC124\uC815 \uB300\uD654\uD615 \uB4F1\uB85D
1755
- setup-gitlab GitLab CI \uC124\uC815 \uB300\uD654\uD615 \uB4F1\uB85D
1840
+ setup-jenkins / setup-github / setup-gitlab CI \uC124\uC815 \uB300\uD654\uD615 \uB4F1\uB85D`,
1841
+ mcp: `${kleur9.bold("mimi-seed mcp")} \u2014 Claude/Codex MCP \uC5F0\uACB0
1842
+
1843
+ \uC11C\uBE0C\uBA85\uB839:
1844
+ mimi-seed mcp \uD604\uC7AC \uC124\uC815 + \uB4F1\uB85D \uC548\uB0B4
1845
+ mimi-seed mcp claude Claude Code \uB4F1\uB85D \uBA85\uB839 \uCD9C\uB825
1846
+ mimi-seed mcp codex Codex \uB4F1\uB85D \uC548\uB0B4
1847
+ mimi-seed mcp codex --write ~/.codex/config.toml\uC5D0 \uC9C1\uC811 \uAE30\uB85D (\u26A0 \uC2E4\uC81C \uD1A0\uD070 \uD3C9\uBB38 \uC800\uC7A5)`
1848
+ };
1849
+ function printCommandHelp(cmd) {
1850
+ const usage = CMD_USAGE[cmd];
1851
+ if (!usage) return false;
1852
+ log4(usage);
1853
+ return true;
1854
+ }
1855
+ function printHelp() {
1856
+ log4(`${kleur9.bold("mimi-seed")} \u2014 Claude Code/Codex\uC5D0\uC11C \uC571 \uCD9C\uC2DC \uC6B4\uC601
1857
+
1858
+ ${kleur9.bold("\uBA85\uB839\uC5B4:")}
1859
+ ${kleur9.cyan("mimi-seed init")} \uD604\uC7AC \uD504\uB85C\uC81D\uD2B8\uB97C Mimi Seed\uC5D0 \uC5F0\uACB0
1860
+ ${kleur9.cyan("mimi-seed status")} \uC5F0\uACB0 \uC0C1\uD0DC + \uB4F1\uB85D \uC571 \uBAA9\uB85D
1861
+ ${kleur9.cyan("mimi-seed auth")} \uB85C\uCEEC \uC778\uC99D (Google OAuth / App Store / Play / BigQuery)
1862
+ ${kleur9.cyan("mimi-seed doctor")} \uD658\uACBD \uC9C4\uB2E8 (\uD1A0\uD070\xB7Git\xB7\uD504\uB85C\uC81D\uD2B8\xB7CI \uCCB4\uD06C)
1863
+ ${kleur9.cyan("mimi-seed check")} \uCD9C\uC2DC \uC804 Readiness \uC810\uAC80
1864
+ ${kleur9.cyan("mimi-seed notes")} \uB9B4\uB9AC\uC988 \uB178\uD2B8 \uC0DD\uC131 (git log \u2192 AI \u2192 \uB9C8\uCF13 \uC801\uC6A9)
1865
+ ${kleur9.cyan("mimi-seed review")} \uB9AC\uBDF0 \uB2F5\uBCC0 AI \uCD08\uC548 \uC0DD\uC131 \uBC0F Play Store \uAC8C\uC2DC
1866
+ ${kleur9.cyan("mimi-seed deploy")} \uC571 \uC790\uB3D9 \uBC30\uD3EC (CI \u2192 Play Store/App Store)
1867
+ ${kleur9.cyan("mimi-seed mcp")} Claude/Codex MCP \uC5F0\uACB0 \uC548\uB0B4 \uBC0F Codex \uC124\uC815 \uC4F0\uAE30
1868
+ ${kleur9.cyan("mimi-seed restart")} MCP \uC11C\uBC84 \uD504\uB85C\uC138\uC2A4 \uC7AC\uC2DC\uC791 (\uAE30\uBCF8: mimi-seed)
1869
+ ${kleur9.cyan("mimi-seed logout")} \uB85C\uCEEC \uC124\uC815 \uC0AD\uC81C
1870
+
1871
+ ${kleur9.dim("\uAC01 \uBA85\uB839 \uC0C1\uC138 \uC635\uC158:")} ${kleur9.cyan("mimi-seed <command> --help")}
1756
1872
 
1757
1873
  ${kleur9.bold("\uD658\uACBD\uBCC0\uC218:")}
1758
1874
  MIMI_SEED_TOKEN PAT \uD1A0\uD070 (CI/CD \uBB34\uC778\uC99D \uBAA8\uB4DC)
@@ -1763,6 +1879,9 @@ ${kleur9.bold("\uD658\uACBD\uBCC0\uC218:")}
1763
1879
  async function main() {
1764
1880
  const cmd = process.argv[2];
1765
1881
  const restArgs = process.argv.slice(3);
1882
+ if (cmd && cmd !== "auth" && (restArgs.includes("--help") || restArgs.includes("-h"))) {
1883
+ if (printCommandHelp(cmd)) return;
1884
+ }
1766
1885
  try {
1767
1886
  switch (cmd) {
1768
1887
  case "init":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mimi-seed",
3
- "version": "0.2.9",
3
+ "version": "0.2.10",
4
4
  "description": "Mimi Seed CLI — Claude Code와 Codex에서 앱 출시 운영을 관리합니다.",
5
5
  "bin": {
6
6
  "mimi-seed": "dist/index.js"