claudekit-cli 3.30.0-dev.1 → 3.30.0-dev.3
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 +578 -399
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7762,6 +7762,7 @@ var init_commands = __esm(() => {
|
|
|
7762
7762
|
release: exports_external.string().optional(),
|
|
7763
7763
|
check: exports_external.boolean().default(false),
|
|
7764
7764
|
yes: exports_external.boolean().default(false),
|
|
7765
|
+
dev: exports_external.boolean().default(false),
|
|
7765
7766
|
beta: exports_external.boolean().default(false),
|
|
7766
7767
|
registry: exports_external.string().url().optional()
|
|
7767
7768
|
}).merge(GlobalOutputOptionsSchema);
|
|
@@ -18149,7 +18150,7 @@ function getPagerArgs(pagerCmd) {
|
|
|
18149
18150
|
return [];
|
|
18150
18151
|
}
|
|
18151
18152
|
async function trySystemPager(content) {
|
|
18152
|
-
return new Promise((
|
|
18153
|
+
return new Promise((resolve12) => {
|
|
18153
18154
|
const pagerCmd = process.env.PAGER || "less";
|
|
18154
18155
|
const pagerArgs = getPagerArgs(pagerCmd);
|
|
18155
18156
|
try {
|
|
@@ -18159,20 +18160,20 @@ async function trySystemPager(content) {
|
|
|
18159
18160
|
});
|
|
18160
18161
|
const timeout = setTimeout(() => {
|
|
18161
18162
|
pager.kill();
|
|
18162
|
-
|
|
18163
|
+
resolve12(false);
|
|
18163
18164
|
}, 30000);
|
|
18164
18165
|
pager.stdin.write(content);
|
|
18165
18166
|
pager.stdin.end();
|
|
18166
18167
|
pager.on("close", (code2) => {
|
|
18167
18168
|
clearTimeout(timeout);
|
|
18168
|
-
|
|
18169
|
+
resolve12(code2 === 0);
|
|
18169
18170
|
});
|
|
18170
18171
|
pager.on("error", () => {
|
|
18171
18172
|
clearTimeout(timeout);
|
|
18172
|
-
|
|
18173
|
+
resolve12(false);
|
|
18173
18174
|
});
|
|
18174
18175
|
} catch {
|
|
18175
|
-
|
|
18176
|
+
resolve12(false);
|
|
18176
18177
|
}
|
|
18177
18178
|
});
|
|
18178
18179
|
}
|
|
@@ -18199,16 +18200,16 @@ async function basicPager(content) {
|
|
|
18199
18200
|
break;
|
|
18200
18201
|
}
|
|
18201
18202
|
const remaining = lines.length - currentLine;
|
|
18202
|
-
await new Promise((
|
|
18203
|
+
await new Promise((resolve12) => {
|
|
18203
18204
|
rl.question(`-- More (${remaining} lines) [Enter/q] --`, (answer) => {
|
|
18204
18205
|
if (answer.toLowerCase() === "q") {
|
|
18205
18206
|
rl.close();
|
|
18206
18207
|
process.exitCode = 0;
|
|
18207
|
-
|
|
18208
|
+
resolve12();
|
|
18208
18209
|
return;
|
|
18209
18210
|
}
|
|
18210
18211
|
process.stdout.write("\x1B[1A\x1B[2K");
|
|
18211
|
-
|
|
18212
|
+
resolve12();
|
|
18212
18213
|
});
|
|
18213
18214
|
});
|
|
18214
18215
|
}
|
|
@@ -35225,22 +35226,11 @@ async function handleDownload(ctx) {
|
|
|
35225
35226
|
};
|
|
35226
35227
|
}
|
|
35227
35228
|
// src/commands/init/phases/merge-handler.ts
|
|
35228
|
-
import { join as
|
|
35229
|
-
|
|
35230
|
-
// src/domains/installation/file-merger.ts
|
|
35231
|
-
init_logger();
|
|
35232
|
-
init_types2();
|
|
35233
|
-
init_dist2();
|
|
35234
|
-
|
|
35235
|
-
// src/domains/installation/merger/copy-executor.ts
|
|
35236
|
-
init_logger();
|
|
35237
|
-
init_types2();
|
|
35238
|
-
var import_fs_extra10 = __toESM(require_lib(), 1);
|
|
35239
|
-
var import_ignore3 = __toESM(require_ignore(), 1);
|
|
35240
|
-
import { dirname as dirname8, join as join43, relative as relative6 } from "node:path";
|
|
35229
|
+
import { join as join54 } from "node:path";
|
|
35241
35230
|
|
|
35242
|
-
// src/domains/installation/
|
|
35243
|
-
import {
|
|
35231
|
+
// src/domains/installation/deletion-handler.ts
|
|
35232
|
+
import { existsSync as existsSync17, lstatSync as lstatSync2, readdirSync, rmSync as rmSync2, rmdirSync, unlinkSync as unlinkSync3 } from "node:fs";
|
|
35233
|
+
import { dirname as dirname6, join as join40, resolve as resolve6 } from "node:path";
|
|
35244
35234
|
|
|
35245
35235
|
// src/services/file-operations/manifest/manifest-reader.ts
|
|
35246
35236
|
import { join as join39 } from "node:path";
|
|
@@ -35389,7 +35379,172 @@ async function getUninstallManifest(claudeDir, kit) {
|
|
|
35389
35379
|
};
|
|
35390
35380
|
}
|
|
35391
35381
|
|
|
35382
|
+
// src/domains/installation/deletion-handler.ts
|
|
35383
|
+
init_logger();
|
|
35384
|
+
var import_fs_extra7 = __toESM(require_lib(), 1);
|
|
35385
|
+
function findFileInMetadata(metadata, path10) {
|
|
35386
|
+
if (!metadata)
|
|
35387
|
+
return null;
|
|
35388
|
+
if (metadata.kits) {
|
|
35389
|
+
for (const kitMeta of Object.values(metadata.kits)) {
|
|
35390
|
+
if (kitMeta?.files) {
|
|
35391
|
+
const found = kitMeta.files.find((f3) => f3.path === path10);
|
|
35392
|
+
if (found)
|
|
35393
|
+
return found;
|
|
35394
|
+
}
|
|
35395
|
+
}
|
|
35396
|
+
}
|
|
35397
|
+
if (metadata.files) {
|
|
35398
|
+
const found = metadata.files.find((f3) => f3.path === path10);
|
|
35399
|
+
if (found)
|
|
35400
|
+
return found;
|
|
35401
|
+
}
|
|
35402
|
+
return null;
|
|
35403
|
+
}
|
|
35404
|
+
function shouldDeletePath(path10, metadata) {
|
|
35405
|
+
const tracked = findFileInMetadata(metadata, path10);
|
|
35406
|
+
if (!tracked)
|
|
35407
|
+
return true;
|
|
35408
|
+
return tracked.ownership !== "user";
|
|
35409
|
+
}
|
|
35410
|
+
var MAX_CLEANUP_ITERATIONS = 50;
|
|
35411
|
+
function cleanupEmptyDirectories(filePath, claudeDir) {
|
|
35412
|
+
const normalizedClaudeDir = resolve6(claudeDir);
|
|
35413
|
+
let currentDir = resolve6(dirname6(filePath));
|
|
35414
|
+
let iterations = 0;
|
|
35415
|
+
while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir) && iterations < MAX_CLEANUP_ITERATIONS) {
|
|
35416
|
+
iterations++;
|
|
35417
|
+
try {
|
|
35418
|
+
const entries = readdirSync(currentDir);
|
|
35419
|
+
if (entries.length === 0) {
|
|
35420
|
+
rmdirSync(currentDir);
|
|
35421
|
+
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
35422
|
+
currentDir = resolve6(dirname6(currentDir));
|
|
35423
|
+
} else {
|
|
35424
|
+
break;
|
|
35425
|
+
}
|
|
35426
|
+
} catch {
|
|
35427
|
+
break;
|
|
35428
|
+
}
|
|
35429
|
+
}
|
|
35430
|
+
}
|
|
35431
|
+
function deletePath(fullPath, claudeDir) {
|
|
35432
|
+
const normalizedPath = resolve6(fullPath);
|
|
35433
|
+
const normalizedClaudeDir = resolve6(claudeDir);
|
|
35434
|
+
if (!normalizedPath.startsWith(`${normalizedClaudeDir}/`) && normalizedPath !== normalizedClaudeDir) {
|
|
35435
|
+
throw new Error(`Path traversal detected: ${fullPath}`);
|
|
35436
|
+
}
|
|
35437
|
+
try {
|
|
35438
|
+
const stat6 = lstatSync2(fullPath);
|
|
35439
|
+
if (stat6.isDirectory()) {
|
|
35440
|
+
rmSync2(fullPath, { recursive: true, force: true });
|
|
35441
|
+
} else {
|
|
35442
|
+
unlinkSync3(fullPath);
|
|
35443
|
+
cleanupEmptyDirectories(fullPath, claudeDir);
|
|
35444
|
+
}
|
|
35445
|
+
} catch (error) {
|
|
35446
|
+
throw new Error(`Failed to delete ${fullPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
35447
|
+
}
|
|
35448
|
+
}
|
|
35449
|
+
async function updateMetadataAfterDeletion(claudeDir, deletedPaths) {
|
|
35450
|
+
const metadataPath = join40(claudeDir, "metadata.json");
|
|
35451
|
+
if (!await import_fs_extra7.pathExists(metadataPath)) {
|
|
35452
|
+
return;
|
|
35453
|
+
}
|
|
35454
|
+
let content;
|
|
35455
|
+
try {
|
|
35456
|
+
content = await import_fs_extra7.readFile(metadataPath, "utf-8");
|
|
35457
|
+
} catch {
|
|
35458
|
+
logger.debug("Failed to read metadata.json for cleanup");
|
|
35459
|
+
return;
|
|
35460
|
+
}
|
|
35461
|
+
let metadata;
|
|
35462
|
+
try {
|
|
35463
|
+
metadata = JSON.parse(content);
|
|
35464
|
+
} catch {
|
|
35465
|
+
logger.debug("Failed to parse metadata.json for cleanup");
|
|
35466
|
+
return;
|
|
35467
|
+
}
|
|
35468
|
+
const deletedSet = new Set(deletedPaths);
|
|
35469
|
+
const isDeletedOrInDeletedDir = (path10) => {
|
|
35470
|
+
if (deletedSet.has(path10))
|
|
35471
|
+
return true;
|
|
35472
|
+
for (const deleted of deletedPaths) {
|
|
35473
|
+
if (path10.startsWith(`${deleted}/`))
|
|
35474
|
+
return true;
|
|
35475
|
+
}
|
|
35476
|
+
return false;
|
|
35477
|
+
};
|
|
35478
|
+
if (metadata.kits) {
|
|
35479
|
+
for (const kitName of Object.keys(metadata.kits)) {
|
|
35480
|
+
const kit = metadata.kits[kitName];
|
|
35481
|
+
if (kit?.files) {
|
|
35482
|
+
kit.files = kit.files.filter((f3) => !isDeletedOrInDeletedDir(f3.path));
|
|
35483
|
+
}
|
|
35484
|
+
}
|
|
35485
|
+
}
|
|
35486
|
+
if (metadata.files) {
|
|
35487
|
+
metadata.files = metadata.files.filter((f3) => !isDeletedOrInDeletedDir(f3.path));
|
|
35488
|
+
}
|
|
35489
|
+
try {
|
|
35490
|
+
await import_fs_extra7.writeFile(metadataPath, JSON.stringify(metadata, null, 2));
|
|
35491
|
+
logger.debug(`Updated metadata.json, removed ${deletedPaths.length} entries`);
|
|
35492
|
+
} catch {
|
|
35493
|
+
logger.debug("Failed to write updated metadata.json");
|
|
35494
|
+
}
|
|
35495
|
+
}
|
|
35496
|
+
async function handleDeletions(sourceMetadata, claudeDir) {
|
|
35497
|
+
const deletions = sourceMetadata.deletions || [];
|
|
35498
|
+
if (deletions.length === 0) {
|
|
35499
|
+
return { deletedPaths: [], preservedPaths: [], errors: [] };
|
|
35500
|
+
}
|
|
35501
|
+
const userMetadata = await readManifest(claudeDir);
|
|
35502
|
+
const result = { deletedPaths: [], preservedPaths: [], errors: [] };
|
|
35503
|
+
for (const path10 of deletions) {
|
|
35504
|
+
const fullPath = join40(claudeDir, path10);
|
|
35505
|
+
const normalizedPath = resolve6(fullPath);
|
|
35506
|
+
const normalizedClaudeDir = resolve6(claudeDir);
|
|
35507
|
+
if (!normalizedPath.startsWith(`${normalizedClaudeDir}/`)) {
|
|
35508
|
+
logger.warning(`Skipping invalid path: ${path10}`);
|
|
35509
|
+
result.errors.push(path10);
|
|
35510
|
+
continue;
|
|
35511
|
+
}
|
|
35512
|
+
if (!shouldDeletePath(path10, userMetadata)) {
|
|
35513
|
+
result.preservedPaths.push(path10);
|
|
35514
|
+
logger.verbose(`Preserved user file: ${path10}`);
|
|
35515
|
+
continue;
|
|
35516
|
+
}
|
|
35517
|
+
if (existsSync17(fullPath)) {
|
|
35518
|
+
try {
|
|
35519
|
+
deletePath(fullPath, claudeDir);
|
|
35520
|
+
result.deletedPaths.push(path10);
|
|
35521
|
+
logger.verbose(`Deleted: ${path10}`);
|
|
35522
|
+
} catch (error) {
|
|
35523
|
+
result.errors.push(path10);
|
|
35524
|
+
logger.debug(`Failed to delete ${path10}: ${error}`);
|
|
35525
|
+
}
|
|
35526
|
+
}
|
|
35527
|
+
}
|
|
35528
|
+
if (result.deletedPaths.length > 0) {
|
|
35529
|
+
await updateMetadataAfterDeletion(claudeDir, result.deletedPaths);
|
|
35530
|
+
}
|
|
35531
|
+
return result;
|
|
35532
|
+
}
|
|
35533
|
+
|
|
35534
|
+
// src/domains/installation/file-merger.ts
|
|
35535
|
+
init_logger();
|
|
35536
|
+
init_types2();
|
|
35537
|
+
init_dist2();
|
|
35538
|
+
|
|
35539
|
+
// src/domains/installation/merger/copy-executor.ts
|
|
35540
|
+
init_logger();
|
|
35541
|
+
init_types2();
|
|
35542
|
+
var import_fs_extra11 = __toESM(require_lib(), 1);
|
|
35543
|
+
var import_ignore3 = __toESM(require_ignore(), 1);
|
|
35544
|
+
import { dirname as dirname9, join as join44, relative as relative6 } from "node:path";
|
|
35545
|
+
|
|
35392
35546
|
// src/domains/installation/selective-merger.ts
|
|
35547
|
+
import { stat as stat6 } from "node:fs/promises";
|
|
35393
35548
|
init_logger();
|
|
35394
35549
|
var import_semver = __toESM(require_semver2(), 1);
|
|
35395
35550
|
|
|
@@ -35562,10 +35717,10 @@ class SelectiveMerger {
|
|
|
35562
35717
|
|
|
35563
35718
|
// src/domains/installation/merger/file-scanner.ts
|
|
35564
35719
|
init_logger();
|
|
35565
|
-
var
|
|
35720
|
+
var import_fs_extra8 = __toESM(require_lib(), 1);
|
|
35566
35721
|
var import_ignore2 = __toESM(require_ignore(), 1);
|
|
35567
35722
|
import { relative as relative5 } from "node:path";
|
|
35568
|
-
import { join as
|
|
35723
|
+
import { join as join41 } from "node:path";
|
|
35569
35724
|
|
|
35570
35725
|
// node_modules/@isaacs/balanced-match/dist/esm/index.js
|
|
35571
35726
|
var balanced = (a3, b3, str) => {
|
|
@@ -37019,12 +37174,12 @@ class FileScanner {
|
|
|
37019
37174
|
}
|
|
37020
37175
|
async getFiles(dir, baseDir = dir) {
|
|
37021
37176
|
const files = [];
|
|
37022
|
-
const entries = await
|
|
37177
|
+
const entries = await import_fs_extra8.readdir(dir, { encoding: "utf8" });
|
|
37023
37178
|
for (const entry of entries) {
|
|
37024
|
-
const fullPath =
|
|
37179
|
+
const fullPath = join41(dir, entry);
|
|
37025
37180
|
const relativePath = relative5(baseDir, fullPath);
|
|
37026
37181
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
37027
|
-
const stats = await
|
|
37182
|
+
const stats = await import_fs_extra8.lstat(fullPath);
|
|
37028
37183
|
if (stats.isSymbolicLink()) {
|
|
37029
37184
|
logger.warning(`Skipping symbolic link: ${normalizedRelativePath}`);
|
|
37030
37185
|
continue;
|
|
@@ -37055,9 +37210,9 @@ class FileScanner {
|
|
|
37055
37210
|
}
|
|
37056
37211
|
|
|
37057
37212
|
// src/domains/config/installed-settings-tracker.ts
|
|
37058
|
-
import { existsSync as
|
|
37059
|
-
import { mkdir as mkdir15, readFile as
|
|
37060
|
-
import { dirname as
|
|
37213
|
+
import { existsSync as existsSync18 } from "node:fs";
|
|
37214
|
+
import { mkdir as mkdir15, readFile as readFile14, writeFile as writeFile11 } from "node:fs/promises";
|
|
37215
|
+
import { dirname as dirname7, join as join42 } from "node:path";
|
|
37061
37216
|
|
|
37062
37217
|
// src/shared/index.ts
|
|
37063
37218
|
init_logger();
|
|
@@ -37097,17 +37252,17 @@ class InstalledSettingsTracker {
|
|
|
37097
37252
|
}
|
|
37098
37253
|
getCkJsonPath() {
|
|
37099
37254
|
if (this.isGlobal) {
|
|
37100
|
-
return
|
|
37255
|
+
return join42(this.projectDir, CK_JSON_FILE);
|
|
37101
37256
|
}
|
|
37102
|
-
return
|
|
37257
|
+
return join42(this.projectDir, ".claude", CK_JSON_FILE);
|
|
37103
37258
|
}
|
|
37104
37259
|
async loadInstalledSettings() {
|
|
37105
37260
|
const ckJsonPath = this.getCkJsonPath();
|
|
37106
|
-
if (!
|
|
37261
|
+
if (!existsSync18(ckJsonPath)) {
|
|
37107
37262
|
return { hooks: [], mcpServers: [] };
|
|
37108
37263
|
}
|
|
37109
37264
|
try {
|
|
37110
|
-
const content = await
|
|
37265
|
+
const content = await readFile14(ckJsonPath, "utf-8");
|
|
37111
37266
|
const data = JSON.parse(content);
|
|
37112
37267
|
const installed = data.kits?.[this.kitName]?.installedSettings;
|
|
37113
37268
|
if (installed) {
|
|
@@ -37123,8 +37278,8 @@ class InstalledSettingsTracker {
|
|
|
37123
37278
|
const ckJsonPath = this.getCkJsonPath();
|
|
37124
37279
|
try {
|
|
37125
37280
|
let data = {};
|
|
37126
|
-
if (
|
|
37127
|
-
const content = await
|
|
37281
|
+
if (existsSync18(ckJsonPath)) {
|
|
37282
|
+
const content = await readFile14(ckJsonPath, "utf-8");
|
|
37128
37283
|
data = JSON.parse(content);
|
|
37129
37284
|
}
|
|
37130
37285
|
if (!data.kits) {
|
|
@@ -37134,8 +37289,8 @@ class InstalledSettingsTracker {
|
|
|
37134
37289
|
data.kits[this.kitName] = {};
|
|
37135
37290
|
}
|
|
37136
37291
|
data.kits[this.kitName].installedSettings = settings;
|
|
37137
|
-
await mkdir15(
|
|
37138
|
-
await
|
|
37292
|
+
await mkdir15(dirname7(ckJsonPath), { recursive: true });
|
|
37293
|
+
await writeFile11(ckJsonPath, JSON.stringify(data, null, 2), "utf-8");
|
|
37139
37294
|
logger.debug(`Saved installed settings to ${ckJsonPath}`);
|
|
37140
37295
|
} catch (error) {
|
|
37141
37296
|
logger.warning(`Failed to save installed settings: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -37556,18 +37711,18 @@ function mergeSettings(source, destination, options) {
|
|
|
37556
37711
|
}
|
|
37557
37712
|
// src/domains/config/merger/file-io.ts
|
|
37558
37713
|
init_logger();
|
|
37559
|
-
var
|
|
37714
|
+
var import_fs_extra9 = __toESM(require_lib(), 1);
|
|
37560
37715
|
import { randomUUID } from "node:crypto";
|
|
37561
|
-
import { dirname as
|
|
37716
|
+
import { dirname as dirname8, join as join43 } from "node:path";
|
|
37562
37717
|
function stripBOM(content) {
|
|
37563
37718
|
return content.charCodeAt(0) === 65279 ? content.slice(1) : content;
|
|
37564
37719
|
}
|
|
37565
37720
|
async function readSettingsFile(filePath) {
|
|
37566
37721
|
try {
|
|
37567
|
-
if (!await
|
|
37722
|
+
if (!await import_fs_extra9.pathExists(filePath)) {
|
|
37568
37723
|
return null;
|
|
37569
37724
|
}
|
|
37570
|
-
const rawContent = await
|
|
37725
|
+
const rawContent = await import_fs_extra9.readFile(filePath, "utf-8");
|
|
37571
37726
|
const content = stripBOM(rawContent);
|
|
37572
37727
|
const parsed = JSON.parse(content);
|
|
37573
37728
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
@@ -37581,15 +37736,15 @@ async function readSettingsFile(filePath) {
|
|
|
37581
37736
|
}
|
|
37582
37737
|
}
|
|
37583
37738
|
async function atomicWriteFile(filePath, content) {
|
|
37584
|
-
const dir =
|
|
37585
|
-
const tempPath =
|
|
37739
|
+
const dir = dirname8(filePath);
|
|
37740
|
+
const tempPath = join43(dir, `.settings-${randomUUID()}.tmp`);
|
|
37586
37741
|
try {
|
|
37587
|
-
await
|
|
37588
|
-
await
|
|
37742
|
+
await import_fs_extra9.writeFile(tempPath, content, "utf-8");
|
|
37743
|
+
await import_fs_extra9.rename(tempPath, filePath);
|
|
37589
37744
|
} catch (error) {
|
|
37590
37745
|
try {
|
|
37591
|
-
if (await
|
|
37592
|
-
await
|
|
37746
|
+
if (await import_fs_extra9.pathExists(tempPath)) {
|
|
37747
|
+
await import_fs_extra9.unlink(tempPath);
|
|
37593
37748
|
}
|
|
37594
37749
|
} catch {}
|
|
37595
37750
|
throw error;
|
|
@@ -37618,7 +37773,7 @@ class SettingsMerger {
|
|
|
37618
37773
|
// src/domains/installation/merger/settings-processor.ts
|
|
37619
37774
|
init_environment();
|
|
37620
37775
|
init_logger();
|
|
37621
|
-
var
|
|
37776
|
+
var import_fs_extra10 = __toESM(require_lib(), 1);
|
|
37622
37777
|
|
|
37623
37778
|
class SettingsProcessor {
|
|
37624
37779
|
isGlobal = false;
|
|
@@ -37651,7 +37806,7 @@ class SettingsProcessor {
|
|
|
37651
37806
|
}
|
|
37652
37807
|
async processSettingsJson(sourceFile, destFile) {
|
|
37653
37808
|
try {
|
|
37654
|
-
const sourceContent = await
|
|
37809
|
+
const sourceContent = await import_fs_extra10.readFile(sourceFile, "utf-8");
|
|
37655
37810
|
let transformedSource = sourceContent;
|
|
37656
37811
|
if (this.isGlobal) {
|
|
37657
37812
|
const homeVar = isWindows() ? '"%USERPROFILE%"' : '"$HOME"';
|
|
@@ -37666,12 +37821,12 @@ class SettingsProcessor {
|
|
|
37666
37821
|
logger.debug(`Transformed .claude/ paths to ${projectDirVar}/.claude/ in settings.json for local installation`);
|
|
37667
37822
|
}
|
|
37668
37823
|
}
|
|
37669
|
-
const destExists = await
|
|
37824
|
+
const destExists = await import_fs_extra10.pathExists(destFile);
|
|
37670
37825
|
if (destExists && !this.forceOverwriteSettings) {
|
|
37671
37826
|
await this.selectiveMergeSettings(transformedSource, destFile);
|
|
37672
37827
|
} else {
|
|
37673
37828
|
const formattedContent = this.formatJsonContent(transformedSource);
|
|
37674
|
-
await
|
|
37829
|
+
await import_fs_extra10.writeFile(destFile, formattedContent, "utf-8");
|
|
37675
37830
|
try {
|
|
37676
37831
|
const parsedSettings = JSON.parse(formattedContent);
|
|
37677
37832
|
if (this.forceOverwriteSettings && destExists) {
|
|
@@ -37685,7 +37840,7 @@ class SettingsProcessor {
|
|
|
37685
37840
|
}
|
|
37686
37841
|
} catch (error) {
|
|
37687
37842
|
logger.error(`Failed to process settings.json: ${error}`);
|
|
37688
|
-
await
|
|
37843
|
+
await import_fs_extra10.copy(sourceFile, destFile, { overwrite: true });
|
|
37689
37844
|
}
|
|
37690
37845
|
}
|
|
37691
37846
|
async selectiveMergeSettings(transformedSourceContent, destFile) {
|
|
@@ -37695,7 +37850,7 @@ class SettingsProcessor {
|
|
|
37695
37850
|
} catch {
|
|
37696
37851
|
logger.warning("Failed to parse source settings.json, falling back to overwrite");
|
|
37697
37852
|
const formattedContent = this.formatJsonContent(transformedSourceContent);
|
|
37698
|
-
await
|
|
37853
|
+
await import_fs_extra10.writeFile(destFile, formattedContent, "utf-8");
|
|
37699
37854
|
return;
|
|
37700
37855
|
}
|
|
37701
37856
|
let destSettings;
|
|
@@ -37781,7 +37936,7 @@ class SettingsProcessor {
|
|
|
37781
37936
|
}
|
|
37782
37937
|
async readAndNormalizeGlobalSettings(destFile) {
|
|
37783
37938
|
try {
|
|
37784
|
-
const content = await
|
|
37939
|
+
const content = await import_fs_extra10.readFile(destFile, "utf-8");
|
|
37785
37940
|
if (!content.trim())
|
|
37786
37941
|
return null;
|
|
37787
37942
|
const homeVar = isWindows() ? "%USERPROFILE%" : "$HOME";
|
|
@@ -37892,8 +38047,8 @@ class CopyExecutor {
|
|
|
37892
38047
|
for (const file of files) {
|
|
37893
38048
|
const relativePath = relative6(sourceDir, file);
|
|
37894
38049
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
37895
|
-
const destPath =
|
|
37896
|
-
if (await
|
|
38050
|
+
const destPath = join44(destDir, relativePath);
|
|
38051
|
+
if (await import_fs_extra11.pathExists(destPath)) {
|
|
37897
38052
|
if (this.fileScanner.shouldNeverCopy(normalizedRelativePath)) {
|
|
37898
38053
|
logger.debug(`Security-sensitive file exists but won't be overwritten: ${normalizedRelativePath}`);
|
|
37899
38054
|
continue;
|
|
@@ -37914,14 +38069,14 @@ class CopyExecutor {
|
|
|
37914
38069
|
for (const file of files) {
|
|
37915
38070
|
const relativePath = relative6(sourceDir, file);
|
|
37916
38071
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
37917
|
-
const destPath =
|
|
38072
|
+
const destPath = join44(destDir, relativePath);
|
|
37918
38073
|
if (this.fileScanner.shouldNeverCopy(normalizedRelativePath)) {
|
|
37919
38074
|
logger.debug(`Skipping security-sensitive file: ${normalizedRelativePath}`);
|
|
37920
38075
|
skippedCount++;
|
|
37921
38076
|
continue;
|
|
37922
38077
|
}
|
|
37923
38078
|
if (this.userConfigChecker.ignores(normalizedRelativePath)) {
|
|
37924
|
-
const fileExists = await
|
|
38079
|
+
const fileExists = await import_fs_extra11.pathExists(destPath);
|
|
37925
38080
|
if (fileExists) {
|
|
37926
38081
|
logger.debug(`Preserving user config: ${normalizedRelativePath}`);
|
|
37927
38082
|
skippedCount++;
|
|
@@ -37952,7 +38107,7 @@ class CopyExecutor {
|
|
|
37952
38107
|
continue;
|
|
37953
38108
|
}
|
|
37954
38109
|
}
|
|
37955
|
-
await withRetry2(() =>
|
|
38110
|
+
await withRetry2(() => import_fs_extra11.copy(file, destPath, { overwrite: true }));
|
|
37956
38111
|
this.trackInstalledFile(normalizedRelativePath);
|
|
37957
38112
|
copiedCount++;
|
|
37958
38113
|
}
|
|
@@ -37991,10 +38146,10 @@ class CopyExecutor {
|
|
|
37991
38146
|
}
|
|
37992
38147
|
trackInstalledFile(relativePath) {
|
|
37993
38148
|
this.installedFiles.add(relativePath);
|
|
37994
|
-
let dir =
|
|
38149
|
+
let dir = dirname9(relativePath);
|
|
37995
38150
|
while (dir && dir !== "." && dir !== "/") {
|
|
37996
38151
|
this.installedDirectories.add(`${dir}/`);
|
|
37997
|
-
dir =
|
|
38152
|
+
dir = dirname9(dir);
|
|
37998
38153
|
}
|
|
37999
38154
|
}
|
|
38000
38155
|
}
|
|
@@ -38084,15 +38239,15 @@ class FileMerger {
|
|
|
38084
38239
|
|
|
38085
38240
|
// src/domains/migration/legacy-migration.ts
|
|
38086
38241
|
import { readdir as readdir9, stat as stat7 } from "node:fs/promises";
|
|
38087
|
-
import { join as
|
|
38242
|
+
import { join as join48, relative as relative7 } from "node:path";
|
|
38088
38243
|
// src/services/file-operations/manifest/manifest-tracker.ts
|
|
38089
|
-
import { join as
|
|
38244
|
+
import { join as join47 } from "node:path";
|
|
38090
38245
|
|
|
38091
38246
|
// src/domains/migration/release-manifest.ts
|
|
38092
38247
|
init_logger();
|
|
38093
38248
|
init_zod();
|
|
38094
|
-
var
|
|
38095
|
-
import { join as
|
|
38249
|
+
var import_fs_extra12 = __toESM(require_lib(), 1);
|
|
38250
|
+
import { join as join45 } from "node:path";
|
|
38096
38251
|
var ReleaseManifestFileSchema = exports_external.object({
|
|
38097
38252
|
path: exports_external.string(),
|
|
38098
38253
|
checksum: exports_external.string().regex(/^[a-f0-9]{64}$/),
|
|
@@ -38107,9 +38262,9 @@ var ReleaseManifestSchema = exports_external.object({
|
|
|
38107
38262
|
|
|
38108
38263
|
class ReleaseManifestLoader {
|
|
38109
38264
|
static async load(extractDir) {
|
|
38110
|
-
const manifestPath =
|
|
38265
|
+
const manifestPath = join45(extractDir, "release-manifest.json");
|
|
38111
38266
|
try {
|
|
38112
|
-
const content = await
|
|
38267
|
+
const content = await import_fs_extra12.readFile(manifestPath, "utf-8");
|
|
38113
38268
|
const parsed = JSON.parse(content);
|
|
38114
38269
|
return ReleaseManifestSchema.parse(parsed);
|
|
38115
38270
|
} catch (error) {
|
|
@@ -38127,15 +38282,15 @@ init_environment();
|
|
|
38127
38282
|
init_logger();
|
|
38128
38283
|
|
|
38129
38284
|
// src/services/file-operations/manifest/manifest-updater.ts
|
|
38130
|
-
import { join as
|
|
38285
|
+
import { join as join46 } from "node:path";
|
|
38131
38286
|
init_logger();
|
|
38132
38287
|
init_types2();
|
|
38133
|
-
var
|
|
38288
|
+
var import_fs_extra13 = __toESM(require_lib(), 1);
|
|
38134
38289
|
var import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
|
|
38135
38290
|
async function writeManifest(claudeDir, kitName, version, scope, kitType, trackedFiles, userConfigFiles) {
|
|
38136
|
-
const metadataPath =
|
|
38291
|
+
const metadataPath = join46(claudeDir, "metadata.json");
|
|
38137
38292
|
const kit = kitType || (/\bmarketing\b/i.test(kitName) ? "marketing" : "engineer");
|
|
38138
|
-
await
|
|
38293
|
+
await import_fs_extra13.ensureFile(metadataPath);
|
|
38139
38294
|
let release = null;
|
|
38140
38295
|
try {
|
|
38141
38296
|
release = await import_proper_lockfile2.lock(metadataPath, {
|
|
@@ -38148,9 +38303,9 @@ async function writeManifest(claudeDir, kitName, version, scope, kitType, tracke
|
|
|
38148
38303
|
logger.warning(`Metadata migration warning: ${migrationResult.error}`);
|
|
38149
38304
|
}
|
|
38150
38305
|
let existingMetadata = { kits: {} };
|
|
38151
|
-
if (await
|
|
38306
|
+
if (await import_fs_extra13.pathExists(metadataPath)) {
|
|
38152
38307
|
try {
|
|
38153
|
-
const content = await
|
|
38308
|
+
const content = await import_fs_extra13.readFile(metadataPath, "utf-8");
|
|
38154
38309
|
const parsed = JSON.parse(content);
|
|
38155
38310
|
if (parsed && typeof parsed === "object" && Object.keys(parsed).length > 0) {
|
|
38156
38311
|
existingMetadata = parsed;
|
|
@@ -38179,7 +38334,7 @@ async function writeManifest(claudeDir, kitName, version, scope, kitType, tracke
|
|
|
38179
38334
|
userConfigFiles: [...USER_CONFIG_PATTERNS, ...userConfigFiles]
|
|
38180
38335
|
};
|
|
38181
38336
|
const validated = MetadataSchema.parse(metadata);
|
|
38182
|
-
await
|
|
38337
|
+
await import_fs_extra13.writeFile(metadataPath, JSON.stringify(validated, null, 2), "utf-8");
|
|
38183
38338
|
logger.debug(`Wrote manifest for kit "${kit}" with ${trackedFiles.length} tracked files`);
|
|
38184
38339
|
} finally {
|
|
38185
38340
|
if (release) {
|
|
@@ -38189,8 +38344,8 @@ async function writeManifest(claudeDir, kitName, version, scope, kitType, tracke
|
|
|
38189
38344
|
}
|
|
38190
38345
|
}
|
|
38191
38346
|
async function removeKitFromManifest(claudeDir, kit) {
|
|
38192
|
-
const metadataPath =
|
|
38193
|
-
if (!await
|
|
38347
|
+
const metadataPath = join46(claudeDir, "metadata.json");
|
|
38348
|
+
if (!await import_fs_extra13.pathExists(metadataPath))
|
|
38194
38349
|
return false;
|
|
38195
38350
|
let release = null;
|
|
38196
38351
|
try {
|
|
@@ -38211,7 +38366,7 @@ async function removeKitFromManifest(claudeDir, kit) {
|
|
|
38211
38366
|
...metadata,
|
|
38212
38367
|
kits: remainingKits
|
|
38213
38368
|
};
|
|
38214
|
-
await
|
|
38369
|
+
await import_fs_extra13.writeFile(metadataPath, JSON.stringify(updated, null, 2), "utf-8");
|
|
38215
38370
|
logger.debug(`Removed kit "${kit}" from metadata, ${Object.keys(remainingKits).length} kit(s) remaining`);
|
|
38216
38371
|
return true;
|
|
38217
38372
|
} finally {
|
|
@@ -38319,7 +38474,7 @@ function buildFileTrackingList(options) {
|
|
|
38319
38474
|
if (!isGlobal && !installedPath.startsWith(".claude/"))
|
|
38320
38475
|
continue;
|
|
38321
38476
|
const relativePath = isGlobal ? installedPath : installedPath.replace(/^\.claude\//, "");
|
|
38322
|
-
const filePath =
|
|
38477
|
+
const filePath = join47(claudeDir, relativePath);
|
|
38323
38478
|
const manifestEntry = releaseManifest ? ReleaseManifestLoader.findFile(releaseManifest, installedPath) : null;
|
|
38324
38479
|
const ownership = manifestEntry ? "ck" : "user";
|
|
38325
38480
|
filesToTrack.push({
|
|
@@ -38392,7 +38547,7 @@ class ManifestWriter {
|
|
|
38392
38547
|
|
|
38393
38548
|
// src/domains/migration/legacy-migration.ts
|
|
38394
38549
|
init_logger();
|
|
38395
|
-
var
|
|
38550
|
+
var import_fs_extra14 = __toESM(require_lib(), 1);
|
|
38396
38551
|
class LegacyMigration {
|
|
38397
38552
|
static async detectLegacy(claudeDir) {
|
|
38398
38553
|
const metadata = await ManifestWriter.readManifest(claudeDir);
|
|
@@ -38425,7 +38580,7 @@ class LegacyMigration {
|
|
|
38425
38580
|
continue;
|
|
38426
38581
|
if (SKIP_DIRS_ALL.includes(entry))
|
|
38427
38582
|
continue;
|
|
38428
|
-
const fullPath =
|
|
38583
|
+
const fullPath = join48(dir, entry);
|
|
38429
38584
|
let stats;
|
|
38430
38585
|
try {
|
|
38431
38586
|
stats = await stat7(fullPath);
|
|
@@ -38527,7 +38682,7 @@ User-created files (sample):`);
|
|
|
38527
38682
|
];
|
|
38528
38683
|
if (filesToChecksum.length > 0) {
|
|
38529
38684
|
const checksumResults = await mapWithLimit(filesToChecksum, async ({ relativePath, ownership }) => {
|
|
38530
|
-
const fullPath =
|
|
38685
|
+
const fullPath = join48(claudeDir, relativePath);
|
|
38531
38686
|
const checksum = await OwnershipChecker.calculateChecksum(fullPath);
|
|
38532
38687
|
return { relativePath, checksum, ownership };
|
|
38533
38688
|
});
|
|
@@ -38548,8 +38703,8 @@ User-created files (sample):`);
|
|
|
38548
38703
|
installedAt: new Date().toISOString(),
|
|
38549
38704
|
files: trackedFiles
|
|
38550
38705
|
};
|
|
38551
|
-
const metadataPath =
|
|
38552
|
-
await
|
|
38706
|
+
const metadataPath = join48(claudeDir, "metadata.json");
|
|
38707
|
+
await import_fs_extra14.writeFile(metadataPath, JSON.stringify(updatedMetadata, null, 2));
|
|
38553
38708
|
logger.success(`Migration complete: tracked ${trackedFiles.length} files`);
|
|
38554
38709
|
return true;
|
|
38555
38710
|
}
|
|
@@ -38651,32 +38806,32 @@ function buildConflictSummary(fileConflicts, hookConflicts, mcpConflicts) {
|
|
|
38651
38806
|
}
|
|
38652
38807
|
|
|
38653
38808
|
// src/services/file-operations/file-scanner.ts
|
|
38654
|
-
import { join as
|
|
38809
|
+
import { join as join49, relative as relative8, resolve as resolve7 } from "node:path";
|
|
38655
38810
|
init_logger();
|
|
38656
|
-
var
|
|
38811
|
+
var import_fs_extra15 = __toESM(require_lib(), 1);
|
|
38657
38812
|
|
|
38658
38813
|
class FileScanner2 {
|
|
38659
38814
|
static async getFiles(dirPath, relativeTo) {
|
|
38660
38815
|
const basePath = relativeTo || dirPath;
|
|
38661
38816
|
const files = [];
|
|
38662
|
-
if (!await
|
|
38817
|
+
if (!await import_fs_extra15.pathExists(dirPath)) {
|
|
38663
38818
|
return files;
|
|
38664
38819
|
}
|
|
38665
38820
|
try {
|
|
38666
|
-
const entries = await
|
|
38821
|
+
const entries = await import_fs_extra15.readdir(dirPath, { encoding: "utf8" });
|
|
38667
38822
|
for (const entry of entries) {
|
|
38668
38823
|
if (SKIP_DIRS_ALL.includes(entry)) {
|
|
38669
38824
|
logger.debug(`Skipping directory: ${entry}`);
|
|
38670
38825
|
continue;
|
|
38671
38826
|
}
|
|
38672
|
-
const fullPath =
|
|
38827
|
+
const fullPath = join49(dirPath, entry);
|
|
38673
38828
|
if (!FileScanner2.isSafePath(basePath, fullPath)) {
|
|
38674
38829
|
logger.warning(`Skipping potentially unsafe path: ${entry}`);
|
|
38675
38830
|
continue;
|
|
38676
38831
|
}
|
|
38677
38832
|
let stats;
|
|
38678
38833
|
try {
|
|
38679
|
-
stats = await
|
|
38834
|
+
stats = await import_fs_extra15.lstat(fullPath);
|
|
38680
38835
|
} catch (error) {
|
|
38681
38836
|
if (error instanceof Error && "code" in error && (error.code === "EACCES" || error.code === "EPERM")) {
|
|
38682
38837
|
logger.warning(`Skipping inaccessible path: ${entry}`);
|
|
@@ -38704,8 +38859,8 @@ class FileScanner2 {
|
|
|
38704
38859
|
return files;
|
|
38705
38860
|
}
|
|
38706
38861
|
static async findCustomFiles(destDir, sourceDir, subPath) {
|
|
38707
|
-
const destSubDir =
|
|
38708
|
-
const sourceSubDir =
|
|
38862
|
+
const destSubDir = join49(destDir, subPath);
|
|
38863
|
+
const sourceSubDir = join49(sourceDir, subPath);
|
|
38709
38864
|
logger.debug(`findCustomFiles - destDir: ${destDir}`);
|
|
38710
38865
|
logger.debug(`findCustomFiles - sourceDir: ${sourceDir}`);
|
|
38711
38866
|
logger.debug(`findCustomFiles - subPath: "${subPath}"`);
|
|
@@ -38715,7 +38870,7 @@ class FileScanner2 {
|
|
|
38715
38870
|
const sourceFiles = await FileScanner2.getFiles(sourceSubDir, sourceDir);
|
|
38716
38871
|
logger.debug(`findCustomFiles - destFiles count: ${destFiles.length}`);
|
|
38717
38872
|
logger.debug(`findCustomFiles - sourceFiles count: ${sourceFiles.length}`);
|
|
38718
|
-
const sourceExists = await
|
|
38873
|
+
const sourceExists = await import_fs_extra15.pathExists(sourceSubDir);
|
|
38719
38874
|
if (sourceExists && sourceFiles.length === 0 && destFiles.length > 100) {
|
|
38720
38875
|
logger.warning(`Source directory exists but is empty while destination has ${destFiles.length} files. This may indicate an extraction issue. Skipping custom file detection.`);
|
|
38721
38876
|
return [];
|
|
@@ -38733,8 +38888,8 @@ class FileScanner2 {
|
|
|
38733
38888
|
return customFiles;
|
|
38734
38889
|
}
|
|
38735
38890
|
static isSafePath(basePath, targetPath) {
|
|
38736
|
-
const resolvedBase =
|
|
38737
|
-
const resolvedTarget =
|
|
38891
|
+
const resolvedBase = resolve7(basePath);
|
|
38892
|
+
const resolvedTarget = resolve7(targetPath);
|
|
38738
38893
|
return resolvedTarget.startsWith(resolvedBase);
|
|
38739
38894
|
}
|
|
38740
38895
|
static toPosixPath(path11) {
|
|
@@ -38744,14 +38899,14 @@ class FileScanner2 {
|
|
|
38744
38899
|
|
|
38745
38900
|
// src/services/transformers/commands-prefix/prefix-applier.ts
|
|
38746
38901
|
init_logger();
|
|
38747
|
-
var
|
|
38902
|
+
var import_fs_extra16 = __toESM(require_lib(), 1);
|
|
38748
38903
|
import { lstat as lstat5, mkdir as mkdir16, readdir as readdir12, stat as stat8 } from "node:fs/promises";
|
|
38749
|
-
import { join as
|
|
38904
|
+
import { join as join51 } from "node:path";
|
|
38750
38905
|
|
|
38751
38906
|
// src/services/transformers/commands-prefix/content-transformer.ts
|
|
38752
38907
|
init_logger();
|
|
38753
|
-
import { readFile as
|
|
38754
|
-
import { join as
|
|
38908
|
+
import { readFile as readFile19, readdir as readdir11, writeFile as writeFile16 } from "node:fs/promises";
|
|
38909
|
+
import { join as join50 } from "node:path";
|
|
38755
38910
|
var TRANSFORMABLE_EXTENSIONS = new Set([
|
|
38756
38911
|
".md",
|
|
38757
38912
|
".txt",
|
|
@@ -38819,7 +38974,7 @@ async function transformCommandReferences(directory, options = {}) {
|
|
|
38819
38974
|
async function processDirectory(dir) {
|
|
38820
38975
|
const entries = await readdir11(dir, { withFileTypes: true });
|
|
38821
38976
|
for (const entry of entries) {
|
|
38822
|
-
const fullPath =
|
|
38977
|
+
const fullPath = join50(dir, entry.name);
|
|
38823
38978
|
if (entry.isDirectory()) {
|
|
38824
38979
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
38825
38980
|
continue;
|
|
@@ -38827,13 +38982,13 @@ async function transformCommandReferences(directory, options = {}) {
|
|
|
38827
38982
|
await processDirectory(fullPath);
|
|
38828
38983
|
} else if (entry.isFile() && shouldTransformFile(entry.name)) {
|
|
38829
38984
|
try {
|
|
38830
|
-
const content = await
|
|
38985
|
+
const content = await readFile19(fullPath, "utf-8");
|
|
38831
38986
|
const { transformed, changes } = transformCommandContent(content);
|
|
38832
38987
|
if (changes > 0) {
|
|
38833
38988
|
if (options.dryRun) {
|
|
38834
38989
|
logger.debug(`[dry-run] Would transform ${changes} command ref(s) in ${fullPath}`);
|
|
38835
38990
|
} else {
|
|
38836
|
-
await
|
|
38991
|
+
await writeFile16(fullPath, transformed, "utf-8");
|
|
38837
38992
|
if (options.verbose) {
|
|
38838
38993
|
logger.verbose(`Transformed ${changes} command ref(s) in ${fullPath}`);
|
|
38839
38994
|
}
|
|
@@ -38894,14 +39049,14 @@ function shouldApplyPrefix(options) {
|
|
|
38894
39049
|
// src/services/transformers/commands-prefix/prefix-applier.ts
|
|
38895
39050
|
async function applyPrefix(extractDir) {
|
|
38896
39051
|
validatePath(extractDir, "extractDir");
|
|
38897
|
-
const commandsDir =
|
|
38898
|
-
if (!await
|
|
39052
|
+
const commandsDir = join51(extractDir, ".claude", "commands");
|
|
39053
|
+
if (!await import_fs_extra16.pathExists(commandsDir)) {
|
|
38899
39054
|
logger.verbose("No commands directory found, skipping prefix application");
|
|
38900
39055
|
return;
|
|
38901
39056
|
}
|
|
38902
39057
|
logger.info("Applying /ck: prefix to slash commands...");
|
|
38903
|
-
const backupDir =
|
|
38904
|
-
const tempDir =
|
|
39058
|
+
const backupDir = join51(extractDir, ".commands-backup");
|
|
39059
|
+
const tempDir = join51(extractDir, ".commands-prefix-temp");
|
|
38905
39060
|
try {
|
|
38906
39061
|
const entries = await readdir12(commandsDir);
|
|
38907
39062
|
if (entries.length === 0) {
|
|
@@ -38909,28 +39064,28 @@ async function applyPrefix(extractDir) {
|
|
|
38909
39064
|
return;
|
|
38910
39065
|
}
|
|
38911
39066
|
if (entries.length === 1 && entries[0] === "ck") {
|
|
38912
|
-
const ckDir2 =
|
|
39067
|
+
const ckDir2 = join51(commandsDir, "ck");
|
|
38913
39068
|
const ckStat = await stat8(ckDir2);
|
|
38914
39069
|
if (ckStat.isDirectory()) {
|
|
38915
39070
|
logger.verbose("Commands already have /ck: prefix, skipping");
|
|
38916
39071
|
return;
|
|
38917
39072
|
}
|
|
38918
39073
|
}
|
|
38919
|
-
await
|
|
39074
|
+
await import_fs_extra16.copy(commandsDir, backupDir);
|
|
38920
39075
|
logger.verbose("Created backup of commands directory");
|
|
38921
39076
|
await mkdir16(tempDir, { recursive: true });
|
|
38922
|
-
const ckDir =
|
|
39077
|
+
const ckDir = join51(tempDir, "ck");
|
|
38923
39078
|
await mkdir16(ckDir, { recursive: true });
|
|
38924
39079
|
let processedCount = 0;
|
|
38925
39080
|
for (const entry of entries) {
|
|
38926
|
-
const sourcePath =
|
|
39081
|
+
const sourcePath = join51(commandsDir, entry);
|
|
38927
39082
|
const stats = await lstat5(sourcePath);
|
|
38928
39083
|
if (stats.isSymbolicLink()) {
|
|
38929
39084
|
logger.warning(`Skipping symlink for security: ${entry}`);
|
|
38930
39085
|
continue;
|
|
38931
39086
|
}
|
|
38932
|
-
const destPath =
|
|
38933
|
-
await
|
|
39087
|
+
const destPath = join51(ckDir, entry);
|
|
39088
|
+
await import_fs_extra16.copy(sourcePath, destPath, {
|
|
38934
39089
|
overwrite: false,
|
|
38935
39090
|
errorOnExist: true
|
|
38936
39091
|
});
|
|
@@ -38939,15 +39094,15 @@ async function applyPrefix(extractDir) {
|
|
|
38939
39094
|
}
|
|
38940
39095
|
if (processedCount === 0) {
|
|
38941
39096
|
logger.warning("No files to move (all were symlinks or invalid)");
|
|
38942
|
-
await
|
|
38943
|
-
await
|
|
39097
|
+
await import_fs_extra16.remove(backupDir);
|
|
39098
|
+
await import_fs_extra16.remove(tempDir);
|
|
38944
39099
|
return;
|
|
38945
39100
|
}
|
|
38946
|
-
await
|
|
38947
|
-
await
|
|
38948
|
-
await
|
|
39101
|
+
await import_fs_extra16.remove(commandsDir);
|
|
39102
|
+
await import_fs_extra16.move(tempDir, commandsDir);
|
|
39103
|
+
await import_fs_extra16.remove(backupDir);
|
|
38949
39104
|
logger.success("Successfully reorganized commands to /ck: prefix");
|
|
38950
|
-
const claudeDir =
|
|
39105
|
+
const claudeDir = join51(extractDir, ".claude");
|
|
38951
39106
|
logger.info("Transforming command references in file contents...");
|
|
38952
39107
|
const transformResult = await transformCommandReferences(claudeDir, {
|
|
38953
39108
|
verbose: logger.isVerbose()
|
|
@@ -38958,46 +39113,46 @@ async function applyPrefix(extractDir) {
|
|
|
38958
39113
|
logger.verbose("No command references needed transformation");
|
|
38959
39114
|
}
|
|
38960
39115
|
} catch (error) {
|
|
38961
|
-
if (await
|
|
39116
|
+
if (await import_fs_extra16.pathExists(backupDir)) {
|
|
38962
39117
|
try {
|
|
38963
|
-
await
|
|
38964
|
-
await
|
|
39118
|
+
await import_fs_extra16.remove(commandsDir).catch(() => {});
|
|
39119
|
+
await import_fs_extra16.move(backupDir, commandsDir);
|
|
38965
39120
|
logger.info("Restored original commands directory from backup");
|
|
38966
39121
|
} catch (rollbackError) {
|
|
38967
39122
|
logger.error(`Rollback failed: ${rollbackError}`);
|
|
38968
39123
|
}
|
|
38969
39124
|
}
|
|
38970
|
-
if (await
|
|
38971
|
-
await
|
|
39125
|
+
if (await import_fs_extra16.pathExists(tempDir)) {
|
|
39126
|
+
await import_fs_extra16.remove(tempDir).catch(() => {});
|
|
38972
39127
|
}
|
|
38973
39128
|
logger.error("Failed to apply /ck: prefix to commands");
|
|
38974
39129
|
throw error;
|
|
38975
39130
|
} finally {
|
|
38976
|
-
if (await
|
|
38977
|
-
await
|
|
39131
|
+
if (await import_fs_extra16.pathExists(backupDir)) {
|
|
39132
|
+
await import_fs_extra16.remove(backupDir).catch(() => {});
|
|
38978
39133
|
}
|
|
38979
|
-
if (await
|
|
38980
|
-
await
|
|
39134
|
+
if (await import_fs_extra16.pathExists(tempDir)) {
|
|
39135
|
+
await import_fs_extra16.remove(tempDir).catch(() => {});
|
|
38981
39136
|
}
|
|
38982
39137
|
}
|
|
38983
39138
|
}
|
|
38984
39139
|
|
|
38985
39140
|
// src/services/transformers/commands-prefix/prefix-cleaner.ts
|
|
38986
39141
|
import { lstat as lstat7, readdir as readdir14 } from "node:fs/promises";
|
|
38987
|
-
import { join as
|
|
39142
|
+
import { join as join53 } from "node:path";
|
|
38988
39143
|
init_logger();
|
|
38989
|
-
var
|
|
39144
|
+
var import_fs_extra18 = __toESM(require_lib(), 1);
|
|
38990
39145
|
|
|
38991
39146
|
// src/services/transformers/commands-prefix/file-processor.ts
|
|
38992
39147
|
import { lstat as lstat6, readdir as readdir13 } from "node:fs/promises";
|
|
38993
|
-
import { join as
|
|
39148
|
+
import { join as join52 } from "node:path";
|
|
38994
39149
|
init_logger();
|
|
38995
|
-
var
|
|
39150
|
+
var import_fs_extra17 = __toESM(require_lib(), 1);
|
|
38996
39151
|
async function scanDirectoryFiles(dir) {
|
|
38997
39152
|
const files = [];
|
|
38998
39153
|
const entries = await readdir13(dir);
|
|
38999
39154
|
for (const entry of entries) {
|
|
39000
|
-
const fullPath =
|
|
39155
|
+
const fullPath = join52(dir, entry);
|
|
39001
39156
|
const stats = await lstat6(fullPath);
|
|
39002
39157
|
if (stats.isSymbolicLink()) {
|
|
39003
39158
|
continue;
|
|
@@ -39020,7 +39175,7 @@ async function processFileOwnership(file, relativePath, metadata, claudeDir, opt
|
|
|
39020
39175
|
action: "delete"
|
|
39021
39176
|
});
|
|
39022
39177
|
if (!dryRun) {
|
|
39023
|
-
await
|
|
39178
|
+
await import_fs_extra17.remove(file);
|
|
39024
39179
|
logger.verbose(`Deleted CK file: ${relativePath}`);
|
|
39025
39180
|
}
|
|
39026
39181
|
accumulator.deletedCount++;
|
|
@@ -39035,7 +39190,7 @@ async function processFileOwnership(file, relativePath, metadata, claudeDir, opt
|
|
|
39035
39190
|
reason: "force overwrite"
|
|
39036
39191
|
});
|
|
39037
39192
|
if (!dryRun) {
|
|
39038
|
-
await
|
|
39193
|
+
await import_fs_extra17.remove(file);
|
|
39039
39194
|
logger.verbose(`Force-deleted modified file: ${relativePath}`);
|
|
39040
39195
|
}
|
|
39041
39196
|
accumulator.deletedCount++;
|
|
@@ -39059,7 +39214,7 @@ async function processFileOwnership(file, relativePath, metadata, claudeDir, opt
|
|
|
39059
39214
|
reason: "force overwrite"
|
|
39060
39215
|
});
|
|
39061
39216
|
if (!dryRun) {
|
|
39062
|
-
await
|
|
39217
|
+
await import_fs_extra17.remove(file);
|
|
39063
39218
|
logger.verbose(`Force-deleted user file: ${relativePath}`);
|
|
39064
39219
|
}
|
|
39065
39220
|
accumulator.deletedCount++;
|
|
@@ -39105,8 +39260,8 @@ function logCleanupSummary(deletedCount, preservedCount, dryRun, results) {
|
|
|
39105
39260
|
async function cleanupCommandsDirectory(targetDir, isGlobal, options = {}) {
|
|
39106
39261
|
const { dryRun = false } = options;
|
|
39107
39262
|
validatePath(targetDir, "targetDir");
|
|
39108
|
-
const claudeDir = isGlobal ? targetDir :
|
|
39109
|
-
const commandsDir =
|
|
39263
|
+
const claudeDir = isGlobal ? targetDir : join53(targetDir, ".claude");
|
|
39264
|
+
const commandsDir = join53(claudeDir, "commands");
|
|
39110
39265
|
const accumulator = {
|
|
39111
39266
|
results: [],
|
|
39112
39267
|
deletedCount: 0,
|
|
@@ -39118,7 +39273,7 @@ async function cleanupCommandsDirectory(targetDir, isGlobal, options = {}) {
|
|
|
39118
39273
|
preservedCount: 0,
|
|
39119
39274
|
wasDryRun: dryRun
|
|
39120
39275
|
};
|
|
39121
|
-
if (!await
|
|
39276
|
+
if (!await import_fs_extra18.pathExists(commandsDir)) {
|
|
39122
39277
|
logger.verbose(`Commands directory does not exist: ${commandsDir}`);
|
|
39123
39278
|
return result;
|
|
39124
39279
|
}
|
|
@@ -39140,7 +39295,7 @@ async function cleanupCommandsDirectory(targetDir, isGlobal, options = {}) {
|
|
|
39140
39295
|
return result;
|
|
39141
39296
|
}
|
|
39142
39297
|
for (const entry of entries) {
|
|
39143
|
-
const entryPath =
|
|
39298
|
+
const entryPath = join53(commandsDir, entry);
|
|
39144
39299
|
const stats = await lstat7(entryPath);
|
|
39145
39300
|
if (stats.isSymbolicLink()) {
|
|
39146
39301
|
addSymlinkSkip(entry, accumulator);
|
|
@@ -39169,7 +39324,7 @@ async function processDirectory(entryPath, entry, claudeDir, metadata, options,
|
|
|
39169
39324
|
}
|
|
39170
39325
|
}
|
|
39171
39326
|
if (canDeleteDir && !dryRun) {
|
|
39172
|
-
await
|
|
39327
|
+
await import_fs_extra18.remove(entryPath);
|
|
39173
39328
|
logger.verbose(`Removed directory: ${entry}`);
|
|
39174
39329
|
}
|
|
39175
39330
|
}
|
|
@@ -39184,7 +39339,7 @@ class CommandsPrefix {
|
|
|
39184
39339
|
// src/commands/init/phases/merge-handler.ts
|
|
39185
39340
|
init_logger();
|
|
39186
39341
|
init_output_manager();
|
|
39187
|
-
var
|
|
39342
|
+
var import_fs_extra19 = __toESM(require_lib(), 1);
|
|
39188
39343
|
async function handleMerge(ctx) {
|
|
39189
39344
|
if (ctx.cancelled || !ctx.extractDir || !ctx.resolvedDir || !ctx.claudeDir || !ctx.kit || !ctx.kitType) {
|
|
39190
39345
|
return ctx;
|
|
@@ -39193,7 +39348,7 @@ async function handleMerge(ctx) {
|
|
|
39193
39348
|
let customClaudeFiles = [];
|
|
39194
39349
|
if (!ctx.options.fresh) {
|
|
39195
39350
|
logger.info("Scanning for custom .claude files...");
|
|
39196
|
-
const scanSourceDir = ctx.options.global ?
|
|
39351
|
+
const scanSourceDir = ctx.options.global ? join54(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
39197
39352
|
const scanTargetSubdir = ctx.options.global ? "" : ".claude";
|
|
39198
39353
|
customClaudeFiles = await FileScanner2.findCustomFiles(ctx.resolvedDir, scanSourceDir, scanTargetSubdir);
|
|
39199
39354
|
} else {
|
|
@@ -39237,7 +39392,7 @@ async function handleMerge(ctx) {
|
|
|
39237
39392
|
if (releaseManifest) {
|
|
39238
39393
|
merger.setManifest(releaseManifest);
|
|
39239
39394
|
}
|
|
39240
|
-
if (!ctx.options.fresh && await
|
|
39395
|
+
if (!ctx.options.fresh && await import_fs_extra19.pathExists(ctx.claudeDir)) {
|
|
39241
39396
|
const legacyDetection = await LegacyMigration.detectLegacy(ctx.claudeDir);
|
|
39242
39397
|
if (legacyDetection.isLegacy && releaseManifest) {
|
|
39243
39398
|
logger.info("Legacy installation detected - migrating to ownership tracking...");
|
|
@@ -39257,13 +39412,34 @@ async function handleMerge(ctx) {
|
|
|
39257
39412
|
return { ...ctx, cancelled: true };
|
|
39258
39413
|
}
|
|
39259
39414
|
}
|
|
39260
|
-
const sourceDir = ctx.options.global ?
|
|
39415
|
+
const sourceDir = ctx.options.global ? join54(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
39261
39416
|
await merger.merge(sourceDir, ctx.resolvedDir, ctx.isNonInteractive);
|
|
39262
39417
|
const fileConflicts = merger.getFileConflicts();
|
|
39263
39418
|
if (fileConflicts.length > 0 && !ctx.isNonInteractive) {
|
|
39264
39419
|
const summary = buildConflictSummary(fileConflicts, [], []);
|
|
39265
39420
|
displayConflictSummary(summary);
|
|
39266
39421
|
}
|
|
39422
|
+
try {
|
|
39423
|
+
const sourceMetadataPath = join54(sourceDir, "metadata.json");
|
|
39424
|
+
if (await import_fs_extra19.pathExists(sourceMetadataPath)) {
|
|
39425
|
+
const metadataContent = await import_fs_extra19.readFile(sourceMetadataPath, "utf-8");
|
|
39426
|
+
const sourceMetadata = JSON.parse(metadataContent);
|
|
39427
|
+
if (sourceMetadata.deletions && sourceMetadata.deletions.length > 0) {
|
|
39428
|
+
const deletionResult = await handleDeletions(sourceMetadata, ctx.claudeDir);
|
|
39429
|
+
if (deletionResult.deletedPaths.length > 0) {
|
|
39430
|
+
logger.info(`Removed ${deletionResult.deletedPaths.length} deprecated file(s)`);
|
|
39431
|
+
for (const path11 of deletionResult.deletedPaths) {
|
|
39432
|
+
logger.verbose(` - ${path11}`);
|
|
39433
|
+
}
|
|
39434
|
+
}
|
|
39435
|
+
if (deletionResult.preservedPaths.length > 0) {
|
|
39436
|
+
logger.verbose(`Preserved ${deletionResult.preservedPaths.length} user-owned file(s)`);
|
|
39437
|
+
}
|
|
39438
|
+
}
|
|
39439
|
+
}
|
|
39440
|
+
} catch (error) {
|
|
39441
|
+
logger.debug(`Cleanup of deprecated files failed: ${error}`);
|
|
39442
|
+
}
|
|
39267
39443
|
const installedFiles = merger.getAllInstalledFiles();
|
|
39268
39444
|
const filesToTrack = buildFileTrackingList({
|
|
39269
39445
|
installedFiles,
|
|
@@ -39286,11 +39462,11 @@ async function handleMerge(ctx) {
|
|
|
39286
39462
|
};
|
|
39287
39463
|
}
|
|
39288
39464
|
// src/commands/init/phases/migration-handler.ts
|
|
39289
|
-
import { join as
|
|
39465
|
+
import { join as join62 } from "node:path";
|
|
39290
39466
|
|
|
39291
39467
|
// src/domains/skills/skills-detector.ts
|
|
39292
39468
|
init_logger();
|
|
39293
|
-
var
|
|
39469
|
+
var import_fs_extra22 = __toESM(require_lib(), 1);
|
|
39294
39470
|
|
|
39295
39471
|
// src/domains/skills/detection/config-detector.ts
|
|
39296
39472
|
init_logger();
|
|
@@ -39298,17 +39474,17 @@ init_logger();
|
|
|
39298
39474
|
// src/domains/skills/skills-manifest.ts
|
|
39299
39475
|
init_logger();
|
|
39300
39476
|
import { createHash as createHash2 } from "node:crypto";
|
|
39301
|
-
import { readFile as
|
|
39302
|
-
import { join as
|
|
39477
|
+
import { readFile as readFile21, readdir as readdir15, writeFile as writeFile17 } from "node:fs/promises";
|
|
39478
|
+
import { join as join55, relative as relative9 } from "node:path";
|
|
39303
39479
|
init_types2();
|
|
39304
|
-
var
|
|
39480
|
+
var import_fs_extra20 = __toESM(require_lib(), 1);
|
|
39305
39481
|
|
|
39306
39482
|
class SkillsManifestManager {
|
|
39307
39483
|
static MANIFEST_FILENAME = ".skills-manifest.json";
|
|
39308
39484
|
static MANIFEST_VERSION = "1.0.0";
|
|
39309
39485
|
static async generateManifest(skillsDir) {
|
|
39310
39486
|
logger.debug(`Generating manifest for: ${skillsDir}`);
|
|
39311
|
-
if (!await
|
|
39487
|
+
if (!await import_fs_extra20.pathExists(skillsDir)) {
|
|
39312
39488
|
throw new SkillsMigrationError(`Skills directory does not exist: ${skillsDir}`);
|
|
39313
39489
|
}
|
|
39314
39490
|
const structure = await SkillsManifestManager.detectStructure(skillsDir);
|
|
@@ -39323,18 +39499,18 @@ class SkillsManifestManager {
|
|
|
39323
39499
|
return manifest;
|
|
39324
39500
|
}
|
|
39325
39501
|
static async writeManifest(skillsDir, manifest) {
|
|
39326
|
-
const manifestPath =
|
|
39327
|
-
await
|
|
39502
|
+
const manifestPath = join55(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
39503
|
+
await writeFile17(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
39328
39504
|
logger.debug(`Wrote manifest to: ${manifestPath}`);
|
|
39329
39505
|
}
|
|
39330
39506
|
static async readManifest(skillsDir) {
|
|
39331
|
-
const manifestPath =
|
|
39332
|
-
if (!await
|
|
39507
|
+
const manifestPath = join55(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
39508
|
+
if (!await import_fs_extra20.pathExists(manifestPath)) {
|
|
39333
39509
|
logger.debug(`No manifest found at: ${manifestPath}`);
|
|
39334
39510
|
return null;
|
|
39335
39511
|
}
|
|
39336
39512
|
try {
|
|
39337
|
-
const content = await
|
|
39513
|
+
const content = await readFile21(manifestPath, "utf-8");
|
|
39338
39514
|
const data = JSON.parse(content);
|
|
39339
39515
|
const manifest = SkillsManifestSchema.parse(data);
|
|
39340
39516
|
logger.debug(`Read manifest from: ${manifestPath}`);
|
|
@@ -39351,7 +39527,7 @@ class SkillsManifestManager {
|
|
|
39351
39527
|
return "flat";
|
|
39352
39528
|
}
|
|
39353
39529
|
for (const dir of dirs.slice(0, 3)) {
|
|
39354
|
-
const dirPath =
|
|
39530
|
+
const dirPath = join55(skillsDir, dir.name);
|
|
39355
39531
|
const subEntries = await readdir15(dirPath, { withFileTypes: true });
|
|
39356
39532
|
const hasSubdirs = subEntries.some((entry) => entry.isDirectory());
|
|
39357
39533
|
if (hasSubdirs) {
|
|
@@ -39370,7 +39546,7 @@ class SkillsManifestManager {
|
|
|
39370
39546
|
const entries = await readdir15(skillsDir, { withFileTypes: true });
|
|
39371
39547
|
for (const entry of entries) {
|
|
39372
39548
|
if (entry.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(entry.name) && !entry.name.startsWith(".")) {
|
|
39373
|
-
const skillPath =
|
|
39549
|
+
const skillPath = join55(skillsDir, entry.name);
|
|
39374
39550
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
39375
39551
|
skills.push({
|
|
39376
39552
|
name: entry.name,
|
|
@@ -39382,11 +39558,11 @@ class SkillsManifestManager {
|
|
|
39382
39558
|
const categories = await readdir15(skillsDir, { withFileTypes: true });
|
|
39383
39559
|
for (const category of categories) {
|
|
39384
39560
|
if (category.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(category.name) && !category.name.startsWith(".")) {
|
|
39385
|
-
const categoryPath =
|
|
39561
|
+
const categoryPath = join55(skillsDir, category.name);
|
|
39386
39562
|
const skillEntries = await readdir15(categoryPath, { withFileTypes: true });
|
|
39387
39563
|
for (const skillEntry of skillEntries) {
|
|
39388
39564
|
if (skillEntry.isDirectory() && !skillEntry.name.startsWith(".")) {
|
|
39389
|
-
const skillPath =
|
|
39565
|
+
const skillPath = join55(categoryPath, skillEntry.name);
|
|
39390
39566
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
39391
39567
|
skills.push({
|
|
39392
39568
|
name: skillEntry.name,
|
|
@@ -39406,7 +39582,7 @@ class SkillsManifestManager {
|
|
|
39406
39582
|
files.sort();
|
|
39407
39583
|
for (const file of files) {
|
|
39408
39584
|
const relativePath = relative9(dirPath, file);
|
|
39409
|
-
const content = await
|
|
39585
|
+
const content = await readFile21(file);
|
|
39410
39586
|
hash.update(relativePath);
|
|
39411
39587
|
hash.update(content);
|
|
39412
39588
|
}
|
|
@@ -39416,7 +39592,7 @@ class SkillsManifestManager {
|
|
|
39416
39592
|
const files = [];
|
|
39417
39593
|
const entries = await readdir15(dirPath, { withFileTypes: true });
|
|
39418
39594
|
for (const entry of entries) {
|
|
39419
|
-
const fullPath =
|
|
39595
|
+
const fullPath = join55(dirPath, entry.name);
|
|
39420
39596
|
if (entry.name.startsWith(".") || BUILD_ARTIFACT_DIRS.includes(entry.name)) {
|
|
39421
39597
|
continue;
|
|
39422
39598
|
}
|
|
@@ -39536,11 +39712,11 @@ function getPathMapping(skillName, oldBasePath, newBasePath) {
|
|
|
39536
39712
|
}
|
|
39537
39713
|
|
|
39538
39714
|
// src/domains/skills/detection/script-detector.ts
|
|
39539
|
-
var
|
|
39715
|
+
var import_fs_extra21 = __toESM(require_lib(), 1);
|
|
39540
39716
|
import { readdir as readdir16 } from "node:fs/promises";
|
|
39541
|
-
import { join as
|
|
39717
|
+
import { join as join56 } from "node:path";
|
|
39542
39718
|
async function scanDirectory(skillsDir) {
|
|
39543
|
-
if (!await
|
|
39719
|
+
if (!await import_fs_extra21.pathExists(skillsDir)) {
|
|
39544
39720
|
return ["flat", []];
|
|
39545
39721
|
}
|
|
39546
39722
|
const entries = await readdir16(skillsDir, { withFileTypes: true });
|
|
@@ -39551,12 +39727,12 @@ async function scanDirectory(skillsDir) {
|
|
|
39551
39727
|
let totalSkillLikeCount = 0;
|
|
39552
39728
|
const allSkills = [];
|
|
39553
39729
|
for (const dir of dirs) {
|
|
39554
|
-
const dirPath =
|
|
39730
|
+
const dirPath = join56(skillsDir, dir.name);
|
|
39555
39731
|
const subEntries = await readdir16(dirPath, { withFileTypes: true });
|
|
39556
39732
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
39557
39733
|
if (subdirs.length > 0) {
|
|
39558
39734
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
39559
|
-
const subdirPath =
|
|
39735
|
+
const subdirPath = join56(dirPath, subdir.name);
|
|
39560
39736
|
const subdirFiles = await readdir16(subdirPath, { withFileTypes: true });
|
|
39561
39737
|
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"));
|
|
39562
39738
|
if (hasSkillMarker) {
|
|
@@ -39678,8 +39854,8 @@ async function detectViaManifest(oldSkillsDir, currentSkillsDir) {
|
|
|
39678
39854
|
class SkillsMigrationDetector {
|
|
39679
39855
|
static async detectMigration(oldSkillsDir, currentSkillsDir) {
|
|
39680
39856
|
logger.debug("Detecting skills migration need...");
|
|
39681
|
-
const oldExists = await
|
|
39682
|
-
const currentExists = await
|
|
39857
|
+
const oldExists = await import_fs_extra22.pathExists(oldSkillsDir);
|
|
39858
|
+
const currentExists = await import_fs_extra22.pathExists(currentSkillsDir);
|
|
39683
39859
|
if (!oldExists && !currentExists) {
|
|
39684
39860
|
logger.debug("No skills directories found, migration not needed");
|
|
39685
39861
|
return {
|
|
@@ -39713,13 +39889,13 @@ class SkillsMigrationDetector {
|
|
|
39713
39889
|
// src/domains/skills/skills-migrator.ts
|
|
39714
39890
|
init_logger();
|
|
39715
39891
|
init_types2();
|
|
39716
|
-
import { join as
|
|
39892
|
+
import { join as join61 } from "node:path";
|
|
39717
39893
|
|
|
39718
39894
|
// src/domains/skills/migrator/migration-executor.ts
|
|
39719
39895
|
init_logger();
|
|
39720
39896
|
import { copyFile as copyFile4, mkdir as mkdir17, readdir as readdir17, rm as rm3 } from "node:fs/promises";
|
|
39721
|
-
import { join as
|
|
39722
|
-
var
|
|
39897
|
+
import { join as join57 } from "node:path";
|
|
39898
|
+
var import_fs_extra23 = __toESM(require_lib(), 1);
|
|
39723
39899
|
|
|
39724
39900
|
// src/domains/skills/skills-migration-prompts.ts
|
|
39725
39901
|
init_environment();
|
|
@@ -39883,8 +40059,8 @@ async function copySkillDirectory(sourceDir, destDir) {
|
|
|
39883
40059
|
await mkdir17(destDir, { recursive: true });
|
|
39884
40060
|
const entries = await readdir17(sourceDir, { withFileTypes: true });
|
|
39885
40061
|
for (const entry of entries) {
|
|
39886
|
-
const sourcePath =
|
|
39887
|
-
const destPath =
|
|
40062
|
+
const sourcePath = join57(sourceDir, entry.name);
|
|
40063
|
+
const destPath = join57(destDir, entry.name);
|
|
39888
40064
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
39889
40065
|
continue;
|
|
39890
40066
|
}
|
|
@@ -39899,14 +40075,14 @@ async function executeInternal(mappings, customizations, currentSkillsDir, inter
|
|
|
39899
40075
|
const migrated = [];
|
|
39900
40076
|
const preserved = [];
|
|
39901
40077
|
const errors2 = [];
|
|
39902
|
-
const tempDir =
|
|
40078
|
+
const tempDir = join57(currentSkillsDir, "..", ".skills-migration-temp");
|
|
39903
40079
|
await mkdir17(tempDir, { recursive: true });
|
|
39904
40080
|
try {
|
|
39905
40081
|
for (const mapping of mappings) {
|
|
39906
40082
|
try {
|
|
39907
40083
|
const skillName = mapping.skillName;
|
|
39908
40084
|
const currentSkillPath = mapping.oldPath;
|
|
39909
|
-
if (!await
|
|
40085
|
+
if (!await import_fs_extra23.pathExists(currentSkillPath)) {
|
|
39910
40086
|
logger.warning(`Skill not found, skipping: ${skillName}`);
|
|
39911
40087
|
continue;
|
|
39912
40088
|
}
|
|
@@ -39920,9 +40096,9 @@ async function executeInternal(mappings, customizations, currentSkillsDir, inter
|
|
|
39920
40096
|
}
|
|
39921
40097
|
}
|
|
39922
40098
|
const category = mapping.category;
|
|
39923
|
-
const targetPath = category ?
|
|
40099
|
+
const targetPath = category ? join57(tempDir, category, skillName) : join57(tempDir, skillName);
|
|
39924
40100
|
if (category) {
|
|
39925
|
-
await mkdir17(
|
|
40101
|
+
await mkdir17(join57(tempDir, category), { recursive: true });
|
|
39926
40102
|
}
|
|
39927
40103
|
await copySkillDirectory(currentSkillPath, targetPath);
|
|
39928
40104
|
migrated.push(skillName);
|
|
@@ -39987,9 +40163,9 @@ function validateMigrationPath(path11, paramName) {
|
|
|
39987
40163
|
// src/domains/skills/skills-backup-manager.ts
|
|
39988
40164
|
init_logger();
|
|
39989
40165
|
init_types2();
|
|
39990
|
-
var
|
|
40166
|
+
var import_fs_extra24 = __toESM(require_lib(), 1);
|
|
39991
40167
|
import { copyFile as copyFile5, mkdir as mkdir18, readdir as readdir18, rm as rm4, stat as stat9 } from "node:fs/promises";
|
|
39992
|
-
import { basename as basename2, join as
|
|
40168
|
+
import { basename as basename2, join as join58, normalize as normalize6 } from "node:path";
|
|
39993
40169
|
function validatePath2(path11, paramName) {
|
|
39994
40170
|
if (!path11 || typeof path11 !== "string") {
|
|
39995
40171
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -40009,13 +40185,13 @@ class SkillsBackupManager {
|
|
|
40009
40185
|
if (parentDir) {
|
|
40010
40186
|
validatePath2(parentDir, "parentDir");
|
|
40011
40187
|
}
|
|
40012
|
-
if (!await
|
|
40188
|
+
if (!await import_fs_extra24.pathExists(skillsDir)) {
|
|
40013
40189
|
throw new SkillsMigrationError(`Cannot create backup: Skills directory does not exist: ${skillsDir}`);
|
|
40014
40190
|
}
|
|
40015
40191
|
const timestamp = Date.now();
|
|
40016
40192
|
const randomSuffix = Math.random().toString(36).substring(2, 8);
|
|
40017
40193
|
const backupDirName = `${SkillsBackupManager.BACKUP_PREFIX}${timestamp}-${randomSuffix}`;
|
|
40018
|
-
const backupDir = parentDir ?
|
|
40194
|
+
const backupDir = parentDir ? join58(parentDir, backupDirName) : join58(skillsDir, "..", backupDirName);
|
|
40019
40195
|
logger.info(`Creating backup at: ${backupDir}`);
|
|
40020
40196
|
try {
|
|
40021
40197
|
await mkdir18(backupDir, { recursive: true });
|
|
@@ -40032,12 +40208,12 @@ class SkillsBackupManager {
|
|
|
40032
40208
|
static async restoreBackup(backupDir, targetDir) {
|
|
40033
40209
|
validatePath2(backupDir, "backupDir");
|
|
40034
40210
|
validatePath2(targetDir, "targetDir");
|
|
40035
|
-
if (!await
|
|
40211
|
+
if (!await import_fs_extra24.pathExists(backupDir)) {
|
|
40036
40212
|
throw new SkillsMigrationError(`Cannot restore: Backup directory does not exist: ${backupDir}`);
|
|
40037
40213
|
}
|
|
40038
40214
|
logger.info(`Restoring from backup: ${backupDir}`);
|
|
40039
40215
|
try {
|
|
40040
|
-
if (await
|
|
40216
|
+
if (await import_fs_extra24.pathExists(targetDir)) {
|
|
40041
40217
|
await rm4(targetDir, { recursive: true, force: true });
|
|
40042
40218
|
}
|
|
40043
40219
|
await mkdir18(targetDir, { recursive: true });
|
|
@@ -40048,7 +40224,7 @@ class SkillsBackupManager {
|
|
|
40048
40224
|
}
|
|
40049
40225
|
}
|
|
40050
40226
|
static async deleteBackup(backupDir) {
|
|
40051
|
-
if (!await
|
|
40227
|
+
if (!await import_fs_extra24.pathExists(backupDir)) {
|
|
40052
40228
|
logger.warning(`Backup directory does not exist: ${backupDir}`);
|
|
40053
40229
|
return;
|
|
40054
40230
|
}
|
|
@@ -40061,12 +40237,12 @@ class SkillsBackupManager {
|
|
|
40061
40237
|
}
|
|
40062
40238
|
}
|
|
40063
40239
|
static async listBackups(parentDir) {
|
|
40064
|
-
if (!await
|
|
40240
|
+
if (!await import_fs_extra24.pathExists(parentDir)) {
|
|
40065
40241
|
return [];
|
|
40066
40242
|
}
|
|
40067
40243
|
try {
|
|
40068
40244
|
const entries = await readdir18(parentDir, { withFileTypes: true });
|
|
40069
|
-
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) =>
|
|
40245
|
+
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) => join58(parentDir, entry.name));
|
|
40070
40246
|
backups.sort().reverse();
|
|
40071
40247
|
return backups;
|
|
40072
40248
|
} catch (error) {
|
|
@@ -40086,7 +40262,7 @@ class SkillsBackupManager {
|
|
|
40086
40262
|
}
|
|
40087
40263
|
}
|
|
40088
40264
|
static async getBackupSize(backupDir) {
|
|
40089
|
-
if (!await
|
|
40265
|
+
if (!await import_fs_extra24.pathExists(backupDir)) {
|
|
40090
40266
|
return 0;
|
|
40091
40267
|
}
|
|
40092
40268
|
return await SkillsBackupManager.getDirectorySize(backupDir);
|
|
@@ -40094,8 +40270,8 @@ class SkillsBackupManager {
|
|
|
40094
40270
|
static async copyDirectory(sourceDir, destDir) {
|
|
40095
40271
|
const entries = await readdir18(sourceDir, { withFileTypes: true });
|
|
40096
40272
|
for (const entry of entries) {
|
|
40097
|
-
const sourcePath =
|
|
40098
|
-
const destPath =
|
|
40273
|
+
const sourcePath = join58(sourceDir, entry.name);
|
|
40274
|
+
const destPath = join58(destDir, entry.name);
|
|
40099
40275
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
40100
40276
|
continue;
|
|
40101
40277
|
}
|
|
@@ -40111,7 +40287,7 @@ class SkillsBackupManager {
|
|
|
40111
40287
|
let size = 0;
|
|
40112
40288
|
const entries = await readdir18(dirPath, { withFileTypes: true });
|
|
40113
40289
|
for (const entry of entries) {
|
|
40114
|
-
const fullPath =
|
|
40290
|
+
const fullPath = join58(dirPath, entry.name);
|
|
40115
40291
|
if (entry.isSymbolicLink()) {
|
|
40116
40292
|
continue;
|
|
40117
40293
|
}
|
|
@@ -40139,19 +40315,19 @@ class SkillsBackupManager {
|
|
|
40139
40315
|
init_logger();
|
|
40140
40316
|
|
|
40141
40317
|
// src/domains/skills/customization/comparison-engine.ts
|
|
40142
|
-
var
|
|
40318
|
+
var import_fs_extra25 = __toESM(require_lib(), 1);
|
|
40143
40319
|
import { relative as relative11 } from "node:path";
|
|
40144
40320
|
|
|
40145
40321
|
// src/domains/skills/customization/hash-calculator.ts
|
|
40146
40322
|
import { createHash as createHash3 } from "node:crypto";
|
|
40147
40323
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
40148
|
-
import { readFile as
|
|
40149
|
-
import { join as
|
|
40324
|
+
import { readFile as readFile22, readdir as readdir19 } from "node:fs/promises";
|
|
40325
|
+
import { join as join59, relative as relative10 } from "node:path";
|
|
40150
40326
|
async function getAllFiles(dirPath) {
|
|
40151
40327
|
const files = [];
|
|
40152
40328
|
const entries = await readdir19(dirPath, { withFileTypes: true });
|
|
40153
40329
|
for (const entry of entries) {
|
|
40154
|
-
const fullPath =
|
|
40330
|
+
const fullPath = join59(dirPath, entry.name);
|
|
40155
40331
|
if (entry.name.startsWith(".") || BUILD_ARTIFACT_DIRS.includes(entry.name) || entry.isSymbolicLink()) {
|
|
40156
40332
|
continue;
|
|
40157
40333
|
}
|
|
@@ -40165,12 +40341,12 @@ async function getAllFiles(dirPath) {
|
|
|
40165
40341
|
return files;
|
|
40166
40342
|
}
|
|
40167
40343
|
async function hashFile(filePath) {
|
|
40168
|
-
return new Promise((
|
|
40344
|
+
return new Promise((resolve8, reject) => {
|
|
40169
40345
|
const hash = createHash3("sha256");
|
|
40170
40346
|
const stream = createReadStream2(filePath);
|
|
40171
40347
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
40172
40348
|
stream.on("end", () => {
|
|
40173
|
-
|
|
40349
|
+
resolve8(hash.digest("hex"));
|
|
40174
40350
|
});
|
|
40175
40351
|
stream.on("error", (error) => {
|
|
40176
40352
|
stream.destroy();
|
|
@@ -40184,7 +40360,7 @@ async function hashDirectory(dirPath) {
|
|
|
40184
40360
|
files.sort();
|
|
40185
40361
|
for (const file of files) {
|
|
40186
40362
|
const relativePath = relative10(dirPath, file);
|
|
40187
|
-
const content = await
|
|
40363
|
+
const content = await readFile22(file);
|
|
40188
40364
|
hash.update(relativePath);
|
|
40189
40365
|
hash.update(content);
|
|
40190
40366
|
}
|
|
@@ -40234,7 +40410,7 @@ async function compareDirectories(dir1, dir2) {
|
|
|
40234
40410
|
async function detectFileChanges(currentSkillPath, baselineSkillPath) {
|
|
40235
40411
|
const changes = [];
|
|
40236
40412
|
const currentFiles = await getAllFiles(currentSkillPath);
|
|
40237
|
-
const baselineFiles = await
|
|
40413
|
+
const baselineFiles = await import_fs_extra25.pathExists(baselineSkillPath) ? await getAllFiles(baselineSkillPath) : [];
|
|
40238
40414
|
const currentFileMap = new Map(await Promise.all(currentFiles.map(async (f3) => {
|
|
40239
40415
|
const relPath = relative11(currentSkillPath, f3);
|
|
40240
40416
|
const hash = await hashFile(f3);
|
|
@@ -40276,9 +40452,9 @@ async function detectFileChanges(currentSkillPath, baselineSkillPath) {
|
|
|
40276
40452
|
|
|
40277
40453
|
// src/domains/skills/customization/scan-reporter.ts
|
|
40278
40454
|
init_types2();
|
|
40279
|
-
var
|
|
40455
|
+
var import_fs_extra26 = __toESM(require_lib(), 1);
|
|
40280
40456
|
import { readdir as readdir20 } from "node:fs/promises";
|
|
40281
|
-
import { join as
|
|
40457
|
+
import { join as join60, normalize as normalize7 } from "node:path";
|
|
40282
40458
|
function validatePath3(path11, paramName) {
|
|
40283
40459
|
if (!path11 || typeof path11 !== "string") {
|
|
40284
40460
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -40291,7 +40467,7 @@ function validatePath3(path11, paramName) {
|
|
|
40291
40467
|
}
|
|
40292
40468
|
}
|
|
40293
40469
|
async function scanSkillsDirectory(skillsDir) {
|
|
40294
|
-
if (!await
|
|
40470
|
+
if (!await import_fs_extra26.pathExists(skillsDir)) {
|
|
40295
40471
|
return ["flat", []];
|
|
40296
40472
|
}
|
|
40297
40473
|
const entries = await readdir20(skillsDir, { withFileTypes: true });
|
|
@@ -40299,13 +40475,13 @@ async function scanSkillsDirectory(skillsDir) {
|
|
|
40299
40475
|
if (dirs.length === 0) {
|
|
40300
40476
|
return ["flat", []];
|
|
40301
40477
|
}
|
|
40302
|
-
const firstDirPath =
|
|
40478
|
+
const firstDirPath = join60(skillsDir, dirs[0].name);
|
|
40303
40479
|
const subEntries = await readdir20(firstDirPath, { withFileTypes: true });
|
|
40304
40480
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
40305
40481
|
if (subdirs.length > 0) {
|
|
40306
40482
|
let skillLikeCount = 0;
|
|
40307
40483
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
40308
|
-
const subdirPath =
|
|
40484
|
+
const subdirPath = join60(firstDirPath, subdir.name);
|
|
40309
40485
|
const subdirFiles = await readdir20(subdirPath, { withFileTypes: true });
|
|
40310
40486
|
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"));
|
|
40311
40487
|
if (hasSkillMarker) {
|
|
@@ -40315,7 +40491,7 @@ async function scanSkillsDirectory(skillsDir) {
|
|
|
40315
40491
|
if (skillLikeCount > 0) {
|
|
40316
40492
|
const skills = [];
|
|
40317
40493
|
for (const dir of dirs) {
|
|
40318
|
-
const categoryPath =
|
|
40494
|
+
const categoryPath = join60(skillsDir, dir.name);
|
|
40319
40495
|
const skillDirs = await readdir20(categoryPath, { withFileTypes: true });
|
|
40320
40496
|
skills.push(...skillDirs.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name));
|
|
40321
40497
|
}
|
|
@@ -40325,8 +40501,8 @@ async function scanSkillsDirectory(skillsDir) {
|
|
|
40325
40501
|
return ["flat", dirs.map((dir) => dir.name)];
|
|
40326
40502
|
}
|
|
40327
40503
|
async function findSkillPath(skillsDir, skillName) {
|
|
40328
|
-
const flatPath =
|
|
40329
|
-
if (await
|
|
40504
|
+
const flatPath = join60(skillsDir, skillName);
|
|
40505
|
+
if (await import_fs_extra26.pathExists(flatPath)) {
|
|
40330
40506
|
return { path: flatPath, category: undefined };
|
|
40331
40507
|
}
|
|
40332
40508
|
const entries = await readdir20(skillsDir, { withFileTypes: true });
|
|
@@ -40334,9 +40510,9 @@ async function findSkillPath(skillsDir, skillName) {
|
|
|
40334
40510
|
if (!entry.isDirectory() || entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
40335
40511
|
continue;
|
|
40336
40512
|
}
|
|
40337
|
-
const categoryPath =
|
|
40338
|
-
const skillPath =
|
|
40339
|
-
if (await
|
|
40513
|
+
const categoryPath = join60(skillsDir, entry.name);
|
|
40514
|
+
const skillPath = join60(categoryPath, skillName);
|
|
40515
|
+
if (await import_fs_extra26.pathExists(skillPath)) {
|
|
40340
40516
|
return { path: skillPath, category: entry.name };
|
|
40341
40517
|
}
|
|
40342
40518
|
}
|
|
@@ -40429,7 +40605,7 @@ class SkillsMigrator {
|
|
|
40429
40605
|
}
|
|
40430
40606
|
}
|
|
40431
40607
|
if (options.backup && !options.dryRun) {
|
|
40432
|
-
const claudeDir =
|
|
40608
|
+
const claudeDir = join61(currentSkillsDir, "..");
|
|
40433
40609
|
result.backupPath = await SkillsBackupManager.createBackup(currentSkillsDir, claudeDir);
|
|
40434
40610
|
logger.success(`Backup created at: ${result.backupPath}`);
|
|
40435
40611
|
}
|
|
@@ -40482,7 +40658,7 @@ class SkillsMigrator {
|
|
|
40482
40658
|
// src/commands/init/phases/migration-handler.ts
|
|
40483
40659
|
init_logger();
|
|
40484
40660
|
init_path_resolver();
|
|
40485
|
-
var
|
|
40661
|
+
var import_fs_extra27 = __toESM(require_lib(), 1);
|
|
40486
40662
|
async function handleMigration(ctx) {
|
|
40487
40663
|
if (ctx.cancelled || !ctx.extractDir || !ctx.resolvedDir)
|
|
40488
40664
|
return ctx;
|
|
@@ -40490,9 +40666,9 @@ async function handleMigration(ctx) {
|
|
|
40490
40666
|
logger.debug("Skipping skills migration (fresh installation)");
|
|
40491
40667
|
return ctx;
|
|
40492
40668
|
}
|
|
40493
|
-
const newSkillsDir =
|
|
40669
|
+
const newSkillsDir = join62(ctx.extractDir, ".claude", "skills");
|
|
40494
40670
|
const currentSkillsDir = PathResolver.buildSkillsPath(ctx.resolvedDir, ctx.options.global);
|
|
40495
|
-
if (!await
|
|
40671
|
+
if (!await import_fs_extra27.pathExists(newSkillsDir) || !await import_fs_extra27.pathExists(currentSkillsDir)) {
|
|
40496
40672
|
return ctx;
|
|
40497
40673
|
}
|
|
40498
40674
|
logger.info("Checking for skills directory migration...");
|
|
@@ -40514,13 +40690,13 @@ async function handleMigration(ctx) {
|
|
|
40514
40690
|
}
|
|
40515
40691
|
// src/commands/init/phases/opencode-handler.ts
|
|
40516
40692
|
import { cp, readdir as readdir22, rm as rm5 } from "node:fs/promises";
|
|
40517
|
-
import { join as
|
|
40693
|
+
import { join as join64 } from "node:path";
|
|
40518
40694
|
|
|
40519
40695
|
// src/services/transformers/opencode-path-transformer.ts
|
|
40520
40696
|
init_logger();
|
|
40521
|
-
import { readFile as
|
|
40697
|
+
import { readFile as readFile23, readdir as readdir21, writeFile as writeFile18 } from "node:fs/promises";
|
|
40522
40698
|
import { platform as platform10 } from "node:os";
|
|
40523
|
-
import { extname as extname2, join as
|
|
40699
|
+
import { extname as extname2, join as join63 } from "node:path";
|
|
40524
40700
|
var IS_WINDOWS3 = platform10() === "win32";
|
|
40525
40701
|
function getOpenCodeGlobalPath() {
|
|
40526
40702
|
return "$HOME/.config/opencode/";
|
|
@@ -40581,7 +40757,7 @@ async function transformPathsForGlobalOpenCode(directory, options = {}) {
|
|
|
40581
40757
|
async function processDirectory2(dir) {
|
|
40582
40758
|
const entries = await readdir21(dir, { withFileTypes: true });
|
|
40583
40759
|
for (const entry of entries) {
|
|
40584
|
-
const fullPath =
|
|
40760
|
+
const fullPath = join63(dir, entry.name);
|
|
40585
40761
|
if (entry.isDirectory()) {
|
|
40586
40762
|
if (entry.name === "node_modules" || entry.name.startsWith(".")) {
|
|
40587
40763
|
continue;
|
|
@@ -40589,10 +40765,10 @@ async function transformPathsForGlobalOpenCode(directory, options = {}) {
|
|
|
40589
40765
|
await processDirectory2(fullPath);
|
|
40590
40766
|
} else if (entry.isFile() && shouldTransformFile2(entry.name)) {
|
|
40591
40767
|
try {
|
|
40592
|
-
const content = await
|
|
40768
|
+
const content = await readFile23(fullPath, "utf-8");
|
|
40593
40769
|
const { transformed, changes } = transformOpenCodeContent(content);
|
|
40594
40770
|
if (changes > 0) {
|
|
40595
|
-
await
|
|
40771
|
+
await writeFile18(fullPath, transformed, "utf-8");
|
|
40596
40772
|
filesTransformed++;
|
|
40597
40773
|
totalChanges += changes;
|
|
40598
40774
|
if (options.verbose) {
|
|
@@ -40615,13 +40791,13 @@ async function transformPathsForGlobalOpenCode(directory, options = {}) {
|
|
|
40615
40791
|
// src/commands/init/phases/opencode-handler.ts
|
|
40616
40792
|
init_logger();
|
|
40617
40793
|
init_path_resolver();
|
|
40618
|
-
var
|
|
40794
|
+
var import_fs_extra28 = __toESM(require_lib(), 1);
|
|
40619
40795
|
async function handleOpenCode(ctx) {
|
|
40620
40796
|
if (ctx.cancelled || !ctx.extractDir || !ctx.resolvedDir) {
|
|
40621
40797
|
return ctx;
|
|
40622
40798
|
}
|
|
40623
|
-
const openCodeSource =
|
|
40624
|
-
if (!await
|
|
40799
|
+
const openCodeSource = join64(ctx.extractDir, ".opencode");
|
|
40800
|
+
if (!await import_fs_extra28.pathExists(openCodeSource)) {
|
|
40625
40801
|
logger.debug("No .opencode directory in archive, skipping");
|
|
40626
40802
|
return ctx;
|
|
40627
40803
|
}
|
|
@@ -40635,12 +40811,12 @@ async function handleOpenCode(ctx) {
|
|
|
40635
40811
|
if (transformResult.totalChanges > 0) {
|
|
40636
40812
|
logger.success(`Transformed ${transformResult.totalChanges} OpenCode path(s) in ${transformResult.filesTransformed} file(s)`);
|
|
40637
40813
|
}
|
|
40638
|
-
await
|
|
40814
|
+
await import_fs_extra28.ensureDir(targetDir);
|
|
40639
40815
|
const entries = await readdir22(openCodeSource, { withFileTypes: true });
|
|
40640
40816
|
for (const entry of entries) {
|
|
40641
|
-
const sourcePath =
|
|
40642
|
-
const targetPath =
|
|
40643
|
-
if (await
|
|
40817
|
+
const sourcePath = join64(openCodeSource, entry.name);
|
|
40818
|
+
const targetPath = join64(targetDir, entry.name);
|
|
40819
|
+
if (await import_fs_extra28.pathExists(targetPath)) {
|
|
40644
40820
|
if (!ctx.options.forceOverwrite) {
|
|
40645
40821
|
logger.verbose(`Skipping existing: ${entry.name}`);
|
|
40646
40822
|
continue;
|
|
@@ -40660,18 +40836,18 @@ async function handleOpenCode(ctx) {
|
|
|
40660
40836
|
init_logger();
|
|
40661
40837
|
init_path_resolver();
|
|
40662
40838
|
init_types2();
|
|
40663
|
-
import { existsSync as
|
|
40664
|
-
import { mkdir as mkdir19, readFile as
|
|
40839
|
+
import { existsSync as existsSync19 } from "node:fs";
|
|
40840
|
+
import { mkdir as mkdir19, readFile as readFile24, rename as rename2, rm as rm6, writeFile as writeFile19 } from "node:fs/promises";
|
|
40665
40841
|
import { chmod as chmod2 } from "node:fs/promises";
|
|
40666
40842
|
import { platform as platform11 } from "node:os";
|
|
40667
|
-
import { join as
|
|
40843
|
+
import { join as join65 } from "node:path";
|
|
40668
40844
|
var PROJECT_CONFIG_FILE = ".ck.json";
|
|
40669
40845
|
|
|
40670
40846
|
class ConfigManager {
|
|
40671
40847
|
static config = null;
|
|
40672
40848
|
static globalFlag = false;
|
|
40673
40849
|
static getProjectConfigDir(projectDir, global3) {
|
|
40674
|
-
return global3 ? projectDir :
|
|
40850
|
+
return global3 ? projectDir : join65(projectDir, ".claude");
|
|
40675
40851
|
}
|
|
40676
40852
|
static setGlobalFlag(global3) {
|
|
40677
40853
|
ConfigManager.globalFlag = global3;
|
|
@@ -40686,8 +40862,8 @@ class ConfigManager {
|
|
|
40686
40862
|
}
|
|
40687
40863
|
const configFile = PathResolver.getConfigFile(ConfigManager.globalFlag);
|
|
40688
40864
|
try {
|
|
40689
|
-
if (
|
|
40690
|
-
const content = await
|
|
40865
|
+
if (existsSync19(configFile)) {
|
|
40866
|
+
const content = await readFile24(configFile, "utf-8");
|
|
40691
40867
|
const data = JSON.parse(content);
|
|
40692
40868
|
ConfigManager.config = ConfigSchema.parse(data);
|
|
40693
40869
|
logger.debug(`Config loaded from ${configFile}`);
|
|
@@ -40704,13 +40880,13 @@ class ConfigManager {
|
|
|
40704
40880
|
const validConfig = ConfigSchema.parse(config);
|
|
40705
40881
|
const configDir = PathResolver.getConfigDir(ConfigManager.globalFlag);
|
|
40706
40882
|
const configFile = PathResolver.getConfigFile(ConfigManager.globalFlag);
|
|
40707
|
-
if (!
|
|
40883
|
+
if (!existsSync19(configDir)) {
|
|
40708
40884
|
await mkdir19(configDir, { recursive: true });
|
|
40709
40885
|
if (platform11() !== "win32") {
|
|
40710
40886
|
await chmod2(configDir, 448);
|
|
40711
40887
|
}
|
|
40712
40888
|
}
|
|
40713
|
-
await
|
|
40889
|
+
await writeFile19(configFile, JSON.stringify(validConfig, null, 2), "utf-8");
|
|
40714
40890
|
if (platform11() !== "win32") {
|
|
40715
40891
|
await chmod2(configFile, 384);
|
|
40716
40892
|
}
|
|
@@ -40738,10 +40914,10 @@ class ConfigManager {
|
|
|
40738
40914
|
}
|
|
40739
40915
|
static async loadProjectConfig(projectDir, global3 = false) {
|
|
40740
40916
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
40741
|
-
const configPath =
|
|
40917
|
+
const configPath = join65(configDir, PROJECT_CONFIG_FILE);
|
|
40742
40918
|
try {
|
|
40743
|
-
if (
|
|
40744
|
-
const content = await
|
|
40919
|
+
if (existsSync19(configPath)) {
|
|
40920
|
+
const content = await readFile24(configPath, "utf-8");
|
|
40745
40921
|
const data = JSON.parse(content);
|
|
40746
40922
|
const folders = FoldersConfigSchema.parse(data.paths || data);
|
|
40747
40923
|
logger.debug(`Project config loaded from ${configPath}`);
|
|
@@ -40754,15 +40930,15 @@ class ConfigManager {
|
|
|
40754
40930
|
}
|
|
40755
40931
|
static async saveProjectConfig(projectDir, folders, global3 = false) {
|
|
40756
40932
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
40757
|
-
const configPath =
|
|
40933
|
+
const configPath = join65(configDir, PROJECT_CONFIG_FILE);
|
|
40758
40934
|
try {
|
|
40759
|
-
if (!
|
|
40935
|
+
if (!existsSync19(configDir)) {
|
|
40760
40936
|
await mkdir19(configDir, { recursive: true });
|
|
40761
40937
|
}
|
|
40762
40938
|
let existingConfig = {};
|
|
40763
|
-
if (
|
|
40939
|
+
if (existsSync19(configPath)) {
|
|
40764
40940
|
try {
|
|
40765
|
-
const content = await
|
|
40941
|
+
const content = await readFile24(configPath, "utf-8");
|
|
40766
40942
|
existingConfig = JSON.parse(content);
|
|
40767
40943
|
} catch (error) {
|
|
40768
40944
|
logger.debug(`Could not parse existing config, starting fresh: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -40777,7 +40953,7 @@ class ConfigManager {
|
|
|
40777
40953
|
...validFolders
|
|
40778
40954
|
}
|
|
40779
40955
|
};
|
|
40780
|
-
await
|
|
40956
|
+
await writeFile19(configPath, JSON.stringify(mergedConfig, null, 2), "utf-8");
|
|
40781
40957
|
logger.debug(`Project config saved to ${configPath}`);
|
|
40782
40958
|
} catch (error) {
|
|
40783
40959
|
throw new Error(`Failed to save project config: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -40803,21 +40979,21 @@ class ConfigManager {
|
|
|
40803
40979
|
}
|
|
40804
40980
|
static projectConfigExists(projectDir, global3 = false) {
|
|
40805
40981
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
40806
|
-
return
|
|
40982
|
+
return existsSync19(join65(configDir, PROJECT_CONFIG_FILE));
|
|
40807
40983
|
}
|
|
40808
40984
|
static async migrateNestedConfig(globalDir) {
|
|
40809
|
-
const correctPath =
|
|
40810
|
-
const incorrectPath =
|
|
40811
|
-
if (
|
|
40985
|
+
const correctPath = join65(globalDir, PROJECT_CONFIG_FILE);
|
|
40986
|
+
const incorrectPath = join65(globalDir, ".claude", PROJECT_CONFIG_FILE);
|
|
40987
|
+
if (existsSync19(correctPath)) {
|
|
40812
40988
|
logger.debug("Config already exists at correct location, skipping migration");
|
|
40813
40989
|
return false;
|
|
40814
40990
|
}
|
|
40815
|
-
if (
|
|
40991
|
+
if (existsSync19(incorrectPath)) {
|
|
40816
40992
|
try {
|
|
40817
40993
|
logger.info("Migrating .ck.json from nested location to correct location...");
|
|
40818
40994
|
await rename2(incorrectPath, correctPath);
|
|
40819
40995
|
logger.success(`Migrated ${PROJECT_CONFIG_FILE} to ${correctPath}`);
|
|
40820
|
-
const nestedClaudeDir =
|
|
40996
|
+
const nestedClaudeDir = join65(globalDir, ".claude");
|
|
40821
40997
|
try {
|
|
40822
40998
|
await rm6(nestedClaudeDir, { recursive: false });
|
|
40823
40999
|
logger.debug("Removed empty nested .claude directory");
|
|
@@ -40908,20 +41084,20 @@ Please use only one download method.`);
|
|
|
40908
41084
|
};
|
|
40909
41085
|
}
|
|
40910
41086
|
// src/commands/init/phases/post-install-handler.ts
|
|
40911
|
-
import { join as
|
|
41087
|
+
import { join as join66 } from "node:path";
|
|
40912
41088
|
init_logger();
|
|
40913
41089
|
init_path_resolver();
|
|
40914
|
-
var
|
|
41090
|
+
var import_fs_extra29 = __toESM(require_lib(), 1);
|
|
40915
41091
|
async function handlePostInstall(ctx) {
|
|
40916
41092
|
if (ctx.cancelled || !ctx.extractDir || !ctx.resolvedDir || !ctx.claudeDir) {
|
|
40917
41093
|
return ctx;
|
|
40918
41094
|
}
|
|
40919
41095
|
if (ctx.options.global) {
|
|
40920
|
-
const claudeMdSource =
|
|
40921
|
-
const claudeMdDest =
|
|
40922
|
-
if (await
|
|
40923
|
-
if (!await
|
|
40924
|
-
await
|
|
41096
|
+
const claudeMdSource = join66(ctx.extractDir, "CLAUDE.md");
|
|
41097
|
+
const claudeMdDest = join66(ctx.resolvedDir, "CLAUDE.md");
|
|
41098
|
+
if (await import_fs_extra29.pathExists(claudeMdSource)) {
|
|
41099
|
+
if (!await import_fs_extra29.pathExists(claudeMdDest)) {
|
|
41100
|
+
await import_fs_extra29.copy(claudeMdSource, claudeMdDest);
|
|
40925
41101
|
logger.success("Copied CLAUDE.md to global directory");
|
|
40926
41102
|
} else {
|
|
40927
41103
|
logger.debug("CLAUDE.md already exists in global directory (preserved)");
|
|
@@ -40966,7 +41142,7 @@ async function handlePostInstall(ctx) {
|
|
|
40966
41142
|
}
|
|
40967
41143
|
if (!ctx.options.skipSetup) {
|
|
40968
41144
|
await promptSetupWizardIfNeeded({
|
|
40969
|
-
envPath:
|
|
41145
|
+
envPath: join66(ctx.claudeDir, ".env"),
|
|
40970
41146
|
claudeDir: ctx.claudeDir,
|
|
40971
41147
|
isGlobal: ctx.options.global,
|
|
40972
41148
|
isNonInteractive: ctx.isNonInteractive,
|
|
@@ -40980,7 +41156,7 @@ async function handlePostInstall(ctx) {
|
|
|
40980
41156
|
}
|
|
40981
41157
|
// src/commands/init/phases/selection-handler.ts
|
|
40982
41158
|
import { mkdir as mkdir20 } from "node:fs/promises";
|
|
40983
|
-
import { join as
|
|
41159
|
+
import { join as join68, resolve as resolve9 } from "node:path";
|
|
40984
41160
|
init_github_client();
|
|
40985
41161
|
|
|
40986
41162
|
// src/domains/github/kit-access-checker.ts
|
|
@@ -41109,10 +41285,10 @@ async function runPreflightChecks() {
|
|
|
41109
41285
|
}
|
|
41110
41286
|
|
|
41111
41287
|
// src/domains/installation/fresh-installer.ts
|
|
41112
|
-
import { existsSync as
|
|
41113
|
-
import { dirname as
|
|
41288
|
+
import { existsSync as existsSync20, readdirSync as readdirSync2, rmSync as rmSync3, rmdirSync as rmdirSync2, unlinkSync as unlinkSync4 } from "node:fs";
|
|
41289
|
+
import { dirname as dirname10, join as join67, resolve as resolve8 } from "node:path";
|
|
41114
41290
|
init_logger();
|
|
41115
|
-
var
|
|
41291
|
+
var import_fs_extra30 = __toESM(require_lib(), 1);
|
|
41116
41292
|
var CLAUDEKIT_SUBDIRECTORIES = ["commands", "agents", "skills", "rules", "hooks"];
|
|
41117
41293
|
async function analyzeFreshInstallation(claudeDir) {
|
|
41118
41294
|
const metadata = await readManifest(claudeDir);
|
|
@@ -41156,16 +41332,16 @@ async function analyzeFreshInstallation(claudeDir) {
|
|
|
41156
41332
|
hasMetadata: true
|
|
41157
41333
|
};
|
|
41158
41334
|
}
|
|
41159
|
-
function
|
|
41160
|
-
const normalizedClaudeDir =
|
|
41161
|
-
let currentDir =
|
|
41335
|
+
function cleanupEmptyDirectories2(filePath, claudeDir) {
|
|
41336
|
+
const normalizedClaudeDir = resolve8(claudeDir);
|
|
41337
|
+
let currentDir = resolve8(dirname10(filePath));
|
|
41162
41338
|
while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir)) {
|
|
41163
41339
|
try {
|
|
41164
|
-
const entries =
|
|
41340
|
+
const entries = readdirSync2(currentDir);
|
|
41165
41341
|
if (entries.length === 0) {
|
|
41166
|
-
|
|
41342
|
+
rmdirSync2(currentDir);
|
|
41167
41343
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
41168
|
-
currentDir =
|
|
41344
|
+
currentDir = resolve8(dirname10(currentDir));
|
|
41169
41345
|
} else {
|
|
41170
41346
|
break;
|
|
41171
41347
|
}
|
|
@@ -41182,13 +41358,13 @@ async function removeFilesByOwnership(claudeDir, analysis, includeModified) {
|
|
|
41182
41358
|
const filesToRemove = includeModified ? [...analysis.ckFiles, ...analysis.ckModifiedFiles] : analysis.ckFiles;
|
|
41183
41359
|
const filesToPreserve = includeModified ? analysis.userFiles : [...analysis.ckModifiedFiles, ...analysis.userFiles];
|
|
41184
41360
|
for (const file of filesToRemove) {
|
|
41185
|
-
const fullPath =
|
|
41361
|
+
const fullPath = join67(claudeDir, file.path);
|
|
41186
41362
|
try {
|
|
41187
|
-
if (
|
|
41188
|
-
|
|
41363
|
+
if (existsSync20(fullPath)) {
|
|
41364
|
+
unlinkSync4(fullPath);
|
|
41189
41365
|
removedFiles.push(file.path);
|
|
41190
41366
|
logger.debug(`Removed: ${file.path}`);
|
|
41191
|
-
|
|
41367
|
+
cleanupEmptyDirectories2(fullPath, claudeDir);
|
|
41192
41368
|
}
|
|
41193
41369
|
} catch (error) {
|
|
41194
41370
|
logger.debug(`Failed to remove ${file.path}: ${error}`);
|
|
@@ -41207,13 +41383,13 @@ async function removeFilesByOwnership(claudeDir, analysis, includeModified) {
|
|
|
41207
41383
|
};
|
|
41208
41384
|
}
|
|
41209
41385
|
async function updateMetadataAfterFresh(claudeDir, removedFiles) {
|
|
41210
|
-
const metadataPath =
|
|
41211
|
-
if (!await
|
|
41386
|
+
const metadataPath = join67(claudeDir, "metadata.json");
|
|
41387
|
+
if (!await import_fs_extra30.pathExists(metadataPath)) {
|
|
41212
41388
|
return;
|
|
41213
41389
|
}
|
|
41214
41390
|
let content;
|
|
41215
41391
|
try {
|
|
41216
|
-
content = await
|
|
41392
|
+
content = await import_fs_extra30.readFile(metadataPath, "utf-8");
|
|
41217
41393
|
} catch (readError) {
|
|
41218
41394
|
logger.warning(`Failed to read metadata.json: ${readError instanceof Error ? readError.message : String(readError)}`);
|
|
41219
41395
|
return;
|
|
@@ -41239,7 +41415,7 @@ async function updateMetadataAfterFresh(claudeDir, removedFiles) {
|
|
|
41239
41415
|
metadata.files = metadata.files.filter((f3) => !removedSet.has(f3.path));
|
|
41240
41416
|
}
|
|
41241
41417
|
try {
|
|
41242
|
-
await
|
|
41418
|
+
await import_fs_extra30.writeFile(metadataPath, JSON.stringify(metadata, null, 2));
|
|
41243
41419
|
logger.debug(`Updated metadata.json, removed ${removedFiles.length} file entries`);
|
|
41244
41420
|
} catch (writeError) {
|
|
41245
41421
|
logger.warning(`Failed to write metadata.json: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
@@ -41250,17 +41426,17 @@ async function removeSubdirectoriesFallback(claudeDir) {
|
|
|
41250
41426
|
const removedFiles = [];
|
|
41251
41427
|
let removedDirCount = 0;
|
|
41252
41428
|
for (const subdir of CLAUDEKIT_SUBDIRECTORIES) {
|
|
41253
|
-
const subdirPath =
|
|
41254
|
-
if (await
|
|
41255
|
-
|
|
41429
|
+
const subdirPath = join67(claudeDir, subdir);
|
|
41430
|
+
if (await import_fs_extra30.pathExists(subdirPath)) {
|
|
41431
|
+
rmSync3(subdirPath, { recursive: true, force: true });
|
|
41256
41432
|
removedDirCount++;
|
|
41257
41433
|
removedFiles.push(`${subdir}/ (entire directory)`);
|
|
41258
41434
|
logger.debug(`Removed subdirectory: ${subdir}/`);
|
|
41259
41435
|
}
|
|
41260
41436
|
}
|
|
41261
|
-
const metadataPath =
|
|
41262
|
-
if (await
|
|
41263
|
-
|
|
41437
|
+
const metadataPath = join67(claudeDir, "metadata.json");
|
|
41438
|
+
if (await import_fs_extra30.pathExists(metadataPath)) {
|
|
41439
|
+
unlinkSync4(metadataPath);
|
|
41264
41440
|
removedFiles.push("metadata.json");
|
|
41265
41441
|
}
|
|
41266
41442
|
return {
|
|
@@ -41272,7 +41448,7 @@ async function removeSubdirectoriesFallback(claudeDir) {
|
|
|
41272
41448
|
};
|
|
41273
41449
|
}
|
|
41274
41450
|
async function handleFreshInstallation(claudeDir, prompts) {
|
|
41275
|
-
if (!await
|
|
41451
|
+
if (!await import_fs_extra30.pathExists(claudeDir)) {
|
|
41276
41452
|
logger.info(".claude directory does not exist, proceeding with fresh installation");
|
|
41277
41453
|
return true;
|
|
41278
41454
|
}
|
|
@@ -41306,7 +41482,7 @@ async function handleFreshInstallation(claudeDir, prompts) {
|
|
|
41306
41482
|
init_logger();
|
|
41307
41483
|
init_path_resolver();
|
|
41308
41484
|
init_types2();
|
|
41309
|
-
var
|
|
41485
|
+
var import_fs_extra31 = __toESM(require_lib(), 1);
|
|
41310
41486
|
|
|
41311
41487
|
// src/commands/init/types.ts
|
|
41312
41488
|
function isSyncContext(ctx) {
|
|
@@ -41475,7 +41651,7 @@ async function handleSelection(ctx) {
|
|
|
41475
41651
|
}
|
|
41476
41652
|
}
|
|
41477
41653
|
}
|
|
41478
|
-
const resolvedDir =
|
|
41654
|
+
const resolvedDir = resolve9(targetDir);
|
|
41479
41655
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
41480
41656
|
if (!ctx.options.global && PathResolver.isLocalSameAsGlobal(resolvedDir)) {
|
|
41481
41657
|
logger.warning("You're at HOME directory. Installing here modifies your GLOBAL ClaudeKit.");
|
|
@@ -41497,7 +41673,7 @@ async function handleSelection(ctx) {
|
|
|
41497
41673
|
return { ...ctx, cancelled: true };
|
|
41498
41674
|
}
|
|
41499
41675
|
}
|
|
41500
|
-
if (!await
|
|
41676
|
+
if (!await import_fs_extra31.pathExists(resolvedDir)) {
|
|
41501
41677
|
if (ctx.options.global) {
|
|
41502
41678
|
await mkdir20(resolvedDir, { recursive: true });
|
|
41503
41679
|
logger.info(`Created global directory: ${resolvedDir}`);
|
|
@@ -41509,7 +41685,7 @@ async function handleSelection(ctx) {
|
|
|
41509
41685
|
}
|
|
41510
41686
|
if (!ctx.options.fresh) {
|
|
41511
41687
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
41512
|
-
const claudeDir = prefix ?
|
|
41688
|
+
const claudeDir = prefix ? join68(resolvedDir, prefix) : resolvedDir;
|
|
41513
41689
|
try {
|
|
41514
41690
|
const existingMetadata = await readManifest(claudeDir);
|
|
41515
41691
|
if (existingMetadata?.kits) {
|
|
@@ -41541,7 +41717,7 @@ async function handleSelection(ctx) {
|
|
|
41541
41717
|
}
|
|
41542
41718
|
if (ctx.options.fresh) {
|
|
41543
41719
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
41544
|
-
const claudeDir = prefix ?
|
|
41720
|
+
const claudeDir = prefix ? join68(resolvedDir, prefix) : resolvedDir;
|
|
41545
41721
|
const canProceed = await handleFreshInstallation(claudeDir, ctx.prompts);
|
|
41546
41722
|
if (!canProceed) {
|
|
41547
41723
|
return { ...ctx, cancelled: true };
|
|
@@ -41560,7 +41736,7 @@ async function handleSelection(ctx) {
|
|
|
41560
41736
|
logger.info("Fetching available versions...");
|
|
41561
41737
|
let currentVersion = null;
|
|
41562
41738
|
try {
|
|
41563
|
-
const metadataPath = ctx.options.global ?
|
|
41739
|
+
const metadataPath = ctx.options.global ? join68(PathResolver.getGlobalKitDir(), "metadata.json") : join68(resolvedDir, ".claude", "metadata.json");
|
|
41564
41740
|
const metadata = await readClaudeKitMetadata(metadataPath);
|
|
41565
41741
|
currentVersion = metadata?.version || null;
|
|
41566
41742
|
if (currentVersion) {
|
|
@@ -41634,25 +41810,25 @@ async function handleSelection(ctx) {
|
|
|
41634
41810
|
};
|
|
41635
41811
|
}
|
|
41636
41812
|
// src/commands/init/phases/sync-handler.ts
|
|
41637
|
-
import { copyFile as copyFile6, mkdir as mkdir21, open, rename as rename3, stat as stat10, unlink as unlink7, writeFile as
|
|
41638
|
-
import { dirname as
|
|
41813
|
+
import { copyFile as copyFile6, mkdir as mkdir21, open, rename as rename3, stat as stat10, unlink as unlink7, writeFile as writeFile21 } from "node:fs/promises";
|
|
41814
|
+
import { dirname as dirname11, join as join69, resolve as resolve10 } from "node:path";
|
|
41639
41815
|
init_logger();
|
|
41640
41816
|
init_path_resolver();
|
|
41641
|
-
var
|
|
41817
|
+
var import_fs_extra32 = __toESM(require_lib(), 1);
|
|
41642
41818
|
var import_picocolors19 = __toESM(require_picocolors(), 1);
|
|
41643
41819
|
async function handleSync(ctx) {
|
|
41644
41820
|
if (!ctx.options.sync) {
|
|
41645
41821
|
return ctx;
|
|
41646
41822
|
}
|
|
41647
|
-
const resolvedDir = ctx.options.global ? PathResolver.getGlobalKitDir() :
|
|
41648
|
-
const claudeDir = ctx.options.global ? resolvedDir :
|
|
41649
|
-
if (!await
|
|
41823
|
+
const resolvedDir = ctx.options.global ? PathResolver.getGlobalKitDir() : resolve10(ctx.options.dir || ".");
|
|
41824
|
+
const claudeDir = ctx.options.global ? resolvedDir : join69(resolvedDir, ".claude");
|
|
41825
|
+
if (!await import_fs_extra32.pathExists(claudeDir)) {
|
|
41650
41826
|
logger.error("Cannot sync: no .claude directory found");
|
|
41651
41827
|
ctx.prompts.note("Run 'ck init' without --sync to install first.", "No Installation Found");
|
|
41652
41828
|
return { ...ctx, cancelled: true };
|
|
41653
41829
|
}
|
|
41654
|
-
const metadataPath =
|
|
41655
|
-
if (!await
|
|
41830
|
+
const metadataPath = join69(claudeDir, "metadata.json");
|
|
41831
|
+
if (!await import_fs_extra32.pathExists(metadataPath)) {
|
|
41656
41832
|
logger.error("Cannot sync: no metadata.json found");
|
|
41657
41833
|
ctx.prompts.note(`Your installation may be from an older version.
|
|
41658
41834
|
Run 'ck init' to update.`, "Legacy Installation");
|
|
@@ -41751,10 +41927,10 @@ function getLockTimeout() {
|
|
|
41751
41927
|
var STALE_LOCK_THRESHOLD_MS = 5 * 60 * 1000;
|
|
41752
41928
|
async function acquireSyncLock(global3) {
|
|
41753
41929
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
41754
|
-
const lockPath =
|
|
41930
|
+
const lockPath = join69(cacheDir, ".sync-lock");
|
|
41755
41931
|
const startTime = Date.now();
|
|
41756
41932
|
const lockTimeout = getLockTimeout();
|
|
41757
|
-
await mkdir21(
|
|
41933
|
+
await mkdir21(dirname11(lockPath), { recursive: true });
|
|
41758
41934
|
while (Date.now() - startTime < lockTimeout) {
|
|
41759
41935
|
try {
|
|
41760
41936
|
const handle = await open(lockPath, "wx");
|
|
@@ -41778,7 +41954,7 @@ async function acquireSyncLock(global3) {
|
|
|
41778
41954
|
}
|
|
41779
41955
|
logger.debug(`Lock stat failed: ${statError}`);
|
|
41780
41956
|
}
|
|
41781
|
-
await new Promise((
|
|
41957
|
+
await new Promise((resolve11) => setTimeout(resolve11, 100));
|
|
41782
41958
|
continue;
|
|
41783
41959
|
}
|
|
41784
41960
|
throw err;
|
|
@@ -41797,7 +41973,7 @@ async function executeSyncMerge(ctx) {
|
|
|
41797
41973
|
const releaseLock = await acquireSyncLock(ctx.options.global);
|
|
41798
41974
|
try {
|
|
41799
41975
|
const trackedFiles = ctx.syncTrackedFiles;
|
|
41800
|
-
const upstreamDir = ctx.options.global ?
|
|
41976
|
+
const upstreamDir = ctx.options.global ? join69(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
41801
41977
|
logger.info("Analyzing file changes...");
|
|
41802
41978
|
const plan = await SyncEngine.createSyncPlan(trackedFiles, ctx.claudeDir, upstreamDir);
|
|
41803
41979
|
displaySyncPlan(plan);
|
|
@@ -41816,7 +41992,7 @@ async function executeSyncMerge(ctx) {
|
|
|
41816
41992
|
try {
|
|
41817
41993
|
const sourcePath = await validateSyncPath(upstreamDir, file.path);
|
|
41818
41994
|
const targetPath = await validateSyncPath(ctx.claudeDir, file.path);
|
|
41819
|
-
const targetDir =
|
|
41995
|
+
const targetDir = join69(targetPath, "..");
|
|
41820
41996
|
try {
|
|
41821
41997
|
await mkdir21(targetDir, { recursive: true });
|
|
41822
41998
|
} catch (mkdirError) {
|
|
@@ -41897,7 +42073,7 @@ async function executeSyncMerge(ctx) {
|
|
|
41897
42073
|
try {
|
|
41898
42074
|
const tempPath = `${currentPath}.tmp.${Date.now()}`;
|
|
41899
42075
|
try {
|
|
41900
|
-
await
|
|
42076
|
+
await writeFile21(tempPath, result.result, "utf-8");
|
|
41901
42077
|
await rename3(tempPath, currentPath);
|
|
41902
42078
|
} catch (atomicError) {
|
|
41903
42079
|
await unlink7(tempPath).catch(() => {});
|
|
@@ -41985,9 +42161,9 @@ async function createBackup(claudeDir, files, backupDir) {
|
|
|
41985
42161
|
for (const file of files) {
|
|
41986
42162
|
try {
|
|
41987
42163
|
const sourcePath = await validateSyncPath(claudeDir, file.path);
|
|
41988
|
-
if (await
|
|
42164
|
+
if (await import_fs_extra32.pathExists(sourcePath)) {
|
|
41989
42165
|
const targetPath = await validateSyncPath(backupDir, file.path);
|
|
41990
|
-
const targetDir =
|
|
42166
|
+
const targetDir = join69(targetPath, "..");
|
|
41991
42167
|
await mkdir21(targetDir, { recursive: true });
|
|
41992
42168
|
await copyFile6(sourcePath, targetPath);
|
|
41993
42169
|
}
|
|
@@ -42001,7 +42177,7 @@ async function createBackup(claudeDir, files, backupDir) {
|
|
|
42001
42177
|
}
|
|
42002
42178
|
}
|
|
42003
42179
|
// src/commands/init/phases/transform-handler.ts
|
|
42004
|
-
import { join as
|
|
42180
|
+
import { join as join73 } from "node:path";
|
|
42005
42181
|
|
|
42006
42182
|
// src/services/transformers/folder-path-transformer.ts
|
|
42007
42183
|
init_logger();
|
|
@@ -42010,40 +42186,40 @@ init_types2();
|
|
|
42010
42186
|
// src/services/transformers/folder-transform/folder-renamer.ts
|
|
42011
42187
|
init_logger();
|
|
42012
42188
|
init_types2();
|
|
42013
|
-
var
|
|
42189
|
+
var import_fs_extra33 = __toESM(require_lib(), 1);
|
|
42014
42190
|
import { rename as rename4, rm as rm7 } from "node:fs/promises";
|
|
42015
|
-
import { join as
|
|
42191
|
+
import { join as join70, relative as relative12 } from "node:path";
|
|
42016
42192
|
async function collectDirsToRename(extractDir, folders) {
|
|
42017
42193
|
const dirsToRename = [];
|
|
42018
42194
|
if (folders.docs !== DEFAULT_FOLDERS.docs) {
|
|
42019
|
-
const docsPath =
|
|
42020
|
-
if (await
|
|
42195
|
+
const docsPath = join70(extractDir, DEFAULT_FOLDERS.docs);
|
|
42196
|
+
if (await import_fs_extra33.pathExists(docsPath)) {
|
|
42021
42197
|
dirsToRename.push({
|
|
42022
42198
|
from: docsPath,
|
|
42023
|
-
to:
|
|
42199
|
+
to: join70(extractDir, folders.docs)
|
|
42024
42200
|
});
|
|
42025
42201
|
}
|
|
42026
|
-
const claudeDocsPath =
|
|
42027
|
-
if (await
|
|
42202
|
+
const claudeDocsPath = join70(extractDir, ".claude", DEFAULT_FOLDERS.docs);
|
|
42203
|
+
if (await import_fs_extra33.pathExists(claudeDocsPath)) {
|
|
42028
42204
|
dirsToRename.push({
|
|
42029
42205
|
from: claudeDocsPath,
|
|
42030
|
-
to:
|
|
42206
|
+
to: join70(extractDir, ".claude", folders.docs)
|
|
42031
42207
|
});
|
|
42032
42208
|
}
|
|
42033
42209
|
}
|
|
42034
42210
|
if (folders.plans !== DEFAULT_FOLDERS.plans) {
|
|
42035
|
-
const plansPath =
|
|
42036
|
-
if (await
|
|
42211
|
+
const plansPath = join70(extractDir, DEFAULT_FOLDERS.plans);
|
|
42212
|
+
if (await import_fs_extra33.pathExists(plansPath)) {
|
|
42037
42213
|
dirsToRename.push({
|
|
42038
42214
|
from: plansPath,
|
|
42039
|
-
to:
|
|
42215
|
+
to: join70(extractDir, folders.plans)
|
|
42040
42216
|
});
|
|
42041
42217
|
}
|
|
42042
|
-
const claudePlansPath =
|
|
42043
|
-
if (await
|
|
42218
|
+
const claudePlansPath = join70(extractDir, ".claude", DEFAULT_FOLDERS.plans);
|
|
42219
|
+
if (await import_fs_extra33.pathExists(claudePlansPath)) {
|
|
42044
42220
|
dirsToRename.push({
|
|
42045
42221
|
from: claudePlansPath,
|
|
42046
|
-
to:
|
|
42222
|
+
to: join70(extractDir, ".claude", folders.plans)
|
|
42047
42223
|
});
|
|
42048
42224
|
}
|
|
42049
42225
|
}
|
|
@@ -42055,7 +42231,7 @@ async function moveAcrossDevices(src, dest) {
|
|
|
42055
42231
|
} catch (e2) {
|
|
42056
42232
|
if (e2.code === "EXDEV") {
|
|
42057
42233
|
logger.debug(`Cross-device move detected, using copy+delete: ${src} -> ${dest}`);
|
|
42058
|
-
await
|
|
42234
|
+
await import_fs_extra33.copy(src, dest, { overwrite: true });
|
|
42059
42235
|
await rm7(src, { recursive: true, force: true });
|
|
42060
42236
|
} else {
|
|
42061
42237
|
throw e2;
|
|
@@ -42083,8 +42259,8 @@ async function renameFolders(dirsToRename, extractDir, options) {
|
|
|
42083
42259
|
// src/services/transformers/folder-transform/path-replacer.ts
|
|
42084
42260
|
init_logger();
|
|
42085
42261
|
init_types2();
|
|
42086
|
-
import { readFile as
|
|
42087
|
-
import { join as
|
|
42262
|
+
import { readFile as readFile26, readdir as readdir23, writeFile as writeFile22 } from "node:fs/promises";
|
|
42263
|
+
import { join as join71, relative as relative13 } from "node:path";
|
|
42088
42264
|
var TRANSFORMABLE_FILE_PATTERNS = [
|
|
42089
42265
|
".md",
|
|
42090
42266
|
".txt",
|
|
@@ -42137,7 +42313,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
42137
42313
|
let replacementsCount = 0;
|
|
42138
42314
|
const entries = await readdir23(dir, { withFileTypes: true });
|
|
42139
42315
|
for (const entry of entries) {
|
|
42140
|
-
const fullPath =
|
|
42316
|
+
const fullPath = join71(dir, entry.name);
|
|
42141
42317
|
if (entry.isDirectory()) {
|
|
42142
42318
|
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
42143
42319
|
continue;
|
|
@@ -42150,7 +42326,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
42150
42326
|
if (!shouldTransform)
|
|
42151
42327
|
continue;
|
|
42152
42328
|
try {
|
|
42153
|
-
const content = await
|
|
42329
|
+
const content = await readFile26(fullPath, "utf-8");
|
|
42154
42330
|
let newContent = content;
|
|
42155
42331
|
let changeCount = 0;
|
|
42156
42332
|
for (const { regex: regex2, replacement } of compiledReplacements) {
|
|
@@ -42166,7 +42342,7 @@ async function transformFileContents(dir, compiledReplacements, options) {
|
|
|
42166
42342
|
if (options.dryRun) {
|
|
42167
42343
|
logger.debug(`[dry-run] Would update ${relative13(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
42168
42344
|
} else {
|
|
42169
|
-
await
|
|
42345
|
+
await writeFile22(fullPath, newContent, "utf-8");
|
|
42170
42346
|
logger.debug(`Updated ${relative13(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
42171
42347
|
}
|
|
42172
42348
|
filesChanged++;
|
|
@@ -42272,9 +42448,9 @@ async function transformFolderPaths(extractDir, folders, options = {}) {
|
|
|
42272
42448
|
|
|
42273
42449
|
// src/services/transformers/global-path-transformer.ts
|
|
42274
42450
|
init_logger();
|
|
42275
|
-
import { readFile as
|
|
42451
|
+
import { readFile as readFile27, readdir as readdir24, writeFile as writeFile23 } from "node:fs/promises";
|
|
42276
42452
|
import { platform as platform12 } from "node:os";
|
|
42277
|
-
import { extname as extname3, join as
|
|
42453
|
+
import { extname as extname3, join as join72 } from "node:path";
|
|
42278
42454
|
var IS_WINDOWS4 = platform12() === "win32";
|
|
42279
42455
|
var HOME_PREFIX = IS_WINDOWS4 ? "%USERPROFILE%" : "$HOME";
|
|
42280
42456
|
function getHomeDirPrefix() {
|
|
@@ -42384,7 +42560,7 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
42384
42560
|
async function processDirectory2(dir) {
|
|
42385
42561
|
const entries = await readdir24(dir, { withFileTypes: true });
|
|
42386
42562
|
for (const entry of entries) {
|
|
42387
|
-
const fullPath =
|
|
42563
|
+
const fullPath = join72(dir, entry.name);
|
|
42388
42564
|
if (entry.isDirectory()) {
|
|
42389
42565
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
42390
42566
|
continue;
|
|
@@ -42392,10 +42568,10 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
42392
42568
|
await processDirectory2(fullPath);
|
|
42393
42569
|
} else if (entry.isFile() && shouldTransformFile3(entry.name)) {
|
|
42394
42570
|
try {
|
|
42395
|
-
const content = await
|
|
42571
|
+
const content = await readFile27(fullPath, "utf-8");
|
|
42396
42572
|
const { transformed, changes } = transformContent(content);
|
|
42397
42573
|
if (changes > 0) {
|
|
42398
|
-
await
|
|
42574
|
+
await writeFile23(fullPath, transformed, "utf-8");
|
|
42399
42575
|
filesTransformed++;
|
|
42400
42576
|
totalChanges += changes;
|
|
42401
42577
|
if (options.verbose) {
|
|
@@ -42460,7 +42636,7 @@ async function handleTransforms(ctx) {
|
|
|
42460
42636
|
logger.debug(ctx.options.global ? "Saved folder configuration to ~/.claude/.ck.json" : "Saved folder configuration to .claude/.ck.json");
|
|
42461
42637
|
}
|
|
42462
42638
|
}
|
|
42463
|
-
const claudeDir = ctx.options.global ? ctx.resolvedDir :
|
|
42639
|
+
const claudeDir = ctx.options.global ? ctx.resolvedDir : join73(ctx.resolvedDir, ".claude");
|
|
42464
42640
|
return {
|
|
42465
42641
|
...ctx,
|
|
42466
42642
|
foldersConfig,
|
|
@@ -42650,11 +42826,11 @@ init_types2();
|
|
|
42650
42826
|
var import_picocolors20 = __toESM(require_picocolors(), 1);
|
|
42651
42827
|
|
|
42652
42828
|
// src/commands/new/phases/directory-setup.ts
|
|
42653
|
-
import { resolve as
|
|
42829
|
+
import { resolve as resolve11 } from "node:path";
|
|
42654
42830
|
init_logger();
|
|
42655
42831
|
init_path_resolver();
|
|
42656
42832
|
init_types2();
|
|
42657
|
-
var
|
|
42833
|
+
var import_fs_extra34 = __toESM(require_lib(), 1);
|
|
42658
42834
|
async function directorySetup(validOptions, prompts) {
|
|
42659
42835
|
const isNonInteractive2 = !process.stdin.isTTY || process.env.CI === "true" || process.env.NON_INTERACTIVE === "true";
|
|
42660
42836
|
const config = await ConfigManager.get();
|
|
@@ -42735,7 +42911,7 @@ async function directorySetup(validOptions, prompts) {
|
|
|
42735
42911
|
targetDir = await prompts.getDirectory(targetDir);
|
|
42736
42912
|
}
|
|
42737
42913
|
}
|
|
42738
|
-
const resolvedDir =
|
|
42914
|
+
const resolvedDir = resolve11(targetDir);
|
|
42739
42915
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
42740
42916
|
if (PathResolver.isLocalSameAsGlobal(resolvedDir)) {
|
|
42741
42917
|
logger.warning("You're creating a project at HOME directory.");
|
|
@@ -42753,8 +42929,8 @@ async function directorySetup(validOptions, prompts) {
|
|
|
42753
42929
|
return null;
|
|
42754
42930
|
}
|
|
42755
42931
|
}
|
|
42756
|
-
if (await
|
|
42757
|
-
const files = await
|
|
42932
|
+
if (await import_fs_extra34.pathExists(resolvedDir)) {
|
|
42933
|
+
const files = await import_fs_extra34.readdir(resolvedDir);
|
|
42758
42934
|
const isEmpty = files.length === 0;
|
|
42759
42935
|
if (!isEmpty) {
|
|
42760
42936
|
if (isNonInteractive2) {
|
|
@@ -42790,7 +42966,7 @@ async function handleDirectorySetup(ctx) {
|
|
|
42790
42966
|
};
|
|
42791
42967
|
}
|
|
42792
42968
|
// src/commands/new/phases/project-creation.ts
|
|
42793
|
-
import { join as
|
|
42969
|
+
import { join as join74 } from "node:path";
|
|
42794
42970
|
init_github_client();
|
|
42795
42971
|
init_logger();
|
|
42796
42972
|
init_output_manager();
|
|
@@ -42917,7 +43093,7 @@ async function projectCreation(kit, resolvedDir, validOptions, isNonInteractive2
|
|
|
42917
43093
|
output.section("Installing");
|
|
42918
43094
|
logger.verbose("Installation target", { directory: resolvedDir });
|
|
42919
43095
|
const merger = new FileMerger;
|
|
42920
|
-
const claudeDir =
|
|
43096
|
+
const claudeDir = join74(resolvedDir, ".claude");
|
|
42921
43097
|
merger.setMultiKitContext(claudeDir, kit);
|
|
42922
43098
|
if (validOptions.exclude && validOptions.exclude.length > 0) {
|
|
42923
43099
|
merger.addIgnorePatterns(validOptions.exclude);
|
|
@@ -42963,7 +43139,7 @@ async function handleProjectCreation(ctx) {
|
|
|
42963
43139
|
};
|
|
42964
43140
|
}
|
|
42965
43141
|
// src/commands/new/phases/post-setup.ts
|
|
42966
|
-
import { join as
|
|
43142
|
+
import { join as join75 } from "node:path";
|
|
42967
43143
|
init_package_installer();
|
|
42968
43144
|
init_logger();
|
|
42969
43145
|
init_path_resolver();
|
|
@@ -42995,9 +43171,9 @@ async function postSetup(resolvedDir, validOptions, isNonInteractive2, prompts)
|
|
|
42995
43171
|
withSudo: validOptions.withSudo
|
|
42996
43172
|
});
|
|
42997
43173
|
}
|
|
42998
|
-
const claudeDir =
|
|
43174
|
+
const claudeDir = join75(resolvedDir, ".claude");
|
|
42999
43175
|
await promptSetupWizardIfNeeded({
|
|
43000
|
-
envPath:
|
|
43176
|
+
envPath: join75(claudeDir, ".env"),
|
|
43001
43177
|
claudeDir,
|
|
43002
43178
|
isGlobal: false,
|
|
43003
43179
|
isNonInteractive: isNonInteractive2,
|
|
@@ -43066,7 +43242,7 @@ var import_picocolors22 = __toESM(require_picocolors(), 1);
|
|
|
43066
43242
|
|
|
43067
43243
|
// src/commands/uninstall/installation-detector.ts
|
|
43068
43244
|
init_path_resolver();
|
|
43069
|
-
var
|
|
43245
|
+
var import_fs_extra35 = __toESM(require_lib(), 1);
|
|
43070
43246
|
async function detectInstallations() {
|
|
43071
43247
|
const installations = [];
|
|
43072
43248
|
const setup = await getClaudeKitSetup(process.cwd());
|
|
@@ -43075,28 +43251,28 @@ async function detectInstallations() {
|
|
|
43075
43251
|
installations.push({
|
|
43076
43252
|
type: "local",
|
|
43077
43253
|
path: setup.project.path,
|
|
43078
|
-
exists: await
|
|
43254
|
+
exists: await import_fs_extra35.pathExists(setup.project.path)
|
|
43079
43255
|
});
|
|
43080
43256
|
}
|
|
43081
43257
|
if (setup.global.path && setup.global.metadata) {
|
|
43082
43258
|
installations.push({
|
|
43083
43259
|
type: "global",
|
|
43084
43260
|
path: setup.global.path,
|
|
43085
|
-
exists: await
|
|
43261
|
+
exists: await import_fs_extra35.pathExists(setup.global.path)
|
|
43086
43262
|
});
|
|
43087
43263
|
}
|
|
43088
43264
|
return installations.filter((i) => i.exists);
|
|
43089
43265
|
}
|
|
43090
43266
|
|
|
43091
43267
|
// src/commands/uninstall/removal-handler.ts
|
|
43092
|
-
import { readdirSync as
|
|
43093
|
-
import { join as
|
|
43268
|
+
import { readdirSync as readdirSync4, rmSync as rmSync5 } from "node:fs";
|
|
43269
|
+
import { join as join77 } from "node:path";
|
|
43094
43270
|
init_logger();
|
|
43095
|
-
var
|
|
43271
|
+
var import_fs_extra36 = __toESM(require_lib(), 1);
|
|
43096
43272
|
|
|
43097
43273
|
// src/commands/uninstall/analysis-handler.ts
|
|
43098
|
-
import { readdirSync as
|
|
43099
|
-
import { dirname as
|
|
43274
|
+
import { readdirSync as readdirSync3, rmSync as rmSync4 } from "node:fs";
|
|
43275
|
+
import { dirname as dirname12, join as join76 } from "node:path";
|
|
43100
43276
|
init_logger();
|
|
43101
43277
|
var import_picocolors21 = __toESM(require_picocolors(), 1);
|
|
43102
43278
|
function classifyFileByOwnership(ownership, forceOverwrite, deleteReason) {
|
|
@@ -43111,17 +43287,17 @@ function classifyFileByOwnership(ownership, forceOverwrite, deleteReason) {
|
|
|
43111
43287
|
}
|
|
43112
43288
|
return { action: "preserve", reason: "user-created" };
|
|
43113
43289
|
}
|
|
43114
|
-
async function
|
|
43290
|
+
async function cleanupEmptyDirectories3(filePath, installationRoot) {
|
|
43115
43291
|
let cleaned = 0;
|
|
43116
|
-
let currentDir =
|
|
43292
|
+
let currentDir = dirname12(filePath);
|
|
43117
43293
|
while (currentDir !== installationRoot && currentDir.startsWith(installationRoot)) {
|
|
43118
43294
|
try {
|
|
43119
|
-
const entries =
|
|
43295
|
+
const entries = readdirSync3(currentDir);
|
|
43120
43296
|
if (entries.length === 0) {
|
|
43121
|
-
|
|
43297
|
+
rmSync4(currentDir, { recursive: true });
|
|
43122
43298
|
cleaned++;
|
|
43123
43299
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
43124
|
-
currentDir =
|
|
43300
|
+
currentDir = dirname12(currentDir);
|
|
43125
43301
|
} else {
|
|
43126
43302
|
break;
|
|
43127
43303
|
}
|
|
@@ -43143,7 +43319,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
43143
43319
|
if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
|
|
43144
43320
|
const kitFiles = metadata.kits[kit].files || [];
|
|
43145
43321
|
for (const trackedFile of kitFiles) {
|
|
43146
|
-
const filePath =
|
|
43322
|
+
const filePath = join76(installation.path, trackedFile.path);
|
|
43147
43323
|
if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
|
|
43148
43324
|
result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
|
|
43149
43325
|
continue;
|
|
@@ -43173,7 +43349,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
43173
43349
|
return result;
|
|
43174
43350
|
}
|
|
43175
43351
|
for (const trackedFile of allTrackedFiles) {
|
|
43176
|
-
const filePath =
|
|
43352
|
+
const filePath = join76(installation.path, trackedFile.path);
|
|
43177
43353
|
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
43178
43354
|
if (!ownershipResult.exists)
|
|
43179
43355
|
continue;
|
|
@@ -43233,21 +43409,21 @@ async function removeInstallations(installations, options) {
|
|
|
43233
43409
|
let removedCount = 0;
|
|
43234
43410
|
let cleanedDirs = 0;
|
|
43235
43411
|
for (const item of analysis.toDelete) {
|
|
43236
|
-
const filePath =
|
|
43237
|
-
if (await
|
|
43238
|
-
await
|
|
43412
|
+
const filePath = join77(installation.path, item.path);
|
|
43413
|
+
if (await import_fs_extra36.pathExists(filePath)) {
|
|
43414
|
+
await import_fs_extra36.remove(filePath);
|
|
43239
43415
|
removedCount++;
|
|
43240
43416
|
logger.debug(`Removed: ${item.path}`);
|
|
43241
|
-
cleanedDirs += await
|
|
43417
|
+
cleanedDirs += await cleanupEmptyDirectories3(filePath, installation.path);
|
|
43242
43418
|
}
|
|
43243
43419
|
}
|
|
43244
43420
|
if (options.kit && analysis.remainingKits.length > 0) {
|
|
43245
43421
|
await ManifestWriter.removeKitFromManifest(installation.path, options.kit);
|
|
43246
43422
|
}
|
|
43247
43423
|
try {
|
|
43248
|
-
const remaining =
|
|
43424
|
+
const remaining = readdirSync4(installation.path);
|
|
43249
43425
|
if (remaining.length === 0) {
|
|
43250
|
-
|
|
43426
|
+
rmSync5(installation.path, { recursive: true });
|
|
43251
43427
|
logger.debug(`Removed empty installation directory: ${installation.path}`);
|
|
43252
43428
|
}
|
|
43253
43429
|
} catch {}
|
|
@@ -43404,7 +43580,7 @@ ${import_picocolors22.default.yellow("User modifications will be permanently del
|
|
|
43404
43580
|
}
|
|
43405
43581
|
// src/commands/update-cli.ts
|
|
43406
43582
|
import { exec as exec8 } from "node:child_process";
|
|
43407
|
-
import { join as
|
|
43583
|
+
import { join as join78 } from "node:path";
|
|
43408
43584
|
import { promisify as promisify8 } from "node:util";
|
|
43409
43585
|
|
|
43410
43586
|
// src/domains/github/npm-registry.ts
|
|
@@ -43475,19 +43651,22 @@ class NpmRegistryClient {
|
|
|
43475
43651
|
}
|
|
43476
43652
|
}
|
|
43477
43653
|
static async getBetaVersion(packageName, registryUrl) {
|
|
43654
|
+
return NpmRegistryClient.getDevVersion(packageName, registryUrl);
|
|
43655
|
+
}
|
|
43656
|
+
static async getDevVersion(packageName, registryUrl) {
|
|
43478
43657
|
try {
|
|
43479
43658
|
const info = await NpmRegistryClient.getPackageInfo(packageName, registryUrl);
|
|
43480
43659
|
if (!info)
|
|
43481
43660
|
return null;
|
|
43482
|
-
const
|
|
43483
|
-
if (!
|
|
43484
|
-
logger.debug(`No
|
|
43661
|
+
const devVersion = info["dist-tags"]?.dev || info["dist-tags"]?.beta || info["dist-tags"]?.next;
|
|
43662
|
+
if (!devVersion) {
|
|
43663
|
+
logger.debug(`No dev version found for ${packageName}`);
|
|
43485
43664
|
return null;
|
|
43486
43665
|
}
|
|
43487
|
-
return
|
|
43666
|
+
return devVersion;
|
|
43488
43667
|
} catch (error) {
|
|
43489
43668
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
43490
|
-
logger.debug(`Failed to get
|
|
43669
|
+
logger.debug(`Failed to get dev version for ${packageName}: ${message}`);
|
|
43491
43670
|
return null;
|
|
43492
43671
|
}
|
|
43493
43672
|
}
|
|
@@ -43547,11 +43726,11 @@ init_logger();
|
|
|
43547
43726
|
init_types2();
|
|
43548
43727
|
init_types2();
|
|
43549
43728
|
var import_compare_versions3 = __toESM(require_umd(), 1);
|
|
43550
|
-
var
|
|
43729
|
+
var import_fs_extra37 = __toESM(require_lib(), 1);
|
|
43551
43730
|
// package.json
|
|
43552
43731
|
var package_default = {
|
|
43553
43732
|
name: "claudekit-cli",
|
|
43554
|
-
version: "3.30.0-dev.
|
|
43733
|
+
version: "3.30.0-dev.3",
|
|
43555
43734
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
43556
43735
|
type: "module",
|
|
43557
43736
|
repository: {
|
|
@@ -43665,7 +43844,7 @@ function buildInitCommand(isGlobal, kit, beta) {
|
|
|
43665
43844
|
function isBetaVersion(version) {
|
|
43666
43845
|
if (!version)
|
|
43667
43846
|
return false;
|
|
43668
|
-
return /-(beta|alpha|rc)[.\d]/i.test(version);
|
|
43847
|
+
return /-(beta|alpha|rc|dev)[.\d]/i.test(version);
|
|
43669
43848
|
}
|
|
43670
43849
|
function selectKitForUpdate(params) {
|
|
43671
43850
|
const { hasLocal, hasGlobal, localKits, globalKits } = params;
|
|
@@ -43698,12 +43877,12 @@ function selectKitForUpdate(params) {
|
|
|
43698
43877
|
};
|
|
43699
43878
|
}
|
|
43700
43879
|
async function readMetadataFile(claudeDir) {
|
|
43701
|
-
const metadataPath =
|
|
43880
|
+
const metadataPath = join78(claudeDir, "metadata.json");
|
|
43702
43881
|
try {
|
|
43703
|
-
if (!await
|
|
43882
|
+
if (!await import_fs_extra37.pathExists(metadataPath)) {
|
|
43704
43883
|
return null;
|
|
43705
43884
|
}
|
|
43706
|
-
const content = await
|
|
43885
|
+
const content = await import_fs_extra37.readFile(metadataPath, "utf-8");
|
|
43707
43886
|
const parsed = JSON.parse(content);
|
|
43708
43887
|
const validated = MetadataSchema.safeParse(parsed);
|
|
43709
43888
|
if (!validated.success) {
|
|
@@ -43786,14 +43965,14 @@ async function updateCliCommand(options) {
|
|
|
43786
43965
|
}
|
|
43787
43966
|
targetVersion = opts.release;
|
|
43788
43967
|
s.stop(`Target version: ${targetVersion}`);
|
|
43789
|
-
} else if (opts.beta) {
|
|
43790
|
-
targetVersion = await NpmRegistryClient.
|
|
43968
|
+
} else if (opts.dev || opts.beta) {
|
|
43969
|
+
targetVersion = await NpmRegistryClient.getDevVersion(PACKAGE_NAME, opts.registry);
|
|
43791
43970
|
if (!targetVersion) {
|
|
43792
|
-
s.stop("No
|
|
43793
|
-
logger.warning("No
|
|
43971
|
+
s.stop("No dev version available");
|
|
43972
|
+
logger.warning("No dev version found. Using latest stable version instead.");
|
|
43794
43973
|
targetVersion = await NpmRegistryClient.getLatestVersion(PACKAGE_NAME, opts.registry);
|
|
43795
43974
|
} else {
|
|
43796
|
-
s.stop(`Latest
|
|
43975
|
+
s.stop(`Latest dev version: ${targetVersion}`);
|
|
43797
43976
|
}
|
|
43798
43977
|
} else {
|
|
43799
43978
|
targetVersion = await NpmRegistryClient.getLatestVersion(PACKAGE_NAME, opts.registry);
|
|
@@ -43805,7 +43984,7 @@ async function updateCliCommand(options) {
|
|
|
43805
43984
|
const comparison = import_compare_versions3.compareVersions(currentVersion, targetVersion);
|
|
43806
43985
|
if (comparison === 0) {
|
|
43807
43986
|
outro(`[+] Already on the latest CLI version (${currentVersion})`);
|
|
43808
|
-
await promptKitUpdate(opts.beta);
|
|
43987
|
+
await promptKitUpdate(opts.dev || opts.beta);
|
|
43809
43988
|
return;
|
|
43810
43989
|
}
|
|
43811
43990
|
if (comparison > 0 && !opts.release) {
|
|
@@ -43819,7 +43998,7 @@ async function updateCliCommand(options) {
|
|
|
43819
43998
|
note(`CLI update available: ${currentVersion} -> ${targetVersion}
|
|
43820
43999
|
|
|
43821
44000
|
Run 'ck update' to install`, "Update Check");
|
|
43822
|
-
await promptKitUpdate(opts.beta);
|
|
44001
|
+
await promptKitUpdate(opts.dev || opts.beta);
|
|
43823
44002
|
outro("Check complete");
|
|
43824
44003
|
return;
|
|
43825
44004
|
}
|
|
@@ -43859,11 +44038,11 @@ Manual update: ${updateCmd}`);
|
|
|
43859
44038
|
const newVersion = newVersionMatch ? newVersionMatch[1] : targetVersion;
|
|
43860
44039
|
s.stop(`Installed version: ${newVersion}`);
|
|
43861
44040
|
outro(`[+] Successfully updated ClaudeKit CLI to ${newVersion}`);
|
|
43862
|
-
await promptKitUpdate(opts.beta);
|
|
44041
|
+
await promptKitUpdate(opts.dev || opts.beta);
|
|
43863
44042
|
} catch {
|
|
43864
44043
|
s.stop("Verification completed");
|
|
43865
44044
|
outro(`[+] Update completed. Please restart your terminal to use CLI ${targetVersion}`);
|
|
43866
|
-
await promptKitUpdate(opts.beta);
|
|
44045
|
+
await promptKitUpdate(opts.dev || opts.beta);
|
|
43867
44046
|
}
|
|
43868
44047
|
} catch (error) {
|
|
43869
44048
|
if (error instanceof CliUpdateError) {
|
|
@@ -43991,7 +44170,7 @@ function registerCommands(cli) {
|
|
|
43991
44170
|
}
|
|
43992
44171
|
await initCommand(options);
|
|
43993
44172
|
});
|
|
43994
|
-
cli.command("update", "Update ClaudeKit CLI to the latest version").option("-r, --release <version>", "Update to a specific version").option("--check", "Check for updates without installing").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("--
|
|
44173
|
+
cli.command("update", "Update ClaudeKit CLI to the latest version").option("-r, --release <version>", "Update to a specific version").option("--check", "Check for updates without installing").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("-d, --dev", "Update to the latest dev version").option("--beta", "Alias for --dev (deprecated)").option("--registry <url>", "Custom npm registry URL").option("--kit <kit>", "[DEPRECATED] Use 'ck init --kit <kit>' instead").option("-g, --global", "[DEPRECATED] Use 'ck init --global' instead").action(async (options) => {
|
|
43995
44174
|
if (options.kit || options.global) {
|
|
43996
44175
|
console.log();
|
|
43997
44176
|
const deprecatedFlags = [options.kit && "--kit", options.global && "--global"].filter(Boolean).join(" and ");
|
|
@@ -44030,8 +44209,8 @@ function registerCommands(cli) {
|
|
|
44030
44209
|
}
|
|
44031
44210
|
|
|
44032
44211
|
// src/cli/version-display.ts
|
|
44033
|
-
import { existsSync as
|
|
44034
|
-
import { join as
|
|
44212
|
+
import { existsSync as existsSync22, readFileSync as readFileSync7 } from "node:fs";
|
|
44213
|
+
import { join as join80 } from "node:path";
|
|
44035
44214
|
|
|
44036
44215
|
// src/domains/versioning/checking/version-utils.ts
|
|
44037
44216
|
var import_compare_versions4 = __toESM(require_umd(), 1);
|
|
@@ -44058,25 +44237,25 @@ init_types2();
|
|
|
44058
44237
|
// src/domains/versioning/version-cache.ts
|
|
44059
44238
|
init_logger();
|
|
44060
44239
|
init_path_resolver();
|
|
44061
|
-
import { existsSync as
|
|
44062
|
-
import { mkdir as mkdir22, readFile as
|
|
44063
|
-
import { join as
|
|
44240
|
+
import { existsSync as existsSync21 } from "node:fs";
|
|
44241
|
+
import { mkdir as mkdir22, readFile as readFile29, writeFile as writeFile24 } from "node:fs/promises";
|
|
44242
|
+
import { join as join79 } from "node:path";
|
|
44064
44243
|
|
|
44065
44244
|
class VersionCacheManager {
|
|
44066
44245
|
static CACHE_FILENAME = "version-check.json";
|
|
44067
44246
|
static CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
44068
44247
|
static getCacheFile() {
|
|
44069
44248
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
44070
|
-
return
|
|
44249
|
+
return join79(cacheDir, VersionCacheManager.CACHE_FILENAME);
|
|
44071
44250
|
}
|
|
44072
44251
|
static async load() {
|
|
44073
44252
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
44074
44253
|
try {
|
|
44075
|
-
if (!
|
|
44254
|
+
if (!existsSync21(cacheFile)) {
|
|
44076
44255
|
logger.debug("Version check cache not found");
|
|
44077
44256
|
return null;
|
|
44078
44257
|
}
|
|
44079
|
-
const content = await
|
|
44258
|
+
const content = await readFile29(cacheFile, "utf-8");
|
|
44080
44259
|
const cache2 = JSON.parse(content);
|
|
44081
44260
|
if (!cache2.lastCheck || !cache2.currentVersion || !cache2.latestVersion) {
|
|
44082
44261
|
logger.debug("Invalid cache structure, ignoring");
|
|
@@ -44093,10 +44272,10 @@ class VersionCacheManager {
|
|
|
44093
44272
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
44094
44273
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
44095
44274
|
try {
|
|
44096
|
-
if (!
|
|
44275
|
+
if (!existsSync21(cacheDir)) {
|
|
44097
44276
|
await mkdir22(cacheDir, { recursive: true, mode: 448 });
|
|
44098
44277
|
}
|
|
44099
|
-
await
|
|
44278
|
+
await writeFile24(cacheFile, JSON.stringify(cache2, null, 2), "utf-8");
|
|
44100
44279
|
logger.debug(`Version check cache saved to ${cacheFile}`);
|
|
44101
44280
|
} catch (error) {
|
|
44102
44281
|
logger.debug(`Failed to save version check cache: ${error}`);
|
|
@@ -44115,7 +44294,7 @@ class VersionCacheManager {
|
|
|
44115
44294
|
static async clear() {
|
|
44116
44295
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
44117
44296
|
try {
|
|
44118
|
-
if (
|
|
44297
|
+
if (existsSync21(cacheFile)) {
|
|
44119
44298
|
const fs14 = await import("node:fs/promises");
|
|
44120
44299
|
await fs14.unlink(cacheFile);
|
|
44121
44300
|
logger.debug("Version check cache cleared");
|
|
@@ -44335,11 +44514,11 @@ async function displayVersion() {
|
|
|
44335
44514
|
let localKitVersion = null;
|
|
44336
44515
|
let isGlobalOnlyKit = false;
|
|
44337
44516
|
const globalKitDir = PathResolver.getGlobalKitDir();
|
|
44338
|
-
const globalMetadataPath =
|
|
44517
|
+
const globalMetadataPath = join80(globalKitDir, "metadata.json");
|
|
44339
44518
|
const prefix = PathResolver.getPathPrefix(false);
|
|
44340
|
-
const localMetadataPath = prefix ?
|
|
44519
|
+
const localMetadataPath = prefix ? join80(process.cwd(), prefix, "metadata.json") : join80(process.cwd(), "metadata.json");
|
|
44341
44520
|
const isLocalSameAsGlobal = localMetadataPath === globalMetadataPath;
|
|
44342
|
-
if (!isLocalSameAsGlobal &&
|
|
44521
|
+
if (!isLocalSameAsGlobal && existsSync22(localMetadataPath)) {
|
|
44343
44522
|
try {
|
|
44344
44523
|
const rawMetadata = JSON.parse(readFileSync7(localMetadataPath, "utf-8"));
|
|
44345
44524
|
const metadata = MetadataSchema.parse(rawMetadata);
|
|
@@ -44353,7 +44532,7 @@ async function displayVersion() {
|
|
|
44353
44532
|
logger.verbose("Failed to parse local metadata.json", { error });
|
|
44354
44533
|
}
|
|
44355
44534
|
}
|
|
44356
|
-
if (
|
|
44535
|
+
if (existsSync22(globalMetadataPath)) {
|
|
44357
44536
|
try {
|
|
44358
44537
|
const rawMetadata = JSON.parse(readFileSync7(globalMetadataPath, "utf-8"));
|
|
44359
44538
|
const metadata = MetadataSchema.parse(rawMetadata);
|