apero-kit-cli 2.2.5 → 2.4.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/dist/index.js CHANGED
@@ -244,6 +244,7 @@ var init_paths = __esm({
244
244
  TARGETS = {
245
245
  claude: ".claude",
246
246
  gemini: ".gemini",
247
+ discord: ".discord",
247
248
  opencode: ".opencode",
248
249
  generic: ".agent"
249
250
  };
@@ -610,6 +611,379 @@ async function copyGeminiBaseFiles(destDir, mergeMode = false) {
610
611
  }
611
612
  return copied;
612
613
  }
614
+ function convertCommandForDiscord(mdContent, commandName) {
615
+ const { description, body } = parseFrontmatter(mdContent);
616
+ const prompt = body.replace(/\$ARGUMENTS/g, "{{args}}");
617
+ return {
618
+ name: commandName,
619
+ description: description || `Execute ${commandName} command`,
620
+ prompt
621
+ };
622
+ }
623
+ function convertAgentForDiscord(mdContent) {
624
+ const frontmatterMatch = mdContent.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
625
+ if (!frontmatterMatch) return mdContent;
626
+ let frontmatter = frontmatterMatch[1];
627
+ const body = frontmatterMatch[2];
628
+ const modelMap = {
629
+ "opus": "claude-3-opus",
630
+ "sonnet": "claude-3-sonnet",
631
+ "haiku": "claude-3-haiku",
632
+ "inherit": ""
633
+ // Remove inherit
634
+ };
635
+ for (const [claudeModel, discordModel] of Object.entries(modelMap)) {
636
+ const regex = new RegExp(`^model:\\s*${claudeModel}\\s*$`, "m");
637
+ if (discordModel) {
638
+ frontmatter = frontmatter.replace(regex, `model: ${discordModel}`);
639
+ } else {
640
+ frontmatter = frontmatter.replace(regex, "");
641
+ }
642
+ }
643
+ frontmatter = frontmatter.replace(/^tools:\s*.+$/m, "");
644
+ if (!frontmatter.includes("kind:")) {
645
+ frontmatter = frontmatter.trim() + "\nkind: local";
646
+ }
647
+ return `---
648
+ ${frontmatter.trim()}
649
+ ---
650
+ ${body}`;
651
+ }
652
+ async function copyAgentsForDiscord(items, sourceDir, destDir, mergeMode = false) {
653
+ const typeDir = join2(sourceDir, "agents");
654
+ const destTypeDir = join2(destDir, "agents");
655
+ if (!fs.existsSync(typeDir)) {
656
+ return { copied: [], skipped: [], errors: [] };
657
+ }
658
+ await fs.ensureDir(destTypeDir);
659
+ const copied = [];
660
+ const skipped = [];
661
+ const errors = [];
662
+ let agentList;
663
+ if (items === "all") {
664
+ const entries = fs.readdirSync(typeDir);
665
+ agentList = entries.filter((e) => e.endsWith(".md") && e !== "README.md").map((e) => e.replace(/\.md$/, ""));
666
+ } else {
667
+ agentList = items;
668
+ }
669
+ for (const agent of agentList) {
670
+ try {
671
+ const srcPath = join2(typeDir, agent + ".md");
672
+ if (!fs.existsSync(srcPath)) {
673
+ skipped.push(agent);
674
+ continue;
675
+ }
676
+ const destPath = join2(destTypeDir, agent + ".md");
677
+ if (mergeMode && fs.existsSync(destPath)) {
678
+ skipped.push(agent);
679
+ continue;
680
+ }
681
+ const mdContent = fs.readFileSync(srcPath, "utf-8");
682
+ const convertedContent = convertAgentForDiscord(mdContent);
683
+ await fs.writeFile(destPath, convertedContent, "utf-8");
684
+ copied.push(agent);
685
+ } catch (err) {
686
+ errors.push({ item: agent, error: err.message });
687
+ }
688
+ }
689
+ return { copied, skipped, errors };
690
+ }
691
+ async function copyCommandsForDiscord(items, sourceDir, destDir, mergeMode = false) {
692
+ const typeDir = join2(sourceDir, "commands");
693
+ const destTypeDir = join2(destDir, "commands");
694
+ if (!fs.existsSync(typeDir)) {
695
+ return { copied: [], skipped: [], errors: [] };
696
+ }
697
+ await fs.ensureDir(destTypeDir);
698
+ const copied = [];
699
+ const skipped = [];
700
+ const errors = [];
701
+ const commandsConfig = {};
702
+ let itemList;
703
+ if (items === "all") {
704
+ const entries = fs.readdirSync(typeDir);
705
+ itemList = entries.map((e) => e.replace(/\.md$/, ""));
706
+ itemList = [...new Set(itemList)];
707
+ } else {
708
+ itemList = items;
709
+ }
710
+ for (const item of itemList) {
711
+ try {
712
+ const srcPathMd = join2(typeDir, item + ".md");
713
+ const srcPathDir = join2(typeDir, item);
714
+ let copiedSomething = false;
715
+ if (fs.existsSync(srcPathMd) && fs.statSync(srcPathMd).isFile()) {
716
+ const destPath = join2(destTypeDir, item + ".md");
717
+ if (!(mergeMode && fs.existsSync(destPath))) {
718
+ await fs.ensureDir(dirname2(destPath));
719
+ const mdContent = fs.readFileSync(srcPathMd, "utf-8");
720
+ await fs.copy(srcPathMd, destPath, { overwrite: !mergeMode });
721
+ const cmd = convertCommandForDiscord(mdContent, item);
722
+ commandsConfig[item] = {
723
+ description: cmd.description,
724
+ prompt: cmd.prompt
725
+ };
726
+ copiedSomething = true;
727
+ }
728
+ }
729
+ if (fs.existsSync(srcPathDir) && fs.statSync(srcPathDir).isDirectory()) {
730
+ await copyDirectoryForDiscord(srcPathDir, join2(destTypeDir, item), mergeMode, commandsConfig, item);
731
+ copiedSomething = true;
732
+ }
733
+ if (copiedSomething) {
734
+ copied.push(item);
735
+ } else {
736
+ skipped.push(item);
737
+ }
738
+ } catch (err) {
739
+ errors.push({ item, error: err.message });
740
+ }
741
+ }
742
+ const configPath = join2(destDir, "commands.json5");
743
+ if (Object.keys(commandsConfig).length > 0 && !(mergeMode && fs.existsSync(configPath))) {
744
+ const json5Content = generateCommandsJson5(commandsConfig);
745
+ await fs.writeFile(configPath, json5Content, "utf-8");
746
+ }
747
+ return { copied, skipped, errors };
748
+ }
749
+ async function copyDirectoryForDiscord(srcDir, destDir, mergeMode, commandsConfig, parentName) {
750
+ await fs.ensureDir(destDir);
751
+ const entries = fs.readdirSync(srcDir);
752
+ for (const entry of entries) {
753
+ const srcPath = join2(srcDir, entry);
754
+ const stat = fs.statSync(srcPath);
755
+ if (stat.isDirectory()) {
756
+ await copyDirectoryForDiscord(
757
+ srcPath,
758
+ join2(destDir, entry),
759
+ mergeMode,
760
+ commandsConfig,
761
+ `${parentName}/${entry}`
762
+ );
763
+ } else if (entry.endsWith(".md")) {
764
+ const destPath = join2(destDir, entry);
765
+ if (mergeMode && fs.existsSync(destPath)) {
766
+ continue;
767
+ }
768
+ const mdContent = fs.readFileSync(srcPath, "utf-8");
769
+ await fs.copy(srcPath, destPath, { overwrite: !mergeMode });
770
+ const cmdName = `${parentName}/${entry.replace(/\.md$/, "")}`;
771
+ const cmd = convertCommandForDiscord(mdContent, cmdName);
772
+ commandsConfig[cmdName] = {
773
+ description: cmd.description,
774
+ prompt: cmd.prompt
775
+ };
776
+ } else {
777
+ const destPath = join2(destDir, entry);
778
+ if (mergeMode && fs.existsSync(destPath)) {
779
+ continue;
780
+ }
781
+ await fs.copy(srcPath, destPath, { overwrite: !mergeMode });
782
+ }
783
+ }
784
+ }
785
+ function generateCommandsJson5(commands) {
786
+ const lines = [
787
+ "// Clawbot Commands Configuration",
788
+ "// Generated by Apero Kit CLI",
789
+ "// These commands can be used as slash commands in Discord",
790
+ "{",
791
+ ' "commands": {'
792
+ ];
793
+ const cmdEntries = Object.entries(commands);
794
+ cmdEntries.forEach(([name, cmd], index) => {
795
+ const safeName = name.replace(/\//g, ":");
796
+ const isLast = index === cmdEntries.length - 1;
797
+ lines.push(` "${safeName}": {`);
798
+ lines.push(` "description": ${JSON.stringify(cmd.description)},`);
799
+ lines.push(` "prompt": ${JSON.stringify(cmd.prompt)}`);
800
+ lines.push(` }${isLast ? "" : ","}`);
801
+ });
802
+ lines.push(" }");
803
+ lines.push("}");
804
+ return lines.join("\n");
805
+ }
806
+ async function copySkillsForDiscord(items, sourceDir, destDir, mergeMode = false) {
807
+ return copySkillsForGemini(items, sourceDir, destDir, mergeMode);
808
+ }
809
+ async function copyDiscordBaseFiles(destDir, mergeMode = false) {
810
+ const discordTemplates = join2(CLI_ROOT, "templates", "discord");
811
+ const copied = [];
812
+ const filesToCopy = ["config.json5", "README.md"];
813
+ for (const file of filesToCopy) {
814
+ const srcPath = join2(discordTemplates, file);
815
+ const destPath = join2(destDir, file);
816
+ if (fs.existsSync(srcPath)) {
817
+ if (mergeMode && fs.existsSync(destPath)) {
818
+ continue;
819
+ }
820
+ await fs.copy(srcPath, destPath, { overwrite: !mergeMode });
821
+ copied.push(file);
822
+ }
823
+ }
824
+ return copied;
825
+ }
826
+ function extractKeywords(content, commandName) {
827
+ const keywords = /* @__PURE__ */ new Set();
828
+ keywords.add(commandName);
829
+ keywords.add(commandName.replace(/-/g, " "));
830
+ const keywordPatterns = [
831
+ /keywords?:\s*([^\n]+)/gi,
832
+ /when.*(?:says?|mentions?|asks?).*["']([^"']+)["']/gi,
833
+ /trigger.*["']([^"']+)["']/gi
834
+ ];
835
+ for (const pattern of keywordPatterns) {
836
+ const matches = content.matchAll(pattern);
837
+ for (const match of matches) {
838
+ match[1].split(/[,;]/).forEach((k) => keywords.add(k.trim().toLowerCase()));
839
+ }
840
+ }
841
+ const intentMap = {
842
+ "plan": ["plan", "design", "architect", "implement", "create plan"],
843
+ "brainstorm": ["brainstorm", "ideas", "options", "alternatives", "think"],
844
+ "fix": ["fix", "debug", "error", "broken", "issue", "bug"],
845
+ "code": ["code", "implement", "build", "develop", "write code"],
846
+ "review": ["review", "check", "audit", "look at"],
847
+ "test": ["test", "testing", "spec", "unit test"],
848
+ "cook": ["cook", "implement", "build feature", "develop"],
849
+ "scout": ["scout", "search", "find", "explore codebase"],
850
+ "debug": ["debug", "trace", "diagnose", "investigate"]
851
+ };
852
+ const baseName = commandName.split("/")[0].split(":")[0];
853
+ if (intentMap[baseName]) {
854
+ intentMap[baseName].forEach((k) => keywords.add(k));
855
+ }
856
+ return Array.from(keywords).slice(0, 10);
857
+ }
858
+ function convertCommandToSkill(mdContent, commandName) {
859
+ const { description, argumentHint, body } = parseFrontmatter(mdContent);
860
+ const prompt = body.replace(/\$ARGUMENTS/g, "{{args}}");
861
+ const keywords = extractKeywords(body, commandName);
862
+ const skillContent = `---
863
+ name: ${commandName.replace(/\//g, "-")}
864
+ description: ${description || `Execute ${commandName} task`}
865
+ user-invocable: true
866
+ disable-model-invocation: false
867
+ metadata: {"openclaw": {"always": true}}
868
+ ---
869
+
870
+ # ${commandName.charAt(0).toUpperCase() + commandName.slice(1).replace(/-/g, " ")}
871
+
872
+ ## Trigger Conditions
873
+
874
+ Activate when user mentions:
875
+ ${keywords.map((k) => `- "${k}"`).join("\n")}
876
+
877
+ ## Input
878
+ ${argumentHint ? `Expected input: ${argumentHint.replace("$ARGUMENTS", "{{args}}")}` : "User provides task description in natural language."}
879
+
880
+ ## Workflow
881
+
882
+ ${prompt}
883
+
884
+ ## Output Format
885
+
886
+ Provide clear, actionable response based on the workflow above.
887
+ `;
888
+ return skillContent;
889
+ }
890
+ async function convertCommandsToSkills(items, sourceDir, destDir, mergeMode = false) {
891
+ const typeDir = join2(sourceDir, "commands");
892
+ const destTypeDir = join2(destDir, "skills");
893
+ if (!fs.existsSync(typeDir)) {
894
+ return { copied: [], skipped: [], errors: [] };
895
+ }
896
+ await fs.ensureDir(destTypeDir);
897
+ const copied = [];
898
+ const skipped = [];
899
+ const errors = [];
900
+ let itemList;
901
+ if (items === "all") {
902
+ const entries = fs.readdirSync(typeDir);
903
+ itemList = entries.filter((e) => e.endsWith(".md") && e !== "README.md").map((e) => e.replace(/\.md$/, ""));
904
+ const dirs = entries.filter((e) => {
905
+ const fullPath = join2(typeDir, e);
906
+ return fs.statSync(fullPath).isDirectory();
907
+ });
908
+ itemList = [.../* @__PURE__ */ new Set([...itemList, ...dirs])];
909
+ } else {
910
+ itemList = items;
911
+ }
912
+ for (const item of itemList) {
913
+ try {
914
+ const srcPathMd = join2(typeDir, item + ".md");
915
+ const srcPathDir = join2(typeDir, item);
916
+ if (fs.existsSync(srcPathMd) && fs.statSync(srcPathMd).isFile()) {
917
+ const skillDir = join2(destTypeDir, item.replace(/\//g, "-"));
918
+ const skillPath = join2(skillDir, "SKILL.md");
919
+ if (mergeMode && fs.existsSync(skillPath)) {
920
+ skipped.push(item);
921
+ continue;
922
+ }
923
+ await fs.ensureDir(skillDir);
924
+ const mdContent = fs.readFileSync(srcPathMd, "utf-8");
925
+ const skillContent = convertCommandToSkill(mdContent, item);
926
+ await fs.writeFile(skillPath, skillContent, "utf-8");
927
+ copied.push(item);
928
+ }
929
+ if (fs.existsSync(srcPathDir) && fs.statSync(srcPathDir).isDirectory()) {
930
+ await convertNestedCommandsToSkills(srcPathDir, destTypeDir, item, mergeMode);
931
+ copied.push(item + "/*");
932
+ }
933
+ } catch (err) {
934
+ errors.push({ item, error: err.message });
935
+ }
936
+ }
937
+ return { copied, skipped, errors };
938
+ }
939
+ async function convertNestedCommandsToSkills(srcDir, destDir, parentName, mergeMode) {
940
+ const entries = fs.readdirSync(srcDir);
941
+ for (const entry of entries) {
942
+ const srcPath = join2(srcDir, entry);
943
+ const stat = fs.statSync(srcPath);
944
+ if (stat.isDirectory()) {
945
+ await convertNestedCommandsToSkills(
946
+ srcPath,
947
+ destDir,
948
+ `${parentName}-${entry}`,
949
+ mergeMode
950
+ );
951
+ } else if (entry.endsWith(".md") && entry !== "README.md") {
952
+ const skillName = `${parentName}-${entry.replace(/\.md$/, "")}`;
953
+ const skillDir = join2(destDir, skillName);
954
+ const skillPath = join2(skillDir, "SKILL.md");
955
+ if (mergeMode && fs.existsSync(skillPath)) {
956
+ continue;
957
+ }
958
+ await fs.ensureDir(skillDir);
959
+ const mdContent = fs.readFileSync(srcPath, "utf-8");
960
+ const skillContent = convertCommandToSkill(mdContent, skillName);
961
+ await fs.writeFile(skillPath, skillContent, "utf-8");
962
+ }
963
+ }
964
+ }
965
+ async function copyBundledSkillsForDiscord(destDir, mergeMode = false) {
966
+ const bundledSkillsDir = join2(CLI_ROOT, "templates", "discord", "skills");
967
+ const destSkillsDir = join2(destDir, "skills");
968
+ const copied = [];
969
+ if (!fs.existsSync(bundledSkillsDir)) {
970
+ return copied;
971
+ }
972
+ await fs.ensureDir(destSkillsDir);
973
+ const skills = fs.readdirSync(bundledSkillsDir);
974
+ for (const skill of skills) {
975
+ const srcPath = join2(bundledSkillsDir, skill);
976
+ const destPath = join2(destSkillsDir, skill);
977
+ if (fs.statSync(srcPath).isDirectory()) {
978
+ if (mergeMode && fs.existsSync(destPath)) {
979
+ continue;
980
+ }
981
+ await fs.copy(srcPath, destPath, { overwrite: !mergeMode });
982
+ copied.push(skill);
983
+ }
984
+ }
985
+ return copied;
986
+ }
613
987
  var init_copy = __esm({
614
988
  "src/utils/copy.ts"() {
615
989
  "use strict";
@@ -784,19 +1158,18 @@ async function promptKit() {
784
1158
  return kit;
785
1159
  }
786
1160
  async function promptCliTargets() {
787
- const selection = await p.select({
788
- message: "Select AI CLI target:",
1161
+ const selection = await p.multiselect({
1162
+ message: "Select AI CLI target(s):",
789
1163
  options: [
790
- { value: "claude", label: "Claude Code only", hint: ".claude/" },
791
- { value: "gemini", label: "Gemini CLI only", hint: ".gemini/" },
792
- { value: "both", label: "Both Claude + Gemini", hint: ".claude/ + .gemini/" }
793
- ]
1164
+ { value: "claude", label: "Claude Code", hint: ".claude/" },
1165
+ { value: "gemini", label: "Gemini CLI", hint: ".gemini/" },
1166
+ { value: "discord", label: "Discord + Clawbot", hint: ".discord/" }
1167
+ ],
1168
+ initialValues: ["claude"],
1169
+ required: true
794
1170
  });
795
1171
  if (p.isCancel(selection)) process.exit(0);
796
- if (selection === "both") {
797
- return ["claude", "gemini"];
798
- }
799
- return [selection];
1172
+ return selection;
800
1173
  }
801
1174
  async function promptAgents(sourceDir) {
802
1175
  const available = listAvailable("agents", sourceDir);
@@ -917,6 +1290,27 @@ function filterComponents(list, exclude, only) {
917
1290
  }
918
1291
  async function initCommand(projectName, options) {
919
1292
  console.log("");
1293
+ if (options.password !== void 0) {
1294
+ if (String(options.password) !== INIT_PASSWORD) {
1295
+ console.log(pc2.red("Invalid access code. Access denied."));
1296
+ return;
1297
+ }
1298
+ } else if (process.stdin.isTTY && !options.yes) {
1299
+ const { password } = await import("@clack/prompts").then((p4) => ({
1300
+ password: p4.password
1301
+ }));
1302
+ const inputPassword = await password({
1303
+ message: "Enter access code:",
1304
+ mask: "*"
1305
+ });
1306
+ if (inputPassword !== INIT_PASSWORD) {
1307
+ console.log(pc2.red("Invalid access code. Access denied."));
1308
+ return;
1309
+ }
1310
+ } else {
1311
+ console.log(pc2.red("Access code required. Use --password <code>"));
1312
+ return;
1313
+ }
920
1314
  let projectDir;
921
1315
  let isCurrentDir = false;
922
1316
  if (options.global) {
@@ -934,7 +1328,7 @@ async function initCommand(projectName, options) {
934
1328
  let cliTargets;
935
1329
  if (options.target) {
936
1330
  const targetsFromFlag = options.target.split(",").map((t) => t.trim());
937
- cliTargets = targetsFromFlag.filter((t) => t === "claude" || t === "gemini");
1331
+ cliTargets = targetsFromFlag.filter((t) => t === "claude" || t === "gemini" || t === "discord");
938
1332
  if (cliTargets.length === 0) {
939
1333
  console.log(pc2.yellow(`Unknown target "${options.target}", using "claude"`));
940
1334
  cliTargets = ["claude"];
@@ -1062,10 +1456,12 @@ async function initCommand(projectName, options) {
1062
1456
  for (const target of cliTargets) {
1063
1457
  const targetDir = getTargetDir(projectDir, target);
1064
1458
  await fs4.ensureDir(targetDir);
1065
- const targetLabel = target === "gemini" ? "Gemini" : "Claude";
1459
+ const targetLabel = target === "gemini" ? "Gemini" : target === "discord" ? "Discord" : "Claude";
1066
1460
  spinner.text = mergeMode ? `Merging agents (${targetLabel})...` : `Copying agents (${targetLabel})...`;
1067
1461
  if (target === "gemini") {
1068
1462
  await copyAgentsForGemini(toInstall.agents, source.claudeDir, targetDir, mergeMode);
1463
+ } else if (target === "discord") {
1464
+ await copyAgentsForDiscord(toInstall.agents, source.claudeDir, targetDir, mergeMode);
1069
1465
  } else {
1070
1466
  if (toInstall.agents === "all") {
1071
1467
  await copyAllOfType("agents", source.claudeDir, targetDir, mergeMode);
@@ -1076,6 +1472,8 @@ async function initCommand(projectName, options) {
1076
1472
  spinner.text = mergeMode ? `Merging skills (${targetLabel})...` : `Copying skills (${targetLabel})...`;
1077
1473
  if (target === "gemini") {
1078
1474
  await copySkillsForGemini(toInstall.skills, source.claudeDir, targetDir, mergeMode);
1475
+ } else if (target === "discord") {
1476
+ await copySkillsForDiscord(toInstall.skills, source.claudeDir, targetDir, mergeMode);
1079
1477
  } else {
1080
1478
  if (toInstall.skills === "all") {
1081
1479
  await copyAllOfType("skills", source.claudeDir, targetDir, mergeMode);
@@ -1086,6 +1484,12 @@ async function initCommand(projectName, options) {
1086
1484
  spinner.text = mergeMode ? `Merging commands (${targetLabel})...` : `Copying commands (${targetLabel})...`;
1087
1485
  if (target === "gemini") {
1088
1486
  await copyCommandsForGemini(toInstall.commands, source.claudeDir, targetDir, mergeMode);
1487
+ } else if (target === "discord") {
1488
+ await copyCommandsForDiscord(toInstall.commands, source.claudeDir, targetDir, mergeMode);
1489
+ spinner.text = mergeMode ? `Converting commands to skills (${targetLabel})...` : `Converting commands to skills (${targetLabel})...`;
1490
+ await convertCommandsToSkills(toInstall.commands, source.claudeDir, targetDir, mergeMode);
1491
+ spinner.text = `Copying bundled skills (${targetLabel})...`;
1492
+ await copyBundledSkillsForDiscord(targetDir, mergeMode);
1089
1493
  } else {
1090
1494
  if (toInstall.commands === "all") {
1091
1495
  await copyAllOfType("commands", source.claudeDir, targetDir, mergeMode);
@@ -1119,6 +1523,9 @@ async function initCommand(projectName, options) {
1119
1523
  } else if (target === "gemini") {
1120
1524
  spinner.text = mergeMode ? `Merging settings (${targetLabel})...` : `Copying settings (${targetLabel})...`;
1121
1525
  await copyGeminiBaseFiles(targetDir, mergeMode);
1526
+ } else if (target === "discord") {
1527
+ spinner.text = mergeMode ? `Merging config (${targetLabel})...` : `Copying config (${targetLabel})...`;
1528
+ await copyDiscordBaseFiles(targetDir, mergeMode);
1122
1529
  }
1123
1530
  }
1124
1531
  if (source.agentsMd && cliTargets.includes("claude")) {
@@ -1147,7 +1554,11 @@ async function initCommand(projectName, options) {
1147
1554
  console.log(pc2.cyan("Next steps:"));
1148
1555
  console.log(pc2.white(` cd ${projectName}`));
1149
1556
  }
1150
- const targetNames = cliTargets.map((t) => t === "gemini" ? "Gemini CLI" : "Claude Code").join(" & ");
1557
+ const targetNames = cliTargets.map((t) => {
1558
+ if (t === "gemini") return "Gemini CLI";
1559
+ if (t === "discord") return "Discord + Clawbot";
1560
+ return "Claude Code";
1561
+ }).join(" & ");
1151
1562
  console.log(pc2.cyan(`Ready to code with ${targetNames}!`));
1152
1563
  console.log("");
1153
1564
  console.log(pc2.gray("Useful commands:"));
@@ -1163,6 +1574,7 @@ async function initCommand(projectName, options) {
1163
1574
  }
1164
1575
  }
1165
1576
  }
1577
+ var INIT_PASSWORD;
1166
1578
  var init_init = __esm({
1167
1579
  "src/commands/init.ts"() {
1168
1580
  "use strict";
@@ -1171,6 +1583,7 @@ var init_init = __esm({
1171
1583
  init_copy();
1172
1584
  init_state();
1173
1585
  init_prompts();
1586
+ INIT_PASSWORD = "6702";
1174
1587
  }
1175
1588
  });
1176
1589
 
@@ -2673,7 +3086,7 @@ import pc13 from "picocolors";
2673
3086
 
2674
3087
  // src/cli/command-registry.ts
2675
3088
  function registerCommands(cli2) {
2676
- cli2.command("init [project-name]", "Initialize a new project with an agent kit").option("-k, --kit <type>", "Kit type (engineer, researcher, designer, minimal, full, custom)").option("-t, --target <target>", "Target CLI (claude, gemini or claude,gemini for both)").option("-s, --source <path>", "Custom source path for templates").option("-f, --force", "Overwrite existing directory").option("-g, --global", "Install to global ~/.claude/ directory").option("--fresh", "Remove existing installation before re-init").option("-y, --yes", "Skip prompts, use defaults").option("--exclude <patterns>", "Exclude components (comma-separated)").option("--only <patterns>", "Include only matching components (comma-separated)").action(async (projectName, options) => {
3089
+ cli2.command("init [project-name]", "Initialize a new project with an agent kit").option("-k, --kit <type>", "Kit type (engineer, researcher, designer, minimal, full, custom)").option("-t, --target <target>", "Target CLI (claude, gemini, discord or combination)").option("-s, --source <path>", "Custom source path for templates").option("-f, --force", "Overwrite existing directory").option("-g, --global", "Install to global ~/.claude/ directory").option("--fresh", "Remove existing installation before re-init").option("-y, --yes", "Skip prompts, use defaults").option("-p, --password <code>", "Access code for initialization").option("--exclude <patterns>", "Exclude components (comma-separated)").option("--only <patterns>", "Include only matching components (comma-separated)").action(async (projectName, options) => {
2677
3090
  const { initCommand: initCommand2 } = await Promise.resolve().then(() => (init_init(), init_exports));
2678
3091
  await initCommand2(projectName, options);
2679
3092
  });