thanh-kit 2.5.10 → 2.5.12

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
@@ -142,12 +142,18 @@ function getCkInternalSource() {
142
142
  for (const basePath of CK_INTERNAL_PATHS) {
143
143
  const claudeDir = join(basePath, ".claude");
144
144
  if (existsSync(claudeDir) && existsSync(join(claudeDir, "skills"))) {
145
+ const agentsDir = join(basePath, ".agents");
145
146
  const agentsMd = join(basePath, "AGENTS.md");
147
+ const claudeMd = join(basePath, "CLAUDE.md");
148
+ const geminiMd = join(basePath, "GEMINI.md");
146
149
  return {
147
150
  path: basePath,
148
151
  type: "ck-internal",
149
152
  claudeDir,
150
- agentsMd: existsSync(agentsMd) ? agentsMd : null
153
+ agentsDir: existsSync(agentsDir) ? agentsDir : null,
154
+ agentsMd: existsSync(agentsMd) ? agentsMd : null,
155
+ claudeMd: existsSync(claudeMd) ? claudeMd : null,
156
+ geminiMd: existsSync(geminiMd) ? geminiMd : null
151
157
  };
152
158
  }
153
159
  }
@@ -155,12 +161,18 @@ function getCkInternalSource() {
155
161
  }
156
162
  function getEmbeddedTemplates() {
157
163
  if (existsSync(TEMPLATES_DIR)) {
164
+ const agentsDir = join(TEMPLATES_DIR, "..", ".agents");
158
165
  const agentsMd = join(TEMPLATES_DIR, "AGENTS.md");
166
+ const claudeMd = join(TEMPLATES_DIR, "CLAUDE.md");
167
+ const geminiMd = join(TEMPLATES_DIR, "GEMINI.md");
159
168
  return {
160
169
  path: TEMPLATES_DIR,
161
170
  type: "embedded",
162
171
  claudeDir: TEMPLATES_DIR,
163
- agentsMd: existsSync(agentsMd) ? agentsMd : null
172
+ agentsDir: existsSync(agentsDir) ? agentsDir : null,
173
+ agentsMd: existsSync(agentsMd) ? agentsMd : null,
174
+ claudeMd: existsSync(claudeMd) ? claudeMd : null,
175
+ geminiMd: existsSync(geminiMd) ? geminiMd : null
164
176
  };
165
177
  }
166
178
  return null;
@@ -175,9 +187,11 @@ function isAkProject(dir = process.cwd()) {
175
187
  const akConfig = join(dir, ".ak", "state.json");
176
188
  const claudeDir = join(dir, ".claude");
177
189
  const geminiDir = join(dir, ".gemini");
190
+ const codexDir = join(dir, ".codex");
191
+ const agentsDir = join(dir, ".agents");
178
192
  const opencodeDir = join(dir, ".opencode");
179
193
  const agentDir = join(dir, ".agent");
180
- return existsSync(akConfig) || existsSync(claudeDir) || existsSync(geminiDir) || existsSync(opencodeDir) || existsSync(agentDir);
194
+ return existsSync(akConfig) || existsSync(claudeDir) || existsSync(geminiDir) || existsSync(codexDir) || existsSync(agentsDir) || existsSync(opencodeDir) || existsSync(agentDir);
181
195
  }
182
196
  function getTargetDir(projectDir, target = "claude") {
183
197
  const folder = TARGETS[target] || TARGETS.claude;
@@ -191,12 +205,16 @@ function resolveSource(sourceFlag) {
191
205
  }
192
206
  const claudeDir = join(resolved, ".claude");
193
207
  const opencodeDir = join(resolved, ".opencode");
208
+ const agentsDir = join(resolved, ".agents");
194
209
  if (existsSync(claudeDir)) {
195
210
  return {
196
211
  path: resolved,
197
212
  type: "custom",
198
213
  claudeDir,
199
- agentsMd: existsSync(join(resolved, "AGENTS.md")) ? join(resolved, "AGENTS.md") : null
214
+ agentsDir: existsSync(agentsDir) ? agentsDir : null,
215
+ agentsMd: existsSync(join(resolved, "AGENTS.md")) ? join(resolved, "AGENTS.md") : null,
216
+ claudeMd: existsSync(join(resolved, "CLAUDE.md")) ? join(resolved, "CLAUDE.md") : null,
217
+ geminiMd: existsSync(join(resolved, "GEMINI.md")) ? join(resolved, "GEMINI.md") : null
200
218
  };
201
219
  }
202
220
  if (existsSync(opencodeDir)) {
@@ -204,7 +222,10 @@ function resolveSource(sourceFlag) {
204
222
  path: resolved,
205
223
  type: "custom",
206
224
  claudeDir: opencodeDir,
207
- agentsMd: existsSync(join(resolved, "AGENTS.md")) ? join(resolved, "AGENTS.md") : null
225
+ agentsDir: existsSync(agentsDir) ? agentsDir : null,
226
+ agentsMd: existsSync(join(resolved, "AGENTS.md")) ? join(resolved, "AGENTS.md") : null,
227
+ claudeMd: existsSync(join(resolved, "CLAUDE.md")) ? join(resolved, "CLAUDE.md") : null,
228
+ geminiMd: existsSync(join(resolved, "GEMINI.md")) ? join(resolved, "GEMINI.md") : null
208
229
  };
209
230
  }
210
231
  if (existsSync(join(resolved, "agents")) || existsSync(join(resolved, "commands"))) {
@@ -212,7 +233,10 @@ function resolveSource(sourceFlag) {
212
233
  path: resolved,
213
234
  type: "custom",
214
235
  claudeDir: resolved,
215
- agentsMd: existsSync(join(resolved, "AGENTS.md")) ? join(resolved, "AGENTS.md") : null
236
+ agentsDir: existsSync(agentsDir) ? agentsDir : null,
237
+ agentsMd: existsSync(join(resolved, "AGENTS.md")) ? join(resolved, "AGENTS.md") : null,
238
+ claudeMd: existsSync(join(resolved, "CLAUDE.md")) ? join(resolved, "CLAUDE.md") : null,
239
+ geminiMd: existsSync(join(resolved, "GEMINI.md")) ? join(resolved, "GEMINI.md") : null
216
240
  };
217
241
  }
218
242
  return { error: `No templates found in: ${sourceFlag}` };
@@ -245,6 +269,8 @@ var init_paths = __esm({
245
269
  TARGETS = {
246
270
  claude: ".claude",
247
271
  gemini: ".gemini",
272
+ codex: ".agents",
273
+ // Codex uses .agents for skills, .codex for config
248
274
  discord: ".discord",
249
275
  opencode: ".opencode",
250
276
  generic: ".agent"
@@ -732,12 +758,24 @@ var init_gemini_adapter = __esm({
732
758
  const { CLI_ROOT: CLI_ROOT2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
733
759
  const geminiTemplates = join4(CLI_ROOT2, "templates", "gemini");
734
760
  const copied = [];
735
- const settingsPath = join4(geminiTemplates, "settings.json");
736
- const destSettingsPath = join4(targetDir, "settings.json");
737
- if (fs3.existsSync(settingsPath)) {
738
- if (!(mergeMode && fs3.existsSync(destSettingsPath))) {
739
- await fs3.copy(settingsPath, destSettingsPath, { overwrite: !mergeMode });
740
- copied.push("settings.json");
761
+ const projectRoot = join4(targetDir, "..");
762
+ const settingsFiles = ["settings.json", "settings.local.json"];
763
+ for (const file of settingsFiles) {
764
+ const srcPath = join4(geminiTemplates, file);
765
+ const destPath = join4(targetDir, file);
766
+ if (fs3.existsSync(srcPath)) {
767
+ if (!(mergeMode && fs3.existsSync(destPath))) {
768
+ await fs3.copy(srcPath, destPath, { overwrite: !mergeMode });
769
+ copied.push(file);
770
+ }
771
+ }
772
+ }
773
+ const geminiMdSrc = join4(geminiTemplates, "GEMINI.md");
774
+ const geminiMdDest = join4(projectRoot, "GEMINI.md");
775
+ if (fs3.existsSync(geminiMdSrc)) {
776
+ if (!(mergeMode && fs3.existsSync(geminiMdDest))) {
777
+ await fs3.copy(geminiMdSrc, geminiMdDest, { overwrite: !mergeMode });
778
+ copied.push("GEMINI.md (project root)");
741
779
  }
742
780
  }
743
781
  return copied;
@@ -791,6 +829,7 @@ var init_codex_adapter = __esm({
791
829
  name: "codex",
792
830
  displayName: "Codex CLI",
793
831
  directory: ".agents",
832
+ // Main directory for skills/agents
794
833
  features: {
795
834
  agents: true,
796
835
  skills: true,
@@ -895,12 +934,26 @@ var init_codex_adapter = __esm({
895
934
  const { CLI_ROOT: CLI_ROOT2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
896
935
  const codexTemplates = join5(CLI_ROOT2, "templates", "codex");
897
936
  const copied = [];
898
- const configPath = join5(codexTemplates, "config.toml");
899
- const destConfigPath = join5(targetDir, "config.toml");
900
- if (fs4.existsSync(configPath)) {
901
- if (!(mergeMode && fs4.existsSync(destConfigPath))) {
902
- await fs4.copy(configPath, destConfigPath, { overwrite: !mergeMode });
903
- copied.push("config.toml");
937
+ const projectRoot = join5(targetDir, "..");
938
+ const codexConfigDir = join5(projectRoot, ".codex");
939
+ await fs4.ensureDir(codexConfigDir);
940
+ const configFiles = ["config.toml", "config.local.toml"];
941
+ for (const file of configFiles) {
942
+ const srcPath = join5(codexTemplates, file);
943
+ const destPath = join5(codexConfigDir, file);
944
+ if (fs4.existsSync(srcPath)) {
945
+ if (!(mergeMode && fs4.existsSync(destPath))) {
946
+ await fs4.copy(srcPath, destPath, { overwrite: !mergeMode });
947
+ copied.push(`.codex/${file}`);
948
+ }
949
+ }
950
+ }
951
+ const agentsMdSrc = join5(codexTemplates, "AGENTS.md");
952
+ const agentsMdDest = join5(projectRoot, "AGENTS.md");
953
+ if (fs4.existsSync(agentsMdSrc)) {
954
+ if (!(mergeMode && fs4.existsSync(agentsMdDest))) {
955
+ await fs4.copy(agentsMdSrc, agentsMdDest, { overwrite: !mergeMode });
956
+ copied.push("AGENTS.md");
904
957
  }
905
958
  }
906
959
  return copied;
@@ -1572,6 +1625,39 @@ async function copyAgentsMd(agentsMdPath, projectDir, mergeMode = false) {
1572
1625
  await fs8.copy(agentsMdPath, destPath, { overwrite: !mergeMode });
1573
1626
  return true;
1574
1627
  }
1628
+ async function copyClaudeMd(claudeMdPath, projectDir, mergeMode = false) {
1629
+ if (!claudeMdPath || !fs8.existsSync(claudeMdPath)) {
1630
+ return false;
1631
+ }
1632
+ const destPath = join9(projectDir, "CLAUDE.md");
1633
+ if (mergeMode && fs8.existsSync(destPath)) {
1634
+ return false;
1635
+ }
1636
+ await fs8.copy(claudeMdPath, destPath, { overwrite: !mergeMode });
1637
+ return true;
1638
+ }
1639
+ async function copyGeminiMd(geminiMdPath, projectDir, mergeMode = false) {
1640
+ if (!geminiMdPath || !fs8.existsSync(geminiMdPath)) {
1641
+ return false;
1642
+ }
1643
+ const destPath = join9(projectDir, "GEMINI.md");
1644
+ if (mergeMode && fs8.existsSync(destPath)) {
1645
+ return false;
1646
+ }
1647
+ await fs8.copy(geminiMdPath, destPath, { overwrite: !mergeMode });
1648
+ return true;
1649
+ }
1650
+ async function copyAgentsDir(agentsDirPath, projectDir, mergeMode = false) {
1651
+ if (!agentsDirPath || !fs8.existsSync(agentsDirPath)) {
1652
+ return false;
1653
+ }
1654
+ const destPath = join9(projectDir, ".agents");
1655
+ if (mergeMode && fs8.existsSync(destPath)) {
1656
+ return false;
1657
+ }
1658
+ await fs8.copy(agentsDirPath, destPath, { overwrite: !mergeMode });
1659
+ return true;
1660
+ }
1575
1661
  function listAvailable(type, sourceDir) {
1576
1662
  const typeDir = join9(sourceDir, type);
1577
1663
  if (!fs8.existsSync(typeDir)) {
@@ -1595,34 +1681,6 @@ var init_copy = __esm({
1595
1681
  // src/utils/prompts.ts
1596
1682
  import * as p from "@clack/prompts";
1597
1683
  import pc from "picocolors";
1598
- async function promptKit() {
1599
- const kits = getKitList();
1600
- const options = [
1601
- ...kits.map((kit2) => ({
1602
- value: kit2.name,
1603
- label: `${kit2.emoji} ${kit2.name}`,
1604
- hint: kit2.description
1605
- })),
1606
- { value: "custom", label: "\u{1F527} custom", hint: "Pick your own agents, skills, and commands" }
1607
- ];
1608
- const kit = await p.select({ message: "Select a kit:", options });
1609
- if (p.isCancel(kit)) process.exit(0);
1610
- return kit;
1611
- }
1612
- async function promptCliTargets() {
1613
- const selection = await p.multiselect({
1614
- message: "Select AI CLI target(s):",
1615
- options: [
1616
- { value: "claude", label: "Claude Code", hint: ".claude/" },
1617
- { value: "gemini", label: "Gemini CLI", hint: ".gemini/" },
1618
- { value: "discord", label: "Discord + Clawbot", hint: ".discord/" }
1619
- ],
1620
- initialValues: ["claude"],
1621
- required: true
1622
- });
1623
- if (p.isCancel(selection)) process.exit(0);
1624
- return selection;
1625
- }
1626
1684
  async function promptAgents(sourceDir) {
1627
1685
  const available = listAvailable("agents", sourceDir);
1628
1686
  if (available.length === 0) return [];
@@ -1683,18 +1741,6 @@ async function promptConfirm(message, defaultValue = true) {
1683
1741
  if (p.isCancel(result)) process.exit(0);
1684
1742
  return result;
1685
1743
  }
1686
- async function promptExistingTarget(targetPath) {
1687
- const action = await p.select({
1688
- message: `${targetPath} already exists. What do you want to do?`,
1689
- options: [
1690
- { value: "override", label: "Override", hint: "Replace all files" },
1691
- { value: "merge", label: "Merge", hint: "Only add missing files" },
1692
- { value: "skip", label: "Skip", hint: "Do nothing" }
1693
- ]
1694
- });
1695
- if (p.isCancel(action)) process.exit(0);
1696
- return action;
1697
- }
1698
1744
  async function promptUpdateConfirm(updates) {
1699
1745
  console.log(pc.cyan("\nChanges to apply:"));
1700
1746
  if (updates.toUpdate.length > 0) {
@@ -2034,14 +2080,12 @@ async function initCommand(projectName, options) {
2034
2080
  console.log(pc2.yellow(`Unknown target "${options.target}", using "claude"`));
2035
2081
  cliTargets = ["claude"];
2036
2082
  }
2037
- } else if (!process.stdin.isTTY || options.yes) {
2038
- cliTargets = ["claude"];
2039
2083
  } else {
2040
- cliTargets = await promptCliTargets();
2084
+ cliTargets = ["claude"];
2041
2085
  }
2042
2086
  let discordConfig = null;
2043
2087
  let openclawSetupSuccess = false;
2044
- if (cliTargets.includes("discord") && process.stdin.isTTY && !options.yes) {
2088
+ if (cliTargets.includes("discord") && options.target && process.stdin.isTTY) {
2045
2089
  discordConfig = await promptDiscordSetup();
2046
2090
  }
2047
2091
  let existingAction = null;
@@ -2063,20 +2107,7 @@ async function initCommand(projectName, options) {
2063
2107
  console.log(pc2.cyan(`Fresh install: removed existing files (${existingTargets.join(", ")})`));
2064
2108
  existingAction = null;
2065
2109
  } else if (existingTargets.length > 0 && !options.force) {
2066
- if (!process.stdin.isTTY || options.yes) {
2067
- if (options.yes) {
2068
- existingAction = "override";
2069
- } else {
2070
- console.log(pc2.yellow(`${existingTargets.join(", ")} already exists. Use --force to override.`));
2071
- return;
2072
- }
2073
- } else {
2074
- existingAction = await promptExistingTarget(existingTargets.join(", "));
2075
- if (existingAction === "skip") {
2076
- console.log(pc2.yellow("Skipped. No changes made."));
2077
- return;
2078
- }
2079
- }
2110
+ existingAction = "override";
2080
2111
  }
2081
2112
  if (!isCurrentDir && fs9.existsSync(projectDir) && !options.force) {
2082
2113
  const files = fs9.readdirSync(projectDir);
@@ -2092,12 +2123,7 @@ async function initCommand(projectName, options) {
2092
2123
  return;
2093
2124
  }
2094
2125
  console.log(pc2.gray(`Source: ${source.path}`));
2095
- let kitName = options.kit;
2096
- if (!kitName && !options.force && !options.yes) {
2097
- kitName = await promptKit();
2098
- } else if (!kitName) {
2099
- kitName = "engineer";
2100
- }
2126
+ let kitName = options.kit || "full";
2101
2127
  const mergeMode = existingAction === "merge";
2102
2128
  let toInstall = {
2103
2129
  agents: [],
@@ -2152,12 +2178,6 @@ async function initCommand(projectName, options) {
2152
2178
  console.log(pc2.gray(` Commands: ${toInstall.commands.length}`));
2153
2179
  }
2154
2180
  console.log("");
2155
- if (!options.force && !options.yes) {
2156
- if (!await promptConfirm("Proceed?")) {
2157
- console.log(pc2.yellow("Cancelled."));
2158
- return;
2159
- }
2160
- }
2161
2181
  const spinner = ora("Creating project...").start();
2162
2182
  try {
2163
2183
  await fs9.ensureDir(projectDir);
@@ -2219,8 +2239,19 @@ async function initCommand(projectName, options) {
2219
2239
  openclawSetupSuccess = true;
2220
2240
  }
2221
2241
  }
2222
- if (source.agentsMd && cliTargets.includes("claude")) {
2223
- await copyAgentsMd(source.agentsMd, projectDir, mergeMode);
2242
+ if (cliTargets.includes("claude")) {
2243
+ if (source.agentsMd) {
2244
+ await copyAgentsMd(source.agentsMd, projectDir, mergeMode);
2245
+ }
2246
+ if (source.claudeMd) {
2247
+ await copyClaudeMd(source.claudeMd, projectDir, mergeMode);
2248
+ }
2249
+ if (source.geminiMd) {
2250
+ await copyGeminiMd(source.geminiMd, projectDir, mergeMode);
2251
+ }
2252
+ if (source.agentsDir) {
2253
+ await copyAgentsDir(source.agentsDir, projectDir, mergeMode);
2254
+ }
2224
2255
  }
2225
2256
  spinner.text = "Saving state...";
2226
2257
  await createInitialState(projectDir, {