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 +121 -90
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/AGENTS.md +61 -0
- package/templates/CLAUDE.md +93 -0
- package/templates/GEMINI.md +75 -0
- package/templates/codex/AGENTS.md +65 -0
- package/templates/codex/config.local.toml +17 -0
- package/templates/codex/config.toml +68 -4
- package/templates/gemini/GEMINI.md +44 -0
- package/templates/gemini/settings.json +68 -2
- package/templates/gemini/settings.local.json +51 -0
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
736
|
-
const
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
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
|
|
899
|
-
const
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
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 =
|
|
2084
|
+
cliTargets = ["claude"];
|
|
2041
2085
|
}
|
|
2042
2086
|
let discordConfig = null;
|
|
2043
2087
|
let openclawSetupSuccess = false;
|
|
2044
|
-
if (cliTargets.includes("discord") && process.stdin.isTTY
|
|
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
|
-
|
|
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 (
|
|
2223
|
-
|
|
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, {
|