claudekit-cli 3.2.0 → 3.3.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.
- package/bin/ck.js +6 -1
- package/dist/index.js +681 -264
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7159,19 +7159,29 @@ __export(exports_types, {
|
|
|
7159
7159
|
GitHubReleaseSchema: () => GitHubReleaseSchema,
|
|
7160
7160
|
GitHubReleaseAssetSchema: () => GitHubReleaseAssetSchema,
|
|
7161
7161
|
GitHubError: () => GitHubError,
|
|
7162
|
+
FoldersConfigSchema: () => FoldersConfigSchema,
|
|
7162
7163
|
ExtractionError: () => ExtractionError,
|
|
7163
7164
|
ExcludePatternSchema: () => ExcludePatternSchema,
|
|
7164
7165
|
DownloadError: () => DownloadError,
|
|
7166
|
+
DEFAULT_FOLDERS: () => DEFAULT_FOLDERS,
|
|
7165
7167
|
ConfigSchema: () => ConfigSchema,
|
|
7166
7168
|
ClaudeKitError: () => ClaudeKitError,
|
|
7167
7169
|
AuthenticationError: () => AuthenticationError,
|
|
7168
7170
|
AVAILABLE_KITS: () => AVAILABLE_KITS
|
|
7169
7171
|
});
|
|
7170
|
-
var KitType, ExcludePatternSchema, NewCommandOptionsSchema, UpdateCommandOptionsSchema, VersionCommandOptionsSchema, UninstallCommandOptionsSchema, UpdateCliOptionsSchema, TrackedFileSchema, MetadataSchema, ConfigSchema, GitHubReleaseAssetSchema, GitHubReleaseSchema, KitConfigSchema, AVAILABLE_KITS, NEVER_COPY_PATTERNS, USER_CONFIG_PATTERNS, PROTECTED_PATTERNS, ClaudeKitError, AuthenticationError, GitHubError, DownloadError, ExtractionError, SkillsManifestSchema, SkillsMigrationError;
|
|
7172
|
+
var KitType, ExcludePatternSchema, FoldersConfigSchema, DEFAULT_FOLDERS, NewCommandOptionsSchema, UpdateCommandOptionsSchema, VersionCommandOptionsSchema, UninstallCommandOptionsSchema, UpdateCliOptionsSchema, TrackedFileSchema, MetadataSchema, ConfigSchema, GitHubReleaseAssetSchema, GitHubReleaseSchema, KitConfigSchema, AVAILABLE_KITS, NEVER_COPY_PATTERNS, USER_CONFIG_PATTERNS, PROTECTED_PATTERNS, ClaudeKitError, AuthenticationError, GitHubError, DownloadError, ExtractionError, SkillsManifestSchema, SkillsMigrationError;
|
|
7171
7173
|
var init_types2 = __esm(() => {
|
|
7172
7174
|
init_zod();
|
|
7173
7175
|
KitType = exports_external.enum(["engineer", "marketing"]);
|
|
7174
7176
|
ExcludePatternSchema = exports_external.string().trim().min(1, "Exclude pattern cannot be empty").max(500, "Exclude pattern too long").refine((val) => !val.startsWith("/"), "Absolute paths not allowed in exclude patterns").refine((val) => !val.includes(".."), "Path traversal not allowed in exclude patterns");
|
|
7177
|
+
FoldersConfigSchema = exports_external.object({
|
|
7178
|
+
docs: exports_external.string().optional(),
|
|
7179
|
+
plans: exports_external.string().optional()
|
|
7180
|
+
});
|
|
7181
|
+
DEFAULT_FOLDERS = {
|
|
7182
|
+
docs: "docs",
|
|
7183
|
+
plans: "plans"
|
|
7184
|
+
};
|
|
7175
7185
|
NewCommandOptionsSchema = exports_external.object({
|
|
7176
7186
|
dir: exports_external.string().default("."),
|
|
7177
7187
|
kit: KitType.optional(),
|
|
@@ -7184,7 +7194,9 @@ var init_types2 = __esm(() => {
|
|
|
7184
7194
|
prefix: exports_external.boolean().default(false),
|
|
7185
7195
|
beta: exports_external.boolean().default(false),
|
|
7186
7196
|
dryRun: exports_external.boolean().default(false),
|
|
7187
|
-
refresh: exports_external.boolean().default(false)
|
|
7197
|
+
refresh: exports_external.boolean().default(false),
|
|
7198
|
+
docsDir: exports_external.string().optional(),
|
|
7199
|
+
plansDir: exports_external.string().optional()
|
|
7188
7200
|
});
|
|
7189
7201
|
UpdateCommandOptionsSchema = exports_external.object({
|
|
7190
7202
|
dir: exports_external.string().default("."),
|
|
@@ -7200,7 +7212,9 @@ var init_types2 = __esm(() => {
|
|
|
7200
7212
|
dryRun: exports_external.boolean().default(false),
|
|
7201
7213
|
forceOverwrite: exports_external.boolean().default(false),
|
|
7202
7214
|
skipSetup: exports_external.boolean().default(false),
|
|
7203
|
-
refresh: exports_external.boolean().default(false)
|
|
7215
|
+
refresh: exports_external.boolean().default(false),
|
|
7216
|
+
docsDir: exports_external.string().optional(),
|
|
7217
|
+
plansDir: exports_external.string().optional()
|
|
7204
7218
|
});
|
|
7205
7219
|
VersionCommandOptionsSchema = exports_external.object({
|
|
7206
7220
|
kit: KitType.optional(),
|
|
@@ -7241,7 +7255,8 @@ var init_types2 = __esm(() => {
|
|
|
7241
7255
|
defaults: exports_external.object({
|
|
7242
7256
|
kit: KitType.optional(),
|
|
7243
7257
|
dir: exports_external.string().optional()
|
|
7244
|
-
}).optional()
|
|
7258
|
+
}).optional(),
|
|
7259
|
+
folders: FoldersConfigSchema.optional()
|
|
7245
7260
|
});
|
|
7246
7261
|
GitHubReleaseAssetSchema = exports_external.object({
|
|
7247
7262
|
id: exports_external.number(),
|
|
@@ -11390,9 +11405,9 @@ async function installOpenCode() {
|
|
|
11390
11405
|
try {
|
|
11391
11406
|
logger.info(`Installing ${displayName}...`);
|
|
11392
11407
|
const { unlink: unlink2 } = await import("node:fs/promises");
|
|
11393
|
-
const { join:
|
|
11408
|
+
const { join: join26 } = await import("node:path");
|
|
11394
11409
|
const { tmpdir: tmpdir3 } = await import("node:os");
|
|
11395
|
-
const tempScriptPath =
|
|
11410
|
+
const tempScriptPath = join26(tmpdir3(), "opencode-install.sh");
|
|
11396
11411
|
try {
|
|
11397
11412
|
logger.info("Downloading OpenCode installation script...");
|
|
11398
11413
|
await execFileAsync("curl", ["-fsSL", "https://opencode.ai/install", "-o", tempScriptPath], {
|
|
@@ -11506,12 +11521,12 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
11506
11521
|
}
|
|
11507
11522
|
try {
|
|
11508
11523
|
const { existsSync: existsSync6 } = await import("node:fs");
|
|
11509
|
-
const { readFile:
|
|
11510
|
-
const { join:
|
|
11524
|
+
const { readFile: readFile13 } = await import("node:fs/promises");
|
|
11525
|
+
const { join: join26 } = await import("node:path");
|
|
11511
11526
|
const clack = await Promise.resolve().then(() => (init_dist2(), exports_dist));
|
|
11512
11527
|
const platform9 = process.platform;
|
|
11513
11528
|
const scriptName = platform9 === "win32" ? "install.ps1" : "install.sh";
|
|
11514
|
-
const scriptPath =
|
|
11529
|
+
const scriptPath = join26(skillsDir, scriptName);
|
|
11515
11530
|
try {
|
|
11516
11531
|
validateScriptPath(skillsDir, scriptPath);
|
|
11517
11532
|
} catch (error2) {
|
|
@@ -11527,7 +11542,7 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
11527
11542
|
logger.warning(`Skills installation script not found: ${scriptPath}`);
|
|
11528
11543
|
logger.info("");
|
|
11529
11544
|
logger.info("\uD83D\uDCD6 Manual Installation Instructions:");
|
|
11530
|
-
logger.info(` See: ${
|
|
11545
|
+
logger.info(` See: ${join26(skillsDir, "INSTALLATION.md")}`);
|
|
11531
11546
|
logger.info("");
|
|
11532
11547
|
logger.info("Quick start:");
|
|
11533
11548
|
logger.info(" cd .claude/skills/ai-multimodal/scripts");
|
|
@@ -11543,7 +11558,7 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
11543
11558
|
logger.info(` Platform: ${platform9 === "win32" ? "Windows (PowerShell)" : "Unix (bash)"}`);
|
|
11544
11559
|
logger.info("");
|
|
11545
11560
|
try {
|
|
11546
|
-
const scriptContent = await
|
|
11561
|
+
const scriptContent = await readFile13(scriptPath, "utf-8");
|
|
11547
11562
|
const previewLines = scriptContent.split(`
|
|
11548
11563
|
`).slice(0, 20);
|
|
11549
11564
|
logger.info("Script preview (first 20 lines):");
|
|
@@ -11571,7 +11586,7 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
11571
11586
|
logger.info(` ${platform9 === "win32" ? `powershell -File "${scriptPath}"` : `bash ${scriptPath}`}`);
|
|
11572
11587
|
logger.info("");
|
|
11573
11588
|
logger.info("Or see complete guide:");
|
|
11574
|
-
logger.info(` ${
|
|
11589
|
+
logger.info(` ${join26(skillsDir, "INSTALLATION.md")}`);
|
|
11575
11590
|
return {
|
|
11576
11591
|
success: false,
|
|
11577
11592
|
package: displayName,
|
|
@@ -11613,8 +11628,8 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
11613
11628
|
logger.info("\uD83D\uDCD6 Manual Installation Instructions:");
|
|
11614
11629
|
logger.info("");
|
|
11615
11630
|
logger.info("See complete guide:");
|
|
11616
|
-
const { join:
|
|
11617
|
-
logger.info(` cat ${
|
|
11631
|
+
const { join: join26 } = await import("node:path");
|
|
11632
|
+
logger.info(` cat ${join26(skillsDir, "INSTALLATION.md")}`);
|
|
11618
11633
|
logger.info("");
|
|
11619
11634
|
logger.info("Quick start:");
|
|
11620
11635
|
logger.info(" cd .claude/skills/ai-multimodal/scripts");
|
|
@@ -11734,6 +11749,21 @@ var init_help_commands = __esm(() => {
|
|
|
11734
11749
|
description: "Add /ck: prefix to all slash commands"
|
|
11735
11750
|
}
|
|
11736
11751
|
]
|
|
11752
|
+
},
|
|
11753
|
+
{
|
|
11754
|
+
title: "Folder Options",
|
|
11755
|
+
options: [
|
|
11756
|
+
{
|
|
11757
|
+
flags: "--docs-dir <name>",
|
|
11758
|
+
description: "Custom docs folder name to avoid conflicts with existing folders",
|
|
11759
|
+
defaultValue: "docs"
|
|
11760
|
+
},
|
|
11761
|
+
{
|
|
11762
|
+
flags: "--plans-dir <name>",
|
|
11763
|
+
description: "Custom plans folder name to avoid conflicts with existing folders",
|
|
11764
|
+
defaultValue: "plans"
|
|
11765
|
+
}
|
|
11766
|
+
]
|
|
11737
11767
|
}
|
|
11738
11768
|
]
|
|
11739
11769
|
};
|
|
@@ -11819,6 +11849,21 @@ var init_help_commands = __esm(() => {
|
|
|
11819
11849
|
description: "Override ownership protections and delete user-modified files"
|
|
11820
11850
|
}
|
|
11821
11851
|
]
|
|
11852
|
+
},
|
|
11853
|
+
{
|
|
11854
|
+
title: "Folder Options",
|
|
11855
|
+
options: [
|
|
11856
|
+
{
|
|
11857
|
+
flags: "--docs-dir <name>",
|
|
11858
|
+
description: "Custom docs folder name to avoid conflicts with existing folders",
|
|
11859
|
+
defaultValue: "docs"
|
|
11860
|
+
},
|
|
11861
|
+
{
|
|
11862
|
+
flags: "--plans-dir <name>",
|
|
11863
|
+
description: "Custom plans folder name to avoid conflicts with existing folders",
|
|
11864
|
+
defaultValue: "plans"
|
|
11865
|
+
}
|
|
11866
|
+
]
|
|
11822
11867
|
}
|
|
11823
11868
|
]
|
|
11824
11869
|
};
|
|
@@ -12149,7 +12194,7 @@ async function basicPager(content) {
|
|
|
12149
12194
|
});
|
|
12150
12195
|
rl.on("SIGINT", () => {
|
|
12151
12196
|
rl.close();
|
|
12152
|
-
process.
|
|
12197
|
+
process.exitCode = 0;
|
|
12153
12198
|
});
|
|
12154
12199
|
while (currentLine < lines.length) {
|
|
12155
12200
|
const pageLines = lines.slice(currentLine, currentLine + pageSize);
|
|
@@ -12164,7 +12209,9 @@ async function basicPager(content) {
|
|
|
12164
12209
|
rl.question(`-- More (${remaining} lines) [Enter/q] --`, (answer) => {
|
|
12165
12210
|
if (answer.toLowerCase() === "q") {
|
|
12166
12211
|
rl.close();
|
|
12167
|
-
process.
|
|
12212
|
+
process.exitCode = 0;
|
|
12213
|
+
resolve6();
|
|
12214
|
+
return;
|
|
12168
12215
|
}
|
|
12169
12216
|
process.stdout.write("\x1B[1A\x1B[2K");
|
|
12170
12217
|
resolve6();
|
|
@@ -12413,7 +12460,7 @@ async function handleHelp(_args) {
|
|
|
12413
12460
|
console.error("Error rendering help:", error2);
|
|
12414
12461
|
return;
|
|
12415
12462
|
}
|
|
12416
|
-
process.
|
|
12463
|
+
process.exitCode = 0;
|
|
12417
12464
|
}
|
|
12418
12465
|
function isHelpRequested(argv) {
|
|
12419
12466
|
return argv.includes("--help") || argv.includes("-h");
|
|
@@ -12426,7 +12473,7 @@ var init_help_interceptor = __esm(() => {
|
|
|
12426
12473
|
|
|
12427
12474
|
// src/index.ts
|
|
12428
12475
|
import { existsSync as existsSync7, readFileSync as readFileSync4 } from "fs";
|
|
12429
|
-
import { join as
|
|
12476
|
+
import { join as join31 } from "path";
|
|
12430
12477
|
|
|
12431
12478
|
// node_modules/cac/dist/index.mjs
|
|
12432
12479
|
import { EventEmitter } from "events";
|
|
@@ -13031,7 +13078,7 @@ var cac = (name = "") => new CAC(name);
|
|
|
13031
13078
|
// package.json
|
|
13032
13079
|
var package_default = {
|
|
13033
13080
|
name: "claudekit-cli",
|
|
13034
|
-
version: "3.
|
|
13081
|
+
version: "3.3.1",
|
|
13035
13082
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
13036
13083
|
type: "module",
|
|
13037
13084
|
repository: {
|
|
@@ -15850,8 +15897,8 @@ async function doctorCommand(options = {}) {
|
|
|
15850
15897
|
}
|
|
15851
15898
|
|
|
15852
15899
|
// src/commands/init.ts
|
|
15853
|
-
var
|
|
15854
|
-
import { join as
|
|
15900
|
+
var import_fs_extra17 = __toESM(require_lib(), 1);
|
|
15901
|
+
import { join as join26, resolve as resolve4 } from "node:path";
|
|
15855
15902
|
|
|
15856
15903
|
// src/lib/commands-prefix.ts
|
|
15857
15904
|
init_logger();
|
|
@@ -26439,6 +26486,7 @@ class DownloadManager {
|
|
|
26439
26486
|
"Thumbs.db",
|
|
26440
26487
|
"*.log"
|
|
26441
26488
|
];
|
|
26489
|
+
static tempDirCounter = 0;
|
|
26442
26490
|
totalExtractedSize = 0;
|
|
26443
26491
|
ig;
|
|
26444
26492
|
userExcludePatterns = [];
|
|
@@ -26876,7 +26924,8 @@ class DownloadManager {
|
|
|
26876
26924
|
}
|
|
26877
26925
|
async createTempDir() {
|
|
26878
26926
|
const timestamp = Date.now();
|
|
26879
|
-
const
|
|
26927
|
+
const counter = DownloadManager.tempDirCounter++;
|
|
26928
|
+
const primaryTempDir = join10(tmpdir2(), `claudekit-${timestamp}-${counter}`);
|
|
26880
26929
|
try {
|
|
26881
26930
|
await mkdir5(primaryTempDir, { recursive: true });
|
|
26882
26931
|
logger.debug(`Created temp directory: ${primaryTempDir}`);
|
|
@@ -26892,7 +26941,7 @@ Solutions:
|
|
|
26892
26941
|
2. Set HOME environment variable
|
|
26893
26942
|
3. Try running from a different directory`);
|
|
26894
26943
|
}
|
|
26895
|
-
const fallbackTempDir = join10(homeDir, ".claudekit", "tmp", `claudekit-${timestamp}`);
|
|
26944
|
+
const fallbackTempDir = join10(homeDir, ".claudekit", "tmp", `claudekit-${timestamp}-${counter}`);
|
|
26896
26945
|
try {
|
|
26897
26946
|
await mkdir5(fallbackTempDir, { recursive: true });
|
|
26898
26947
|
logger.debug(`Created temp directory (fallback): ${fallbackTempDir}`);
|
|
@@ -26925,13 +26974,235 @@ Solutions:
|
|
|
26925
26974
|
}
|
|
26926
26975
|
}
|
|
26927
26976
|
|
|
26928
|
-
// src/lib/
|
|
26977
|
+
// src/lib/folder-path-transformer.ts
|
|
26978
|
+
init_types2();
|
|
26929
26979
|
init_logger();
|
|
26930
26980
|
var import_fs_extra4 = __toESM(require_lib(), 1);
|
|
26931
|
-
import {
|
|
26981
|
+
import { readFile as readFile5, readdir as readdir3, rename, writeFile as writeFile4 } from "node:fs/promises";
|
|
26982
|
+
import { join as join11, relative as relative3 } from "node:path";
|
|
26983
|
+
var TRANSFORMABLE_FILE_PATTERNS = [
|
|
26984
|
+
".md",
|
|
26985
|
+
".txt",
|
|
26986
|
+
".json",
|
|
26987
|
+
".yaml",
|
|
26988
|
+
".yml",
|
|
26989
|
+
".toml",
|
|
26990
|
+
".sh",
|
|
26991
|
+
".bash",
|
|
26992
|
+
".zsh",
|
|
26993
|
+
".ps1",
|
|
26994
|
+
".ts",
|
|
26995
|
+
".js",
|
|
26996
|
+
".mjs",
|
|
26997
|
+
".cjs"
|
|
26998
|
+
];
|
|
26999
|
+
async function transformFolderPaths(extractDir, folders, options = {}) {
|
|
27000
|
+
const result = {
|
|
27001
|
+
foldersRenamed: 0,
|
|
27002
|
+
filesTransformed: 0,
|
|
27003
|
+
totalReferences: 0
|
|
27004
|
+
};
|
|
27005
|
+
const needsTransform = folders.docs !== DEFAULT_FOLDERS.docs || folders.plans !== DEFAULT_FOLDERS.plans;
|
|
27006
|
+
if (!needsTransform) {
|
|
27007
|
+
logger.debug("No folder transformation needed (using defaults)");
|
|
27008
|
+
return result;
|
|
27009
|
+
}
|
|
27010
|
+
logger.info("Transforming folder paths...");
|
|
27011
|
+
const replacements = new Map;
|
|
27012
|
+
if (folders.docs !== DEFAULT_FOLDERS.docs) {
|
|
27013
|
+
replacements.set(`${DEFAULT_FOLDERS.docs}/`, `${folders.docs}/`);
|
|
27014
|
+
replacements.set(`"${DEFAULT_FOLDERS.docs}"`, `"${folders.docs}"`);
|
|
27015
|
+
replacements.set(`'${DEFAULT_FOLDERS.docs}'`, `'${folders.docs}'`);
|
|
27016
|
+
replacements.set(`/${DEFAULT_FOLDERS.docs}`, `/${folders.docs}`);
|
|
27017
|
+
replacements.set(`./${DEFAULT_FOLDERS.docs}`, `./${folders.docs}`);
|
|
27018
|
+
}
|
|
27019
|
+
if (folders.plans !== DEFAULT_FOLDERS.plans) {
|
|
27020
|
+
replacements.set(`${DEFAULT_FOLDERS.plans}/`, `${folders.plans}/`);
|
|
27021
|
+
replacements.set(`"${DEFAULT_FOLDERS.plans}"`, `"${folders.plans}"`);
|
|
27022
|
+
replacements.set(`'${DEFAULT_FOLDERS.plans}'`, `'${folders.plans}'`);
|
|
27023
|
+
replacements.set(`/${DEFAULT_FOLDERS.plans}`, `/${folders.plans}`);
|
|
27024
|
+
replacements.set(`./${DEFAULT_FOLDERS.plans}`, `./${folders.plans}`);
|
|
27025
|
+
}
|
|
27026
|
+
const dirsToRename = [];
|
|
27027
|
+
if (folders.docs !== DEFAULT_FOLDERS.docs) {
|
|
27028
|
+
const docsPath = join11(extractDir, DEFAULT_FOLDERS.docs);
|
|
27029
|
+
if (await import_fs_extra4.pathExists(docsPath)) {
|
|
27030
|
+
dirsToRename.push({
|
|
27031
|
+
from: docsPath,
|
|
27032
|
+
to: join11(extractDir, folders.docs)
|
|
27033
|
+
});
|
|
27034
|
+
}
|
|
27035
|
+
const claudeDocsPath = join11(extractDir, ".claude", DEFAULT_FOLDERS.docs);
|
|
27036
|
+
if (await import_fs_extra4.pathExists(claudeDocsPath)) {
|
|
27037
|
+
dirsToRename.push({
|
|
27038
|
+
from: claudeDocsPath,
|
|
27039
|
+
to: join11(extractDir, ".claude", folders.docs)
|
|
27040
|
+
});
|
|
27041
|
+
}
|
|
27042
|
+
}
|
|
27043
|
+
if (folders.plans !== DEFAULT_FOLDERS.plans) {
|
|
27044
|
+
const plansPath = join11(extractDir, DEFAULT_FOLDERS.plans);
|
|
27045
|
+
if (await import_fs_extra4.pathExists(plansPath)) {
|
|
27046
|
+
dirsToRename.push({
|
|
27047
|
+
from: plansPath,
|
|
27048
|
+
to: join11(extractDir, folders.plans)
|
|
27049
|
+
});
|
|
27050
|
+
}
|
|
27051
|
+
const claudePlansPath = join11(extractDir, ".claude", DEFAULT_FOLDERS.plans);
|
|
27052
|
+
if (await import_fs_extra4.pathExists(claudePlansPath)) {
|
|
27053
|
+
dirsToRename.push({
|
|
27054
|
+
from: claudePlansPath,
|
|
27055
|
+
to: join11(extractDir, ".claude", folders.plans)
|
|
27056
|
+
});
|
|
27057
|
+
}
|
|
27058
|
+
}
|
|
27059
|
+
for (const { from, to } of dirsToRename) {
|
|
27060
|
+
if (options.dryRun) {
|
|
27061
|
+
logger.info(`[dry-run] Would rename: ${relative3(extractDir, from)} → ${relative3(extractDir, to)}`);
|
|
27062
|
+
} else {
|
|
27063
|
+
try {
|
|
27064
|
+
await rename(from, to);
|
|
27065
|
+
logger.debug(`Renamed: ${relative3(extractDir, from)} → ${relative3(extractDir, to)}`);
|
|
27066
|
+
result.foldersRenamed++;
|
|
27067
|
+
} catch (error2) {
|
|
27068
|
+
logger.warning(`Failed to rename ${from}: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
27069
|
+
}
|
|
27070
|
+
}
|
|
27071
|
+
}
|
|
27072
|
+
const compiledReplacements = [];
|
|
27073
|
+
for (const [search, replace3] of replacements) {
|
|
27074
|
+
compiledReplacements.push({
|
|
27075
|
+
regex: new RegExp(escapeRegExp(search), "g"),
|
|
27076
|
+
replacement: replace3
|
|
27077
|
+
});
|
|
27078
|
+
}
|
|
27079
|
+
const transformedFiles = await transformFileContents(extractDir, compiledReplacements, options);
|
|
27080
|
+
result.filesTransformed = transformedFiles.filesChanged;
|
|
27081
|
+
result.totalReferences = transformedFiles.replacementsCount;
|
|
27082
|
+
if (options.verbose) {
|
|
27083
|
+
logger.info(`Folder transformation complete: ${result.foldersRenamed} folders renamed, ` + `${result.filesTransformed} files updated, ${result.totalReferences} references changed`);
|
|
27084
|
+
}
|
|
27085
|
+
return result;
|
|
27086
|
+
}
|
|
27087
|
+
async function transformFileContents(dir, compiledReplacements, options) {
|
|
27088
|
+
let filesChanged = 0;
|
|
27089
|
+
let replacementsCount = 0;
|
|
27090
|
+
const entries = await readdir3(dir, { withFileTypes: true });
|
|
27091
|
+
for (const entry of entries) {
|
|
27092
|
+
const fullPath = join11(dir, entry.name);
|
|
27093
|
+
if (entry.isDirectory()) {
|
|
27094
|
+
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
27095
|
+
continue;
|
|
27096
|
+
}
|
|
27097
|
+
const subResult = await transformFileContents(fullPath, compiledReplacements, options);
|
|
27098
|
+
filesChanged += subResult.filesChanged;
|
|
27099
|
+
replacementsCount += subResult.replacementsCount;
|
|
27100
|
+
} else if (entry.isFile()) {
|
|
27101
|
+
const shouldTransform = TRANSFORMABLE_FILE_PATTERNS.some((ext) => entry.name.toLowerCase().endsWith(ext));
|
|
27102
|
+
if (!shouldTransform)
|
|
27103
|
+
continue;
|
|
27104
|
+
try {
|
|
27105
|
+
const content = await readFile5(fullPath, "utf-8");
|
|
27106
|
+
let newContent = content;
|
|
27107
|
+
let changeCount = 0;
|
|
27108
|
+
for (const { regex: regex2, replacement } of compiledReplacements) {
|
|
27109
|
+
regex2.lastIndex = 0;
|
|
27110
|
+
const matches = newContent.match(regex2);
|
|
27111
|
+
if (matches) {
|
|
27112
|
+
changeCount += matches.length;
|
|
27113
|
+
regex2.lastIndex = 0;
|
|
27114
|
+
newContent = newContent.replace(regex2, replacement);
|
|
27115
|
+
}
|
|
27116
|
+
}
|
|
27117
|
+
if (changeCount > 0) {
|
|
27118
|
+
if (options.dryRun) {
|
|
27119
|
+
logger.debug(`[dry-run] Would update ${relative3(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
27120
|
+
} else {
|
|
27121
|
+
await writeFile4(fullPath, newContent, "utf-8");
|
|
27122
|
+
logger.debug(`Updated ${relative3(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
27123
|
+
}
|
|
27124
|
+
filesChanged++;
|
|
27125
|
+
replacementsCount += changeCount;
|
|
27126
|
+
}
|
|
27127
|
+
} catch (error2) {
|
|
27128
|
+
if (error2.code !== "ENOENT") {
|
|
27129
|
+
logger.debug(`Skipped ${entry.name}: ${error2 instanceof Error ? error2.message : "Unknown"}`);
|
|
27130
|
+
}
|
|
27131
|
+
}
|
|
27132
|
+
}
|
|
27133
|
+
}
|
|
27134
|
+
return { filesChanged, replacementsCount };
|
|
27135
|
+
}
|
|
27136
|
+
function escapeRegExp(string) {
|
|
27137
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
27138
|
+
}
|
|
27139
|
+
function validateFolderOptions(options) {
|
|
27140
|
+
if (options.docsDir) {
|
|
27141
|
+
const docsError = validateFolderName(options.docsDir);
|
|
27142
|
+
if (docsError) {
|
|
27143
|
+
logger.error(`Invalid --docs-dir value: ${docsError}`);
|
|
27144
|
+
process.exit(1);
|
|
27145
|
+
}
|
|
27146
|
+
}
|
|
27147
|
+
if (options.plansDir) {
|
|
27148
|
+
const plansError = validateFolderName(options.plansDir);
|
|
27149
|
+
if (plansError) {
|
|
27150
|
+
logger.error(`Invalid --plans-dir value: ${plansError}`);
|
|
27151
|
+
process.exit(1);
|
|
27152
|
+
}
|
|
27153
|
+
}
|
|
27154
|
+
}
|
|
27155
|
+
function validateFolderName(name2) {
|
|
27156
|
+
if (!name2 || name2.trim().length === 0) {
|
|
27157
|
+
return "Folder name cannot be empty";
|
|
27158
|
+
}
|
|
27159
|
+
if (name2.includes("..") || name2.includes("/") || name2.includes("\\")) {
|
|
27160
|
+
return "Folder name cannot contain path separators or parent references";
|
|
27161
|
+
}
|
|
27162
|
+
const invalidChars = /[<>:"|?*\x00-\x1f]/;
|
|
27163
|
+
if (invalidChars.test(name2)) {
|
|
27164
|
+
return "Folder name contains invalid characters";
|
|
27165
|
+
}
|
|
27166
|
+
const reservedNames = [
|
|
27167
|
+
"CON",
|
|
27168
|
+
"PRN",
|
|
27169
|
+
"AUX",
|
|
27170
|
+
"NUL",
|
|
27171
|
+
"COM1",
|
|
27172
|
+
"COM2",
|
|
27173
|
+
"COM3",
|
|
27174
|
+
"COM4",
|
|
27175
|
+
"COM5",
|
|
27176
|
+
"COM6",
|
|
27177
|
+
"COM7",
|
|
27178
|
+
"COM8",
|
|
27179
|
+
"COM9",
|
|
27180
|
+
"LPT1",
|
|
27181
|
+
"LPT2",
|
|
27182
|
+
"LPT3",
|
|
27183
|
+
"LPT4",
|
|
27184
|
+
"LPT5",
|
|
27185
|
+
"LPT6",
|
|
27186
|
+
"LPT7",
|
|
27187
|
+
"LPT8",
|
|
27188
|
+
"LPT9"
|
|
27189
|
+
];
|
|
27190
|
+
if (reservedNames.includes(name2.toUpperCase())) {
|
|
27191
|
+
return "Folder name is a reserved system name";
|
|
27192
|
+
}
|
|
27193
|
+
if (name2.length > 255) {
|
|
27194
|
+
return "Folder name is too long (max 255 characters)";
|
|
27195
|
+
}
|
|
27196
|
+
return null;
|
|
27197
|
+
}
|
|
27198
|
+
|
|
27199
|
+
// src/lib/fresh-installer.ts
|
|
27200
|
+
init_logger();
|
|
27201
|
+
var import_fs_extra5 = __toESM(require_lib(), 1);
|
|
27202
|
+
import { join as join12 } from "node:path";
|
|
26932
27203
|
var CLAUDEKIT_SUBDIRECTORIES = ["commands", "agents", "skills", "workflows", "hooks"];
|
|
26933
27204
|
async function handleFreshInstallation(claudeDir, prompts) {
|
|
26934
|
-
if (!await
|
|
27205
|
+
if (!await import_fs_extra5.pathExists(claudeDir)) {
|
|
26935
27206
|
logger.info(".claude directory does not exist, proceeding with fresh installation");
|
|
26936
27207
|
return true;
|
|
26937
27208
|
}
|
|
@@ -26946,8 +27217,8 @@ async function handleFreshInstallation(claudeDir, prompts) {
|
|
|
26946
27217
|
const { rmSync } = await import("node:fs");
|
|
26947
27218
|
let removedCount = 0;
|
|
26948
27219
|
for (const subdir of CLAUDEKIT_SUBDIRECTORIES) {
|
|
26949
|
-
const subdirPath =
|
|
26950
|
-
if (await
|
|
27220
|
+
const subdirPath = join12(claudeDir, subdir);
|
|
27221
|
+
if (await import_fs_extra5.pathExists(subdirPath)) {
|
|
26951
27222
|
rmSync(subdirPath, { recursive: true, force: true });
|
|
26952
27223
|
removedCount++;
|
|
26953
27224
|
logger.debug(`Removed subdirectory: ${subdir}/`);
|
|
@@ -26963,9 +27234,9 @@ async function handleFreshInstallation(claudeDir, prompts) {
|
|
|
26963
27234
|
|
|
26964
27235
|
// src/lib/global-path-transformer.ts
|
|
26965
27236
|
init_logger();
|
|
26966
|
-
import { readFile as
|
|
27237
|
+
import { readFile as readFile6, readdir as readdir4, writeFile as writeFile5 } from "node:fs/promises";
|
|
26967
27238
|
import { platform as platform7 } from "node:os";
|
|
26968
|
-
import { extname, join as
|
|
27239
|
+
import { extname, join as join13 } from "node:path";
|
|
26969
27240
|
var IS_WINDOWS = platform7() === "win32";
|
|
26970
27241
|
var HOME_PREFIX = IS_WINDOWS ? "%USERPROFILE%" : "$HOME";
|
|
26971
27242
|
function getHomeDirPrefix() {
|
|
@@ -27055,9 +27326,9 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
27055
27326
|
let filesSkipped = 0;
|
|
27056
27327
|
const skippedFiles = [];
|
|
27057
27328
|
async function processDirectory(dir) {
|
|
27058
|
-
const entries = await
|
|
27329
|
+
const entries = await readdir4(dir, { withFileTypes: true });
|
|
27059
27330
|
for (const entry of entries) {
|
|
27060
|
-
const fullPath =
|
|
27331
|
+
const fullPath = join13(dir, entry.name);
|
|
27061
27332
|
if (entry.isDirectory()) {
|
|
27062
27333
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
27063
27334
|
continue;
|
|
@@ -27065,10 +27336,10 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
27065
27336
|
await processDirectory(fullPath);
|
|
27066
27337
|
} else if (entry.isFile() && shouldTransformFile(entry.name)) {
|
|
27067
27338
|
try {
|
|
27068
|
-
const content = await
|
|
27339
|
+
const content = await readFile6(fullPath, "utf-8");
|
|
27069
27340
|
const { transformed, changes } = transformContent(content);
|
|
27070
27341
|
if (changes > 0) {
|
|
27071
|
-
await
|
|
27342
|
+
await writeFile5(fullPath, transformed, "utf-8");
|
|
27072
27343
|
filesTransformed++;
|
|
27073
27344
|
totalChanges += changes;
|
|
27074
27345
|
if (options.verbose) {
|
|
@@ -27096,9 +27367,9 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
27096
27367
|
|
|
27097
27368
|
// src/lib/merge.ts
|
|
27098
27369
|
init_dist2();
|
|
27099
|
-
var
|
|
27370
|
+
var import_fs_extra6 = __toESM(require_lib(), 1);
|
|
27100
27371
|
var import_ignore2 = __toESM(require_ignore(), 1);
|
|
27101
|
-
import { dirname as dirname3, join as
|
|
27372
|
+
import { dirname as dirname3, join as join14, relative as relative4 } from "node:path";
|
|
27102
27373
|
|
|
27103
27374
|
// node_modules/@isaacs/balanced-match/dist/esm/index.js
|
|
27104
27375
|
var balanced = (a3, b3, str) => {
|
|
@@ -28572,10 +28843,10 @@ class FileMerger {
|
|
|
28572
28843
|
const conflicts = [];
|
|
28573
28844
|
const files = await this.getFiles(sourceDir, sourceDir);
|
|
28574
28845
|
for (const file of files) {
|
|
28575
|
-
const relativePath =
|
|
28846
|
+
const relativePath = relative4(sourceDir, file);
|
|
28576
28847
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
28577
|
-
const destPath =
|
|
28578
|
-
if (await
|
|
28848
|
+
const destPath = join14(destDir, relativePath);
|
|
28849
|
+
if (await import_fs_extra6.pathExists(destPath)) {
|
|
28579
28850
|
if (this.neverCopyChecker.ignores(normalizedRelativePath)) {
|
|
28580
28851
|
logger.debug(`Security-sensitive file exists but won't be overwritten: ${normalizedRelativePath}`);
|
|
28581
28852
|
continue;
|
|
@@ -28594,16 +28865,16 @@ class FileMerger {
|
|
|
28594
28865
|
let copiedCount = 0;
|
|
28595
28866
|
let skippedCount = 0;
|
|
28596
28867
|
for (const file of files) {
|
|
28597
|
-
const relativePath =
|
|
28868
|
+
const relativePath = relative4(sourceDir, file);
|
|
28598
28869
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
28599
|
-
const destPath =
|
|
28870
|
+
const destPath = join14(destDir, relativePath);
|
|
28600
28871
|
if (this.neverCopyChecker.ignores(normalizedRelativePath)) {
|
|
28601
28872
|
logger.debug(`Skipping security-sensitive file: ${normalizedRelativePath}`);
|
|
28602
28873
|
skippedCount++;
|
|
28603
28874
|
continue;
|
|
28604
28875
|
}
|
|
28605
28876
|
if (this.userConfigChecker.ignores(normalizedRelativePath)) {
|
|
28606
|
-
const fileExists = await
|
|
28877
|
+
const fileExists = await import_fs_extra6.pathExists(destPath);
|
|
28607
28878
|
if (fileExists) {
|
|
28608
28879
|
logger.debug(`Skipping existing user config file: ${normalizedRelativePath}`);
|
|
28609
28880
|
skippedCount++;
|
|
@@ -28617,7 +28888,7 @@ class FileMerger {
|
|
|
28617
28888
|
copiedCount++;
|
|
28618
28889
|
continue;
|
|
28619
28890
|
}
|
|
28620
|
-
await
|
|
28891
|
+
await import_fs_extra6.copy(file, destPath, { overwrite: true });
|
|
28621
28892
|
this.trackInstalledFile(normalizedRelativePath);
|
|
28622
28893
|
copiedCount++;
|
|
28623
28894
|
}
|
|
@@ -28625,7 +28896,7 @@ class FileMerger {
|
|
|
28625
28896
|
}
|
|
28626
28897
|
async processSettingsJson(sourceFile, destFile) {
|
|
28627
28898
|
try {
|
|
28628
|
-
const content = await
|
|
28899
|
+
const content = await import_fs_extra6.readFile(sourceFile, "utf-8");
|
|
28629
28900
|
const isWindows5 = process.platform === "win32";
|
|
28630
28901
|
let processedContent = content;
|
|
28631
28902
|
if (this.isGlobal) {
|
|
@@ -28640,20 +28911,20 @@ class FileMerger {
|
|
|
28640
28911
|
logger.debug("Converted Unix env var syntax to Windows syntax in settings.json");
|
|
28641
28912
|
}
|
|
28642
28913
|
}
|
|
28643
|
-
await
|
|
28914
|
+
await import_fs_extra6.writeFile(destFile, processedContent, "utf-8");
|
|
28644
28915
|
} catch (error2) {
|
|
28645
28916
|
logger.error(`Failed to process settings.json: ${error2}`);
|
|
28646
|
-
await
|
|
28917
|
+
await import_fs_extra6.copy(sourceFile, destFile, { overwrite: true });
|
|
28647
28918
|
}
|
|
28648
28919
|
}
|
|
28649
28920
|
async getFiles(dir, baseDir = dir) {
|
|
28650
28921
|
const files = [];
|
|
28651
|
-
const entries = await
|
|
28922
|
+
const entries = await import_fs_extra6.readdir(dir, { encoding: "utf8" });
|
|
28652
28923
|
for (const entry of entries) {
|
|
28653
|
-
const fullPath =
|
|
28654
|
-
const relativePath =
|
|
28924
|
+
const fullPath = join14(dir, entry);
|
|
28925
|
+
const relativePath = relative4(baseDir, fullPath);
|
|
28655
28926
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
28656
|
-
const stats = await
|
|
28927
|
+
const stats = await import_fs_extra6.lstat(fullPath);
|
|
28657
28928
|
if (stats.isSymbolicLink()) {
|
|
28658
28929
|
logger.warning(`Skipping symbolic link: ${normalizedRelativePath}`);
|
|
28659
28930
|
continue;
|
|
@@ -28711,15 +28982,15 @@ class FileMerger {
|
|
|
28711
28982
|
|
|
28712
28983
|
// src/lib/migration/legacy-migration.ts
|
|
28713
28984
|
init_logger();
|
|
28714
|
-
var
|
|
28715
|
-
import { readdir as
|
|
28716
|
-
import { join as
|
|
28985
|
+
var import_fs_extra8 = __toESM(require_lib(), 1);
|
|
28986
|
+
import { readdir as readdir6, stat as stat3 } from "node:fs/promises";
|
|
28987
|
+
import { join as join16, relative as relative5 } from "node:path";
|
|
28717
28988
|
|
|
28718
28989
|
// src/lib/migration/release-manifest.ts
|
|
28719
28990
|
init_zod();
|
|
28720
28991
|
init_logger();
|
|
28721
|
-
var
|
|
28722
|
-
import { join as
|
|
28992
|
+
var import_fs_extra7 = __toESM(require_lib(), 1);
|
|
28993
|
+
import { join as join15 } from "node:path";
|
|
28723
28994
|
var ReleaseManifestFileSchema = exports_external.object({
|
|
28724
28995
|
path: exports_external.string(),
|
|
28725
28996
|
checksum: exports_external.string().regex(/^[a-f0-9]{64}$/),
|
|
@@ -28733,9 +29004,9 @@ var ReleaseManifestSchema = exports_external.object({
|
|
|
28733
29004
|
|
|
28734
29005
|
class ReleaseManifestLoader {
|
|
28735
29006
|
static async load(extractDir) {
|
|
28736
|
-
const manifestPath =
|
|
29007
|
+
const manifestPath = join15(extractDir, "release-manifest.json");
|
|
28737
29008
|
try {
|
|
28738
|
-
const content = await
|
|
29009
|
+
const content = await import_fs_extra7.readFile(manifestPath, "utf-8");
|
|
28739
29010
|
const parsed = JSON.parse(content);
|
|
28740
29011
|
return ReleaseManifestSchema.parse(parsed);
|
|
28741
29012
|
} catch (error2) {
|
|
@@ -28764,7 +29035,7 @@ class LegacyMigration {
|
|
|
28764
29035
|
const files = [];
|
|
28765
29036
|
let entries;
|
|
28766
29037
|
try {
|
|
28767
|
-
entries = await
|
|
29038
|
+
entries = await readdir6(dir);
|
|
28768
29039
|
} catch (err) {
|
|
28769
29040
|
const error2 = err;
|
|
28770
29041
|
if (error2.code === "ENOENT") {
|
|
@@ -28779,7 +29050,7 @@ class LegacyMigration {
|
|
|
28779
29050
|
for (const entry of entries) {
|
|
28780
29051
|
if (entry === "metadata.json")
|
|
28781
29052
|
continue;
|
|
28782
|
-
const fullPath =
|
|
29053
|
+
const fullPath = join16(dir, entry);
|
|
28783
29054
|
let stats;
|
|
28784
29055
|
try {
|
|
28785
29056
|
stats = await stat3(fullPath);
|
|
@@ -28812,7 +29083,7 @@ class LegacyMigration {
|
|
|
28812
29083
|
};
|
|
28813
29084
|
const filesInManifest = [];
|
|
28814
29085
|
for (const file of files) {
|
|
28815
|
-
const relativePath =
|
|
29086
|
+
const relativePath = relative5(claudeDir, file).replace(/\\/g, "/");
|
|
28816
29087
|
const manifestEntry = ReleaseManifestLoader.findFile(manifest, relativePath);
|
|
28817
29088
|
if (!manifestEntry) {
|
|
28818
29089
|
preview.userCreated.push(relativePath);
|
|
@@ -28881,7 +29152,7 @@ User-created files (sample):`);
|
|
|
28881
29152
|
];
|
|
28882
29153
|
if (filesToChecksum.length > 0) {
|
|
28883
29154
|
const checksumResults = await Promise.all(filesToChecksum.map(async ({ relativePath, ownership }) => {
|
|
28884
|
-
const fullPath =
|
|
29155
|
+
const fullPath = join16(claudeDir, relativePath);
|
|
28885
29156
|
const checksum = await OwnershipChecker.calculateChecksum(fullPath);
|
|
28886
29157
|
return { relativePath, checksum, ownership };
|
|
28887
29158
|
}));
|
|
@@ -28902,8 +29173,8 @@ User-created files (sample):`);
|
|
|
28902
29173
|
installedAt: new Date().toISOString(),
|
|
28903
29174
|
files: trackedFiles
|
|
28904
29175
|
};
|
|
28905
|
-
const metadataPath =
|
|
28906
|
-
await
|
|
29176
|
+
const metadataPath = join16(claudeDir, "metadata.json");
|
|
29177
|
+
await import_fs_extra8.writeFile(metadataPath, JSON.stringify(updatedMetadata, null, 2));
|
|
28907
29178
|
logger.success(`Migration complete: tracked ${trackedFiles.length} files`);
|
|
28908
29179
|
return true;
|
|
28909
29180
|
}
|
|
@@ -29493,12 +29764,12 @@ class PromptsManager {
|
|
|
29493
29764
|
// src/lib/setup-wizard.ts
|
|
29494
29765
|
init_dist2();
|
|
29495
29766
|
init_logger();
|
|
29496
|
-
var
|
|
29497
|
-
import { join as
|
|
29767
|
+
var import_fs_extra10 = __toESM(require_lib(), 1);
|
|
29768
|
+
import { join as join18 } from "node:path";
|
|
29498
29769
|
|
|
29499
29770
|
// src/lib/config-generator.ts
|
|
29500
|
-
var
|
|
29501
|
-
import { join as
|
|
29771
|
+
var import_fs_extra9 = __toESM(require_lib(), 1);
|
|
29772
|
+
import { join as join17 } from "node:path";
|
|
29502
29773
|
async function generateEnvFile(targetDir, values) {
|
|
29503
29774
|
const lines = [
|
|
29504
29775
|
"# Generated by ClaudeKit CLI setup wizard",
|
|
@@ -29510,8 +29781,8 @@ async function generateEnvFile(targetDir, values) {
|
|
|
29510
29781
|
lines.push(`${key}=${value}`);
|
|
29511
29782
|
}
|
|
29512
29783
|
}
|
|
29513
|
-
const envPath =
|
|
29514
|
-
await
|
|
29784
|
+
const envPath = join17(targetDir, ".env");
|
|
29785
|
+
await import_fs_extra9.writeFile(envPath, `${lines.join(`
|
|
29515
29786
|
`)}
|
|
29516
29787
|
`, { mode: 384 });
|
|
29517
29788
|
}
|
|
@@ -29555,7 +29826,7 @@ var ESSENTIAL_CONFIGS = [
|
|
|
29555
29826
|
];
|
|
29556
29827
|
async function parseEnvFile(path9) {
|
|
29557
29828
|
try {
|
|
29558
|
-
const content = await
|
|
29829
|
+
const content = await import_fs_extra10.readFile(path9, "utf-8");
|
|
29559
29830
|
const env2 = {};
|
|
29560
29831
|
for (const line of content.split(`
|
|
29561
29832
|
`)) {
|
|
@@ -29581,8 +29852,8 @@ async function parseEnvFile(path9) {
|
|
|
29581
29852
|
}
|
|
29582
29853
|
}
|
|
29583
29854
|
async function checkGlobalConfig() {
|
|
29584
|
-
const globalEnvPath =
|
|
29585
|
-
if (!await
|
|
29855
|
+
const globalEnvPath = join18(PathResolver.getGlobalKitDir(), ".env");
|
|
29856
|
+
if (!await import_fs_extra10.pathExists(globalEnvPath))
|
|
29586
29857
|
return false;
|
|
29587
29858
|
const env2 = await parseEnvFile(globalEnvPath);
|
|
29588
29859
|
return Object.keys(env2).length > 0;
|
|
@@ -29597,8 +29868,8 @@ async function runSetupWizard(options) {
|
|
|
29597
29868
|
let globalEnv = {};
|
|
29598
29869
|
const hasGlobalConfig = !isGlobal && await checkGlobalConfig();
|
|
29599
29870
|
if (!isGlobal) {
|
|
29600
|
-
const globalEnvPath =
|
|
29601
|
-
if (await
|
|
29871
|
+
const globalEnvPath = join18(PathResolver.getGlobalKitDir(), ".env");
|
|
29872
|
+
if (await import_fs_extra10.pathExists(globalEnvPath)) {
|
|
29602
29873
|
globalEnv = await parseEnvFile(globalEnvPath);
|
|
29603
29874
|
}
|
|
29604
29875
|
}
|
|
@@ -29650,30 +29921,30 @@ async function runSetupWizard(options) {
|
|
|
29650
29921
|
}
|
|
29651
29922
|
}
|
|
29652
29923
|
await generateEnvFile(targetDir, values);
|
|
29653
|
-
f2.success(`Configuration saved to ${
|
|
29924
|
+
f2.success(`Configuration saved to ${join18(targetDir, ".env")}`);
|
|
29654
29925
|
return true;
|
|
29655
29926
|
}
|
|
29656
29927
|
|
|
29657
29928
|
// src/lib/skills-detector.ts
|
|
29658
29929
|
init_logger();
|
|
29659
|
-
var
|
|
29660
|
-
import { readdir as
|
|
29661
|
-
import { join as
|
|
29930
|
+
var import_fs_extra12 = __toESM(require_lib(), 1);
|
|
29931
|
+
import { readdir as readdir8 } from "node:fs/promises";
|
|
29932
|
+
import { join as join20 } from "node:path";
|
|
29662
29933
|
|
|
29663
29934
|
// src/lib/skills-manifest.ts
|
|
29664
29935
|
init_types2();
|
|
29665
29936
|
init_logger();
|
|
29666
|
-
var
|
|
29937
|
+
var import_fs_extra11 = __toESM(require_lib(), 1);
|
|
29667
29938
|
import { createHash as createHash2 } from "node:crypto";
|
|
29668
|
-
import { readFile as
|
|
29669
|
-
import { join as
|
|
29939
|
+
import { readFile as readFile10, readdir as readdir7, writeFile as writeFile9 } from "node:fs/promises";
|
|
29940
|
+
import { join as join19, relative as relative6 } from "node:path";
|
|
29670
29941
|
|
|
29671
29942
|
class SkillsManifestManager {
|
|
29672
29943
|
static MANIFEST_FILENAME = ".skills-manifest.json";
|
|
29673
29944
|
static MANIFEST_VERSION = "1.0.0";
|
|
29674
29945
|
static async generateManifest(skillsDir) {
|
|
29675
29946
|
logger.debug(`Generating manifest for: ${skillsDir}`);
|
|
29676
|
-
if (!await
|
|
29947
|
+
if (!await import_fs_extra11.pathExists(skillsDir)) {
|
|
29677
29948
|
throw new SkillsMigrationError(`Skills directory does not exist: ${skillsDir}`);
|
|
29678
29949
|
}
|
|
29679
29950
|
const structure = await SkillsManifestManager.detectStructure(skillsDir);
|
|
@@ -29688,18 +29959,18 @@ class SkillsManifestManager {
|
|
|
29688
29959
|
return manifest;
|
|
29689
29960
|
}
|
|
29690
29961
|
static async writeManifest(skillsDir, manifest) {
|
|
29691
|
-
const manifestPath =
|
|
29692
|
-
await
|
|
29962
|
+
const manifestPath = join19(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
29963
|
+
await writeFile9(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
29693
29964
|
logger.debug(`Wrote manifest to: ${manifestPath}`);
|
|
29694
29965
|
}
|
|
29695
29966
|
static async readManifest(skillsDir) {
|
|
29696
|
-
const manifestPath =
|
|
29697
|
-
if (!await
|
|
29967
|
+
const manifestPath = join19(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
29968
|
+
if (!await import_fs_extra11.pathExists(manifestPath)) {
|
|
29698
29969
|
logger.debug(`No manifest found at: ${manifestPath}`);
|
|
29699
29970
|
return null;
|
|
29700
29971
|
}
|
|
29701
29972
|
try {
|
|
29702
|
-
const content = await
|
|
29973
|
+
const content = await readFile10(manifestPath, "utf-8");
|
|
29703
29974
|
const data = JSON.parse(content);
|
|
29704
29975
|
const manifest = SkillsManifestSchema.parse(data);
|
|
29705
29976
|
logger.debug(`Read manifest from: ${manifestPath}`);
|
|
@@ -29710,14 +29981,14 @@ class SkillsManifestManager {
|
|
|
29710
29981
|
}
|
|
29711
29982
|
}
|
|
29712
29983
|
static async detectStructure(skillsDir) {
|
|
29713
|
-
const entries = await
|
|
29984
|
+
const entries = await readdir7(skillsDir, { withFileTypes: true });
|
|
29714
29985
|
const dirs = entries.filter((entry) => entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith("."));
|
|
29715
29986
|
if (dirs.length === 0) {
|
|
29716
29987
|
return "flat";
|
|
29717
29988
|
}
|
|
29718
29989
|
for (const dir of dirs.slice(0, 3)) {
|
|
29719
|
-
const dirPath =
|
|
29720
|
-
const subEntries = await
|
|
29990
|
+
const dirPath = join19(skillsDir, dir.name);
|
|
29991
|
+
const subEntries = await readdir7(dirPath, { withFileTypes: true });
|
|
29721
29992
|
const hasSubdirs = subEntries.some((entry) => entry.isDirectory());
|
|
29722
29993
|
if (hasSubdirs) {
|
|
29723
29994
|
return "categorized";
|
|
@@ -29732,10 +30003,10 @@ class SkillsManifestManager {
|
|
|
29732
30003
|
static async scanSkills(skillsDir, structure) {
|
|
29733
30004
|
const skills = [];
|
|
29734
30005
|
if (structure === "flat") {
|
|
29735
|
-
const entries = await
|
|
30006
|
+
const entries = await readdir7(skillsDir, { withFileTypes: true });
|
|
29736
30007
|
for (const entry of entries) {
|
|
29737
30008
|
if (entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith(".")) {
|
|
29738
|
-
const skillPath =
|
|
30009
|
+
const skillPath = join19(skillsDir, entry.name);
|
|
29739
30010
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
29740
30011
|
skills.push({
|
|
29741
30012
|
name: entry.name,
|
|
@@ -29744,14 +30015,14 @@ class SkillsManifestManager {
|
|
|
29744
30015
|
}
|
|
29745
30016
|
}
|
|
29746
30017
|
} else {
|
|
29747
|
-
const categories = await
|
|
30018
|
+
const categories = await readdir7(skillsDir, { withFileTypes: true });
|
|
29748
30019
|
for (const category of categories) {
|
|
29749
30020
|
if (category.isDirectory() && category.name !== "node_modules" && !category.name.startsWith(".")) {
|
|
29750
|
-
const categoryPath =
|
|
29751
|
-
const skillEntries = await
|
|
30021
|
+
const categoryPath = join19(skillsDir, category.name);
|
|
30022
|
+
const skillEntries = await readdir7(categoryPath, { withFileTypes: true });
|
|
29752
30023
|
for (const skillEntry of skillEntries) {
|
|
29753
30024
|
if (skillEntry.isDirectory() && !skillEntry.name.startsWith(".")) {
|
|
29754
|
-
const skillPath =
|
|
30025
|
+
const skillPath = join19(categoryPath, skillEntry.name);
|
|
29755
30026
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
29756
30027
|
skills.push({
|
|
29757
30028
|
name: skillEntry.name,
|
|
@@ -29770,8 +30041,8 @@ class SkillsManifestManager {
|
|
|
29770
30041
|
const files = await SkillsManifestManager.getAllFiles(dirPath);
|
|
29771
30042
|
files.sort();
|
|
29772
30043
|
for (const file of files) {
|
|
29773
|
-
const relativePath =
|
|
29774
|
-
const content = await
|
|
30044
|
+
const relativePath = relative6(dirPath, file);
|
|
30045
|
+
const content = await readFile10(file);
|
|
29775
30046
|
hash.update(relativePath);
|
|
29776
30047
|
hash.update(content);
|
|
29777
30048
|
}
|
|
@@ -29779,9 +30050,9 @@ class SkillsManifestManager {
|
|
|
29779
30050
|
}
|
|
29780
30051
|
static async getAllFiles(dirPath) {
|
|
29781
30052
|
const files = [];
|
|
29782
|
-
const entries = await
|
|
30053
|
+
const entries = await readdir7(dirPath, { withFileTypes: true });
|
|
29783
30054
|
for (const entry of entries) {
|
|
29784
|
-
const fullPath =
|
|
30055
|
+
const fullPath = join19(dirPath, entry.name);
|
|
29785
30056
|
if (entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
29786
30057
|
continue;
|
|
29787
30058
|
}
|
|
@@ -29901,8 +30172,8 @@ function getPathMapping(skillName, oldBasePath, newBasePath) {
|
|
|
29901
30172
|
class SkillsMigrationDetector {
|
|
29902
30173
|
static async detectMigration(oldSkillsDir, currentSkillsDir) {
|
|
29903
30174
|
logger.debug("Detecting skills migration need...");
|
|
29904
|
-
const oldExists = await
|
|
29905
|
-
const currentExists = await
|
|
30175
|
+
const oldExists = await import_fs_extra12.pathExists(oldSkillsDir);
|
|
30176
|
+
const currentExists = await import_fs_extra12.pathExists(currentSkillsDir);
|
|
29906
30177
|
if (!oldExists && !currentExists) {
|
|
29907
30178
|
logger.debug("No skills directories found, migration not needed");
|
|
29908
30179
|
return {
|
|
@@ -30013,10 +30284,10 @@ class SkillsMigrationDetector {
|
|
|
30013
30284
|
};
|
|
30014
30285
|
}
|
|
30015
30286
|
static async scanDirectory(skillsDir) {
|
|
30016
|
-
if (!await
|
|
30287
|
+
if (!await import_fs_extra12.pathExists(skillsDir)) {
|
|
30017
30288
|
return ["flat", []];
|
|
30018
30289
|
}
|
|
30019
|
-
const entries = await
|
|
30290
|
+
const entries = await readdir8(skillsDir, { withFileTypes: true });
|
|
30020
30291
|
const dirs = entries.filter((entry) => entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith("."));
|
|
30021
30292
|
if (dirs.length === 0) {
|
|
30022
30293
|
return ["flat", []];
|
|
@@ -30024,13 +30295,13 @@ class SkillsMigrationDetector {
|
|
|
30024
30295
|
let totalSkillLikeCount = 0;
|
|
30025
30296
|
const allSkills = [];
|
|
30026
30297
|
for (const dir of dirs) {
|
|
30027
|
-
const dirPath =
|
|
30028
|
-
const subEntries = await
|
|
30298
|
+
const dirPath = join20(skillsDir, dir.name);
|
|
30299
|
+
const subEntries = await readdir8(dirPath, { withFileTypes: true });
|
|
30029
30300
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
30030
30301
|
if (subdirs.length > 0) {
|
|
30031
30302
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
30032
|
-
const subdirPath =
|
|
30033
|
-
const subdirFiles = await
|
|
30303
|
+
const subdirPath = join20(dirPath, subdir.name);
|
|
30304
|
+
const subdirFiles = await readdir8(subdirPath, { withFileTypes: true });
|
|
30034
30305
|
const hasSkillMarker = subdirFiles.some((file) => file.isFile() && (file.name === "skill.md" || file.name === "README.md" || file.name === "readme.md" || file.name === "config.json" || file.name === "package.json"));
|
|
30035
30306
|
if (hasSkillMarker) {
|
|
30036
30307
|
totalSkillLikeCount++;
|
|
@@ -30066,16 +30337,16 @@ class SkillsMigrationDetector {
|
|
|
30066
30337
|
// src/lib/skills-migrator.ts
|
|
30067
30338
|
init_types2();
|
|
30068
30339
|
init_logger();
|
|
30069
|
-
var
|
|
30070
|
-
import { copyFile as copyFile2, mkdir as mkdir7, readdir as
|
|
30071
|
-
import { join as
|
|
30340
|
+
var import_fs_extra15 = __toESM(require_lib(), 1);
|
|
30341
|
+
import { copyFile as copyFile2, mkdir as mkdir7, readdir as readdir11, rm as rm2 } from "node:fs/promises";
|
|
30342
|
+
import { join as join23 } from "node:path";
|
|
30072
30343
|
|
|
30073
30344
|
// src/lib/skills-backup-manager.ts
|
|
30074
30345
|
init_types2();
|
|
30075
30346
|
init_logger();
|
|
30076
|
-
var
|
|
30077
|
-
import { copyFile, mkdir as mkdir6, readdir as
|
|
30078
|
-
import { basename as basename2, join as
|
|
30347
|
+
var import_fs_extra13 = __toESM(require_lib(), 1);
|
|
30348
|
+
import { copyFile, mkdir as mkdir6, readdir as readdir9, rm, stat as stat4 } from "node:fs/promises";
|
|
30349
|
+
import { basename as basename2, join as join21, normalize as normalize2 } from "node:path";
|
|
30079
30350
|
function validatePath2(path9, paramName) {
|
|
30080
30351
|
if (!path9 || typeof path9 !== "string") {
|
|
30081
30352
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -30095,13 +30366,13 @@ class SkillsBackupManager {
|
|
|
30095
30366
|
if (parentDir) {
|
|
30096
30367
|
validatePath2(parentDir, "parentDir");
|
|
30097
30368
|
}
|
|
30098
|
-
if (!await
|
|
30369
|
+
if (!await import_fs_extra13.pathExists(skillsDir)) {
|
|
30099
30370
|
throw new SkillsMigrationError(`Cannot create backup: Skills directory does not exist: ${skillsDir}`);
|
|
30100
30371
|
}
|
|
30101
30372
|
const timestamp = Date.now();
|
|
30102
30373
|
const randomSuffix = Math.random().toString(36).substring(2, 8);
|
|
30103
30374
|
const backupDirName = `${SkillsBackupManager.BACKUP_PREFIX}${timestamp}-${randomSuffix}`;
|
|
30104
|
-
const backupDir = parentDir ?
|
|
30375
|
+
const backupDir = parentDir ? join21(parentDir, backupDirName) : join21(skillsDir, "..", backupDirName);
|
|
30105
30376
|
logger.info(`Creating backup at: ${backupDir}`);
|
|
30106
30377
|
try {
|
|
30107
30378
|
await mkdir6(backupDir, { recursive: true });
|
|
@@ -30118,12 +30389,12 @@ class SkillsBackupManager {
|
|
|
30118
30389
|
static async restoreBackup(backupDir, targetDir) {
|
|
30119
30390
|
validatePath2(backupDir, "backupDir");
|
|
30120
30391
|
validatePath2(targetDir, "targetDir");
|
|
30121
|
-
if (!await
|
|
30392
|
+
if (!await import_fs_extra13.pathExists(backupDir)) {
|
|
30122
30393
|
throw new SkillsMigrationError(`Cannot restore: Backup directory does not exist: ${backupDir}`);
|
|
30123
30394
|
}
|
|
30124
30395
|
logger.info(`Restoring from backup: ${backupDir}`);
|
|
30125
30396
|
try {
|
|
30126
|
-
if (await
|
|
30397
|
+
if (await import_fs_extra13.pathExists(targetDir)) {
|
|
30127
30398
|
await rm(targetDir, { recursive: true, force: true });
|
|
30128
30399
|
}
|
|
30129
30400
|
await mkdir6(targetDir, { recursive: true });
|
|
@@ -30134,7 +30405,7 @@ class SkillsBackupManager {
|
|
|
30134
30405
|
}
|
|
30135
30406
|
}
|
|
30136
30407
|
static async deleteBackup(backupDir) {
|
|
30137
|
-
if (!await
|
|
30408
|
+
if (!await import_fs_extra13.pathExists(backupDir)) {
|
|
30138
30409
|
logger.warning(`Backup directory does not exist: ${backupDir}`);
|
|
30139
30410
|
return;
|
|
30140
30411
|
}
|
|
@@ -30147,12 +30418,12 @@ class SkillsBackupManager {
|
|
|
30147
30418
|
}
|
|
30148
30419
|
}
|
|
30149
30420
|
static async listBackups(parentDir) {
|
|
30150
|
-
if (!await
|
|
30421
|
+
if (!await import_fs_extra13.pathExists(parentDir)) {
|
|
30151
30422
|
return [];
|
|
30152
30423
|
}
|
|
30153
30424
|
try {
|
|
30154
|
-
const entries = await
|
|
30155
|
-
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) =>
|
|
30425
|
+
const entries = await readdir9(parentDir, { withFileTypes: true });
|
|
30426
|
+
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) => join21(parentDir, entry.name));
|
|
30156
30427
|
backups.sort().reverse();
|
|
30157
30428
|
return backups;
|
|
30158
30429
|
} catch (error2) {
|
|
@@ -30172,16 +30443,16 @@ class SkillsBackupManager {
|
|
|
30172
30443
|
}
|
|
30173
30444
|
}
|
|
30174
30445
|
static async getBackupSize(backupDir) {
|
|
30175
|
-
if (!await
|
|
30446
|
+
if (!await import_fs_extra13.pathExists(backupDir)) {
|
|
30176
30447
|
return 0;
|
|
30177
30448
|
}
|
|
30178
30449
|
return await SkillsBackupManager.getDirectorySize(backupDir);
|
|
30179
30450
|
}
|
|
30180
30451
|
static async copyDirectory(sourceDir, destDir) {
|
|
30181
|
-
const entries = await
|
|
30452
|
+
const entries = await readdir9(sourceDir, { withFileTypes: true });
|
|
30182
30453
|
for (const entry of entries) {
|
|
30183
|
-
const sourcePath =
|
|
30184
|
-
const destPath =
|
|
30454
|
+
const sourcePath = join21(sourceDir, entry.name);
|
|
30455
|
+
const destPath = join21(destDir, entry.name);
|
|
30185
30456
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
30186
30457
|
continue;
|
|
30187
30458
|
}
|
|
@@ -30195,9 +30466,9 @@ class SkillsBackupManager {
|
|
|
30195
30466
|
}
|
|
30196
30467
|
static async getDirectorySize(dirPath) {
|
|
30197
30468
|
let size = 0;
|
|
30198
|
-
const entries = await
|
|
30469
|
+
const entries = await readdir9(dirPath, { withFileTypes: true });
|
|
30199
30470
|
for (const entry of entries) {
|
|
30200
|
-
const fullPath =
|
|
30471
|
+
const fullPath = join21(dirPath, entry.name);
|
|
30201
30472
|
if (entry.isSymbolicLink()) {
|
|
30202
30473
|
continue;
|
|
30203
30474
|
}
|
|
@@ -30224,11 +30495,11 @@ class SkillsBackupManager {
|
|
|
30224
30495
|
// src/lib/skills-customization-scanner.ts
|
|
30225
30496
|
init_types2();
|
|
30226
30497
|
init_logger();
|
|
30227
|
-
var
|
|
30498
|
+
var import_fs_extra14 = __toESM(require_lib(), 1);
|
|
30228
30499
|
import { createHash as createHash3 } from "node:crypto";
|
|
30229
30500
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
30230
|
-
import { readFile as
|
|
30231
|
-
import { join as
|
|
30501
|
+
import { readFile as readFile11, readdir as readdir10 } from "node:fs/promises";
|
|
30502
|
+
import { join as join22, normalize as normalize3, relative as relative7 } from "node:path";
|
|
30232
30503
|
function validatePath3(path9, paramName) {
|
|
30233
30504
|
if (!path9 || typeof path9 !== "string") {
|
|
30234
30505
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -30307,14 +30578,14 @@ class SkillsCustomizationScanner {
|
|
|
30307
30578
|
static async detectFileChanges(currentSkillPath, baselineSkillPath) {
|
|
30308
30579
|
const changes = [];
|
|
30309
30580
|
const currentFiles = await SkillsCustomizationScanner.getAllFiles(currentSkillPath);
|
|
30310
|
-
const baselineFiles = await
|
|
30581
|
+
const baselineFiles = await import_fs_extra14.pathExists(baselineSkillPath) ? await SkillsCustomizationScanner.getAllFiles(baselineSkillPath) : [];
|
|
30311
30582
|
const currentFileMap = new Map(await Promise.all(currentFiles.map(async (f3) => {
|
|
30312
|
-
const relPath =
|
|
30583
|
+
const relPath = relative7(currentSkillPath, f3);
|
|
30313
30584
|
const hash = await SkillsCustomizationScanner.hashFile(f3);
|
|
30314
30585
|
return [relPath, hash];
|
|
30315
30586
|
})));
|
|
30316
30587
|
const baselineFileMap = new Map(await Promise.all(baselineFiles.map(async (f3) => {
|
|
30317
|
-
const relPath =
|
|
30588
|
+
const relPath = relative7(baselineSkillPath, f3);
|
|
30318
30589
|
const hash = await SkillsCustomizationScanner.hashFile(f3);
|
|
30319
30590
|
return [relPath, hash];
|
|
30320
30591
|
})));
|
|
@@ -30352,8 +30623,8 @@ class SkillsCustomizationScanner {
|
|
|
30352
30623
|
if (files1.length !== files2.length) {
|
|
30353
30624
|
return true;
|
|
30354
30625
|
}
|
|
30355
|
-
const relFiles1 = files1.map((f3) =>
|
|
30356
|
-
const relFiles2 = files2.map((f3) =>
|
|
30626
|
+
const relFiles1 = files1.map((f3) => relative7(dir1, f3)).sort();
|
|
30627
|
+
const relFiles2 = files2.map((f3) => relative7(dir2, f3)).sort();
|
|
30357
30628
|
if (JSON.stringify(relFiles1) !== JSON.stringify(relFiles2)) {
|
|
30358
30629
|
return true;
|
|
30359
30630
|
}
|
|
@@ -30367,22 +30638,22 @@ class SkillsCustomizationScanner {
|
|
|
30367
30638
|
return false;
|
|
30368
30639
|
}
|
|
30369
30640
|
static async scanSkillsDirectory(skillsDir) {
|
|
30370
|
-
if (!await
|
|
30641
|
+
if (!await import_fs_extra14.pathExists(skillsDir)) {
|
|
30371
30642
|
return ["flat", []];
|
|
30372
30643
|
}
|
|
30373
|
-
const entries = await
|
|
30644
|
+
const entries = await readdir10(skillsDir, { withFileTypes: true });
|
|
30374
30645
|
const dirs = entries.filter((entry) => entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith("."));
|
|
30375
30646
|
if (dirs.length === 0) {
|
|
30376
30647
|
return ["flat", []];
|
|
30377
30648
|
}
|
|
30378
|
-
const firstDirPath =
|
|
30379
|
-
const subEntries = await
|
|
30649
|
+
const firstDirPath = join22(skillsDir, dirs[0].name);
|
|
30650
|
+
const subEntries = await readdir10(firstDirPath, { withFileTypes: true });
|
|
30380
30651
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
30381
30652
|
if (subdirs.length > 0) {
|
|
30382
30653
|
let skillLikeCount = 0;
|
|
30383
30654
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
30384
|
-
const subdirPath =
|
|
30385
|
-
const subdirFiles = await
|
|
30655
|
+
const subdirPath = join22(firstDirPath, subdir.name);
|
|
30656
|
+
const subdirFiles = await readdir10(subdirPath, { withFileTypes: true });
|
|
30386
30657
|
const hasSkillMarker = subdirFiles.some((file) => file.isFile() && (file.name === "skill.md" || file.name === "README.md" || file.name === "readme.md" || file.name === "config.json" || file.name === "package.json"));
|
|
30387
30658
|
if (hasSkillMarker) {
|
|
30388
30659
|
skillLikeCount++;
|
|
@@ -30391,8 +30662,8 @@ class SkillsCustomizationScanner {
|
|
|
30391
30662
|
if (skillLikeCount > 0) {
|
|
30392
30663
|
const skills = [];
|
|
30393
30664
|
for (const dir of dirs) {
|
|
30394
|
-
const categoryPath =
|
|
30395
|
-
const skillDirs = await
|
|
30665
|
+
const categoryPath = join22(skillsDir, dir.name);
|
|
30666
|
+
const skillDirs = await readdir10(categoryPath, { withFileTypes: true });
|
|
30396
30667
|
skills.push(...skillDirs.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name));
|
|
30397
30668
|
}
|
|
30398
30669
|
return ["categorized", skills];
|
|
@@ -30401,18 +30672,18 @@ class SkillsCustomizationScanner {
|
|
|
30401
30672
|
return ["flat", dirs.map((dir) => dir.name)];
|
|
30402
30673
|
}
|
|
30403
30674
|
static async findSkillPath(skillsDir, skillName) {
|
|
30404
|
-
const flatPath =
|
|
30405
|
-
if (await
|
|
30675
|
+
const flatPath = join22(skillsDir, skillName);
|
|
30676
|
+
if (await import_fs_extra14.pathExists(flatPath)) {
|
|
30406
30677
|
return { path: flatPath, category: undefined };
|
|
30407
30678
|
}
|
|
30408
|
-
const entries = await
|
|
30679
|
+
const entries = await readdir10(skillsDir, { withFileTypes: true });
|
|
30409
30680
|
for (const entry of entries) {
|
|
30410
30681
|
if (!entry.isDirectory() || entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
30411
30682
|
continue;
|
|
30412
30683
|
}
|
|
30413
|
-
const categoryPath =
|
|
30414
|
-
const skillPath =
|
|
30415
|
-
if (await
|
|
30684
|
+
const categoryPath = join22(skillsDir, entry.name);
|
|
30685
|
+
const skillPath = join22(categoryPath, skillName);
|
|
30686
|
+
if (await import_fs_extra14.pathExists(skillPath)) {
|
|
30416
30687
|
return { path: skillPath, category: entry.name };
|
|
30417
30688
|
}
|
|
30418
30689
|
}
|
|
@@ -30420,9 +30691,9 @@ class SkillsCustomizationScanner {
|
|
|
30420
30691
|
}
|
|
30421
30692
|
static async getAllFiles(dirPath) {
|
|
30422
30693
|
const files = [];
|
|
30423
|
-
const entries = await
|
|
30694
|
+
const entries = await readdir10(dirPath, { withFileTypes: true });
|
|
30424
30695
|
for (const entry of entries) {
|
|
30425
|
-
const fullPath =
|
|
30696
|
+
const fullPath = join22(dirPath, entry.name);
|
|
30426
30697
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
30427
30698
|
continue;
|
|
30428
30699
|
}
|
|
@@ -30454,8 +30725,8 @@ class SkillsCustomizationScanner {
|
|
|
30454
30725
|
const files = await SkillsCustomizationScanner.getAllFiles(dirPath);
|
|
30455
30726
|
files.sort();
|
|
30456
30727
|
for (const file of files) {
|
|
30457
|
-
const relativePath =
|
|
30458
|
-
const content = await
|
|
30728
|
+
const relativePath = relative7(dirPath, file);
|
|
30729
|
+
const content = await readFile11(file);
|
|
30459
30730
|
hash.update(relativePath);
|
|
30460
30731
|
hash.update(content);
|
|
30461
30732
|
}
|
|
@@ -30665,7 +30936,7 @@ class SkillsMigrator {
|
|
|
30665
30936
|
}
|
|
30666
30937
|
}
|
|
30667
30938
|
if (options.backup && !options.dryRun) {
|
|
30668
|
-
const claudeDir =
|
|
30939
|
+
const claudeDir = join23(currentSkillsDir, "..");
|
|
30669
30940
|
result.backupPath = await SkillsBackupManager.createBackup(currentSkillsDir, claudeDir);
|
|
30670
30941
|
logger.success(`Backup created at: ${result.backupPath}`);
|
|
30671
30942
|
}
|
|
@@ -30717,14 +30988,14 @@ class SkillsMigrator {
|
|
|
30717
30988
|
const migrated = [];
|
|
30718
30989
|
const preserved = [];
|
|
30719
30990
|
const errors2 = [];
|
|
30720
|
-
const tempDir =
|
|
30991
|
+
const tempDir = join23(currentSkillsDir, "..", ".skills-migration-temp");
|
|
30721
30992
|
await mkdir7(tempDir, { recursive: true });
|
|
30722
30993
|
try {
|
|
30723
30994
|
for (const mapping of mappings) {
|
|
30724
30995
|
try {
|
|
30725
30996
|
const skillName = mapping.skillName;
|
|
30726
30997
|
const currentSkillPath = mapping.oldPath;
|
|
30727
|
-
if (!await
|
|
30998
|
+
if (!await import_fs_extra15.pathExists(currentSkillPath)) {
|
|
30728
30999
|
logger.warning(`Skill not found, skipping: ${skillName}`);
|
|
30729
31000
|
continue;
|
|
30730
31001
|
}
|
|
@@ -30738,9 +31009,9 @@ class SkillsMigrator {
|
|
|
30738
31009
|
}
|
|
30739
31010
|
}
|
|
30740
31011
|
const category = mapping.category;
|
|
30741
|
-
const targetPath = category ?
|
|
31012
|
+
const targetPath = category ? join23(tempDir, category, skillName) : join23(tempDir, skillName);
|
|
30742
31013
|
if (category) {
|
|
30743
|
-
await mkdir7(
|
|
31014
|
+
await mkdir7(join23(tempDir, category), { recursive: true });
|
|
30744
31015
|
}
|
|
30745
31016
|
await SkillsMigrator.copySkillDirectory(currentSkillPath, targetPath);
|
|
30746
31017
|
migrated.push(skillName);
|
|
@@ -30772,10 +31043,10 @@ class SkillsMigrator {
|
|
|
30772
31043
|
}
|
|
30773
31044
|
static async copySkillDirectory(sourceDir, destDir) {
|
|
30774
31045
|
await mkdir7(destDir, { recursive: true });
|
|
30775
|
-
const entries = await
|
|
31046
|
+
const entries = await readdir11(sourceDir, { withFileTypes: true });
|
|
30776
31047
|
for (const entry of entries) {
|
|
30777
|
-
const sourcePath =
|
|
30778
|
-
const destPath =
|
|
31048
|
+
const sourcePath = join23(sourceDir, entry.name);
|
|
31049
|
+
const destPath = join23(destDir, entry.name);
|
|
30779
31050
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
30780
31051
|
continue;
|
|
30781
31052
|
}
|
|
@@ -30795,12 +31066,18 @@ init_types2();
|
|
|
30795
31066
|
init_types2();
|
|
30796
31067
|
init_logger();
|
|
30797
31068
|
import { existsSync as existsSync5 } from "node:fs";
|
|
30798
|
-
import { mkdir as mkdir8, readFile as
|
|
31069
|
+
import { mkdir as mkdir8, readFile as readFile12, rename as rename2, rm as rm3, writeFile as writeFile10 } from "node:fs/promises";
|
|
30799
31070
|
import { chmod as chmod2 } from "node:fs/promises";
|
|
30800
31071
|
import { platform as platform8 } from "node:os";
|
|
31072
|
+
import { join as join24 } from "node:path";
|
|
31073
|
+
var PROJECT_CONFIG_FILE = ".ck.json";
|
|
31074
|
+
|
|
30801
31075
|
class ConfigManager {
|
|
30802
31076
|
static config = null;
|
|
30803
31077
|
static globalFlag = false;
|
|
31078
|
+
static getProjectConfigDir(projectDir, global3) {
|
|
31079
|
+
return global3 ? projectDir : join24(projectDir, ".claude");
|
|
31080
|
+
}
|
|
30804
31081
|
static setGlobalFlag(global3) {
|
|
30805
31082
|
ConfigManager.globalFlag = global3;
|
|
30806
31083
|
ConfigManager.config = null;
|
|
@@ -30815,7 +31092,7 @@ class ConfigManager {
|
|
|
30815
31092
|
const configFile = PathResolver.getConfigFile(ConfigManager.globalFlag);
|
|
30816
31093
|
try {
|
|
30817
31094
|
if (existsSync5(configFile)) {
|
|
30818
|
-
const content = await
|
|
31095
|
+
const content = await readFile12(configFile, "utf-8");
|
|
30819
31096
|
const data = JSON.parse(content);
|
|
30820
31097
|
ConfigManager.config = ConfigSchema.parse(data);
|
|
30821
31098
|
logger.debug(`Config loaded from ${configFile}`);
|
|
@@ -30838,7 +31115,7 @@ class ConfigManager {
|
|
|
30838
31115
|
await chmod2(configDir, 448);
|
|
30839
31116
|
}
|
|
30840
31117
|
}
|
|
30841
|
-
await
|
|
31118
|
+
await writeFile10(configFile, JSON.stringify(validConfig, null, 2), "utf-8");
|
|
30842
31119
|
if (platform8() !== "win32") {
|
|
30843
31120
|
await chmod2(configFile, 384);
|
|
30844
31121
|
}
|
|
@@ -30864,6 +31141,85 @@ class ConfigManager {
|
|
|
30864
31141
|
current[keys[keys.length - 1]] = value;
|
|
30865
31142
|
await ConfigManager.save(config);
|
|
30866
31143
|
}
|
|
31144
|
+
static async loadProjectConfig(projectDir, global3 = false) {
|
|
31145
|
+
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
31146
|
+
const configPath = join24(configDir, PROJECT_CONFIG_FILE);
|
|
31147
|
+
try {
|
|
31148
|
+
if (existsSync5(configPath)) {
|
|
31149
|
+
const content = await readFile12(configPath, "utf-8");
|
|
31150
|
+
const data = JSON.parse(content);
|
|
31151
|
+
const folders = FoldersConfigSchema.parse(data.paths || data);
|
|
31152
|
+
logger.debug(`Project config loaded from ${configPath}`);
|
|
31153
|
+
return folders;
|
|
31154
|
+
}
|
|
31155
|
+
} catch (error2) {
|
|
31156
|
+
logger.warning(`Failed to load project config from ${configPath}: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
31157
|
+
}
|
|
31158
|
+
return null;
|
|
31159
|
+
}
|
|
31160
|
+
static async saveProjectConfig(projectDir, folders, global3 = false) {
|
|
31161
|
+
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
31162
|
+
const configPath = join24(configDir, PROJECT_CONFIG_FILE);
|
|
31163
|
+
try {
|
|
31164
|
+
if (!existsSync5(configDir)) {
|
|
31165
|
+
await mkdir8(configDir, { recursive: true });
|
|
31166
|
+
}
|
|
31167
|
+
const validFolders = FoldersConfigSchema.parse(folders);
|
|
31168
|
+
await writeFile10(configPath, JSON.stringify({ paths: validFolders }, null, 2), "utf-8");
|
|
31169
|
+
logger.debug(`Project config saved to ${configPath}`);
|
|
31170
|
+
} catch (error2) {
|
|
31171
|
+
throw new Error(`Failed to save project config: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
31172
|
+
}
|
|
31173
|
+
}
|
|
31174
|
+
static async resolveFoldersConfig(projectDir, cliOptions, global3 = false) {
|
|
31175
|
+
const result = { ...DEFAULT_FOLDERS };
|
|
31176
|
+
const globalConfig = await ConfigManager.load();
|
|
31177
|
+
if (globalConfig.folders?.docs)
|
|
31178
|
+
result.docs = globalConfig.folders.docs;
|
|
31179
|
+
if (globalConfig.folders?.plans)
|
|
31180
|
+
result.plans = globalConfig.folders.plans;
|
|
31181
|
+
const projectConfig = await ConfigManager.loadProjectConfig(projectDir, global3);
|
|
31182
|
+
if (projectConfig?.docs)
|
|
31183
|
+
result.docs = projectConfig.docs;
|
|
31184
|
+
if (projectConfig?.plans)
|
|
31185
|
+
result.plans = projectConfig.plans;
|
|
31186
|
+
if (cliOptions?.docsDir)
|
|
31187
|
+
result.docs = cliOptions.docsDir;
|
|
31188
|
+
if (cliOptions?.plansDir)
|
|
31189
|
+
result.plans = cliOptions.plansDir;
|
|
31190
|
+
return result;
|
|
31191
|
+
}
|
|
31192
|
+
static projectConfigExists(projectDir, global3 = false) {
|
|
31193
|
+
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
31194
|
+
return existsSync5(join24(configDir, PROJECT_CONFIG_FILE));
|
|
31195
|
+
}
|
|
31196
|
+
static async migrateNestedConfig(globalDir) {
|
|
31197
|
+
const correctPath = join24(globalDir, PROJECT_CONFIG_FILE);
|
|
31198
|
+
const incorrectPath = join24(globalDir, ".claude", PROJECT_CONFIG_FILE);
|
|
31199
|
+
if (existsSync5(correctPath)) {
|
|
31200
|
+
logger.debug("Config already exists at correct location, skipping migration");
|
|
31201
|
+
return false;
|
|
31202
|
+
}
|
|
31203
|
+
if (existsSync5(incorrectPath)) {
|
|
31204
|
+
try {
|
|
31205
|
+
logger.info("Migrating .ck.json from nested location to correct location...");
|
|
31206
|
+
await rename2(incorrectPath, correctPath);
|
|
31207
|
+
logger.success(`Migrated ${PROJECT_CONFIG_FILE} to ${correctPath}`);
|
|
31208
|
+
const nestedClaudeDir = join24(globalDir, ".claude");
|
|
31209
|
+
try {
|
|
31210
|
+
await rm3(nestedClaudeDir, { recursive: false });
|
|
31211
|
+
logger.debug("Removed empty nested .claude directory");
|
|
31212
|
+
} catch (rmError) {
|
|
31213
|
+
logger.debug(`Could not remove nested .claude dir (may contain other files): ${rmError instanceof Error ? rmError.message : "Unknown"}`);
|
|
31214
|
+
}
|
|
31215
|
+
return true;
|
|
31216
|
+
} catch (error2) {
|
|
31217
|
+
logger.warning(`Failed to migrate config: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
31218
|
+
return false;
|
|
31219
|
+
}
|
|
31220
|
+
}
|
|
31221
|
+
return false;
|
|
31222
|
+
}
|
|
30867
31223
|
}
|
|
30868
31224
|
|
|
30869
31225
|
// src/commands/init.ts
|
|
@@ -30871,8 +31227,8 @@ init_environment();
|
|
|
30871
31227
|
|
|
30872
31228
|
// src/utils/file-scanner.ts
|
|
30873
31229
|
init_logger();
|
|
30874
|
-
var
|
|
30875
|
-
import { join as
|
|
31230
|
+
var import_fs_extra16 = __toESM(require_lib(), 1);
|
|
31231
|
+
import { join as join25, relative as relative8, resolve as resolve2 } from "node:path";
|
|
30876
31232
|
var SKIP_DIRS = [
|
|
30877
31233
|
"node_modules",
|
|
30878
31234
|
".venv",
|
|
@@ -30889,24 +31245,24 @@ class FileScanner {
|
|
|
30889
31245
|
static async getFiles(dirPath, relativeTo) {
|
|
30890
31246
|
const basePath = relativeTo || dirPath;
|
|
30891
31247
|
const files = [];
|
|
30892
|
-
if (!await
|
|
31248
|
+
if (!await import_fs_extra16.pathExists(dirPath)) {
|
|
30893
31249
|
return files;
|
|
30894
31250
|
}
|
|
30895
31251
|
try {
|
|
30896
|
-
const entries = await
|
|
31252
|
+
const entries = await import_fs_extra16.readdir(dirPath, { encoding: "utf8" });
|
|
30897
31253
|
for (const entry of entries) {
|
|
30898
31254
|
if (SKIP_DIRS.includes(entry)) {
|
|
30899
31255
|
logger.debug(`Skipping directory: ${entry}`);
|
|
30900
31256
|
continue;
|
|
30901
31257
|
}
|
|
30902
|
-
const fullPath =
|
|
31258
|
+
const fullPath = join25(dirPath, entry);
|
|
30903
31259
|
if (!FileScanner.isSafePath(basePath, fullPath)) {
|
|
30904
31260
|
logger.warning(`Skipping potentially unsafe path: ${entry}`);
|
|
30905
31261
|
continue;
|
|
30906
31262
|
}
|
|
30907
31263
|
let stats;
|
|
30908
31264
|
try {
|
|
30909
|
-
stats = await
|
|
31265
|
+
stats = await import_fs_extra16.lstat(fullPath);
|
|
30910
31266
|
} catch (error2) {
|
|
30911
31267
|
if (error2 instanceof Error && "code" in error2 && (error2.code === "EACCES" || error2.code === "EPERM")) {
|
|
30912
31268
|
logger.warning(`Skipping inaccessible path: ${entry}`);
|
|
@@ -30922,7 +31278,7 @@ class FileScanner {
|
|
|
30922
31278
|
const subFiles = await FileScanner.getFiles(fullPath, basePath);
|
|
30923
31279
|
files.push(...subFiles);
|
|
30924
31280
|
} else if (stats.isFile()) {
|
|
30925
|
-
const relativePath =
|
|
31281
|
+
const relativePath = relative8(basePath, fullPath);
|
|
30926
31282
|
files.push(FileScanner.toPosixPath(relativePath));
|
|
30927
31283
|
}
|
|
30928
31284
|
}
|
|
@@ -30934,8 +31290,8 @@ class FileScanner {
|
|
|
30934
31290
|
return files;
|
|
30935
31291
|
}
|
|
30936
31292
|
static async findCustomFiles(destDir, sourceDir, subPath) {
|
|
30937
|
-
const destSubDir =
|
|
30938
|
-
const sourceSubDir =
|
|
31293
|
+
const destSubDir = join25(destDir, subPath);
|
|
31294
|
+
const sourceSubDir = join25(sourceDir, subPath);
|
|
30939
31295
|
const destFiles = await FileScanner.getFiles(destSubDir, destDir);
|
|
30940
31296
|
const sourceFiles = await FileScanner.getFiles(sourceSubDir, sourceDir);
|
|
30941
31297
|
const sourceFileSet = new Set(sourceFiles);
|
|
@@ -30973,8 +31329,8 @@ async function initCommand(options) {
|
|
|
30973
31329
|
}
|
|
30974
31330
|
const isNonInteractive2 = !process.stdin.isTTY || process.env.CI === "true" || process.env.NON_INTERACTIVE === "true";
|
|
30975
31331
|
if (validOptions.global) {
|
|
30976
|
-
const localSettingsPath =
|
|
30977
|
-
if (await
|
|
31332
|
+
const localSettingsPath = join26(process.cwd(), ".claude", "settings.json");
|
|
31333
|
+
if (await import_fs_extra17.pathExists(localSettingsPath)) {
|
|
30978
31334
|
if (isNonInteractive2) {
|
|
30979
31335
|
logger.warning("Local .claude/settings.json detected. Local settings take precedence over global.");
|
|
30980
31336
|
logger.warning("Consider removing local installation: rm -rf .claude");
|
|
@@ -30985,9 +31341,9 @@ async function initCommand(options) {
|
|
|
30985
31341
|
return;
|
|
30986
31342
|
}
|
|
30987
31343
|
if (choice === "remove") {
|
|
30988
|
-
const localClaudeDir =
|
|
31344
|
+
const localClaudeDir = join26(process.cwd(), ".claude");
|
|
30989
31345
|
try {
|
|
30990
|
-
await
|
|
31346
|
+
await import_fs_extra17.remove(localClaudeDir);
|
|
30991
31347
|
logger.success("Removed local .claude/ directory");
|
|
30992
31348
|
} catch (error2) {
|
|
30993
31349
|
logger.error(`Failed to remove local installation: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
@@ -31022,7 +31378,7 @@ async function initCommand(options) {
|
|
|
31022
31378
|
}
|
|
31023
31379
|
const resolvedDir = resolve4(targetDir);
|
|
31024
31380
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
31025
|
-
if (!await
|
|
31381
|
+
if (!await import_fs_extra17.pathExists(resolvedDir)) {
|
|
31026
31382
|
if (validOptions.global) {
|
|
31027
31383
|
const { mkdir: mkdir9 } = await import("node:fs/promises");
|
|
31028
31384
|
await mkdir9(resolvedDir, { recursive: true });
|
|
@@ -31035,7 +31391,7 @@ async function initCommand(options) {
|
|
|
31035
31391
|
}
|
|
31036
31392
|
if (validOptions.fresh) {
|
|
31037
31393
|
const prefix = PathResolver.getPathPrefix(validOptions.global);
|
|
31038
|
-
const claudeDir2 = prefix ?
|
|
31394
|
+
const claudeDir2 = prefix ? join26(resolvedDir, prefix) : resolvedDir;
|
|
31039
31395
|
const canProceed = await handleFreshInstallation(claudeDir2, prompts);
|
|
31040
31396
|
if (!canProceed) {
|
|
31041
31397
|
return;
|
|
@@ -31145,10 +31501,33 @@ async function initCommand(options) {
|
|
|
31145
31501
|
});
|
|
31146
31502
|
logger.success(`Transformed ${transformResult.totalChanges} path(s) in ${transformResult.filesTransformed} file(s)`);
|
|
31147
31503
|
}
|
|
31504
|
+
if (validOptions.global) {
|
|
31505
|
+
await ConfigManager.migrateNestedConfig(resolvedDir);
|
|
31506
|
+
}
|
|
31507
|
+
const foldersConfig = await ConfigManager.resolveFoldersConfig(resolvedDir, {
|
|
31508
|
+
docsDir: validOptions.docsDir,
|
|
31509
|
+
plansDir: validOptions.plansDir
|
|
31510
|
+
}, validOptions.global);
|
|
31511
|
+
validateFolderOptions(validOptions);
|
|
31512
|
+
const hasCustomFolders = foldersConfig.docs !== DEFAULT_FOLDERS.docs || foldersConfig.plans !== DEFAULT_FOLDERS.plans;
|
|
31513
|
+
if (hasCustomFolders) {
|
|
31514
|
+
logger.info(`Using custom folder names: docs=${foldersConfig.docs}, plans=${foldersConfig.plans}`);
|
|
31515
|
+
const folderTransformResult = await transformFolderPaths(extractDir, foldersConfig, {
|
|
31516
|
+
verbose: logger.isVerbose()
|
|
31517
|
+
});
|
|
31518
|
+
logger.success(`Transformed ${folderTransformResult.foldersRenamed} folder(s), ${folderTransformResult.totalReferences} reference(s) in ${folderTransformResult.filesTransformed} file(s)`);
|
|
31519
|
+
if (validOptions.docsDir || validOptions.plansDir) {
|
|
31520
|
+
await ConfigManager.saveProjectConfig(resolvedDir, {
|
|
31521
|
+
docs: foldersConfig.docs,
|
|
31522
|
+
plans: foldersConfig.plans
|
|
31523
|
+
}, validOptions.global);
|
|
31524
|
+
logger.debug(validOptions.global ? "Saved folder configuration to ~/.claude/.ck.json" : "Saved folder configuration to .claude/.ck.json");
|
|
31525
|
+
}
|
|
31526
|
+
}
|
|
31148
31527
|
if (!validOptions.fresh) {
|
|
31149
|
-
const newSkillsDir =
|
|
31528
|
+
const newSkillsDir = join26(extractDir, ".claude", "skills");
|
|
31150
31529
|
const currentSkillsDir = PathResolver.buildSkillsPath(resolvedDir, validOptions.global);
|
|
31151
|
-
if (await
|
|
31530
|
+
if (await import_fs_extra17.pathExists(newSkillsDir) && await import_fs_extra17.pathExists(currentSkillsDir)) {
|
|
31152
31531
|
logger.info("Checking for skills directory migration...");
|
|
31153
31532
|
const migrationDetection = await SkillsMigrationDetector.detectMigration(newSkillsDir, currentSkillsDir);
|
|
31154
31533
|
if (migrationDetection.status === "recommended" || migrationDetection.status === "required") {
|
|
@@ -31171,7 +31550,7 @@ async function initCommand(options) {
|
|
|
31171
31550
|
let customClaudeFiles = [];
|
|
31172
31551
|
if (!validOptions.fresh) {
|
|
31173
31552
|
logger.info("Scanning for custom .claude files...");
|
|
31174
|
-
const scanSourceDir = validOptions.global ?
|
|
31553
|
+
const scanSourceDir = validOptions.global ? join26(extractDir, ".claude") : extractDir;
|
|
31175
31554
|
const scanTargetSubdir = validOptions.global ? "" : ".claude";
|
|
31176
31555
|
customClaudeFiles = await FileScanner.findCustomFiles(resolvedDir, scanSourceDir, scanTargetSubdir);
|
|
31177
31556
|
} else {
|
|
@@ -31200,9 +31579,9 @@ async function initCommand(options) {
|
|
|
31200
31579
|
merger.addIgnorePatterns(validOptions.exclude);
|
|
31201
31580
|
}
|
|
31202
31581
|
merger.setGlobalFlag(validOptions.global);
|
|
31203
|
-
const claudeDir = validOptions.global ? resolvedDir :
|
|
31582
|
+
const claudeDir = validOptions.global ? resolvedDir : join26(resolvedDir, ".claude");
|
|
31204
31583
|
const releaseManifest = await ReleaseManifestLoader.load(extractDir);
|
|
31205
|
-
if (!validOptions.fresh && await
|
|
31584
|
+
if (!validOptions.fresh && await import_fs_extra17.pathExists(claudeDir)) {
|
|
31206
31585
|
const legacyDetection = await LegacyMigration.detectLegacy(claudeDir);
|
|
31207
31586
|
if (legacyDetection.isLegacy && releaseManifest) {
|
|
31208
31587
|
logger.info("Legacy installation detected - migrating to ownership tracking...");
|
|
@@ -31222,7 +31601,7 @@ async function initCommand(options) {
|
|
|
31222
31601
|
return;
|
|
31223
31602
|
}
|
|
31224
31603
|
}
|
|
31225
|
-
const sourceDir = validOptions.global ?
|
|
31604
|
+
const sourceDir = validOptions.global ? join26(extractDir, ".claude") : extractDir;
|
|
31226
31605
|
await merger.merge(sourceDir, resolvedDir, false);
|
|
31227
31606
|
const manifestWriter = new ManifestWriter;
|
|
31228
31607
|
const installedFiles = merger.getAllInstalledFiles();
|
|
@@ -31231,7 +31610,7 @@ async function initCommand(options) {
|
|
|
31231
31610
|
if (!validOptions.global && !installedPath.startsWith(".claude/"))
|
|
31232
31611
|
continue;
|
|
31233
31612
|
const relativePath = validOptions.global ? installedPath : installedPath.replace(/^\.claude\//, "");
|
|
31234
|
-
const filePath =
|
|
31613
|
+
const filePath = join26(claudeDir, relativePath);
|
|
31235
31614
|
const manifestEntry = releaseManifest ? ReleaseManifestLoader.findFile(releaseManifest, installedPath) : null;
|
|
31236
31615
|
const ownership = manifestEntry ? "ck" : "user";
|
|
31237
31616
|
filesToTrack.push({
|
|
@@ -31252,11 +31631,11 @@ async function initCommand(options) {
|
|
|
31252
31631
|
trackingSpinner.succeed(`Tracked ${trackResult.success} files`);
|
|
31253
31632
|
await manifestWriter.writeManifest(claudeDir, kitConfig.name, release.tag_name, validOptions.global ? "global" : "local");
|
|
31254
31633
|
if (validOptions.global) {
|
|
31255
|
-
const claudeMdSource =
|
|
31256
|
-
const claudeMdDest =
|
|
31257
|
-
if (await
|
|
31258
|
-
if (!await
|
|
31259
|
-
await
|
|
31634
|
+
const claudeMdSource = join26(extractDir, "CLAUDE.md");
|
|
31635
|
+
const claudeMdDest = join26(resolvedDir, "CLAUDE.md");
|
|
31636
|
+
if (await import_fs_extra17.pathExists(claudeMdSource)) {
|
|
31637
|
+
if (!await import_fs_extra17.pathExists(claudeMdDest)) {
|
|
31638
|
+
await import_fs_extra17.copy(claudeMdSource, claudeMdDest);
|
|
31260
31639
|
logger.success("Copied CLAUDE.md to global directory");
|
|
31261
31640
|
} else {
|
|
31262
31641
|
logger.debug("CLAUDE.md already exists in global directory (preserved)");
|
|
@@ -31273,8 +31652,8 @@ async function initCommand(options) {
|
|
|
31273
31652
|
await handleSkillsInstallation2(skillsDir);
|
|
31274
31653
|
}
|
|
31275
31654
|
if (!validOptions.skipSetup && !isNonInteractive2) {
|
|
31276
|
-
const envPath =
|
|
31277
|
-
if (!await
|
|
31655
|
+
const envPath = join26(claudeDir, ".env");
|
|
31656
|
+
if (!await import_fs_extra17.pathExists(envPath)) {
|
|
31278
31657
|
const shouldSetup = await prompts.confirm("Set up API keys now? (Gemini API key for ai-multimodal skill, optional webhooks)");
|
|
31279
31658
|
if (shouldSetup) {
|
|
31280
31659
|
await runSetupWizard({
|
|
@@ -31304,8 +31683,8 @@ Protected files (.env, etc.) were not modified.`;
|
|
|
31304
31683
|
}
|
|
31305
31684
|
|
|
31306
31685
|
// src/commands/new.ts
|
|
31307
|
-
var
|
|
31308
|
-
import { join as
|
|
31686
|
+
var import_fs_extra18 = __toESM(require_lib(), 1);
|
|
31687
|
+
import { join as join27, resolve as resolve5 } from "node:path";
|
|
31309
31688
|
init_types2();
|
|
31310
31689
|
init_environment();
|
|
31311
31690
|
init_logger();
|
|
@@ -31336,8 +31715,8 @@ async function newCommand(options) {
|
|
|
31336
31715
|
}
|
|
31337
31716
|
const resolvedDir = resolve5(targetDir);
|
|
31338
31717
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
31339
|
-
if (await
|
|
31340
|
-
const files = await
|
|
31718
|
+
if (await import_fs_extra18.pathExists(resolvedDir)) {
|
|
31719
|
+
const files = await import_fs_extra18.readdir(resolvedDir);
|
|
31341
31720
|
const isEmpty = files.length === 0;
|
|
31342
31721
|
if (!isEmpty) {
|
|
31343
31722
|
if (isNonInteractive2) {
|
|
@@ -31451,6 +31830,23 @@ async function newCommand(options) {
|
|
|
31451
31830
|
if (CommandsPrefix.shouldApplyPrefix(validOptions)) {
|
|
31452
31831
|
await CommandsPrefix.applyPrefix(extractDir);
|
|
31453
31832
|
}
|
|
31833
|
+
const foldersConfig = await ConfigManager.resolveFoldersConfig(resolvedDir, {
|
|
31834
|
+
docsDir: validOptions.docsDir,
|
|
31835
|
+
plansDir: validOptions.plansDir
|
|
31836
|
+
});
|
|
31837
|
+
validateFolderOptions(validOptions);
|
|
31838
|
+
const hasCustomFolders = foldersConfig.docs !== DEFAULT_FOLDERS.docs || foldersConfig.plans !== DEFAULT_FOLDERS.plans;
|
|
31839
|
+
if (hasCustomFolders) {
|
|
31840
|
+
const transformResult = await transformFolderPaths(extractDir, foldersConfig, {
|
|
31841
|
+
verbose: logger.isVerbose()
|
|
31842
|
+
});
|
|
31843
|
+
logger.success(`Transformed ${transformResult.foldersRenamed} folder(s), ` + `${transformResult.totalReferences} reference(s) in ${transformResult.filesTransformed} file(s)`);
|
|
31844
|
+
await ConfigManager.saveProjectConfig(resolvedDir, {
|
|
31845
|
+
docs: foldersConfig.docs,
|
|
31846
|
+
plans: foldersConfig.plans
|
|
31847
|
+
});
|
|
31848
|
+
logger.debug("Saved folder configuration to .claude/.ck.json");
|
|
31849
|
+
}
|
|
31454
31850
|
const merger = new FileMerger;
|
|
31455
31851
|
if (validOptions.exclude && validOptions.exclude.length > 0) {
|
|
31456
31852
|
merger.addIgnorePatterns(validOptions.exclude);
|
|
@@ -31459,7 +31855,7 @@ async function newCommand(options) {
|
|
|
31459
31855
|
await CommandsPrefix.cleanupCommandsDirectory(resolvedDir, false);
|
|
31460
31856
|
}
|
|
31461
31857
|
await merger.merge(extractDir, resolvedDir, true);
|
|
31462
|
-
const claudeDir =
|
|
31858
|
+
const claudeDir = join27(resolvedDir, ".claude");
|
|
31463
31859
|
const manifestWriter = new ManifestWriter;
|
|
31464
31860
|
const releaseManifest = await ReleaseManifestLoader.load(extractDir);
|
|
31465
31861
|
const installedFiles = merger.getAllInstalledFiles();
|
|
@@ -31468,7 +31864,7 @@ async function newCommand(options) {
|
|
|
31468
31864
|
if (!installedPath.startsWith(".claude/"))
|
|
31469
31865
|
continue;
|
|
31470
31866
|
const relativePath = installedPath.replace(/^\.claude\//, "");
|
|
31471
|
-
const filePath =
|
|
31867
|
+
const filePath = join27(claudeDir, relativePath);
|
|
31472
31868
|
const manifestEntry = releaseManifest ? ReleaseManifestLoader.findFile(releaseManifest, installedPath) : null;
|
|
31473
31869
|
const ownership = manifestEntry ? "ck" : "user";
|
|
31474
31870
|
filesToTrack.push({
|
|
@@ -31521,10 +31917,10 @@ async function newCommand(options) {
|
|
|
31521
31917
|
|
|
31522
31918
|
// src/commands/uninstall.ts
|
|
31523
31919
|
init_dist2();
|
|
31524
|
-
var
|
|
31920
|
+
var import_fs_extra19 = __toESM(require_lib(), 1);
|
|
31525
31921
|
var import_picocolors10 = __toESM(require_picocolors(), 1);
|
|
31526
31922
|
import { readdirSync, rmSync } from "node:fs";
|
|
31527
|
-
import { dirname as dirname4, join as
|
|
31923
|
+
import { dirname as dirname4, join as join28 } from "node:path";
|
|
31528
31924
|
init_types2();
|
|
31529
31925
|
init_logger();
|
|
31530
31926
|
async function detectInstallations() {
|
|
@@ -31534,14 +31930,14 @@ async function detectInstallations() {
|
|
|
31534
31930
|
installations.push({
|
|
31535
31931
|
type: "local",
|
|
31536
31932
|
path: setup.project.path,
|
|
31537
|
-
exists: await
|
|
31933
|
+
exists: await import_fs_extra19.pathExists(setup.project.path)
|
|
31538
31934
|
});
|
|
31539
31935
|
}
|
|
31540
31936
|
if (setup.global.path && setup.global.metadata) {
|
|
31541
31937
|
installations.push({
|
|
31542
31938
|
type: "global",
|
|
31543
31939
|
path: setup.global.path,
|
|
31544
|
-
exists: await
|
|
31940
|
+
exists: await import_fs_extra19.pathExists(setup.global.path)
|
|
31545
31941
|
});
|
|
31546
31942
|
}
|
|
31547
31943
|
return installations.filter((i) => i.exists);
|
|
@@ -31615,7 +32011,7 @@ async function analyzeInstallation(installation, forceOverwrite) {
|
|
|
31615
32011
|
return result;
|
|
31616
32012
|
}
|
|
31617
32013
|
for (const trackedFile of metadata.files) {
|
|
31618
|
-
const filePath =
|
|
32014
|
+
const filePath = join28(installation.path, trackedFile.path);
|
|
31619
32015
|
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
31620
32016
|
if (!ownershipResult.exists)
|
|
31621
32017
|
continue;
|
|
@@ -31673,9 +32069,9 @@ async function removeInstallations(installations, options) {
|
|
|
31673
32069
|
let removedCount = 0;
|
|
31674
32070
|
let cleanedDirs = 0;
|
|
31675
32071
|
for (const item of analysis.toDelete) {
|
|
31676
|
-
const filePath =
|
|
31677
|
-
if (await
|
|
31678
|
-
await
|
|
32072
|
+
const filePath = join28(installation.path, item.path);
|
|
32073
|
+
if (await import_fs_extra19.pathExists(filePath)) {
|
|
32074
|
+
await import_fs_extra19.remove(filePath);
|
|
31679
32075
|
removedCount++;
|
|
31680
32076
|
logger.debug(`Removed: ${item.path}`);
|
|
31681
32077
|
cleanedDirs += await cleanupEmptyDirectories(filePath, installation.path);
|
|
@@ -31775,7 +32171,7 @@ import { promisify as promisify6 } from "node:util";
|
|
|
31775
32171
|
// package.json
|
|
31776
32172
|
var package_default2 = {
|
|
31777
32173
|
name: "claudekit-cli",
|
|
31778
|
-
version: "3.
|
|
32174
|
+
version: "3.3.1",
|
|
31779
32175
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
31780
32176
|
type: "module",
|
|
31781
32177
|
repository: {
|
|
@@ -32220,14 +32616,14 @@ var import_picocolors12 = __toESM(require_picocolors(), 1);
|
|
|
32220
32616
|
// src/lib/version-cache.ts
|
|
32221
32617
|
init_logger();
|
|
32222
32618
|
import { existsSync as existsSync6 } from "node:fs";
|
|
32223
|
-
import { mkdir as mkdir9, readFile as
|
|
32224
|
-
import { join as
|
|
32619
|
+
import { mkdir as mkdir9, readFile as readFile13, writeFile as writeFile11 } from "node:fs/promises";
|
|
32620
|
+
import { join as join29 } from "node:path";
|
|
32225
32621
|
class VersionCacheManager {
|
|
32226
32622
|
static CACHE_FILENAME = "version-check.json";
|
|
32227
32623
|
static CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
32228
32624
|
static getCacheFile() {
|
|
32229
32625
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
32230
|
-
return
|
|
32626
|
+
return join29(cacheDir, VersionCacheManager.CACHE_FILENAME);
|
|
32231
32627
|
}
|
|
32232
32628
|
static async load() {
|
|
32233
32629
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
@@ -32236,7 +32632,7 @@ class VersionCacheManager {
|
|
|
32236
32632
|
logger.debug("Version check cache not found");
|
|
32237
32633
|
return null;
|
|
32238
32634
|
}
|
|
32239
|
-
const content = await
|
|
32635
|
+
const content = await readFile13(cacheFile, "utf-8");
|
|
32240
32636
|
const cache2 = JSON.parse(content);
|
|
32241
32637
|
if (!cache2.lastCheck || !cache2.currentVersion || !cache2.latestVersion) {
|
|
32242
32638
|
logger.debug("Invalid cache structure, ignoring");
|
|
@@ -32256,7 +32652,7 @@ class VersionCacheManager {
|
|
|
32256
32652
|
if (!existsSync6(cacheDir)) {
|
|
32257
32653
|
await mkdir9(cacheDir, { recursive: true, mode: 448 });
|
|
32258
32654
|
}
|
|
32259
|
-
await
|
|
32655
|
+
await writeFile11(cacheFile, JSON.stringify(cache2, null, 2), "utf-8");
|
|
32260
32656
|
logger.debug(`Version check cache saved to ${cacheFile}`);
|
|
32261
32657
|
} catch (error2) {
|
|
32262
32658
|
logger.debug(`Failed to save version check cache: ${error2}`);
|
|
@@ -32467,6 +32863,10 @@ class CliVersionChecker {
|
|
|
32467
32863
|
init_zod();
|
|
32468
32864
|
var KitType2 = exports_external.enum(["engineer", "marketing"]);
|
|
32469
32865
|
var ExcludePatternSchema2 = exports_external.string().trim().min(1, "Exclude pattern cannot be empty").max(500, "Exclude pattern too long").refine((val) => !val.startsWith("/"), "Absolute paths not allowed in exclude patterns").refine((val) => !val.includes(".."), "Path traversal not allowed in exclude patterns");
|
|
32866
|
+
var FoldersConfigSchema2 = exports_external.object({
|
|
32867
|
+
docs: exports_external.string().optional(),
|
|
32868
|
+
plans: exports_external.string().optional()
|
|
32869
|
+
});
|
|
32470
32870
|
var NewCommandOptionsSchema2 = exports_external.object({
|
|
32471
32871
|
dir: exports_external.string().default("."),
|
|
32472
32872
|
kit: KitType2.optional(),
|
|
@@ -32479,7 +32879,9 @@ var NewCommandOptionsSchema2 = exports_external.object({
|
|
|
32479
32879
|
prefix: exports_external.boolean().default(false),
|
|
32480
32880
|
beta: exports_external.boolean().default(false),
|
|
32481
32881
|
dryRun: exports_external.boolean().default(false),
|
|
32482
|
-
refresh: exports_external.boolean().default(false)
|
|
32882
|
+
refresh: exports_external.boolean().default(false),
|
|
32883
|
+
docsDir: exports_external.string().optional(),
|
|
32884
|
+
plansDir: exports_external.string().optional()
|
|
32483
32885
|
});
|
|
32484
32886
|
var UpdateCommandOptionsSchema2 = exports_external.object({
|
|
32485
32887
|
dir: exports_external.string().default("."),
|
|
@@ -32495,7 +32897,9 @@ var UpdateCommandOptionsSchema2 = exports_external.object({
|
|
|
32495
32897
|
dryRun: exports_external.boolean().default(false),
|
|
32496
32898
|
forceOverwrite: exports_external.boolean().default(false),
|
|
32497
32899
|
skipSetup: exports_external.boolean().default(false),
|
|
32498
|
-
refresh: exports_external.boolean().default(false)
|
|
32900
|
+
refresh: exports_external.boolean().default(false),
|
|
32901
|
+
docsDir: exports_external.string().optional(),
|
|
32902
|
+
plansDir: exports_external.string().optional()
|
|
32499
32903
|
});
|
|
32500
32904
|
var VersionCommandOptionsSchema2 = exports_external.object({
|
|
32501
32905
|
kit: KitType2.optional(),
|
|
@@ -32536,7 +32940,8 @@ var ConfigSchema2 = exports_external.object({
|
|
|
32536
32940
|
defaults: exports_external.object({
|
|
32537
32941
|
kit: KitType2.optional(),
|
|
32538
32942
|
dir: exports_external.string().optional()
|
|
32539
|
-
}).optional()
|
|
32943
|
+
}).optional(),
|
|
32944
|
+
folders: FoldersConfigSchema2.optional()
|
|
32540
32945
|
});
|
|
32541
32946
|
var GitHubReleaseAssetSchema2 = exports_external.object({
|
|
32542
32947
|
id: exports_external.number(),
|
|
@@ -32693,7 +33098,7 @@ var logger2 = new Logger2;
|
|
|
32693
33098
|
|
|
32694
33099
|
// src/utils/path-resolver.ts
|
|
32695
33100
|
import { homedir as homedir2, platform as platform9 } from "node:os";
|
|
32696
|
-
import { join as
|
|
33101
|
+
import { join as join30, normalize as normalize4 } from "node:path";
|
|
32697
33102
|
|
|
32698
33103
|
class PathResolver2 {
|
|
32699
33104
|
static getTestHomeDir() {
|
|
@@ -32726,50 +33131,50 @@ class PathResolver2 {
|
|
|
32726
33131
|
static getConfigDir(global3 = false) {
|
|
32727
33132
|
const testHome = PathResolver2.getTestHomeDir();
|
|
32728
33133
|
if (testHome) {
|
|
32729
|
-
return global3 ?
|
|
33134
|
+
return global3 ? join30(testHome, ".config", "claude") : join30(testHome, ".claudekit");
|
|
32730
33135
|
}
|
|
32731
33136
|
if (!global3) {
|
|
32732
|
-
return
|
|
33137
|
+
return join30(homedir2(), ".claudekit");
|
|
32733
33138
|
}
|
|
32734
33139
|
const os2 = platform9();
|
|
32735
33140
|
if (os2 === "win32") {
|
|
32736
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
32737
|
-
return
|
|
33141
|
+
const localAppData = process.env.LOCALAPPDATA || join30(homedir2(), "AppData", "Local");
|
|
33142
|
+
return join30(localAppData, "claude");
|
|
32738
33143
|
}
|
|
32739
33144
|
const xdgConfigHome = process.env.XDG_CONFIG_HOME;
|
|
32740
33145
|
if (xdgConfigHome) {
|
|
32741
|
-
return
|
|
33146
|
+
return join30(xdgConfigHome, "claude");
|
|
32742
33147
|
}
|
|
32743
|
-
return
|
|
33148
|
+
return join30(homedir2(), ".config", "claude");
|
|
32744
33149
|
}
|
|
32745
33150
|
static getConfigFile(global3 = false) {
|
|
32746
|
-
return
|
|
33151
|
+
return join30(PathResolver2.getConfigDir(global3), "config.json");
|
|
32747
33152
|
}
|
|
32748
33153
|
static getCacheDir(global3 = false) {
|
|
32749
33154
|
const testHome = PathResolver2.getTestHomeDir();
|
|
32750
33155
|
if (testHome) {
|
|
32751
|
-
return global3 ?
|
|
33156
|
+
return global3 ? join30(testHome, ".cache", "claude") : join30(testHome, ".claudekit", "cache");
|
|
32752
33157
|
}
|
|
32753
33158
|
if (!global3) {
|
|
32754
|
-
return
|
|
33159
|
+
return join30(homedir2(), ".claudekit", "cache");
|
|
32755
33160
|
}
|
|
32756
33161
|
const os2 = platform9();
|
|
32757
33162
|
if (os2 === "win32") {
|
|
32758
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
32759
|
-
return
|
|
33163
|
+
const localAppData = process.env.LOCALAPPDATA || join30(homedir2(), "AppData", "Local");
|
|
33164
|
+
return join30(localAppData, "claude", "cache");
|
|
32760
33165
|
}
|
|
32761
33166
|
const xdgCacheHome = process.env.XDG_CACHE_HOME;
|
|
32762
33167
|
if (xdgCacheHome) {
|
|
32763
|
-
return
|
|
33168
|
+
return join30(xdgCacheHome, "claude");
|
|
32764
33169
|
}
|
|
32765
|
-
return
|
|
33170
|
+
return join30(homedir2(), ".cache", "claude");
|
|
32766
33171
|
}
|
|
32767
33172
|
static getGlobalKitDir() {
|
|
32768
33173
|
const testHome = PathResolver2.getTestHomeDir();
|
|
32769
33174
|
if (testHome) {
|
|
32770
|
-
return
|
|
33175
|
+
return join30(testHome, ".claude");
|
|
32771
33176
|
}
|
|
32772
|
-
return
|
|
33177
|
+
return join30(homedir2(), ".claude");
|
|
32773
33178
|
}
|
|
32774
33179
|
static getPathPrefix(global3) {
|
|
32775
33180
|
return global3 ? "" : ".claude";
|
|
@@ -32777,9 +33182,9 @@ class PathResolver2 {
|
|
|
32777
33182
|
static buildSkillsPath(baseDir, global3) {
|
|
32778
33183
|
const prefix = PathResolver2.getPathPrefix(global3);
|
|
32779
33184
|
if (prefix) {
|
|
32780
|
-
return
|
|
33185
|
+
return join30(baseDir, prefix, "skills");
|
|
32781
33186
|
}
|
|
32782
|
-
return
|
|
33187
|
+
return join30(baseDir, "skills");
|
|
32783
33188
|
}
|
|
32784
33189
|
static buildComponentPath(baseDir, component, global3) {
|
|
32785
33190
|
if (!PathResolver2.isPathSafe(component)) {
|
|
@@ -32787,9 +33192,9 @@ class PathResolver2 {
|
|
|
32787
33192
|
}
|
|
32788
33193
|
const prefix = PathResolver2.getPathPrefix(global3);
|
|
32789
33194
|
if (prefix) {
|
|
32790
|
-
return
|
|
33195
|
+
return join30(baseDir, prefix, component);
|
|
32791
33196
|
}
|
|
32792
|
-
return
|
|
33197
|
+
return join30(baseDir, component);
|
|
32793
33198
|
}
|
|
32794
33199
|
}
|
|
32795
33200
|
|
|
@@ -32807,9 +33212,9 @@ async function displayVersion() {
|
|
|
32807
33212
|
let localKitVersion = null;
|
|
32808
33213
|
let isGlobalOnlyKit = false;
|
|
32809
33214
|
const globalKitDir = PathResolver2.getGlobalKitDir();
|
|
32810
|
-
const globalMetadataPath =
|
|
33215
|
+
const globalMetadataPath = join31(globalKitDir, "metadata.json");
|
|
32811
33216
|
const prefix = PathResolver2.getPathPrefix(false);
|
|
32812
|
-
const localMetadataPath = prefix ?
|
|
33217
|
+
const localMetadataPath = prefix ? join31(process.cwd(), prefix, "metadata.json") : join31(process.cwd(), "metadata.json");
|
|
32813
33218
|
const isLocalSameAsGlobal = localMetadataPath === globalMetadataPath;
|
|
32814
33219
|
if (!isLocalSameAsGlobal && existsSync7(localMetadataPath)) {
|
|
32815
33220
|
try {
|
|
@@ -32867,13 +33272,13 @@ async function displayVersion() {
|
|
|
32867
33272
|
var cli = cac("ck");
|
|
32868
33273
|
cli.option("--verbose", "Enable verbose logging for debugging");
|
|
32869
33274
|
cli.option("--log-file <path>", "Write logs to file");
|
|
32870
|
-
cli.command("new", "Bootstrap a new ClaudeKit project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to use (engineer, marketing)").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--force", "Overwrite existing files without confirmation").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--opencode", "Install OpenCode CLI package (non-interactive mode)").option("--gemini", "Install Google Gemini CLI package (non-interactive mode)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--prefix", "Add /ck: prefix to all slash commands by moving them to commands/ck/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").action(async (options) => {
|
|
33275
|
+
cli.command("new", "Bootstrap a new ClaudeKit project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to use (engineer, marketing)").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--force", "Overwrite existing files without confirmation").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--opencode", "Install OpenCode CLI package (non-interactive mode)").option("--gemini", "Install Google Gemini CLI package (non-interactive mode)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--prefix", "Add /ck: prefix to all slash commands by moving them to commands/ck/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").action(async (options) => {
|
|
32871
33276
|
if (options.exclude && !Array.isArray(options.exclude)) {
|
|
32872
33277
|
options.exclude = [options.exclude];
|
|
32873
33278
|
}
|
|
32874
33279
|
await newCommand(options);
|
|
32875
33280
|
});
|
|
32876
|
-
cli.command("init", "Initialize or update ClaudeKit project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to use (engineer, marketing)").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--only <pattern>", "Include only files matching glob pattern (can be used multiple times)").option("-g, --global", "Use platform-specific user configuration directory").option("--fresh", "Completely remove .claude directory before downloading (requires confirmation)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--prefix", "Add /ck: prefix to all slash commands by moving them to commands/ck/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--dry-run", "Preview changes without applying them (requires --prefix)").option("--force-overwrite", "Override ownership protections and delete user-modified files (requires --prefix)").option("--skip-setup", "Skip interactive configuration wizard").action(async (options) => {
|
|
33281
|
+
cli.command("init", "Initialize or update ClaudeKit project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to use (engineer, marketing)").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--only <pattern>", "Include only files matching glob pattern (can be used multiple times)").option("-g, --global", "Use platform-specific user configuration directory").option("--fresh", "Completely remove .claude directory before downloading (requires confirmation)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--prefix", "Add /ck: prefix to all slash commands by moving them to commands/ck/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--dry-run", "Preview changes without applying them (requires --prefix)").option("--force-overwrite", "Override ownership protections and delete user-modified files (requires --prefix)").option("--skip-setup", "Skip interactive configuration wizard").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").action(async (options) => {
|
|
32877
33282
|
if (options.exclude && !Array.isArray(options.exclude)) {
|
|
32878
33283
|
options.exclude = [options.exclude];
|
|
32879
33284
|
}
|
|
@@ -32918,27 +33323,39 @@ cli.command("uninstall", "Remove ClaudeKit installations").option("-y, --yes", "
|
|
|
32918
33323
|
cli.option("-V, --version", "Display version number");
|
|
32919
33324
|
cli.option("-h, --help", "Display help information");
|
|
32920
33325
|
var parsed = cli.parse(process.argv, { run: false });
|
|
32921
|
-
|
|
32922
|
-
|
|
32923
|
-
|
|
32924
|
-
|
|
32925
|
-
|
|
32926
|
-
|
|
32927
|
-
|
|
32928
|
-
|
|
32929
|
-
|
|
32930
|
-
|
|
32931
|
-
|
|
32932
|
-
|
|
32933
|
-
|
|
32934
|
-
|
|
32935
|
-
|
|
32936
|
-
|
|
32937
|
-
|
|
32938
|
-
|
|
32939
|
-
|
|
32940
|
-
|
|
32941
|
-
|
|
32942
|
-
|
|
33326
|
+
(async () => {
|
|
33327
|
+
try {
|
|
33328
|
+
if (parsed.options.version) {
|
|
33329
|
+
await displayVersion();
|
|
33330
|
+
process.exitCode = 0;
|
|
33331
|
+
return;
|
|
33332
|
+
}
|
|
33333
|
+
if (parsed.options.help || !cli.matchedCommand && parsed.args.length === 0) {
|
|
33334
|
+
const { handleHelp: handleHelp2 } = await Promise.resolve().then(() => (init_help_interceptor(), exports_help_interceptor));
|
|
33335
|
+
await handleHelp2(parsed.args);
|
|
33336
|
+
return;
|
|
33337
|
+
}
|
|
33338
|
+
const envVerbose = process.env.CLAUDEKIT_VERBOSE === "1" || process.env.CLAUDEKIT_VERBOSE === "true";
|
|
33339
|
+
const isVerbose = parsed.options.verbose || envVerbose;
|
|
33340
|
+
if (isVerbose) {
|
|
33341
|
+
logger2.setVerbose(true);
|
|
33342
|
+
}
|
|
33343
|
+
if (parsed.options.logFile) {
|
|
33344
|
+
logger2.setLogFile(parsed.options.logFile);
|
|
33345
|
+
}
|
|
33346
|
+
logger2.verbose("ClaudeKit CLI starting", {
|
|
33347
|
+
version: packageVersion,
|
|
33348
|
+
command: parsed.args[0] || "none",
|
|
33349
|
+
options: parsed.options,
|
|
33350
|
+
cwd: process.cwd(),
|
|
33351
|
+
node: process.version
|
|
33352
|
+
});
|
|
33353
|
+
cli.parse();
|
|
33354
|
+
} catch (error2) {
|
|
33355
|
+
console.error("CLI error:", error2 instanceof Error ? error2.message : error2);
|
|
33356
|
+
process.exitCode = 1;
|
|
33357
|
+
}
|
|
33358
|
+
})().catch((error2) => {
|
|
33359
|
+
console.error("Unhandled error:", error2 instanceof Error ? error2.message : error2);
|
|
33360
|
+
process.exitCode = 1;
|
|
32943
33361
|
});
|
|
32944
|
-
cli.parse();
|