claudekit-cli 3.7.1 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +292 -87
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6324,6 +6324,7 @@ var init_types2 = __esm(() => {
|
|
|
6324
6324
|
beta: exports_external.boolean().default(false),
|
|
6325
6325
|
dryRun: exports_external.boolean().default(false),
|
|
6326
6326
|
forceOverwrite: exports_external.boolean().default(false),
|
|
6327
|
+
forceOverwriteSettings: exports_external.boolean().default(false),
|
|
6327
6328
|
skipSetup: exports_external.boolean().default(false),
|
|
6328
6329
|
refresh: exports_external.boolean().default(false),
|
|
6329
6330
|
docsDir: exports_external.string().optional(),
|
|
@@ -13157,7 +13158,7 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
13157
13158
|
}
|
|
13158
13159
|
try {
|
|
13159
13160
|
const { existsSync: existsSync6 } = await import("node:fs");
|
|
13160
|
-
const { readFile:
|
|
13161
|
+
const { readFile: readFile12 } = await import("node:fs/promises");
|
|
13161
13162
|
const clack = await Promise.resolve().then(() => (init_dist2(), exports_dist));
|
|
13162
13163
|
const platform9 = process.platform;
|
|
13163
13164
|
const scriptName = platform9 === "win32" ? "install.ps1" : "install.sh";
|
|
@@ -13193,7 +13194,7 @@ async function installSkillsDependencies(skillsDir) {
|
|
|
13193
13194
|
logger.info(` Platform: ${platform9 === "win32" ? "Windows (PowerShell)" : "Unix (bash)"}`);
|
|
13194
13195
|
logger.info("");
|
|
13195
13196
|
try {
|
|
13196
|
-
const scriptContent = await
|
|
13197
|
+
const scriptContent = await readFile12(scriptPath, "utf-8");
|
|
13197
13198
|
const previewLines = scriptContent.split(`
|
|
13198
13199
|
`).slice(0, 20);
|
|
13199
13200
|
logger.info("Script preview (first 20 lines):");
|
|
@@ -14925,7 +14926,7 @@ var cac = (name = "") => new CAC(name);
|
|
|
14925
14926
|
// package.json
|
|
14926
14927
|
var package_default = {
|
|
14927
14928
|
name: "claudekit-cli",
|
|
14928
|
-
version: "3.
|
|
14929
|
+
version: "3.8.0",
|
|
14929
14930
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
14930
14931
|
type: "module",
|
|
14931
14932
|
repository: {
|
|
@@ -18765,7 +18766,7 @@ async function doctorCommand(options = {}) {
|
|
|
18765
18766
|
}
|
|
18766
18767
|
|
|
18767
18768
|
// src/commands/init.ts
|
|
18768
|
-
var
|
|
18769
|
+
var import_fs_extra18 = __toESM(require_lib(), 1);
|
|
18769
18770
|
import { join as join29, resolve as resolve5 } from "node:path";
|
|
18770
18771
|
|
|
18771
18772
|
// src/lib/commands-prefix.ts
|
|
@@ -28492,7 +28493,7 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
28492
28493
|
|
|
28493
28494
|
// src/lib/merge.ts
|
|
28494
28495
|
init_dist2();
|
|
28495
|
-
var
|
|
28496
|
+
var import_fs_extra7 = __toESM(require_lib(), 1);
|
|
28496
28497
|
var import_ignore2 = __toESM(require_ignore(), 1);
|
|
28497
28498
|
import { dirname as dirname4, join as join15, relative as relative4 } from "node:path";
|
|
28498
28499
|
|
|
@@ -29934,11 +29935,168 @@ minimatch.unescape = unescape;
|
|
|
29934
29935
|
init_types2();
|
|
29935
29936
|
init_logger();
|
|
29936
29937
|
|
|
29938
|
+
// src/lib/settings-merger.ts
|
|
29939
|
+
init_logger();
|
|
29940
|
+
var import_fs_extra6 = __toESM(require_lib(), 1);
|
|
29941
|
+
|
|
29942
|
+
class SettingsMerger {
|
|
29943
|
+
static merge(source, destination) {
|
|
29944
|
+
const result = {
|
|
29945
|
+
merged: { ...destination },
|
|
29946
|
+
hooksAdded: 0,
|
|
29947
|
+
hooksPreserved: 0,
|
|
29948
|
+
mcpServersPreserved: 0,
|
|
29949
|
+
conflictsDetected: []
|
|
29950
|
+
};
|
|
29951
|
+
if (source.hooks) {
|
|
29952
|
+
result.merged.hooks = SettingsMerger.mergeHooks(source.hooks, destination.hooks || {}, result);
|
|
29953
|
+
}
|
|
29954
|
+
if (source.mcp) {
|
|
29955
|
+
result.merged.mcp = SettingsMerger.mergeMcp(source.mcp, destination.mcp || {}, result);
|
|
29956
|
+
}
|
|
29957
|
+
for (const key of Object.keys(source)) {
|
|
29958
|
+
if (key !== "hooks" && key !== "mcp" && !(key in destination)) {
|
|
29959
|
+
result.merged[key] = source[key];
|
|
29960
|
+
}
|
|
29961
|
+
}
|
|
29962
|
+
return result;
|
|
29963
|
+
}
|
|
29964
|
+
static mergeHooks(sourceHooks, destHooks, result) {
|
|
29965
|
+
const merged = { ...destHooks };
|
|
29966
|
+
for (const [eventName, sourceEntries] of Object.entries(sourceHooks)) {
|
|
29967
|
+
const destEntries = destHooks[eventName] || [];
|
|
29968
|
+
merged[eventName] = SettingsMerger.mergeHookEntries(sourceEntries, destEntries, eventName, result);
|
|
29969
|
+
}
|
|
29970
|
+
return merged;
|
|
29971
|
+
}
|
|
29972
|
+
static mergeHookEntries(sourceEntries, destEntries, eventName, result) {
|
|
29973
|
+
const existingCommands = new Set;
|
|
29974
|
+
SettingsMerger.extractCommands(destEntries, existingCommands);
|
|
29975
|
+
if (destEntries.length > 0) {
|
|
29976
|
+
result.hooksPreserved += destEntries.length;
|
|
29977
|
+
}
|
|
29978
|
+
const merged = [...destEntries];
|
|
29979
|
+
for (const entry of sourceEntries) {
|
|
29980
|
+
const commands = SettingsMerger.getEntryCommands(entry);
|
|
29981
|
+
const isFullyDuplicated = commands.length > 0 && commands.every((cmd) => existingCommands.has(cmd));
|
|
29982
|
+
const duplicateCommands = commands.filter((cmd) => existingCommands.has(cmd));
|
|
29983
|
+
if (duplicateCommands.length > 0) {
|
|
29984
|
+
const summary = duplicateCommands.length === 1 ? `"${SettingsMerger.truncateCommand(duplicateCommands[0])}"` : `${duplicateCommands.length} commands`;
|
|
29985
|
+
result.conflictsDetected.push(`${eventName}: duplicate ${summary}`);
|
|
29986
|
+
}
|
|
29987
|
+
if (!isFullyDuplicated) {
|
|
29988
|
+
merged.push(entry);
|
|
29989
|
+
result.hooksAdded++;
|
|
29990
|
+
for (const cmd of commands) {
|
|
29991
|
+
existingCommands.add(cmd);
|
|
29992
|
+
}
|
|
29993
|
+
}
|
|
29994
|
+
}
|
|
29995
|
+
return merged;
|
|
29996
|
+
}
|
|
29997
|
+
static extractCommands(entries, commands) {
|
|
29998
|
+
for (const entry of entries) {
|
|
29999
|
+
if ("command" in entry && entry.command) {
|
|
30000
|
+
commands.add(entry.command);
|
|
30001
|
+
}
|
|
30002
|
+
if ("hooks" in entry && entry.hooks) {
|
|
30003
|
+
for (const hook of entry.hooks) {
|
|
30004
|
+
if (hook.command) {
|
|
30005
|
+
commands.add(hook.command);
|
|
30006
|
+
}
|
|
30007
|
+
}
|
|
30008
|
+
}
|
|
30009
|
+
}
|
|
30010
|
+
}
|
|
30011
|
+
static getEntryCommands(entry) {
|
|
30012
|
+
const commands = [];
|
|
30013
|
+
if ("command" in entry && entry.command) {
|
|
30014
|
+
commands.push(entry.command);
|
|
30015
|
+
}
|
|
30016
|
+
if ("hooks" in entry && entry.hooks) {
|
|
30017
|
+
for (const hook of entry.hooks) {
|
|
30018
|
+
if (hook.command) {
|
|
30019
|
+
commands.push(hook.command);
|
|
30020
|
+
}
|
|
30021
|
+
}
|
|
30022
|
+
}
|
|
30023
|
+
return commands;
|
|
30024
|
+
}
|
|
30025
|
+
static truncateCommand(cmd, maxLen = 50) {
|
|
30026
|
+
if (cmd.length <= maxLen)
|
|
30027
|
+
return cmd;
|
|
30028
|
+
return `${cmd.slice(0, maxLen - 3)}...`;
|
|
30029
|
+
}
|
|
30030
|
+
static mergeMcp(sourceMcp, destMcp, result) {
|
|
30031
|
+
if (!sourceMcp)
|
|
30032
|
+
return destMcp;
|
|
30033
|
+
if (!destMcp)
|
|
30034
|
+
return sourceMcp;
|
|
30035
|
+
const merged = { ...destMcp };
|
|
30036
|
+
if (sourceMcp.servers) {
|
|
30037
|
+
const destServers = destMcp.servers || {};
|
|
30038
|
+
merged.servers = { ...destServers };
|
|
30039
|
+
for (const [serverName, serverConfig] of Object.entries(sourceMcp.servers)) {
|
|
30040
|
+
if (serverName in destServers) {
|
|
30041
|
+
result.mcpServersPreserved++;
|
|
30042
|
+
logger.debug(`Preserved user MCP server: ${serverName}`);
|
|
30043
|
+
} else {
|
|
30044
|
+
merged.servers[serverName] = serverConfig;
|
|
30045
|
+
logger.debug(`Added ClaudeKit MCP server: ${serverName}`);
|
|
30046
|
+
}
|
|
30047
|
+
}
|
|
30048
|
+
}
|
|
30049
|
+
for (const key of Object.keys(sourceMcp)) {
|
|
30050
|
+
if (key !== "servers" && !(key in merged)) {
|
|
30051
|
+
merged[key] = sourceMcp[key];
|
|
30052
|
+
}
|
|
30053
|
+
}
|
|
30054
|
+
return merged;
|
|
30055
|
+
}
|
|
30056
|
+
static async readSettingsFile(filePath) {
|
|
30057
|
+
try {
|
|
30058
|
+
if (!await import_fs_extra6.pathExists(filePath)) {
|
|
30059
|
+
return null;
|
|
30060
|
+
}
|
|
30061
|
+
const content = await import_fs_extra6.readFile(filePath, "utf-8");
|
|
30062
|
+
const parsed = JSON.parse(content);
|
|
30063
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
30064
|
+
logger.warning(`Invalid settings file format (expected object): ${filePath}`);
|
|
30065
|
+
return null;
|
|
30066
|
+
}
|
|
30067
|
+
return parsed;
|
|
30068
|
+
} catch (error) {
|
|
30069
|
+
logger.warning(`Failed to parse settings file: ${filePath} - ${error}`);
|
|
30070
|
+
return null;
|
|
30071
|
+
}
|
|
30072
|
+
}
|
|
30073
|
+
static async writeSettingsFile(filePath, settings) {
|
|
30074
|
+
const content = JSON.stringify(settings, null, "\t");
|
|
30075
|
+
await import_fs_extra6.writeFile(filePath, content, "utf-8");
|
|
30076
|
+
}
|
|
30077
|
+
static async createBackup(filePath) {
|
|
30078
|
+
try {
|
|
30079
|
+
if (!await import_fs_extra6.pathExists(filePath)) {
|
|
30080
|
+
return null;
|
|
30081
|
+
}
|
|
30082
|
+
const backupPath = `${filePath}.backup`;
|
|
30083
|
+
const content = await import_fs_extra6.readFile(filePath, "utf-8");
|
|
30084
|
+
await import_fs_extra6.writeFile(backupPath, content, "utf-8");
|
|
30085
|
+
return backupPath;
|
|
30086
|
+
} catch (error) {
|
|
30087
|
+
logger.warning(`Failed to create backup: ${error}`);
|
|
30088
|
+
return null;
|
|
30089
|
+
}
|
|
30090
|
+
}
|
|
30091
|
+
}
|
|
30092
|
+
|
|
30093
|
+
// src/lib/merge.ts
|
|
29937
30094
|
class FileMerger {
|
|
29938
30095
|
neverCopyChecker = import_ignore2.default().add(NEVER_COPY_PATTERNS);
|
|
29939
30096
|
userConfigChecker = import_ignore2.default().add(USER_CONFIG_PATTERNS);
|
|
29940
30097
|
includePatterns = [];
|
|
29941
30098
|
isGlobal = false;
|
|
30099
|
+
forceOverwriteSettings = false;
|
|
29942
30100
|
installedFiles = new Set;
|
|
29943
30101
|
installedDirectories = new Set;
|
|
29944
30102
|
setIncludePatterns(patterns) {
|
|
@@ -29947,6 +30105,9 @@ class FileMerger {
|
|
|
29947
30105
|
setGlobalFlag(isGlobal) {
|
|
29948
30106
|
this.isGlobal = isGlobal;
|
|
29949
30107
|
}
|
|
30108
|
+
setForceOverwriteSettings(force) {
|
|
30109
|
+
this.forceOverwriteSettings = force;
|
|
30110
|
+
}
|
|
29950
30111
|
async merge(sourceDir, destDir, skipConfirmation = false) {
|
|
29951
30112
|
const conflicts = await this.detectConflicts(sourceDir, destDir);
|
|
29952
30113
|
if (conflicts.length > 0 && !skipConfirmation) {
|
|
@@ -29971,7 +30132,7 @@ class FileMerger {
|
|
|
29971
30132
|
const relativePath = relative4(sourceDir, file);
|
|
29972
30133
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
29973
30134
|
const destPath = join15(destDir, relativePath);
|
|
29974
|
-
if (await
|
|
30135
|
+
if (await import_fs_extra7.pathExists(destPath)) {
|
|
29975
30136
|
if (this.neverCopyChecker.ignores(normalizedRelativePath)) {
|
|
29976
30137
|
logger.debug(`Security-sensitive file exists but won't be overwritten: ${normalizedRelativePath}`);
|
|
29977
30138
|
continue;
|
|
@@ -29999,7 +30160,7 @@ class FileMerger {
|
|
|
29999
30160
|
continue;
|
|
30000
30161
|
}
|
|
30001
30162
|
if (this.userConfigChecker.ignores(normalizedRelativePath)) {
|
|
30002
|
-
const fileExists = await
|
|
30163
|
+
const fileExists = await import_fs_extra7.pathExists(destPath);
|
|
30003
30164
|
if (fileExists) {
|
|
30004
30165
|
logger.debug(`Skipping existing user config file: ${normalizedRelativePath}`);
|
|
30005
30166
|
skippedCount++;
|
|
@@ -30013,7 +30174,7 @@ class FileMerger {
|
|
|
30013
30174
|
copiedCount++;
|
|
30014
30175
|
continue;
|
|
30015
30176
|
}
|
|
30016
|
-
await
|
|
30177
|
+
await import_fs_extra7.copy(file, destPath, { overwrite: true });
|
|
30017
30178
|
this.trackInstalledFile(normalizedRelativePath);
|
|
30018
30179
|
copiedCount++;
|
|
30019
30180
|
}
|
|
@@ -30021,27 +30182,69 @@ class FileMerger {
|
|
|
30021
30182
|
}
|
|
30022
30183
|
async processSettingsJson(sourceFile, destFile) {
|
|
30023
30184
|
try {
|
|
30024
|
-
const
|
|
30185
|
+
const sourceContent = await import_fs_extra7.readFile(sourceFile, "utf-8");
|
|
30025
30186
|
const isWindows5 = process.platform === "win32";
|
|
30026
|
-
let
|
|
30187
|
+
let transformedSource = sourceContent;
|
|
30027
30188
|
if (this.isGlobal) {
|
|
30028
30189
|
const homeVar = isWindows5 ? '"%USERPROFILE%"' : '"$HOME"';
|
|
30029
|
-
|
|
30030
|
-
if (
|
|
30190
|
+
transformedSource = this.transformClaudePaths(sourceContent, homeVar);
|
|
30191
|
+
if (transformedSource !== sourceContent) {
|
|
30031
30192
|
logger.debug(`Transformed .claude/ paths to ${homeVar}/.claude/ in settings.json for global installation`);
|
|
30032
30193
|
}
|
|
30033
30194
|
} else {
|
|
30034
30195
|
const projectDirVar = isWindows5 ? '"%CLAUDE_PROJECT_DIR%"' : '"$CLAUDE_PROJECT_DIR"';
|
|
30035
|
-
|
|
30036
|
-
if (
|
|
30196
|
+
transformedSource = this.transformClaudePaths(sourceContent, projectDirVar);
|
|
30197
|
+
if (transformedSource !== sourceContent) {
|
|
30037
30198
|
logger.debug(`Transformed .claude/ paths to ${projectDirVar}/.claude/ in settings.json for local installation`);
|
|
30038
30199
|
}
|
|
30039
30200
|
}
|
|
30040
|
-
await
|
|
30201
|
+
const destExists = await import_fs_extra7.pathExists(destFile);
|
|
30202
|
+
if (destExists && !this.forceOverwriteSettings) {
|
|
30203
|
+
await this.selectiveMergeSettings(transformedSource, destFile);
|
|
30204
|
+
} else {
|
|
30205
|
+
await import_fs_extra7.writeFile(destFile, transformedSource, "utf-8");
|
|
30206
|
+
if (this.forceOverwriteSettings && destExists) {
|
|
30207
|
+
logger.debug("Force overwrite enabled, replaced settings.json completely");
|
|
30208
|
+
}
|
|
30209
|
+
}
|
|
30041
30210
|
} catch (error) {
|
|
30042
30211
|
logger.error(`Failed to process settings.json: ${error}`);
|
|
30043
|
-
await
|
|
30212
|
+
await import_fs_extra7.copy(sourceFile, destFile, { overwrite: true });
|
|
30213
|
+
}
|
|
30214
|
+
}
|
|
30215
|
+
async selectiveMergeSettings(transformedSourceContent, destFile) {
|
|
30216
|
+
let sourceSettings;
|
|
30217
|
+
try {
|
|
30218
|
+
sourceSettings = JSON.parse(transformedSourceContent);
|
|
30219
|
+
} catch {
|
|
30220
|
+
logger.warning("Failed to parse source settings.json, falling back to overwrite");
|
|
30221
|
+
await import_fs_extra7.writeFile(destFile, transformedSourceContent, "utf-8");
|
|
30222
|
+
return;
|
|
30223
|
+
}
|
|
30224
|
+
const destSettings = await SettingsMerger.readSettingsFile(destFile);
|
|
30225
|
+
if (!destSettings) {
|
|
30226
|
+
await import_fs_extra7.writeFile(destFile, transformedSourceContent, "utf-8");
|
|
30227
|
+
return;
|
|
30228
|
+
}
|
|
30229
|
+
const backupPath = await SettingsMerger.createBackup(destFile);
|
|
30230
|
+
if (backupPath) {
|
|
30231
|
+
logger.debug(`Created settings backup: ${backupPath}`);
|
|
30232
|
+
}
|
|
30233
|
+
const mergeResult = SettingsMerger.merge(sourceSettings, destSettings);
|
|
30234
|
+
if (mergeResult.hooksAdded > 0) {
|
|
30235
|
+
logger.debug(`Added ${mergeResult.hooksAdded} new hook(s)`);
|
|
30044
30236
|
}
|
|
30237
|
+
if (mergeResult.hooksPreserved > 0) {
|
|
30238
|
+
logger.debug(`Preserved ${mergeResult.hooksPreserved} existing hook(s)`);
|
|
30239
|
+
}
|
|
30240
|
+
if (mergeResult.mcpServersPreserved > 0) {
|
|
30241
|
+
logger.debug(`Preserved ${mergeResult.mcpServersPreserved} MCP server(s)`);
|
|
30242
|
+
}
|
|
30243
|
+
if (mergeResult.conflictsDetected.length > 0) {
|
|
30244
|
+
logger.warning(`Duplicate hooks detected (skipped): ${mergeResult.conflictsDetected.join(", ")}`);
|
|
30245
|
+
}
|
|
30246
|
+
await SettingsMerger.writeSettingsFile(destFile, mergeResult.merged);
|
|
30247
|
+
logger.success("Merged settings.json (user customizations preserved)");
|
|
30045
30248
|
}
|
|
30046
30249
|
transformClaudePaths(content, prefix) {
|
|
30047
30250
|
if (/\.claude\/[^\s"']*[;`$&|><]/.test(content)) {
|
|
@@ -30060,12 +30263,12 @@ class FileMerger {
|
|
|
30060
30263
|
}
|
|
30061
30264
|
async getFiles(dir, baseDir = dir) {
|
|
30062
30265
|
const files = [];
|
|
30063
|
-
const entries = await
|
|
30266
|
+
const entries = await import_fs_extra7.readdir(dir, { encoding: "utf8" });
|
|
30064
30267
|
for (const entry of entries) {
|
|
30065
30268
|
const fullPath = join15(dir, entry);
|
|
30066
30269
|
const relativePath = relative4(baseDir, fullPath);
|
|
30067
30270
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
30068
|
-
const stats = await
|
|
30271
|
+
const stats = await import_fs_extra7.lstat(fullPath);
|
|
30069
30272
|
if (stats.isSymbolicLink()) {
|
|
30070
30273
|
logger.warning(`Skipping symbolic link: ${normalizedRelativePath}`);
|
|
30071
30274
|
continue;
|
|
@@ -30123,14 +30326,14 @@ class FileMerger {
|
|
|
30123
30326
|
|
|
30124
30327
|
// src/lib/migration/legacy-migration.ts
|
|
30125
30328
|
init_logger();
|
|
30126
|
-
var
|
|
30329
|
+
var import_fs_extra9 = __toESM(require_lib(), 1);
|
|
30127
30330
|
import { readdir as readdir7, stat as stat3 } from "node:fs/promises";
|
|
30128
30331
|
import { join as join17, relative as relative5 } from "node:path";
|
|
30129
30332
|
|
|
30130
30333
|
// src/lib/migration/release-manifest.ts
|
|
30131
30334
|
init_zod();
|
|
30132
30335
|
init_logger();
|
|
30133
|
-
var
|
|
30336
|
+
var import_fs_extra8 = __toESM(require_lib(), 1);
|
|
30134
30337
|
import { join as join16 } from "node:path";
|
|
30135
30338
|
var ReleaseManifestFileSchema = exports_external.object({
|
|
30136
30339
|
path: exports_external.string(),
|
|
@@ -30147,7 +30350,7 @@ class ReleaseManifestLoader {
|
|
|
30147
30350
|
static async load(extractDir) {
|
|
30148
30351
|
const manifestPath = join16(extractDir, "release-manifest.json");
|
|
30149
30352
|
try {
|
|
30150
|
-
const content = await
|
|
30353
|
+
const content = await import_fs_extra8.readFile(manifestPath, "utf-8");
|
|
30151
30354
|
const parsed = JSON.parse(content);
|
|
30152
30355
|
return ReleaseManifestSchema.parse(parsed);
|
|
30153
30356
|
} catch (error) {
|
|
@@ -30315,7 +30518,7 @@ User-created files (sample):`);
|
|
|
30315
30518
|
files: trackedFiles
|
|
30316
30519
|
};
|
|
30317
30520
|
const metadataPath = join17(claudeDir, "metadata.json");
|
|
30318
|
-
await
|
|
30521
|
+
await import_fs_extra9.writeFile(metadataPath, JSON.stringify(updatedMetadata, null, 2));
|
|
30319
30522
|
logger.success(`Migration complete: tracked ${trackedFiles.length} files`);
|
|
30320
30523
|
return true;
|
|
30321
30524
|
}
|
|
@@ -30894,11 +31097,11 @@ class PromptsManager {
|
|
|
30894
31097
|
// src/lib/setup-wizard.ts
|
|
30895
31098
|
init_dist2();
|
|
30896
31099
|
init_logger();
|
|
30897
|
-
var
|
|
31100
|
+
var import_fs_extra11 = __toESM(require_lib(), 1);
|
|
30898
31101
|
import { join as join21 } from "node:path";
|
|
30899
31102
|
|
|
30900
31103
|
// src/lib/config-generator.ts
|
|
30901
|
-
var
|
|
31104
|
+
var import_fs_extra10 = __toESM(require_lib(), 1);
|
|
30902
31105
|
import { join as join20 } from "node:path";
|
|
30903
31106
|
async function generateEnvFile(targetDir, values) {
|
|
30904
31107
|
const lines = [
|
|
@@ -30912,7 +31115,7 @@ async function generateEnvFile(targetDir, values) {
|
|
|
30912
31115
|
}
|
|
30913
31116
|
}
|
|
30914
31117
|
const envPath = join20(targetDir, ".env");
|
|
30915
|
-
await
|
|
31118
|
+
await import_fs_extra10.writeFile(envPath, `${lines.join(`
|
|
30916
31119
|
`)}
|
|
30917
31120
|
`, { mode: 384 });
|
|
30918
31121
|
}
|
|
@@ -30956,7 +31159,7 @@ var ESSENTIAL_CONFIGS = [
|
|
|
30956
31159
|
];
|
|
30957
31160
|
async function parseEnvFile(path9) {
|
|
30958
31161
|
try {
|
|
30959
|
-
const content = await
|
|
31162
|
+
const content = await import_fs_extra11.readFile(path9, "utf-8");
|
|
30960
31163
|
const env2 = {};
|
|
30961
31164
|
for (const line of content.split(`
|
|
30962
31165
|
`)) {
|
|
@@ -30983,7 +31186,7 @@ async function parseEnvFile(path9) {
|
|
|
30983
31186
|
}
|
|
30984
31187
|
async function checkGlobalConfig() {
|
|
30985
31188
|
const globalEnvPath = join21(PathResolver.getGlobalKitDir(), ".env");
|
|
30986
|
-
if (!await
|
|
31189
|
+
if (!await import_fs_extra11.pathExists(globalEnvPath))
|
|
30987
31190
|
return false;
|
|
30988
31191
|
const env2 = await parseEnvFile(globalEnvPath);
|
|
30989
31192
|
return Object.keys(env2).length > 0;
|
|
@@ -30999,7 +31202,7 @@ async function runSetupWizard(options) {
|
|
|
30999
31202
|
const hasGlobalConfig = !isGlobal && await checkGlobalConfig();
|
|
31000
31203
|
if (!isGlobal) {
|
|
31001
31204
|
const globalEnvPath = join21(PathResolver.getGlobalKitDir(), ".env");
|
|
31002
|
-
if (await
|
|
31205
|
+
if (await import_fs_extra11.pathExists(globalEnvPath)) {
|
|
31003
31206
|
globalEnv = await parseEnvFile(globalEnvPath);
|
|
31004
31207
|
}
|
|
31005
31208
|
}
|
|
@@ -31057,16 +31260,16 @@ async function runSetupWizard(options) {
|
|
|
31057
31260
|
|
|
31058
31261
|
// src/lib/skills-detector.ts
|
|
31059
31262
|
init_logger();
|
|
31060
|
-
var
|
|
31263
|
+
var import_fs_extra13 = __toESM(require_lib(), 1);
|
|
31061
31264
|
import { readdir as readdir9 } from "node:fs/promises";
|
|
31062
31265
|
import { join as join23 } from "node:path";
|
|
31063
31266
|
|
|
31064
31267
|
// src/lib/skills-manifest.ts
|
|
31065
31268
|
init_types2();
|
|
31066
31269
|
init_logger();
|
|
31067
|
-
var
|
|
31270
|
+
var import_fs_extra12 = __toESM(require_lib(), 1);
|
|
31068
31271
|
import { createHash as createHash2 } from "node:crypto";
|
|
31069
|
-
import { readFile as
|
|
31272
|
+
import { readFile as readFile13, readdir as readdir8, writeFile as writeFile12 } from "node:fs/promises";
|
|
31070
31273
|
import { join as join22, relative as relative6 } from "node:path";
|
|
31071
31274
|
|
|
31072
31275
|
class SkillsManifestManager {
|
|
@@ -31074,7 +31277,7 @@ class SkillsManifestManager {
|
|
|
31074
31277
|
static MANIFEST_VERSION = "1.0.0";
|
|
31075
31278
|
static async generateManifest(skillsDir) {
|
|
31076
31279
|
logger.debug(`Generating manifest for: ${skillsDir}`);
|
|
31077
|
-
if (!await
|
|
31280
|
+
if (!await import_fs_extra12.pathExists(skillsDir)) {
|
|
31078
31281
|
throw new SkillsMigrationError(`Skills directory does not exist: ${skillsDir}`);
|
|
31079
31282
|
}
|
|
31080
31283
|
const structure = await SkillsManifestManager.detectStructure(skillsDir);
|
|
@@ -31090,17 +31293,17 @@ class SkillsManifestManager {
|
|
|
31090
31293
|
}
|
|
31091
31294
|
static async writeManifest(skillsDir, manifest) {
|
|
31092
31295
|
const manifestPath = join22(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
31093
|
-
await
|
|
31296
|
+
await writeFile12(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
31094
31297
|
logger.debug(`Wrote manifest to: ${manifestPath}`);
|
|
31095
31298
|
}
|
|
31096
31299
|
static async readManifest(skillsDir) {
|
|
31097
31300
|
const manifestPath = join22(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
31098
|
-
if (!await
|
|
31301
|
+
if (!await import_fs_extra12.pathExists(manifestPath)) {
|
|
31099
31302
|
logger.debug(`No manifest found at: ${manifestPath}`);
|
|
31100
31303
|
return null;
|
|
31101
31304
|
}
|
|
31102
31305
|
try {
|
|
31103
|
-
const content = await
|
|
31306
|
+
const content = await readFile13(manifestPath, "utf-8");
|
|
31104
31307
|
const data = JSON.parse(content);
|
|
31105
31308
|
const manifest = SkillsManifestSchema.parse(data);
|
|
31106
31309
|
logger.debug(`Read manifest from: ${manifestPath}`);
|
|
@@ -31172,7 +31375,7 @@ class SkillsManifestManager {
|
|
|
31172
31375
|
files.sort();
|
|
31173
31376
|
for (const file of files) {
|
|
31174
31377
|
const relativePath = relative6(dirPath, file);
|
|
31175
|
-
const content = await
|
|
31378
|
+
const content = await readFile13(file);
|
|
31176
31379
|
hash.update(relativePath);
|
|
31177
31380
|
hash.update(content);
|
|
31178
31381
|
}
|
|
@@ -31302,8 +31505,8 @@ function getPathMapping(skillName, oldBasePath, newBasePath) {
|
|
|
31302
31505
|
class SkillsMigrationDetector {
|
|
31303
31506
|
static async detectMigration(oldSkillsDir, currentSkillsDir) {
|
|
31304
31507
|
logger.debug("Detecting skills migration need...");
|
|
31305
|
-
const oldExists = await
|
|
31306
|
-
const currentExists = await
|
|
31508
|
+
const oldExists = await import_fs_extra13.pathExists(oldSkillsDir);
|
|
31509
|
+
const currentExists = await import_fs_extra13.pathExists(currentSkillsDir);
|
|
31307
31510
|
if (!oldExists && !currentExists) {
|
|
31308
31511
|
logger.debug("No skills directories found, migration not needed");
|
|
31309
31512
|
return {
|
|
@@ -31414,7 +31617,7 @@ class SkillsMigrationDetector {
|
|
|
31414
31617
|
};
|
|
31415
31618
|
}
|
|
31416
31619
|
static async scanDirectory(skillsDir) {
|
|
31417
|
-
if (!await
|
|
31620
|
+
if (!await import_fs_extra13.pathExists(skillsDir)) {
|
|
31418
31621
|
return ["flat", []];
|
|
31419
31622
|
}
|
|
31420
31623
|
const entries = await readdir9(skillsDir, { withFileTypes: true });
|
|
@@ -31467,14 +31670,14 @@ class SkillsMigrationDetector {
|
|
|
31467
31670
|
// src/lib/skills-migrator.ts
|
|
31468
31671
|
init_types2();
|
|
31469
31672
|
init_logger();
|
|
31470
|
-
var
|
|
31673
|
+
var import_fs_extra16 = __toESM(require_lib(), 1);
|
|
31471
31674
|
import { copyFile as copyFile2, mkdir as mkdir8, readdir as readdir12, rm as rm2 } from "node:fs/promises";
|
|
31472
31675
|
import { join as join26 } from "node:path";
|
|
31473
31676
|
|
|
31474
31677
|
// src/lib/skills-backup-manager.ts
|
|
31475
31678
|
init_types2();
|
|
31476
31679
|
init_logger();
|
|
31477
|
-
var
|
|
31680
|
+
var import_fs_extra14 = __toESM(require_lib(), 1);
|
|
31478
31681
|
import { copyFile, mkdir as mkdir7, readdir as readdir10, rm, stat as stat4 } from "node:fs/promises";
|
|
31479
31682
|
import { basename as basename2, join as join24, normalize as normalize4 } from "node:path";
|
|
31480
31683
|
function validatePath2(path9, paramName) {
|
|
@@ -31496,7 +31699,7 @@ class SkillsBackupManager {
|
|
|
31496
31699
|
if (parentDir) {
|
|
31497
31700
|
validatePath2(parentDir, "parentDir");
|
|
31498
31701
|
}
|
|
31499
|
-
if (!await
|
|
31702
|
+
if (!await import_fs_extra14.pathExists(skillsDir)) {
|
|
31500
31703
|
throw new SkillsMigrationError(`Cannot create backup: Skills directory does not exist: ${skillsDir}`);
|
|
31501
31704
|
}
|
|
31502
31705
|
const timestamp = Date.now();
|
|
@@ -31519,12 +31722,12 @@ class SkillsBackupManager {
|
|
|
31519
31722
|
static async restoreBackup(backupDir, targetDir) {
|
|
31520
31723
|
validatePath2(backupDir, "backupDir");
|
|
31521
31724
|
validatePath2(targetDir, "targetDir");
|
|
31522
|
-
if (!await
|
|
31725
|
+
if (!await import_fs_extra14.pathExists(backupDir)) {
|
|
31523
31726
|
throw new SkillsMigrationError(`Cannot restore: Backup directory does not exist: ${backupDir}`);
|
|
31524
31727
|
}
|
|
31525
31728
|
logger.info(`Restoring from backup: ${backupDir}`);
|
|
31526
31729
|
try {
|
|
31527
|
-
if (await
|
|
31730
|
+
if (await import_fs_extra14.pathExists(targetDir)) {
|
|
31528
31731
|
await rm(targetDir, { recursive: true, force: true });
|
|
31529
31732
|
}
|
|
31530
31733
|
await mkdir7(targetDir, { recursive: true });
|
|
@@ -31535,7 +31738,7 @@ class SkillsBackupManager {
|
|
|
31535
31738
|
}
|
|
31536
31739
|
}
|
|
31537
31740
|
static async deleteBackup(backupDir) {
|
|
31538
|
-
if (!await
|
|
31741
|
+
if (!await import_fs_extra14.pathExists(backupDir)) {
|
|
31539
31742
|
logger.warning(`Backup directory does not exist: ${backupDir}`);
|
|
31540
31743
|
return;
|
|
31541
31744
|
}
|
|
@@ -31548,7 +31751,7 @@ class SkillsBackupManager {
|
|
|
31548
31751
|
}
|
|
31549
31752
|
}
|
|
31550
31753
|
static async listBackups(parentDir) {
|
|
31551
|
-
if (!await
|
|
31754
|
+
if (!await import_fs_extra14.pathExists(parentDir)) {
|
|
31552
31755
|
return [];
|
|
31553
31756
|
}
|
|
31554
31757
|
try {
|
|
@@ -31573,7 +31776,7 @@ class SkillsBackupManager {
|
|
|
31573
31776
|
}
|
|
31574
31777
|
}
|
|
31575
31778
|
static async getBackupSize(backupDir) {
|
|
31576
|
-
if (!await
|
|
31779
|
+
if (!await import_fs_extra14.pathExists(backupDir)) {
|
|
31577
31780
|
return 0;
|
|
31578
31781
|
}
|
|
31579
31782
|
return await SkillsBackupManager.getDirectorySize(backupDir);
|
|
@@ -31625,10 +31828,10 @@ class SkillsBackupManager {
|
|
|
31625
31828
|
// src/lib/skills-customization-scanner.ts
|
|
31626
31829
|
init_types2();
|
|
31627
31830
|
init_logger();
|
|
31628
|
-
var
|
|
31831
|
+
var import_fs_extra15 = __toESM(require_lib(), 1);
|
|
31629
31832
|
import { createHash as createHash3 } from "node:crypto";
|
|
31630
31833
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
31631
|
-
import { readFile as
|
|
31834
|
+
import { readFile as readFile14, readdir as readdir11 } from "node:fs/promises";
|
|
31632
31835
|
import { join as join25, normalize as normalize5, relative as relative7 } from "node:path";
|
|
31633
31836
|
function validatePath3(path9, paramName) {
|
|
31634
31837
|
if (!path9 || typeof path9 !== "string") {
|
|
@@ -31708,7 +31911,7 @@ class SkillsCustomizationScanner {
|
|
|
31708
31911
|
static async detectFileChanges(currentSkillPath, baselineSkillPath) {
|
|
31709
31912
|
const changes = [];
|
|
31710
31913
|
const currentFiles = await SkillsCustomizationScanner.getAllFiles(currentSkillPath);
|
|
31711
|
-
const baselineFiles = await
|
|
31914
|
+
const baselineFiles = await import_fs_extra15.pathExists(baselineSkillPath) ? await SkillsCustomizationScanner.getAllFiles(baselineSkillPath) : [];
|
|
31712
31915
|
const currentFileMap = new Map(await Promise.all(currentFiles.map(async (f3) => {
|
|
31713
31916
|
const relPath = relative7(currentSkillPath, f3);
|
|
31714
31917
|
const hash = await SkillsCustomizationScanner.hashFile(f3);
|
|
@@ -31768,7 +31971,7 @@ class SkillsCustomizationScanner {
|
|
|
31768
31971
|
return false;
|
|
31769
31972
|
}
|
|
31770
31973
|
static async scanSkillsDirectory(skillsDir) {
|
|
31771
|
-
if (!await
|
|
31974
|
+
if (!await import_fs_extra15.pathExists(skillsDir)) {
|
|
31772
31975
|
return ["flat", []];
|
|
31773
31976
|
}
|
|
31774
31977
|
const entries = await readdir11(skillsDir, { withFileTypes: true });
|
|
@@ -31803,7 +32006,7 @@ class SkillsCustomizationScanner {
|
|
|
31803
32006
|
}
|
|
31804
32007
|
static async findSkillPath(skillsDir, skillName) {
|
|
31805
32008
|
const flatPath = join25(skillsDir, skillName);
|
|
31806
|
-
if (await
|
|
32009
|
+
if (await import_fs_extra15.pathExists(flatPath)) {
|
|
31807
32010
|
return { path: flatPath, category: undefined };
|
|
31808
32011
|
}
|
|
31809
32012
|
const entries = await readdir11(skillsDir, { withFileTypes: true });
|
|
@@ -31813,7 +32016,7 @@ class SkillsCustomizationScanner {
|
|
|
31813
32016
|
}
|
|
31814
32017
|
const categoryPath = join25(skillsDir, entry.name);
|
|
31815
32018
|
const skillPath = join25(categoryPath, skillName);
|
|
31816
|
-
if (await
|
|
32019
|
+
if (await import_fs_extra15.pathExists(skillPath)) {
|
|
31817
32020
|
return { path: skillPath, category: entry.name };
|
|
31818
32021
|
}
|
|
31819
32022
|
}
|
|
@@ -31856,7 +32059,7 @@ class SkillsCustomizationScanner {
|
|
|
31856
32059
|
files.sort();
|
|
31857
32060
|
for (const file of files) {
|
|
31858
32061
|
const relativePath = relative7(dirPath, file);
|
|
31859
|
-
const content = await
|
|
32062
|
+
const content = await readFile14(file);
|
|
31860
32063
|
hash.update(relativePath);
|
|
31861
32064
|
hash.update(content);
|
|
31862
32065
|
}
|
|
@@ -32125,7 +32328,7 @@ class SkillsMigrator {
|
|
|
32125
32328
|
try {
|
|
32126
32329
|
const skillName = mapping.skillName;
|
|
32127
32330
|
const currentSkillPath = mapping.oldPath;
|
|
32128
|
-
if (!await
|
|
32331
|
+
if (!await import_fs_extra16.pathExists(currentSkillPath)) {
|
|
32129
32332
|
logger.warning(`Skill not found, skipping: ${skillName}`);
|
|
32130
32333
|
continue;
|
|
32131
32334
|
}
|
|
@@ -32196,7 +32399,7 @@ init_types2();
|
|
|
32196
32399
|
init_types2();
|
|
32197
32400
|
init_logger();
|
|
32198
32401
|
import { existsSync as existsSync6 } from "node:fs";
|
|
32199
|
-
import { mkdir as mkdir9, readFile as
|
|
32402
|
+
import { mkdir as mkdir9, readFile as readFile15, rename as rename2, rm as rm3, writeFile as writeFile13 } from "node:fs/promises";
|
|
32200
32403
|
import { chmod as chmod2 } from "node:fs/promises";
|
|
32201
32404
|
import { platform as platform9 } from "node:os";
|
|
32202
32405
|
import { join as join27 } from "node:path";
|
|
@@ -32222,7 +32425,7 @@ class ConfigManager {
|
|
|
32222
32425
|
const configFile = PathResolver.getConfigFile(ConfigManager.globalFlag);
|
|
32223
32426
|
try {
|
|
32224
32427
|
if (existsSync6(configFile)) {
|
|
32225
|
-
const content = await
|
|
32428
|
+
const content = await readFile15(configFile, "utf-8");
|
|
32226
32429
|
const data = JSON.parse(content);
|
|
32227
32430
|
ConfigManager.config = ConfigSchema.parse(data);
|
|
32228
32431
|
logger.debug(`Config loaded from ${configFile}`);
|
|
@@ -32245,7 +32448,7 @@ class ConfigManager {
|
|
|
32245
32448
|
await chmod2(configDir, 448);
|
|
32246
32449
|
}
|
|
32247
32450
|
}
|
|
32248
|
-
await
|
|
32451
|
+
await writeFile13(configFile, JSON.stringify(validConfig, null, 2), "utf-8");
|
|
32249
32452
|
if (platform9() !== "win32") {
|
|
32250
32453
|
await chmod2(configFile, 384);
|
|
32251
32454
|
}
|
|
@@ -32276,7 +32479,7 @@ class ConfigManager {
|
|
|
32276
32479
|
const configPath = join27(configDir, PROJECT_CONFIG_FILE);
|
|
32277
32480
|
try {
|
|
32278
32481
|
if (existsSync6(configPath)) {
|
|
32279
|
-
const content = await
|
|
32482
|
+
const content = await readFile15(configPath, "utf-8");
|
|
32280
32483
|
const data = JSON.parse(content);
|
|
32281
32484
|
const folders = FoldersConfigSchema.parse(data.paths || data);
|
|
32282
32485
|
logger.debug(`Project config loaded from ${configPath}`);
|
|
@@ -32295,7 +32498,7 @@ class ConfigManager {
|
|
|
32295
32498
|
await mkdir9(configDir, { recursive: true });
|
|
32296
32499
|
}
|
|
32297
32500
|
const validFolders = FoldersConfigSchema.parse(folders);
|
|
32298
|
-
await
|
|
32501
|
+
await writeFile13(configPath, JSON.stringify({ paths: validFolders }, null, 2), "utf-8");
|
|
32299
32502
|
logger.debug(`Project config saved to ${configPath}`);
|
|
32300
32503
|
} catch (error) {
|
|
32301
32504
|
throw new Error(`Failed to save project config: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -32357,7 +32560,7 @@ init_environment();
|
|
|
32357
32560
|
|
|
32358
32561
|
// src/utils/file-scanner.ts
|
|
32359
32562
|
init_logger();
|
|
32360
|
-
var
|
|
32563
|
+
var import_fs_extra17 = __toESM(require_lib(), 1);
|
|
32361
32564
|
import { join as join28, relative as relative8, resolve as resolve4 } from "node:path";
|
|
32362
32565
|
var SKIP_DIRS2 = [
|
|
32363
32566
|
"node_modules",
|
|
@@ -32383,11 +32586,11 @@ class FileScanner {
|
|
|
32383
32586
|
static async getFiles(dirPath, relativeTo) {
|
|
32384
32587
|
const basePath = relativeTo || dirPath;
|
|
32385
32588
|
const files = [];
|
|
32386
|
-
if (!await
|
|
32589
|
+
if (!await import_fs_extra17.pathExists(dirPath)) {
|
|
32387
32590
|
return files;
|
|
32388
32591
|
}
|
|
32389
32592
|
try {
|
|
32390
|
-
const entries = await
|
|
32593
|
+
const entries = await import_fs_extra17.readdir(dirPath, { encoding: "utf8" });
|
|
32391
32594
|
for (const entry of entries) {
|
|
32392
32595
|
if (SKIP_DIRS2.includes(entry)) {
|
|
32393
32596
|
logger.debug(`Skipping directory: ${entry}`);
|
|
@@ -32400,7 +32603,7 @@ class FileScanner {
|
|
|
32400
32603
|
}
|
|
32401
32604
|
let stats;
|
|
32402
32605
|
try {
|
|
32403
|
-
stats = await
|
|
32606
|
+
stats = await import_fs_extra17.lstat(fullPath);
|
|
32404
32607
|
} catch (error) {
|
|
32405
32608
|
if (error instanceof Error && "code" in error && (error.code === "EACCES" || error.code === "EPERM")) {
|
|
32406
32609
|
logger.warning(`Skipping inaccessible path: ${entry}`);
|
|
@@ -32439,7 +32642,7 @@ class FileScanner {
|
|
|
32439
32642
|
const sourceFiles = await FileScanner.getFiles(sourceSubDir, sourceDir);
|
|
32440
32643
|
logger.debug(`findCustomFiles - destFiles count: ${destFiles.length}`);
|
|
32441
32644
|
logger.debug(`findCustomFiles - sourceFiles count: ${sourceFiles.length}`);
|
|
32442
|
-
const sourceExists = await
|
|
32645
|
+
const sourceExists = await import_fs_extra17.pathExists(sourceSubDir);
|
|
32443
32646
|
if (sourceExists && sourceFiles.length === 0 && destFiles.length > 100) {
|
|
32444
32647
|
logger.warning(`Source directory exists but is empty while destination has ${destFiles.length} files. This may indicate an extraction issue. Skipping custom file detection.`);
|
|
32445
32648
|
return [];
|
|
@@ -32487,7 +32690,7 @@ async function initCommand(options) {
|
|
|
32487
32690
|
const cwdResolved = resolve5(process.cwd());
|
|
32488
32691
|
const isInGlobalDir = cwdResolved === globalKitDir || cwdResolved === resolve5(globalKitDir, "..");
|
|
32489
32692
|
const localSettingsPath = join29(process.cwd(), ".claude", "settings.json");
|
|
32490
|
-
if (!isInGlobalDir && await
|
|
32693
|
+
if (!isInGlobalDir && await import_fs_extra18.pathExists(localSettingsPath)) {
|
|
32491
32694
|
if (isNonInteractive2) {
|
|
32492
32695
|
logger.warning("Local .claude/settings.json detected. Local settings take precedence over global.");
|
|
32493
32696
|
logger.warning("Consider removing local installation: rm -rf .claude");
|
|
@@ -32500,7 +32703,7 @@ async function initCommand(options) {
|
|
|
32500
32703
|
if (choice === "remove") {
|
|
32501
32704
|
const localClaudeDir = join29(process.cwd(), ".claude");
|
|
32502
32705
|
try {
|
|
32503
|
-
await
|
|
32706
|
+
await import_fs_extra18.remove(localClaudeDir);
|
|
32504
32707
|
logger.success("Removed local .claude/ directory");
|
|
32505
32708
|
} catch (error) {
|
|
32506
32709
|
logger.error(`Failed to remove local installation: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -32544,7 +32747,7 @@ async function initCommand(options) {
|
|
|
32544
32747
|
}
|
|
32545
32748
|
const resolvedDir = resolve5(targetDir);
|
|
32546
32749
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
32547
|
-
if (!await
|
|
32750
|
+
if (!await import_fs_extra18.pathExists(resolvedDir)) {
|
|
32548
32751
|
if (validOptions.global) {
|
|
32549
32752
|
const { mkdir: mkdir10 } = await import("node:fs/promises");
|
|
32550
32753
|
await mkdir10(resolvedDir, { recursive: true });
|
|
@@ -32696,7 +32899,7 @@ async function initCommand(options) {
|
|
|
32696
32899
|
if (!validOptions.fresh) {
|
|
32697
32900
|
const newSkillsDir = join29(extractDir, ".claude", "skills");
|
|
32698
32901
|
const currentSkillsDir = PathResolver.buildSkillsPath(resolvedDir, validOptions.global);
|
|
32699
|
-
if (await
|
|
32902
|
+
if (await import_fs_extra18.pathExists(newSkillsDir) && await import_fs_extra18.pathExists(currentSkillsDir)) {
|
|
32700
32903
|
logger.info("Checking for skills directory migration...");
|
|
32701
32904
|
const migrationDetection = await SkillsMigrationDetector.detectMigration(newSkillsDir, currentSkillsDir);
|
|
32702
32905
|
if (migrationDetection.status === "recommended" || migrationDetection.status === "required") {
|
|
@@ -32748,9 +32951,10 @@ async function initCommand(options) {
|
|
|
32748
32951
|
merger.addIgnorePatterns(validOptions.exclude);
|
|
32749
32952
|
}
|
|
32750
32953
|
merger.setGlobalFlag(validOptions.global);
|
|
32954
|
+
merger.setForceOverwriteSettings(validOptions.forceOverwriteSettings);
|
|
32751
32955
|
const claudeDir = validOptions.global ? resolvedDir : join29(resolvedDir, ".claude");
|
|
32752
32956
|
const releaseManifest = await ReleaseManifestLoader.load(extractDir);
|
|
32753
|
-
if (!validOptions.fresh && await
|
|
32957
|
+
if (!validOptions.fresh && await import_fs_extra18.pathExists(claudeDir)) {
|
|
32754
32958
|
const legacyDetection = await LegacyMigration.detectLegacy(claudeDir);
|
|
32755
32959
|
if (legacyDetection.isLegacy && releaseManifest) {
|
|
32756
32960
|
logger.info("Legacy installation detected - migrating to ownership tracking...");
|
|
@@ -32802,9 +33006,9 @@ async function initCommand(options) {
|
|
|
32802
33006
|
if (validOptions.global) {
|
|
32803
33007
|
const claudeMdSource = join29(extractDir, "CLAUDE.md");
|
|
32804
33008
|
const claudeMdDest = join29(resolvedDir, "CLAUDE.md");
|
|
32805
|
-
if (await
|
|
32806
|
-
if (!await
|
|
32807
|
-
await
|
|
33009
|
+
if (await import_fs_extra18.pathExists(claudeMdSource)) {
|
|
33010
|
+
if (!await import_fs_extra18.pathExists(claudeMdDest)) {
|
|
33011
|
+
await import_fs_extra18.copy(claudeMdSource, claudeMdDest);
|
|
32808
33012
|
logger.success("Copied CLAUDE.md to global directory");
|
|
32809
33013
|
} else {
|
|
32810
33014
|
logger.debug("CLAUDE.md already exists in global directory (preserved)");
|
|
@@ -32822,7 +33026,7 @@ async function initCommand(options) {
|
|
|
32822
33026
|
}
|
|
32823
33027
|
if (!validOptions.skipSetup && !isNonInteractive2) {
|
|
32824
33028
|
const envPath = join29(claudeDir, ".env");
|
|
32825
|
-
if (!await
|
|
33029
|
+
if (!await import_fs_extra18.pathExists(envPath)) {
|
|
32826
33030
|
const shouldSetup = await prompts.confirm("Set up API keys now? (Gemini API key for ai-multimodal skill, optional webhooks)");
|
|
32827
33031
|
if (shouldSetup) {
|
|
32828
33032
|
await runSetupWizard({
|
|
@@ -32852,7 +33056,7 @@ Protected files (.env, etc.) were not modified.`;
|
|
|
32852
33056
|
}
|
|
32853
33057
|
|
|
32854
33058
|
// src/commands/new.ts
|
|
32855
|
-
var
|
|
33059
|
+
var import_fs_extra19 = __toESM(require_lib(), 1);
|
|
32856
33060
|
import { join as join30, resolve as resolve6 } from "node:path";
|
|
32857
33061
|
init_types2();
|
|
32858
33062
|
init_environment();
|
|
@@ -32884,8 +33088,8 @@ async function newCommand(options) {
|
|
|
32884
33088
|
}
|
|
32885
33089
|
const resolvedDir = resolve6(targetDir);
|
|
32886
33090
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
32887
|
-
if (await
|
|
32888
|
-
const files = await
|
|
33091
|
+
if (await import_fs_extra19.pathExists(resolvedDir)) {
|
|
33092
|
+
const files = await import_fs_extra19.readdir(resolvedDir);
|
|
32889
33093
|
const isEmpty = files.length === 0;
|
|
32890
33094
|
if (!isEmpty) {
|
|
32891
33095
|
if (isNonInteractive2) {
|
|
@@ -33085,7 +33289,7 @@ async function newCommand(options) {
|
|
|
33085
33289
|
}
|
|
33086
33290
|
|
|
33087
33291
|
// src/commands/uninstall.ts
|
|
33088
|
-
var
|
|
33292
|
+
var import_fs_extra20 = __toESM(require_lib(), 1);
|
|
33089
33293
|
var import_picocolors10 = __toESM(require_picocolors(), 1);
|
|
33090
33294
|
import { readdirSync, rmSync } from "node:fs";
|
|
33091
33295
|
import { dirname as dirname5, join as join31 } from "node:path";
|
|
@@ -33098,14 +33302,14 @@ async function detectInstallations() {
|
|
|
33098
33302
|
installations.push({
|
|
33099
33303
|
type: "local",
|
|
33100
33304
|
path: setup.project.path,
|
|
33101
|
-
exists: await
|
|
33305
|
+
exists: await import_fs_extra20.pathExists(setup.project.path)
|
|
33102
33306
|
});
|
|
33103
33307
|
}
|
|
33104
33308
|
if (setup.global.path && setup.global.metadata) {
|
|
33105
33309
|
installations.push({
|
|
33106
33310
|
type: "global",
|
|
33107
33311
|
path: setup.global.path,
|
|
33108
|
-
exists: await
|
|
33312
|
+
exists: await import_fs_extra20.pathExists(setup.global.path)
|
|
33109
33313
|
});
|
|
33110
33314
|
}
|
|
33111
33315
|
return installations.filter((i) => i.exists);
|
|
@@ -33238,8 +33442,8 @@ async function removeInstallations(installations, options) {
|
|
|
33238
33442
|
let cleanedDirs = 0;
|
|
33239
33443
|
for (const item of analysis.toDelete) {
|
|
33240
33444
|
const filePath = join31(installation.path, item.path);
|
|
33241
|
-
if (await
|
|
33242
|
-
await
|
|
33445
|
+
if (await import_fs_extra20.pathExists(filePath)) {
|
|
33446
|
+
await import_fs_extra20.remove(filePath);
|
|
33243
33447
|
removedCount++;
|
|
33244
33448
|
logger.debug(`Removed: ${item.path}`);
|
|
33245
33449
|
cleanedDirs += await cleanupEmptyDirectories(filePath, installation.path);
|
|
@@ -33338,7 +33542,7 @@ import { promisify as promisify6 } from "node:util";
|
|
|
33338
33542
|
// package.json
|
|
33339
33543
|
var package_default2 = {
|
|
33340
33544
|
name: "claudekit-cli",
|
|
33341
|
-
version: "3.
|
|
33545
|
+
version: "3.8.0",
|
|
33342
33546
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
33343
33547
|
type: "module",
|
|
33344
33548
|
repository: {
|
|
@@ -33784,7 +33988,7 @@ var import_picocolors12 = __toESM(require_picocolors(), 1);
|
|
|
33784
33988
|
// src/lib/version-cache.ts
|
|
33785
33989
|
init_logger();
|
|
33786
33990
|
import { existsSync as existsSync7 } from "node:fs";
|
|
33787
|
-
import { mkdir as mkdir10, readFile as
|
|
33991
|
+
import { mkdir as mkdir10, readFile as readFile16, writeFile as writeFile14 } from "node:fs/promises";
|
|
33788
33992
|
import { join as join32 } from "node:path";
|
|
33789
33993
|
class VersionCacheManager {
|
|
33790
33994
|
static CACHE_FILENAME = "version-check.json";
|
|
@@ -33800,7 +34004,7 @@ class VersionCacheManager {
|
|
|
33800
34004
|
logger.debug("Version check cache not found");
|
|
33801
34005
|
return null;
|
|
33802
34006
|
}
|
|
33803
|
-
const content = await
|
|
34007
|
+
const content = await readFile16(cacheFile, "utf-8");
|
|
33804
34008
|
const cache2 = JSON.parse(content);
|
|
33805
34009
|
if (!cache2.lastCheck || !cache2.currentVersion || !cache2.latestVersion) {
|
|
33806
34010
|
logger.debug("Invalid cache structure, ignoring");
|
|
@@ -33820,7 +34024,7 @@ class VersionCacheManager {
|
|
|
33820
34024
|
if (!existsSync7(cacheDir)) {
|
|
33821
34025
|
await mkdir10(cacheDir, { recursive: true, mode: 448 });
|
|
33822
34026
|
}
|
|
33823
|
-
await
|
|
34027
|
+
await writeFile14(cacheFile, JSON.stringify(cache2, null, 2), "utf-8");
|
|
33824
34028
|
logger.debug(`Version check cache saved to ${cacheFile}`);
|
|
33825
34029
|
} catch (error) {
|
|
33826
34030
|
logger.debug(`Failed to save version check cache: ${error}`);
|
|
@@ -34064,6 +34268,7 @@ var UpdateCommandOptionsSchema2 = exports_external.object({
|
|
|
34064
34268
|
beta: exports_external.boolean().default(false),
|
|
34065
34269
|
dryRun: exports_external.boolean().default(false),
|
|
34066
34270
|
forceOverwrite: exports_external.boolean().default(false),
|
|
34271
|
+
forceOverwriteSettings: exports_external.boolean().default(false),
|
|
34067
34272
|
skipSetup: exports_external.boolean().default(false),
|
|
34068
34273
|
refresh: exports_external.boolean().default(false),
|
|
34069
34274
|
docsDir: exports_external.string().optional(),
|
|
@@ -34447,7 +34652,7 @@ cli.command("new", "Bootstrap a new ClaudeKit project (with interactive version
|
|
|
34447
34652
|
}
|
|
34448
34653
|
await newCommand(options);
|
|
34449
34654
|
});
|
|
34450
|
-
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)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").action(async (options) => {
|
|
34655
|
+
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("--force-overwrite-settings", "Fully replace settings.json instead of selective merge (destroys user customizations)").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)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").action(async (options) => {
|
|
34451
34656
|
if (options.exclude && !Array.isArray(options.exclude)) {
|
|
34452
34657
|
options.exclude = [options.exclude];
|
|
34453
34658
|
}
|