claudekit-cli 4.3.1-dev.17 → 4.3.1-dev.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/postinstall-hook-restore.cjs +151 -0
- package/bin/postinstall-self-heal.cjs +13 -1
- package/cli-manifest.json +2 -2
- package/dist/index.js +597 -520
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -12622,6 +12622,217 @@ var init_converters = __esm(() => {
|
|
|
12622
12622
|
init_skill_md();
|
|
12623
12623
|
});
|
|
12624
12624
|
|
|
12625
|
+
// src/shared/path-resolver.ts
|
|
12626
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
12627
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
12628
|
+
import { homedir as homedir3, platform as platform2 } from "node:os";
|
|
12629
|
+
import { join as join2, normalize, resolve } from "node:path";
|
|
12630
|
+
function getEnvVar(name) {
|
|
12631
|
+
const val = process.env[name];
|
|
12632
|
+
if (!val || val.trim() === "")
|
|
12633
|
+
return;
|
|
12634
|
+
if (val.includes("..")) {
|
|
12635
|
+
console.warn(`Environment variable ${name} contains path traversal: ${val}`);
|
|
12636
|
+
return;
|
|
12637
|
+
}
|
|
12638
|
+
return val;
|
|
12639
|
+
}
|
|
12640
|
+
function isWSL() {
|
|
12641
|
+
try {
|
|
12642
|
+
return process.platform === "linux" && existsSync2("/proc/version") && readFileSync2("/proc/version", "utf8").toLowerCase().includes("microsoft");
|
|
12643
|
+
} catch {
|
|
12644
|
+
return false;
|
|
12645
|
+
}
|
|
12646
|
+
}
|
|
12647
|
+
function normalizeWSLPath(p) {
|
|
12648
|
+
if (!isWSL())
|
|
12649
|
+
return p;
|
|
12650
|
+
const windowsMatch = p.match(/^([A-Za-z]):(.*)/);
|
|
12651
|
+
if (windowsMatch) {
|
|
12652
|
+
const drive = windowsMatch[1].toLowerCase();
|
|
12653
|
+
const rest = windowsMatch[2].replace(/\\/g, "/");
|
|
12654
|
+
return `/mnt/${drive}${rest}`;
|
|
12655
|
+
}
|
|
12656
|
+
return p;
|
|
12657
|
+
}
|
|
12658
|
+
|
|
12659
|
+
class PathResolver {
|
|
12660
|
+
static getTestHomeDir() {
|
|
12661
|
+
return process.env.CK_TEST_HOME;
|
|
12662
|
+
}
|
|
12663
|
+
static isValidComponentName(name) {
|
|
12664
|
+
if (!name || typeof name !== "string") {
|
|
12665
|
+
return false;
|
|
12666
|
+
}
|
|
12667
|
+
const dangerousPatterns = [
|
|
12668
|
+
"..",
|
|
12669
|
+
"~"
|
|
12670
|
+
];
|
|
12671
|
+
for (const pattern of dangerousPatterns) {
|
|
12672
|
+
if (name.includes(pattern)) {
|
|
12673
|
+
return false;
|
|
12674
|
+
}
|
|
12675
|
+
}
|
|
12676
|
+
const normalized = normalize(name);
|
|
12677
|
+
for (const pattern of dangerousPatterns) {
|
|
12678
|
+
if (normalized.includes(pattern)) {
|
|
12679
|
+
return false;
|
|
12680
|
+
}
|
|
12681
|
+
}
|
|
12682
|
+
if (name.startsWith("/") || normalized.startsWith("/") || /^[a-zA-Z]:/.test(name) || name.startsWith("\\\\") || normalized.startsWith("\\\\")) {
|
|
12683
|
+
return false;
|
|
12684
|
+
}
|
|
12685
|
+
return true;
|
|
12686
|
+
}
|
|
12687
|
+
static getConfigDir(global2 = false) {
|
|
12688
|
+
const testHome = PathResolver.getTestHomeDir();
|
|
12689
|
+
if (testHome) {
|
|
12690
|
+
return global2 ? join2(testHome, ".config", "claude") : join2(testHome, ".claudekit");
|
|
12691
|
+
}
|
|
12692
|
+
if (!global2) {
|
|
12693
|
+
return join2(homedir3(), ".claudekit");
|
|
12694
|
+
}
|
|
12695
|
+
const os = platform2();
|
|
12696
|
+
if (os === "win32") {
|
|
12697
|
+
const localAppData = getEnvVar("LOCALAPPDATA") ?? join2(homedir3(), "AppData", "Local");
|
|
12698
|
+
return join2(localAppData, "claude");
|
|
12699
|
+
}
|
|
12700
|
+
const xdgConfigHome = getEnvVar("XDG_CONFIG_HOME");
|
|
12701
|
+
if (xdgConfigHome) {
|
|
12702
|
+
return join2(xdgConfigHome, "claude");
|
|
12703
|
+
}
|
|
12704
|
+
return join2(homedir3(), ".config", "claude");
|
|
12705
|
+
}
|
|
12706
|
+
static getConfigFile(global2 = false) {
|
|
12707
|
+
return join2(PathResolver.getConfigDir(global2), "config.json");
|
|
12708
|
+
}
|
|
12709
|
+
static getCacheDir(global2 = false) {
|
|
12710
|
+
const testHome = PathResolver.getTestHomeDir();
|
|
12711
|
+
if (testHome) {
|
|
12712
|
+
return global2 ? join2(testHome, ".cache", "claude") : join2(testHome, ".claudekit", "cache");
|
|
12713
|
+
}
|
|
12714
|
+
if (!global2) {
|
|
12715
|
+
return join2(homedir3(), ".claudekit", "cache");
|
|
12716
|
+
}
|
|
12717
|
+
const os = platform2();
|
|
12718
|
+
if (os === "win32") {
|
|
12719
|
+
const localAppData = getEnvVar("LOCALAPPDATA") ?? join2(homedir3(), "AppData", "Local");
|
|
12720
|
+
return join2(localAppData, "claude", "cache");
|
|
12721
|
+
}
|
|
12722
|
+
const xdgCacheHome = getEnvVar("XDG_CACHE_HOME");
|
|
12723
|
+
if (xdgCacheHome) {
|
|
12724
|
+
return join2(xdgCacheHome, "claude");
|
|
12725
|
+
}
|
|
12726
|
+
return join2(homedir3(), ".cache", "claude");
|
|
12727
|
+
}
|
|
12728
|
+
static getGlobalKitDir() {
|
|
12729
|
+
const testHome = PathResolver.getTestHomeDir();
|
|
12730
|
+
if (testHome) {
|
|
12731
|
+
return join2(testHome, ".claude");
|
|
12732
|
+
}
|
|
12733
|
+
const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR;
|
|
12734
|
+
if (claudeConfigDir) {
|
|
12735
|
+
return claudeConfigDir;
|
|
12736
|
+
}
|
|
12737
|
+
return join2(homedir3(), ".claude");
|
|
12738
|
+
}
|
|
12739
|
+
static getClaudeKitDir() {
|
|
12740
|
+
const testHome = PathResolver.getTestHomeDir();
|
|
12741
|
+
if (testHome) {
|
|
12742
|
+
return join2(testHome, ".claudekit");
|
|
12743
|
+
}
|
|
12744
|
+
return join2(homedir3(), ".claudekit");
|
|
12745
|
+
}
|
|
12746
|
+
static getProjectsRegistryPath() {
|
|
12747
|
+
return join2(PathResolver.getClaudeKitDir(), "projects.json");
|
|
12748
|
+
}
|
|
12749
|
+
static getOpenCodeDir(global2, baseDir) {
|
|
12750
|
+
const testHome = PathResolver.getTestHomeDir();
|
|
12751
|
+
if (testHome) {
|
|
12752
|
+
return global2 ? join2(testHome, ".config", "opencode") : join2(baseDir || testHome, ".opencode");
|
|
12753
|
+
}
|
|
12754
|
+
if (!global2) {
|
|
12755
|
+
return join2(baseDir || process.cwd(), ".opencode");
|
|
12756
|
+
}
|
|
12757
|
+
const xdgConfigHome = process.env.XDG_CONFIG_HOME;
|
|
12758
|
+
if (xdgConfigHome) {
|
|
12759
|
+
return join2(xdgConfigHome, "opencode");
|
|
12760
|
+
}
|
|
12761
|
+
return join2(homedir3(), ".config", "opencode");
|
|
12762
|
+
}
|
|
12763
|
+
static getPathPrefix(global2) {
|
|
12764
|
+
return global2 ? "" : ".claude";
|
|
12765
|
+
}
|
|
12766
|
+
static buildSkillsPath(baseDir, global2) {
|
|
12767
|
+
const prefix = PathResolver.getPathPrefix(global2);
|
|
12768
|
+
if (prefix) {
|
|
12769
|
+
return join2(baseDir, prefix, "skills");
|
|
12770
|
+
}
|
|
12771
|
+
return join2(baseDir, "skills");
|
|
12772
|
+
}
|
|
12773
|
+
static buildComponentPath(baseDir, component, global2) {
|
|
12774
|
+
if (!PathResolver.isValidComponentName(component)) {
|
|
12775
|
+
throw new Error(`Invalid component name: "${component}" contains path traversal patterns. Valid names are simple directory names like "agents", "commands", "rules", "skills", or "hooks".`);
|
|
12776
|
+
}
|
|
12777
|
+
const prefix = PathResolver.getPathPrefix(global2);
|
|
12778
|
+
if (prefix) {
|
|
12779
|
+
return join2(baseDir, prefix, component);
|
|
12780
|
+
}
|
|
12781
|
+
return join2(baseDir, component);
|
|
12782
|
+
}
|
|
12783
|
+
static getBackupDir(timestamp) {
|
|
12784
|
+
const testHome = PathResolver.getTestHomeDir();
|
|
12785
|
+
const baseDir = testHome ? join2(testHome, ".claudekit") : join2(homedir3(), ".claudekit");
|
|
12786
|
+
if (timestamp) {
|
|
12787
|
+
return join2(baseDir, "backups", timestamp);
|
|
12788
|
+
}
|
|
12789
|
+
const now = new Date;
|
|
12790
|
+
const dateStr = now.toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
12791
|
+
const ms = now.getMilliseconds().toString().padStart(3, "0");
|
|
12792
|
+
const random = Math.random().toString(36).slice(2, 6);
|
|
12793
|
+
const ts = `${dateStr}-${ms}-${random}`;
|
|
12794
|
+
return join2(baseDir, "backups", ts);
|
|
12795
|
+
}
|
|
12796
|
+
static normalizeWSLPath(p) {
|
|
12797
|
+
return normalizeWSLPath(p);
|
|
12798
|
+
}
|
|
12799
|
+
static isWSL() {
|
|
12800
|
+
return isWSL();
|
|
12801
|
+
}
|
|
12802
|
+
static isAtHomeDirectory(cwd2) {
|
|
12803
|
+
const currentDir = normalize(cwd2 || process.cwd());
|
|
12804
|
+
const homeDir = normalize(homedir3());
|
|
12805
|
+
return currentDir === homeDir;
|
|
12806
|
+
}
|
|
12807
|
+
static getLocalClaudeDir(baseDir) {
|
|
12808
|
+
const dir = baseDir || process.cwd();
|
|
12809
|
+
return join2(dir, ".claude");
|
|
12810
|
+
}
|
|
12811
|
+
static isLocalSameAsGlobal(cwd2) {
|
|
12812
|
+
const localPath = normalize(PathResolver.getLocalClaudeDir(cwd2));
|
|
12813
|
+
const globalPath = normalize(PathResolver.getGlobalKitDir());
|
|
12814
|
+
return localPath === globalPath;
|
|
12815
|
+
}
|
|
12816
|
+
static isGlobPattern(pattern) {
|
|
12817
|
+
return pattern.includes("*") || pattern.includes("?") || pattern.includes("{");
|
|
12818
|
+
}
|
|
12819
|
+
static computeProjectHash(projectRoot) {
|
|
12820
|
+
let normalized = resolve(projectRoot).replace(/[/\\]+$/, "");
|
|
12821
|
+
if (process.platform === "darwin" || process.platform === "win32") {
|
|
12822
|
+
normalized = normalized.toLowerCase();
|
|
12823
|
+
}
|
|
12824
|
+
return createHash3("sha256").update(normalized).digest("hex").slice(0, 12);
|
|
12825
|
+
}
|
|
12826
|
+
static getPlansRegistriesDir() {
|
|
12827
|
+
return join2(PathResolver.getGlobalKitDir(), "plans-registries");
|
|
12828
|
+
}
|
|
12829
|
+
static getPlansRegistryPath(projectRoot) {
|
|
12830
|
+
const hash = PathResolver.computeProjectHash(projectRoot);
|
|
12831
|
+
return join2(PathResolver.getPlansRegistriesDir(), `${hash}.json`);
|
|
12832
|
+
}
|
|
12833
|
+
}
|
|
12834
|
+
var init_path_resolver = () => {};
|
|
12835
|
+
|
|
12625
12836
|
// src/commands/portable/reconcile-types.ts
|
|
12626
12837
|
function normalizeChecksum(checksum) {
|
|
12627
12838
|
if (!checksum)
|
|
@@ -12686,18 +12897,16 @@ function providerConfigAppliesToType(config, type) {
|
|
|
12686
12897
|
var UNKNOWN_CHECKSUM = "unknown";
|
|
12687
12898
|
|
|
12688
12899
|
// src/commands/portable/portable-registry.ts
|
|
12689
|
-
import { existsSync as
|
|
12900
|
+
import { existsSync as existsSync3 } from "node:fs";
|
|
12690
12901
|
import { mkdir, readFile as readFile2, rename, unlink, writeFile } from "node:fs/promises";
|
|
12691
|
-
import {
|
|
12692
|
-
import { dirname, join as join2, resolve } from "node:path";
|
|
12902
|
+
import { dirname, join as join3, resolve as resolve2 } from "node:path";
|
|
12693
12903
|
function getPortableRegistryPaths() {
|
|
12694
|
-
const
|
|
12695
|
-
const claudekitDir = join2(home2, ".claudekit");
|
|
12904
|
+
const claudekitDir = PathResolver.getConfigDir(false);
|
|
12696
12905
|
return {
|
|
12697
|
-
registryPath:
|
|
12698
|
-
registryLockPath:
|
|
12699
|
-
legacyRegistryPath:
|
|
12700
|
-
migrationLockPath:
|
|
12906
|
+
registryPath: join3(claudekitDir, "portable-registry.json"),
|
|
12907
|
+
registryLockPath: join3(claudekitDir, "portable-registry.lock"),
|
|
12908
|
+
legacyRegistryPath: join3(claudekitDir, "skill-registry.json"),
|
|
12909
|
+
migrationLockPath: join3(claudekitDir, ".migration.lock")
|
|
12701
12910
|
};
|
|
12702
12911
|
}
|
|
12703
12912
|
function isErrnoCode(error, code) {
|
|
@@ -12721,19 +12930,19 @@ function getCliVersion() {
|
|
|
12721
12930
|
if (process.env.npm_package_version) {
|
|
12722
12931
|
return process.env.npm_package_version;
|
|
12723
12932
|
}
|
|
12724
|
-
const { readFileSync:
|
|
12933
|
+
const { readFileSync: readFileSync3 } = __require("node:fs");
|
|
12725
12934
|
const { dirname: dn, join: jp } = __require("node:path");
|
|
12726
12935
|
const { fileURLToPath } = __require("node:url");
|
|
12727
12936
|
const __dirname2 = dn(fileURLToPath(import.meta.url));
|
|
12728
12937
|
const pkgPath = jp(__dirname2, "../../../package.json");
|
|
12729
|
-
const pkg = JSON.parse(
|
|
12938
|
+
const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
|
|
12730
12939
|
return pkg.version || "unknown";
|
|
12731
12940
|
} catch {
|
|
12732
12941
|
return "unknown";
|
|
12733
12942
|
}
|
|
12734
12943
|
}
|
|
12735
|
-
async function migrateLegacyRegistry() {
|
|
12736
|
-
const { legacyRegistryPath } =
|
|
12944
|
+
async function migrateLegacyRegistry(paths = getPortableRegistryPaths()) {
|
|
12945
|
+
const { legacyRegistryPath } = paths;
|
|
12737
12946
|
try {
|
|
12738
12947
|
const content = await readFile2(legacyRegistryPath, "utf-8");
|
|
12739
12948
|
const data = JSON.parse(content);
|
|
@@ -12762,7 +12971,7 @@ async function migrateRegistryV2ToV3(v2Registry) {
|
|
|
12762
12971
|
for (const item of v2Registry.installations) {
|
|
12763
12972
|
let targetChecksum = UNKNOWN_CHECKSUM;
|
|
12764
12973
|
try {
|
|
12765
|
-
if (
|
|
12974
|
+
if (existsSync3(item.path)) {
|
|
12766
12975
|
targetChecksum = await computeFileChecksum(item.path);
|
|
12767
12976
|
}
|
|
12768
12977
|
} catch (error) {
|
|
@@ -12819,7 +13028,7 @@ async function repairStaleRegistryV3(registry) {
|
|
|
12819
13028
|
const installations = [];
|
|
12820
13029
|
for (const item of registry.installations) {
|
|
12821
13030
|
let targetChecksum = normalizeChecksum(getStringField(item, "targetChecksum")) || UNKNOWN_CHECKSUM;
|
|
12822
|
-
if (targetChecksum === UNKNOWN_CHECKSUM &&
|
|
13031
|
+
if (targetChecksum === UNKNOWN_CHECKSUM && existsSync3(item.path)) {
|
|
12823
13032
|
try {
|
|
12824
13033
|
targetChecksum = await computeFileChecksum(item.path);
|
|
12825
13034
|
} catch {
|
|
@@ -12842,15 +13051,15 @@ async function repairStaleRegistryV3(registry) {
|
|
|
12842
13051
|
appliedManifestVersion: registry.appliedManifestVersion
|
|
12843
13052
|
});
|
|
12844
13053
|
}
|
|
12845
|
-
async function persistCurrentStaleRegistryV3Repair(preparedRepair) {
|
|
12846
|
-
return withRegistryLock(async () => {
|
|
12847
|
-
const { registryPath } =
|
|
13054
|
+
async function persistCurrentStaleRegistryV3Repair(preparedRepair, paths = getPortableRegistryPaths()) {
|
|
13055
|
+
return withRegistryLock(async (lockedPaths) => {
|
|
13056
|
+
const { registryPath } = lockedPaths;
|
|
12848
13057
|
let content;
|
|
12849
13058
|
try {
|
|
12850
13059
|
content = await readFile2(registryPath, "utf-8");
|
|
12851
13060
|
} catch (error) {
|
|
12852
13061
|
if (isErrnoCode(error, "ENOENT")) {
|
|
12853
|
-
return readPortableRegistryInternal({ persistStaleV3Repair: false });
|
|
13062
|
+
return readPortableRegistryInternal({ persistStaleV3Repair: false }, lockedPaths);
|
|
12854
13063
|
}
|
|
12855
13064
|
throw error;
|
|
12856
13065
|
}
|
|
@@ -12866,20 +13075,20 @@ async function persistCurrentStaleRegistryV3Repair(preparedRepair) {
|
|
|
12866
13075
|
}
|
|
12867
13076
|
const repairableV3Result = RepairablePortableRegistrySchemaV3.safeParse(data);
|
|
12868
13077
|
if (!repairableV3Result.success) {
|
|
12869
|
-
return readPortableRegistryInternal({ persistStaleV3Repair: false });
|
|
13078
|
+
return readPortableRegistryInternal({ persistStaleV3Repair: false }, lockedPaths);
|
|
12870
13079
|
}
|
|
12871
13080
|
const repairedRegistry = preparedRepair && preparedRepair.sourceContent === content ? preparedRepair.repairedRegistry : await repairStaleRegistryV3(repairableV3Result.data);
|
|
12872
|
-
if (await isMigrationLocked()) {
|
|
13081
|
+
if (await isMigrationLocked(lockedPaths)) {
|
|
12873
13082
|
logger.verbose("Migration in progress by another process, using repaired v3 view");
|
|
12874
13083
|
return repairedRegistry;
|
|
12875
13084
|
}
|
|
12876
13085
|
logger.verbose("Repairing stale portable registry v3.0 fields");
|
|
12877
|
-
await writePortableRegistry(repairedRegistry);
|
|
13086
|
+
await writePortableRegistry(repairedRegistry, lockedPaths);
|
|
12878
13087
|
return repairedRegistry;
|
|
12879
|
-
});
|
|
13088
|
+
}, paths);
|
|
12880
13089
|
}
|
|
12881
|
-
async function isMigrationLocked() {
|
|
12882
|
-
const { migrationLockPath } =
|
|
13090
|
+
async function isMigrationLocked(paths = getPortableRegistryPaths()) {
|
|
13091
|
+
const { migrationLockPath } = paths;
|
|
12883
13092
|
try {
|
|
12884
13093
|
const lockContent = await readFile2(migrationLockPath, "utf-8");
|
|
12885
13094
|
const lockTime = Number.parseInt(lockContent, 10);
|
|
@@ -12903,16 +13112,16 @@ async function isMigrationLocked() {
|
|
|
12903
13112
|
return true;
|
|
12904
13113
|
}
|
|
12905
13114
|
}
|
|
12906
|
-
async function createMigrationLock() {
|
|
12907
|
-
const { migrationLockPath } =
|
|
13115
|
+
async function createMigrationLock(paths = getPortableRegistryPaths()) {
|
|
13116
|
+
const { migrationLockPath } = paths;
|
|
12908
13117
|
const lockDir = dirname(migrationLockPath);
|
|
12909
|
-
if (!
|
|
13118
|
+
if (!existsSync3(lockDir)) {
|
|
12910
13119
|
await mkdir(lockDir, { recursive: true });
|
|
12911
13120
|
}
|
|
12912
13121
|
await writeFile(migrationLockPath, Date.now().toString(), "utf-8");
|
|
12913
13122
|
}
|
|
12914
|
-
async function removeMigrationLock() {
|
|
12915
|
-
const { migrationLockPath } =
|
|
13123
|
+
async function removeMigrationLock(paths = getPortableRegistryPaths()) {
|
|
13124
|
+
const { migrationLockPath } = paths;
|
|
12916
13125
|
try {
|
|
12917
13126
|
await unlink(migrationLockPath);
|
|
12918
13127
|
} catch {}
|
|
@@ -12920,8 +13129,8 @@ async function removeMigrationLock() {
|
|
|
12920
13129
|
async function readPortableRegistry() {
|
|
12921
13130
|
return readPortableRegistryInternal({ persistStaleV3Repair: true });
|
|
12922
13131
|
}
|
|
12923
|
-
async function readPortableRegistryInternal(options2) {
|
|
12924
|
-
const { registryPath } =
|
|
13132
|
+
async function readPortableRegistryInternal(options2, paths = getPortableRegistryPaths()) {
|
|
13133
|
+
const { registryPath } = paths;
|
|
12925
13134
|
try {
|
|
12926
13135
|
const content = await readFile2(registryPath, "utf-8");
|
|
12927
13136
|
let data;
|
|
@@ -12940,61 +13149,61 @@ async function readPortableRegistryInternal(options2) {
|
|
|
12940
13149
|
if (!options2.persistStaleV3Repair) {
|
|
12941
13150
|
return repairedRegistry;
|
|
12942
13151
|
}
|
|
12943
|
-
if (await isMigrationLocked()) {
|
|
13152
|
+
if (await isMigrationLocked(paths)) {
|
|
12944
13153
|
logger.verbose("Migration in progress by another process, using repaired v3 view");
|
|
12945
13154
|
return repairedRegistry;
|
|
12946
13155
|
}
|
|
12947
13156
|
return persistCurrentStaleRegistryV3Repair({
|
|
12948
13157
|
sourceContent: content,
|
|
12949
13158
|
repairedRegistry
|
|
12950
|
-
});
|
|
13159
|
+
}, paths);
|
|
12951
13160
|
}
|
|
12952
13161
|
const v2Result = PortableRegistrySchema.safeParse(data);
|
|
12953
13162
|
if (!v2Result.success) {
|
|
12954
13163
|
throw new Error("portable-registry.json has unsupported schema/version");
|
|
12955
13164
|
}
|
|
12956
|
-
if (await isMigrationLocked()) {
|
|
13165
|
+
if (await isMigrationLocked(paths)) {
|
|
12957
13166
|
logger.verbose("Migration in progress by another process, using in-memory v2→v3 view");
|
|
12958
13167
|
return normalizePortableRegistryChecksums(await migrateRegistryV2ToV3(v2Result.data));
|
|
12959
13168
|
}
|
|
12960
13169
|
logger.verbose("Auto-migrating registry from v2.0 to v3.0");
|
|
12961
|
-
await createMigrationLock();
|
|
13170
|
+
await createMigrationLock(paths);
|
|
12962
13171
|
try {
|
|
12963
13172
|
const v3Registry = normalizePortableRegistryChecksums(await migrateRegistryV2ToV3(v2Result.data));
|
|
12964
|
-
await writePortableRegistry(v3Registry);
|
|
13173
|
+
await writePortableRegistry(v3Registry, paths);
|
|
12965
13174
|
return v3Registry;
|
|
12966
13175
|
} finally {
|
|
12967
|
-
await removeMigrationLock();
|
|
13176
|
+
await removeMigrationLock(paths);
|
|
12968
13177
|
}
|
|
12969
13178
|
} catch (error) {
|
|
12970
13179
|
if (!isErrnoCode(error, "ENOENT")) {
|
|
12971
13180
|
throw error;
|
|
12972
13181
|
}
|
|
12973
13182
|
}
|
|
12974
|
-
const migratedV2 = await migrateLegacyRegistry();
|
|
13183
|
+
const migratedV2 = await migrateLegacyRegistry(paths);
|
|
12975
13184
|
if (migratedV2) {
|
|
12976
|
-
if (await isMigrationLocked()) {
|
|
13185
|
+
if (await isMigrationLocked(paths)) {
|
|
12977
13186
|
logger.verbose("Migration in progress by another process, using in-memory v2→v3 view");
|
|
12978
13187
|
return normalizePortableRegistryChecksums(await migrateRegistryV2ToV3(migratedV2));
|
|
12979
13188
|
}
|
|
12980
|
-
await createMigrationLock();
|
|
13189
|
+
await createMigrationLock(paths);
|
|
12981
13190
|
try {
|
|
12982
13191
|
const v3Registry = normalizePortableRegistryChecksums(await migrateRegistryV2ToV3(migratedV2));
|
|
12983
|
-
await writePortableRegistry(v3Registry);
|
|
13192
|
+
await writePortableRegistry(v3Registry, paths);
|
|
12984
13193
|
return v3Registry;
|
|
12985
13194
|
} finally {
|
|
12986
|
-
await removeMigrationLock();
|
|
13195
|
+
await removeMigrationLock(paths);
|
|
12987
13196
|
}
|
|
12988
13197
|
}
|
|
12989
13198
|
return { version: "3.0", installations: [] };
|
|
12990
13199
|
}
|
|
12991
|
-
async function readPortableRegistryWithinRegistryLock() {
|
|
12992
|
-
return readPortableRegistryInternal({ persistStaleV3Repair: false });
|
|
13200
|
+
async function readPortableRegistryWithinRegistryLock(paths) {
|
|
13201
|
+
return readPortableRegistryInternal({ persistStaleV3Repair: false }, paths);
|
|
12993
13202
|
}
|
|
12994
|
-
async function writePortableRegistry(registry) {
|
|
12995
|
-
const { registryPath } =
|
|
13203
|
+
async function writePortableRegistry(registry, paths = getPortableRegistryPaths()) {
|
|
13204
|
+
const { registryPath } = paths;
|
|
12996
13205
|
const dir = dirname(registryPath);
|
|
12997
|
-
if (!
|
|
13206
|
+
if (!existsSync3(dir)) {
|
|
12998
13207
|
await mkdir(dir, { recursive: true });
|
|
12999
13208
|
}
|
|
13000
13209
|
const normalizedRegistry = normalizePortableRegistryChecksums(registry);
|
|
@@ -13009,13 +13218,13 @@ async function writePortableRegistry(registry) {
|
|
|
13009
13218
|
throw error;
|
|
13010
13219
|
}
|
|
13011
13220
|
}
|
|
13012
|
-
async function withRegistryLock(operation) {
|
|
13013
|
-
const { registryLockPath } =
|
|
13221
|
+
async function withRegistryLock(operation, paths = getPortableRegistryPaths()) {
|
|
13222
|
+
const { registryLockPath } = paths;
|
|
13014
13223
|
const lockDir = dirname(registryLockPath);
|
|
13015
|
-
if (!
|
|
13224
|
+
if (!existsSync3(lockDir)) {
|
|
13016
13225
|
await mkdir(lockDir, { recursive: true });
|
|
13017
13226
|
}
|
|
13018
|
-
if (!
|
|
13227
|
+
if (!existsSync3(registryLockPath)) {
|
|
13019
13228
|
await writeFile(registryLockPath, "", "utf-8");
|
|
13020
13229
|
}
|
|
13021
13230
|
const release = await import_proper_lockfile.default.lock(registryLockPath, {
|
|
@@ -13028,14 +13237,14 @@ async function withRegistryLock(operation) {
|
|
|
13028
13237
|
}
|
|
13029
13238
|
});
|
|
13030
13239
|
try {
|
|
13031
|
-
return await operation();
|
|
13240
|
+
return await operation(paths);
|
|
13032
13241
|
} finally {
|
|
13033
13242
|
await release();
|
|
13034
13243
|
}
|
|
13035
13244
|
}
|
|
13036
13245
|
async function addPortableInstallation(item, type, provider, global2, path2, sourcePath, options2) {
|
|
13037
|
-
await withRegistryLock(async () => {
|
|
13038
|
-
const registry = await readPortableRegistryWithinRegistryLock();
|
|
13246
|
+
await withRegistryLock(async (lockedPaths) => {
|
|
13247
|
+
const registry = await readPortableRegistryWithinRegistryLock(lockedPaths);
|
|
13039
13248
|
registry.installations = registry.installations.filter((i) => !(i.item === item && i.type === type && i.provider === provider && i.global === global2));
|
|
13040
13249
|
registry.installations.push({
|
|
13041
13250
|
item,
|
|
@@ -13051,17 +13260,17 @@ async function addPortableInstallation(item, type, provider, global2, path2, sou
|
|
|
13051
13260
|
installSource: options2?.installSource || "kit",
|
|
13052
13261
|
ownedSections: options2?.ownedSections
|
|
13053
13262
|
});
|
|
13054
|
-
await writePortableRegistry(registry);
|
|
13263
|
+
await writePortableRegistry(registry, lockedPaths);
|
|
13055
13264
|
});
|
|
13056
13265
|
}
|
|
13057
13266
|
async function removePortableInstallation(item, type, provider, global2, options2) {
|
|
13058
|
-
return withRegistryLock(async () => {
|
|
13059
|
-
const registry = await readPortableRegistryWithinRegistryLock();
|
|
13060
|
-
const index = registry.installations.findIndex((i) => i.item === item && i.type === type && i.provider === provider && i.global === global2 && (!options2?.path ||
|
|
13267
|
+
return withRegistryLock(async (lockedPaths) => {
|
|
13268
|
+
const registry = await readPortableRegistryWithinRegistryLock(lockedPaths);
|
|
13269
|
+
const index = registry.installations.findIndex((i) => i.item === item && i.type === type && i.provider === provider && i.global === global2 && (!options2?.path || resolve2(i.path) === resolve2(options2.path)));
|
|
13061
13270
|
if (index === -1)
|
|
13062
13271
|
return null;
|
|
13063
13272
|
const [removed] = registry.installations.splice(index, 1);
|
|
13064
|
-
await writePortableRegistry(registry);
|
|
13273
|
+
await writePortableRegistry(registry, lockedPaths);
|
|
13065
13274
|
return removed;
|
|
13066
13275
|
});
|
|
13067
13276
|
}
|
|
@@ -13079,15 +13288,15 @@ function findPortableInstallations(registry, item, type, provider, global2) {
|
|
|
13079
13288
|
});
|
|
13080
13289
|
}
|
|
13081
13290
|
async function updateAppliedManifestVersion(version) {
|
|
13082
|
-
await withRegistryLock(async () => {
|
|
13083
|
-
const registry = await readPortableRegistryWithinRegistryLock();
|
|
13291
|
+
await withRegistryLock(async (lockedPaths) => {
|
|
13292
|
+
const registry = await readPortableRegistryWithinRegistryLock(lockedPaths);
|
|
13084
13293
|
registry.appliedManifestVersion = version;
|
|
13085
|
-
await writePortableRegistry(registry);
|
|
13294
|
+
await writePortableRegistry(registry, lockedPaths);
|
|
13086
13295
|
});
|
|
13087
13296
|
}
|
|
13088
13297
|
async function removeInstallationsByFilter(predicate) {
|
|
13089
|
-
return withRegistryLock(async () => {
|
|
13090
|
-
const registry = await readPortableRegistryWithinRegistryLock();
|
|
13298
|
+
return withRegistryLock(async (lockedPaths) => {
|
|
13299
|
+
const registry = await readPortableRegistryWithinRegistryLock(lockedPaths);
|
|
13091
13300
|
const removed = [];
|
|
13092
13301
|
registry.installations = registry.installations.filter((entry) => {
|
|
13093
13302
|
if (predicate(entry)) {
|
|
@@ -13097,24 +13306,24 @@ async function removeInstallationsByFilter(predicate) {
|
|
|
13097
13306
|
return true;
|
|
13098
13307
|
});
|
|
13099
13308
|
if (removed.length > 0) {
|
|
13100
|
-
await writePortableRegistry(registry);
|
|
13309
|
+
await writePortableRegistry(registry, lockedPaths);
|
|
13101
13310
|
}
|
|
13102
13311
|
return removed;
|
|
13103
13312
|
});
|
|
13104
13313
|
}
|
|
13105
13314
|
async function syncPortableRegistry() {
|
|
13106
|
-
return withRegistryLock(async () => {
|
|
13107
|
-
const registry = await readPortableRegistryWithinRegistryLock();
|
|
13315
|
+
return withRegistryLock(async (lockedPaths) => {
|
|
13316
|
+
const registry = await readPortableRegistryWithinRegistryLock(lockedPaths);
|
|
13108
13317
|
const removed = [];
|
|
13109
13318
|
registry.installations = registry.installations.filter((i) => {
|
|
13110
|
-
if (!
|
|
13319
|
+
if (!existsSync3(i.path)) {
|
|
13111
13320
|
removed.push(i);
|
|
13112
13321
|
return false;
|
|
13113
13322
|
}
|
|
13114
13323
|
return true;
|
|
13115
13324
|
});
|
|
13116
13325
|
if (removed.length > 0) {
|
|
13117
|
-
await writePortableRegistry(registry);
|
|
13326
|
+
await writePortableRegistry(registry, lockedPaths);
|
|
13118
13327
|
}
|
|
13119
13328
|
return { removed };
|
|
13120
13329
|
});
|
|
@@ -13123,6 +13332,7 @@ var import_proper_lockfile, PortableInstallationSchema, PortableRegistrySchema,
|
|
|
13123
13332
|
var init_portable_registry = __esm(() => {
|
|
13124
13333
|
init_zod();
|
|
13125
13334
|
init_logger();
|
|
13335
|
+
init_path_resolver();
|
|
13126
13336
|
init_checksum_utils();
|
|
13127
13337
|
import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
|
|
13128
13338
|
PortableInstallationSchema = exports_external.object({
|
|
@@ -13181,10 +13391,10 @@ var init_portable_registry = __esm(() => {
|
|
|
13181
13391
|
});
|
|
13182
13392
|
|
|
13183
13393
|
// src/commands/portable/codex-toml-installer.ts
|
|
13184
|
-
import { existsSync as
|
|
13394
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
13185
13395
|
import { mkdir as mkdir2, readFile as readFile3, realpath, unlink as unlink2, writeFile as writeFile2 } from "node:fs/promises";
|
|
13186
13396
|
import { homedir as homedir4 } from "node:os";
|
|
13187
|
-
import { basename, dirname as dirname2, isAbsolute, join as
|
|
13397
|
+
import { basename, dirname as dirname2, isAbsolute, join as join4, relative, resolve as resolve3 } from "node:path";
|
|
13188
13398
|
function resolveCodexTomlRegistryDeps(deps) {
|
|
13189
13399
|
return {
|
|
13190
13400
|
...defaultCodexTomlRegistryDeps,
|
|
@@ -13193,7 +13403,7 @@ function resolveCodexTomlRegistryDeps(deps) {
|
|
|
13193
13403
|
}
|
|
13194
13404
|
async function ensureDir(filePath) {
|
|
13195
13405
|
const dir = dirname2(filePath);
|
|
13196
|
-
if (!
|
|
13406
|
+
if (!existsSync4(dir)) {
|
|
13197
13407
|
await mkdir2(dir, { recursive: true });
|
|
13198
13408
|
}
|
|
13199
13409
|
}
|
|
@@ -13201,7 +13411,7 @@ function isErrnoCode2(error, code) {
|
|
|
13201
13411
|
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
13202
13412
|
}
|
|
13203
13413
|
function normalizePathForComparison(path2) {
|
|
13204
|
-
const normalized =
|
|
13414
|
+
const normalized = resolve3(path2);
|
|
13205
13415
|
return process.platform === "win32" ? normalized.toLowerCase() : normalized;
|
|
13206
13416
|
}
|
|
13207
13417
|
function isPathWithinBoundary(targetPath, boundaryPath) {
|
|
@@ -13217,7 +13427,7 @@ async function resolveRealPathSafe(path2) {
|
|
|
13217
13427
|
try {
|
|
13218
13428
|
return await realpath(path2);
|
|
13219
13429
|
} catch {
|
|
13220
|
-
return
|
|
13430
|
+
return resolve3(path2);
|
|
13221
13431
|
}
|
|
13222
13432
|
}
|
|
13223
13433
|
async function isCanonicalPathWithinBoundary(targetPath, boundaryPath) {
|
|
@@ -13391,10 +13601,10 @@ function mergeConfigTomlWithDiagnostics(existing, managedBlock) {
|
|
|
13391
13601
|
};
|
|
13392
13602
|
}
|
|
13393
13603
|
function getCodexLockPath(configTomlPath) {
|
|
13394
|
-
return
|
|
13604
|
+
return join4(dirname2(configTomlPath), `.${basename(configTomlPath)}.ck-codex.lock`);
|
|
13395
13605
|
}
|
|
13396
13606
|
async function withCodexTargetLock(configTomlPath, operation) {
|
|
13397
|
-
const resolvedTargetPath =
|
|
13607
|
+
const resolvedTargetPath = resolve3(configTomlPath);
|
|
13398
13608
|
await ensureDir(resolvedTargetPath);
|
|
13399
13609
|
const release = await import_proper_lockfile2.default.lock(dirname2(resolvedTargetPath), {
|
|
13400
13610
|
realpath: false,
|
|
@@ -13473,8 +13683,8 @@ async function installCodexToml(items, provider, portableType, options2, deps) {
|
|
|
13473
13683
|
};
|
|
13474
13684
|
}
|
|
13475
13685
|
const boundary = options2.global ? homedir4() : process.cwd();
|
|
13476
|
-
const agentsDir =
|
|
13477
|
-
const configTomlPath =
|
|
13686
|
+
const agentsDir = resolve3(basePath);
|
|
13687
|
+
const configTomlPath = join4(dirname2(agentsDir), "config.toml");
|
|
13478
13688
|
if (!isPathWithinBoundary(agentsDir, boundary)) {
|
|
13479
13689
|
return {
|
|
13480
13690
|
provider,
|
|
@@ -13568,7 +13778,7 @@ async function installCodexToml(items, provider, portableType, options2, deps) {
|
|
|
13568
13778
|
continue;
|
|
13569
13779
|
}
|
|
13570
13780
|
seenSlugOwners.set(slug, item.name);
|
|
13571
|
-
const agentTomlPath =
|
|
13781
|
+
const agentTomlPath = join4(agentsDir, `${slug}.toml`);
|
|
13572
13782
|
if (process.platform === "win32" && agentTomlPath.length > MAX_WINDOWS_PATH_LENGTH) {
|
|
13573
13783
|
allWarnings.push(`Skipped ${item.name}: target path exceeds ${MAX_WINDOWS_PATH_LENGTH} characters on Windows`);
|
|
13574
13784
|
continue;
|
|
@@ -13695,9 +13905,9 @@ async function cleanupStaleCodexConfigEntries(options2) {
|
|
|
13695
13905
|
const basePath = options2.global ? pathConfig.globalPath : pathConfig.projectPath;
|
|
13696
13906
|
if (!basePath)
|
|
13697
13907
|
return [];
|
|
13698
|
-
const agentsDir =
|
|
13699
|
-
const configTomlPath =
|
|
13700
|
-
if (!
|
|
13908
|
+
const agentsDir = resolve3(basePath);
|
|
13909
|
+
const configTomlPath = join4(dirname2(agentsDir), "config.toml");
|
|
13910
|
+
if (!existsSync4(configTomlPath))
|
|
13701
13911
|
return [];
|
|
13702
13912
|
try {
|
|
13703
13913
|
return await withCodexTargetLock(configTomlPath, async () => {
|
|
@@ -13713,8 +13923,8 @@ async function cleanupStaleCodexConfigEntries(options2) {
|
|
|
13713
13923
|
if (managedEntries.size > 0) {
|
|
13714
13924
|
const validEntries = new Map;
|
|
13715
13925
|
for (const [slug, entry] of managedEntries) {
|
|
13716
|
-
const tomlPath =
|
|
13717
|
-
if (
|
|
13926
|
+
const tomlPath = join4(agentsDir, `${slug}.toml`);
|
|
13927
|
+
if (existsSync4(tomlPath)) {
|
|
13718
13928
|
validEntries.set(slug, entry);
|
|
13719
13929
|
} else {
|
|
13720
13930
|
allStaleSlugs.push(slug);
|
|
@@ -13744,10 +13954,10 @@ async function cleanupStaleCodexConfigEntries(options2) {
|
|
|
13744
13954
|
const unmanagedSlugs = extractUnmanagedAgentSlugs(analysis.unmanagedContent);
|
|
13745
13955
|
const legacyStaleSlugs = [];
|
|
13746
13956
|
for (const slug of unmanagedSlugs) {
|
|
13747
|
-
const tomlPath =
|
|
13957
|
+
const tomlPath = join4(agentsDir, `${slug}.toml`);
|
|
13748
13958
|
if (!isPathWithinBoundary(tomlPath, agentsDir))
|
|
13749
13959
|
continue;
|
|
13750
|
-
if (!
|
|
13960
|
+
if (!existsSync4(tomlPath)) {
|
|
13751
13961
|
legacyStaleSlugs.push(slug);
|
|
13752
13962
|
}
|
|
13753
13963
|
}
|
|
@@ -13992,13 +14202,13 @@ var init_merge_single_sections = __esm(() => {
|
|
|
13992
14202
|
});
|
|
13993
14203
|
|
|
13994
14204
|
// src/commands/portable/portable-installer.ts
|
|
13995
|
-
import { existsSync as
|
|
14205
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
13996
14206
|
import { lstat, mkdir as mkdir3, readFile as readFile4, realpath as realpath2, unlink as unlink3, writeFile as writeFile3 } from "node:fs/promises";
|
|
13997
14207
|
import { homedir as homedir5 } from "node:os";
|
|
13998
|
-
import { basename as basename2, dirname as dirname3, join as
|
|
14208
|
+
import { basename as basename2, dirname as dirname3, join as join5, relative as relative2, resolve as resolve4, sep } from "node:path";
|
|
13999
14209
|
function isSamePath(path1, path2) {
|
|
14000
14210
|
try {
|
|
14001
|
-
return
|
|
14211
|
+
return resolve4(path1) === resolve4(path2);
|
|
14002
14212
|
} catch {
|
|
14003
14213
|
return false;
|
|
14004
14214
|
}
|
|
@@ -14027,8 +14237,8 @@ function isWindowsAbsolutePath(path2) {
|
|
|
14027
14237
|
return /^[a-zA-Z]:[\\/]/.test(path2) || /^\\\\/.test(path2);
|
|
14028
14238
|
}
|
|
14029
14239
|
function isPathWithinBoundary2(targetPath, boundaryPath) {
|
|
14030
|
-
const resolvedTarget =
|
|
14031
|
-
const resolvedBoundary =
|
|
14240
|
+
const resolvedTarget = resolve4(targetPath);
|
|
14241
|
+
const resolvedBoundary = resolve4(boundaryPath);
|
|
14032
14242
|
return resolvedTarget === resolvedBoundary || resolvedTarget.startsWith(`${resolvedBoundary}${sep}`);
|
|
14033
14243
|
}
|
|
14034
14244
|
function validateStrategyTargetPath(targetPath, options2) {
|
|
@@ -14054,16 +14264,16 @@ function resolvePerFileOutputFilename(filename, pathConfig) {
|
|
|
14054
14264
|
return `${nameWithoutExt.replace(/\//g, "-")}${ext}`;
|
|
14055
14265
|
}
|
|
14056
14266
|
function validateResolvedTargetWithinBase(targetPath, basePath, pathConfig) {
|
|
14057
|
-
const resolvedTarget =
|
|
14058
|
-
const resolvedBase = pathConfig.writeStrategy === "single-file" ?
|
|
14267
|
+
const resolvedTarget = resolve4(targetPath);
|
|
14268
|
+
const resolvedBase = pathConfig.writeStrategy === "single-file" ? resolve4(dirname3(basePath)) : resolve4(basePath);
|
|
14059
14269
|
if (!resolvedTarget.startsWith(`${resolvedBase}${sep}`) && resolvedTarget !== resolvedBase) {
|
|
14060
14270
|
return "Unsafe path: target escapes base directory";
|
|
14061
14271
|
}
|
|
14062
14272
|
return null;
|
|
14063
14273
|
}
|
|
14064
14274
|
async function validateNoSymlinkComponents(targetPath, boundaryPath) {
|
|
14065
|
-
const resolvedTarget =
|
|
14066
|
-
const resolvedBoundary =
|
|
14275
|
+
const resolvedTarget = resolve4(targetPath);
|
|
14276
|
+
const resolvedBoundary = resolve4(boundaryPath);
|
|
14067
14277
|
if (!isPathWithinBoundary2(resolvedTarget, resolvedBoundary)) {
|
|
14068
14278
|
return `Unsafe path: target escapes ${resolvedBoundary}`;
|
|
14069
14279
|
}
|
|
@@ -14071,7 +14281,7 @@ async function validateNoSymlinkComponents(targetPath, boundaryPath) {
|
|
|
14071
14281
|
let cursor = resolvedBoundary;
|
|
14072
14282
|
let deepestExisting = resolvedBoundary;
|
|
14073
14283
|
for (const segment of segments) {
|
|
14074
|
-
cursor =
|
|
14284
|
+
cursor = join5(cursor, segment);
|
|
14075
14285
|
try {
|
|
14076
14286
|
await lstat(cursor);
|
|
14077
14287
|
deepestExisting = cursor;
|
|
@@ -14181,13 +14391,13 @@ function buildPerFileCollisionSkips(items, provider, configDisplayName, basePath
|
|
|
14181
14391
|
continue;
|
|
14182
14392
|
}
|
|
14183
14393
|
const resolvedFilename = resolvePerFileOutputFilename(result.filename, pathConfig);
|
|
14184
|
-
const targetPath = pathConfig.writeStrategy === "single-file" ? basePath :
|
|
14394
|
+
const targetPath = pathConfig.writeStrategy === "single-file" ? basePath : join5(basePath, resolvedFilename);
|
|
14185
14395
|
if (validateResolvedTargetWithinBase(targetPath, basePath, pathConfig)) {
|
|
14186
14396
|
continue;
|
|
14187
14397
|
}
|
|
14188
|
-
const first = seenTargets.get(
|
|
14398
|
+
const first = seenTargets.get(resolve4(targetPath));
|
|
14189
14399
|
if (!first) {
|
|
14190
|
-
seenTargets.set(
|
|
14400
|
+
seenTargets.set(resolve4(targetPath), { itemName: item.name, targetPath });
|
|
14191
14401
|
continue;
|
|
14192
14402
|
}
|
|
14193
14403
|
skipped.set(index, {
|
|
@@ -14267,16 +14477,16 @@ async function installPerFileItems(items, provider, portableType, pathConfig, op
|
|
|
14267
14477
|
}
|
|
14268
14478
|
async function ensureDir2(filePath) {
|
|
14269
14479
|
const dir = dirname3(filePath);
|
|
14270
|
-
if (!
|
|
14480
|
+
if (!existsSync5(dir)) {
|
|
14271
14481
|
await mkdir3(dir, { recursive: true });
|
|
14272
14482
|
}
|
|
14273
14483
|
}
|
|
14274
14484
|
function getMergeTargetLockPath(targetPath) {
|
|
14275
14485
|
const lockName = `.${basename2(targetPath)}.ck-merge.lock`;
|
|
14276
|
-
return
|
|
14486
|
+
return join5(dirname3(targetPath), lockName);
|
|
14277
14487
|
}
|
|
14278
14488
|
async function withMergeTargetLock(targetPath, operation) {
|
|
14279
|
-
const resolvedTargetPath =
|
|
14489
|
+
const resolvedTargetPath = resolve4(targetPath);
|
|
14280
14490
|
await ensureDir2(resolvedTargetPath);
|
|
14281
14491
|
const release = await import_proper_lockfile3.default.lock(dirname3(resolvedTargetPath), {
|
|
14282
14492
|
realpath: false,
|
|
@@ -14393,7 +14603,7 @@ async function installPerFile(item, provider, portableType, options2, registryDe
|
|
|
14393
14603
|
};
|
|
14394
14604
|
}
|
|
14395
14605
|
const resolvedFilename = resolvePerFileOutputFilename(result.filename, pathConfig);
|
|
14396
|
-
targetPath = pathConfig.writeStrategy === "single-file" ? basePath :
|
|
14606
|
+
targetPath = pathConfig.writeStrategy === "single-file" ? basePath : join5(basePath, resolvedFilename);
|
|
14397
14607
|
const targetPathError = validateResolvedTargetWithinBase(targetPath, basePath, pathConfig);
|
|
14398
14608
|
if (targetPathError) {
|
|
14399
14609
|
return {
|
|
@@ -14520,7 +14730,7 @@ async function installMergeSingle(items, provider, portableType, options2, regis
|
|
|
14520
14730
|
error: "Config merge target accepts only one item per install"
|
|
14521
14731
|
};
|
|
14522
14732
|
}
|
|
14523
|
-
const alreadyExists =
|
|
14733
|
+
const alreadyExists = existsSync5(targetPath);
|
|
14524
14734
|
let existingSections = [];
|
|
14525
14735
|
let existingPreamble = "";
|
|
14526
14736
|
const allWarnings = [];
|
|
@@ -14723,7 +14933,7 @@ async function installYamlMerge(items, provider, portableType, options2, registr
|
|
|
14723
14933
|
}
|
|
14724
14934
|
let targetSnapshot = null;
|
|
14725
14935
|
try {
|
|
14726
|
-
const alreadyExists =
|
|
14936
|
+
const alreadyExists = existsSync5(targetPath);
|
|
14727
14937
|
let existingModes = new Map;
|
|
14728
14938
|
if (alreadyExists) {
|
|
14729
14939
|
try {
|
|
@@ -14899,7 +15109,7 @@ async function installJsonMerge(items, provider, portableType, options2, registr
|
|
|
14899
15109
|
}
|
|
14900
15110
|
modes.push(parsedMode.data);
|
|
14901
15111
|
}
|
|
14902
|
-
const modesPath =
|
|
15112
|
+
const modesPath = join5(basePath, "cline_custom_modes.json");
|
|
14903
15113
|
failurePath = modesPath;
|
|
14904
15114
|
const modesSymlinkError = await validateWritableTargetPath(modesPath, options2);
|
|
14905
15115
|
if (modesSymlinkError) {
|
|
@@ -14912,7 +15122,7 @@ async function installJsonMerge(items, provider, portableType, options2, registr
|
|
|
14912
15122
|
};
|
|
14913
15123
|
}
|
|
14914
15124
|
await ensureDir2(modesPath);
|
|
14915
|
-
const alreadyExists =
|
|
15125
|
+
const alreadyExists = existsSync5(modesPath);
|
|
14916
15126
|
if (alreadyExists) {
|
|
14917
15127
|
try {
|
|
14918
15128
|
const existingRaw = JSON.parse(await readFile4(modesPath, "utf-8"));
|
|
@@ -14948,7 +15158,7 @@ async function installJsonMerge(items, provider, portableType, options2, registr
|
|
|
14948
15158
|
await writeFile3(modesPath, modesJson, "utf-8");
|
|
14949
15159
|
const targetChecksum = computeContentChecksum(modesJson);
|
|
14950
15160
|
const ownedSections = modes.map((m2) => m2.slug);
|
|
14951
|
-
const rulesDir =
|
|
15161
|
+
const rulesDir = join5(dirname3(basePath), ".clinerules");
|
|
14952
15162
|
await mkdir3(rulesDir, { recursive: true });
|
|
14953
15163
|
const capturedRuleSnapshots = new Set;
|
|
14954
15164
|
for (const item of items) {
|
|
@@ -14970,10 +15180,10 @@ async function installJsonMerge(items, provider, portableType, options2, registr
|
|
|
14970
15180
|
}
|
|
14971
15181
|
}
|
|
14972
15182
|
const filename = `${namespacedName}.md`;
|
|
14973
|
-
const rulePath =
|
|
15183
|
+
const rulePath = join5(rulesDir, filename);
|
|
14974
15184
|
failurePath = rulePath;
|
|
14975
|
-
const resolvedRulePath =
|
|
14976
|
-
const resolvedRulesDir =
|
|
15185
|
+
const resolvedRulePath = resolve4(rulePath);
|
|
15186
|
+
const resolvedRulesDir = resolve4(rulesDir);
|
|
14977
15187
|
if (!resolvedRulePath.startsWith(resolvedRulesDir + sep) && resolvedRulePath !== resolvedRulesDir) {
|
|
14978
15188
|
throw new Error(`Unsafe path: rule target escapes rules directory (${rulePath})`);
|
|
14979
15189
|
}
|
|
@@ -16182,26 +16392,26 @@ var init_types3 = __esm(() => {
|
|
|
16182
16392
|
});
|
|
16183
16393
|
|
|
16184
16394
|
// src/shared/kit-layout.ts
|
|
16185
|
-
import { existsSync as
|
|
16186
|
-
import { join as
|
|
16395
|
+
import { existsSync as existsSync6, readFileSync as readFileSync3 } from "node:fs";
|
|
16396
|
+
import { join as join6 } from "node:path";
|
|
16187
16397
|
function uniquePaths(paths) {
|
|
16188
16398
|
return [...new Set(paths)];
|
|
16189
16399
|
}
|
|
16190
16400
|
function findFirstExistingPath(paths) {
|
|
16191
16401
|
for (const candidate of paths) {
|
|
16192
|
-
if (
|
|
16402
|
+
if (existsSync6(candidate)) {
|
|
16193
16403
|
return candidate;
|
|
16194
16404
|
}
|
|
16195
16405
|
}
|
|
16196
16406
|
return null;
|
|
16197
16407
|
}
|
|
16198
16408
|
function resolveKitLayout(projectRoot) {
|
|
16199
|
-
const packageJsonPath =
|
|
16200
|
-
if (!
|
|
16409
|
+
const packageJsonPath = join6(projectRoot, "package.json");
|
|
16410
|
+
if (!existsSync6(packageJsonPath)) {
|
|
16201
16411
|
return DEFAULT_KIT_LAYOUT;
|
|
16202
16412
|
}
|
|
16203
16413
|
try {
|
|
16204
|
-
const parsed = ClaudeKitPackageMetadataSchema.parse(JSON.parse(
|
|
16414
|
+
const parsed = ClaudeKitPackageMetadataSchema.parse(JSON.parse(readFileSync3(packageJsonPath, "utf8")));
|
|
16205
16415
|
return KitLayoutSchema.parse({
|
|
16206
16416
|
...DEFAULT_KIT_LAYOUT,
|
|
16207
16417
|
...parsed.claudekit ?? {}
|
|
@@ -16213,8 +16423,8 @@ function resolveKitLayout(projectRoot) {
|
|
|
16213
16423
|
function getProjectLayoutCandidates(projectRoot, subPath) {
|
|
16214
16424
|
const layout = resolveKitLayout(projectRoot);
|
|
16215
16425
|
return uniquePaths([
|
|
16216
|
-
|
|
16217
|
-
|
|
16426
|
+
join6(projectRoot, layout.sourceDir, subPath),
|
|
16427
|
+
join6(projectRoot, DEFAULT_KIT_LAYOUT.sourceDir, subPath)
|
|
16218
16428
|
]);
|
|
16219
16429
|
}
|
|
16220
16430
|
function findExistingProjectLayoutPath(projectRoot, subPath) {
|
|
@@ -16223,9 +16433,9 @@ function findExistingProjectLayoutPath(projectRoot, subPath) {
|
|
|
16223
16433
|
function getProjectConfigCandidates(projectRoot) {
|
|
16224
16434
|
const layout = resolveKitLayout(projectRoot);
|
|
16225
16435
|
return uniquePaths([
|
|
16226
|
-
|
|
16227
|
-
|
|
16228
|
-
|
|
16436
|
+
join6(projectRoot, "CLAUDE.md"),
|
|
16437
|
+
join6(projectRoot, layout.sourceDir, "CLAUDE.md"),
|
|
16438
|
+
join6(projectRoot, DEFAULT_KIT_LAYOUT.sourceDir, "CLAUDE.md")
|
|
16229
16439
|
]);
|
|
16230
16440
|
}
|
|
16231
16441
|
function findExistingProjectConfigPath(projectRoot) {
|
|
@@ -16339,9 +16549,9 @@ var init_frontmatter_parser = __esm(() => {
|
|
|
16339
16549
|
// src/commands/agents/agents-discovery.ts
|
|
16340
16550
|
import { readdir } from "node:fs/promises";
|
|
16341
16551
|
import { homedir as homedir6 } from "node:os";
|
|
16342
|
-
import { join as
|
|
16552
|
+
import { join as join7 } from "node:path";
|
|
16343
16553
|
function getAgentSourcePath(globalOnly = false) {
|
|
16344
|
-
const globalPath =
|
|
16554
|
+
const globalPath = join7(homedir6(), ".claude/agents");
|
|
16345
16555
|
if (globalOnly) {
|
|
16346
16556
|
return findFirstExistingPath([globalPath]);
|
|
16347
16557
|
}
|
|
@@ -16360,7 +16570,7 @@ async function discoverAgents(sourcePath) {
|
|
|
16360
16570
|
for (const entry of entries) {
|
|
16361
16571
|
if (!entry.isFile() || !entry.name.endsWith(".md"))
|
|
16362
16572
|
continue;
|
|
16363
|
-
const filePath =
|
|
16573
|
+
const filePath = join7(searchPath, entry.name);
|
|
16364
16574
|
try {
|
|
16365
16575
|
const { frontmatter, body } = await parseFrontmatterFile(filePath);
|
|
16366
16576
|
const name = entry.name.replace(/\.md$/, "");
|
|
@@ -19423,217 +19633,6 @@ var init_safe_spinner = __esm(() => {
|
|
|
19423
19633
|
};
|
|
19424
19634
|
});
|
|
19425
19635
|
|
|
19426
|
-
// src/shared/path-resolver.ts
|
|
19427
|
-
import { createHash as createHash3 } from "node:crypto";
|
|
19428
|
-
import { existsSync as existsSync8, readFileSync as readFileSync4 } from "node:fs";
|
|
19429
|
-
import { homedir as homedir9, platform as platform2 } from "node:os";
|
|
19430
|
-
import { join as join11, normalize, resolve as resolve4 } from "node:path";
|
|
19431
|
-
function getEnvVar(name) {
|
|
19432
|
-
const val = process.env[name];
|
|
19433
|
-
if (!val || val.trim() === "")
|
|
19434
|
-
return;
|
|
19435
|
-
if (val.includes("..")) {
|
|
19436
|
-
console.warn(`Environment variable ${name} contains path traversal: ${val}`);
|
|
19437
|
-
return;
|
|
19438
|
-
}
|
|
19439
|
-
return val;
|
|
19440
|
-
}
|
|
19441
|
-
function isWSL() {
|
|
19442
|
-
try {
|
|
19443
|
-
return process.platform === "linux" && existsSync8("/proc/version") && readFileSync4("/proc/version", "utf8").toLowerCase().includes("microsoft");
|
|
19444
|
-
} catch {
|
|
19445
|
-
return false;
|
|
19446
|
-
}
|
|
19447
|
-
}
|
|
19448
|
-
function normalizeWSLPath(p) {
|
|
19449
|
-
if (!isWSL())
|
|
19450
|
-
return p;
|
|
19451
|
-
const windowsMatch = p.match(/^([A-Za-z]):(.*)/);
|
|
19452
|
-
if (windowsMatch) {
|
|
19453
|
-
const drive = windowsMatch[1].toLowerCase();
|
|
19454
|
-
const rest = windowsMatch[2].replace(/\\/g, "/");
|
|
19455
|
-
return `/mnt/${drive}${rest}`;
|
|
19456
|
-
}
|
|
19457
|
-
return p;
|
|
19458
|
-
}
|
|
19459
|
-
|
|
19460
|
-
class PathResolver {
|
|
19461
|
-
static getTestHomeDir() {
|
|
19462
|
-
return process.env.CK_TEST_HOME;
|
|
19463
|
-
}
|
|
19464
|
-
static isValidComponentName(name) {
|
|
19465
|
-
if (!name || typeof name !== "string") {
|
|
19466
|
-
return false;
|
|
19467
|
-
}
|
|
19468
|
-
const dangerousPatterns = [
|
|
19469
|
-
"..",
|
|
19470
|
-
"~"
|
|
19471
|
-
];
|
|
19472
|
-
for (const pattern of dangerousPatterns) {
|
|
19473
|
-
if (name.includes(pattern)) {
|
|
19474
|
-
return false;
|
|
19475
|
-
}
|
|
19476
|
-
}
|
|
19477
|
-
const normalized = normalize(name);
|
|
19478
|
-
for (const pattern of dangerousPatterns) {
|
|
19479
|
-
if (normalized.includes(pattern)) {
|
|
19480
|
-
return false;
|
|
19481
|
-
}
|
|
19482
|
-
}
|
|
19483
|
-
if (name.startsWith("/") || normalized.startsWith("/") || /^[a-zA-Z]:/.test(name) || name.startsWith("\\\\") || normalized.startsWith("\\\\")) {
|
|
19484
|
-
return false;
|
|
19485
|
-
}
|
|
19486
|
-
return true;
|
|
19487
|
-
}
|
|
19488
|
-
static getConfigDir(global3 = false) {
|
|
19489
|
-
const testHome = PathResolver.getTestHomeDir();
|
|
19490
|
-
if (testHome) {
|
|
19491
|
-
return global3 ? join11(testHome, ".config", "claude") : join11(testHome, ".claudekit");
|
|
19492
|
-
}
|
|
19493
|
-
if (!global3) {
|
|
19494
|
-
return join11(homedir9(), ".claudekit");
|
|
19495
|
-
}
|
|
19496
|
-
const os2 = platform2();
|
|
19497
|
-
if (os2 === "win32") {
|
|
19498
|
-
const localAppData = getEnvVar("LOCALAPPDATA") ?? join11(homedir9(), "AppData", "Local");
|
|
19499
|
-
return join11(localAppData, "claude");
|
|
19500
|
-
}
|
|
19501
|
-
const xdgConfigHome = getEnvVar("XDG_CONFIG_HOME");
|
|
19502
|
-
if (xdgConfigHome) {
|
|
19503
|
-
return join11(xdgConfigHome, "claude");
|
|
19504
|
-
}
|
|
19505
|
-
return join11(homedir9(), ".config", "claude");
|
|
19506
|
-
}
|
|
19507
|
-
static getConfigFile(global3 = false) {
|
|
19508
|
-
return join11(PathResolver.getConfigDir(global3), "config.json");
|
|
19509
|
-
}
|
|
19510
|
-
static getCacheDir(global3 = false) {
|
|
19511
|
-
const testHome = PathResolver.getTestHomeDir();
|
|
19512
|
-
if (testHome) {
|
|
19513
|
-
return global3 ? join11(testHome, ".cache", "claude") : join11(testHome, ".claudekit", "cache");
|
|
19514
|
-
}
|
|
19515
|
-
if (!global3) {
|
|
19516
|
-
return join11(homedir9(), ".claudekit", "cache");
|
|
19517
|
-
}
|
|
19518
|
-
const os2 = platform2();
|
|
19519
|
-
if (os2 === "win32") {
|
|
19520
|
-
const localAppData = getEnvVar("LOCALAPPDATA") ?? join11(homedir9(), "AppData", "Local");
|
|
19521
|
-
return join11(localAppData, "claude", "cache");
|
|
19522
|
-
}
|
|
19523
|
-
const xdgCacheHome = getEnvVar("XDG_CACHE_HOME");
|
|
19524
|
-
if (xdgCacheHome) {
|
|
19525
|
-
return join11(xdgCacheHome, "claude");
|
|
19526
|
-
}
|
|
19527
|
-
return join11(homedir9(), ".cache", "claude");
|
|
19528
|
-
}
|
|
19529
|
-
static getGlobalKitDir() {
|
|
19530
|
-
const testHome = PathResolver.getTestHomeDir();
|
|
19531
|
-
if (testHome) {
|
|
19532
|
-
return join11(testHome, ".claude");
|
|
19533
|
-
}
|
|
19534
|
-
const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR;
|
|
19535
|
-
if (claudeConfigDir) {
|
|
19536
|
-
return claudeConfigDir;
|
|
19537
|
-
}
|
|
19538
|
-
return join11(homedir9(), ".claude");
|
|
19539
|
-
}
|
|
19540
|
-
static getClaudeKitDir() {
|
|
19541
|
-
const testHome = PathResolver.getTestHomeDir();
|
|
19542
|
-
if (testHome) {
|
|
19543
|
-
return join11(testHome, ".claudekit");
|
|
19544
|
-
}
|
|
19545
|
-
return join11(homedir9(), ".claudekit");
|
|
19546
|
-
}
|
|
19547
|
-
static getProjectsRegistryPath() {
|
|
19548
|
-
return join11(PathResolver.getClaudeKitDir(), "projects.json");
|
|
19549
|
-
}
|
|
19550
|
-
static getOpenCodeDir(global3, baseDir) {
|
|
19551
|
-
const testHome = PathResolver.getTestHomeDir();
|
|
19552
|
-
if (testHome) {
|
|
19553
|
-
return global3 ? join11(testHome, ".config", "opencode") : join11(baseDir || testHome, ".opencode");
|
|
19554
|
-
}
|
|
19555
|
-
if (!global3) {
|
|
19556
|
-
return join11(baseDir || process.cwd(), ".opencode");
|
|
19557
|
-
}
|
|
19558
|
-
const xdgConfigHome = process.env.XDG_CONFIG_HOME;
|
|
19559
|
-
if (xdgConfigHome) {
|
|
19560
|
-
return join11(xdgConfigHome, "opencode");
|
|
19561
|
-
}
|
|
19562
|
-
return join11(homedir9(), ".config", "opencode");
|
|
19563
|
-
}
|
|
19564
|
-
static getPathPrefix(global3) {
|
|
19565
|
-
return global3 ? "" : ".claude";
|
|
19566
|
-
}
|
|
19567
|
-
static buildSkillsPath(baseDir, global3) {
|
|
19568
|
-
const prefix = PathResolver.getPathPrefix(global3);
|
|
19569
|
-
if (prefix) {
|
|
19570
|
-
return join11(baseDir, prefix, "skills");
|
|
19571
|
-
}
|
|
19572
|
-
return join11(baseDir, "skills");
|
|
19573
|
-
}
|
|
19574
|
-
static buildComponentPath(baseDir, component, global3) {
|
|
19575
|
-
if (!PathResolver.isValidComponentName(component)) {
|
|
19576
|
-
throw new Error(`Invalid component name: "${component}" contains path traversal patterns. Valid names are simple directory names like "agents", "commands", "rules", "skills", or "hooks".`);
|
|
19577
|
-
}
|
|
19578
|
-
const prefix = PathResolver.getPathPrefix(global3);
|
|
19579
|
-
if (prefix) {
|
|
19580
|
-
return join11(baseDir, prefix, component);
|
|
19581
|
-
}
|
|
19582
|
-
return join11(baseDir, component);
|
|
19583
|
-
}
|
|
19584
|
-
static getBackupDir(timestamp) {
|
|
19585
|
-
const testHome = PathResolver.getTestHomeDir();
|
|
19586
|
-
const baseDir = testHome ? join11(testHome, ".claudekit") : join11(homedir9(), ".claudekit");
|
|
19587
|
-
if (timestamp) {
|
|
19588
|
-
return join11(baseDir, "backups", timestamp);
|
|
19589
|
-
}
|
|
19590
|
-
const now = new Date;
|
|
19591
|
-
const dateStr = now.toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
19592
|
-
const ms = now.getMilliseconds().toString().padStart(3, "0");
|
|
19593
|
-
const random = Math.random().toString(36).slice(2, 6);
|
|
19594
|
-
const ts = `${dateStr}-${ms}-${random}`;
|
|
19595
|
-
return join11(baseDir, "backups", ts);
|
|
19596
|
-
}
|
|
19597
|
-
static normalizeWSLPath(p) {
|
|
19598
|
-
return normalizeWSLPath(p);
|
|
19599
|
-
}
|
|
19600
|
-
static isWSL() {
|
|
19601
|
-
return isWSL();
|
|
19602
|
-
}
|
|
19603
|
-
static isAtHomeDirectory(cwd2) {
|
|
19604
|
-
const currentDir = normalize(cwd2 || process.cwd());
|
|
19605
|
-
const homeDir = normalize(homedir9());
|
|
19606
|
-
return currentDir === homeDir;
|
|
19607
|
-
}
|
|
19608
|
-
static getLocalClaudeDir(baseDir) {
|
|
19609
|
-
const dir = baseDir || process.cwd();
|
|
19610
|
-
return join11(dir, ".claude");
|
|
19611
|
-
}
|
|
19612
|
-
static isLocalSameAsGlobal(cwd2) {
|
|
19613
|
-
const localPath = normalize(PathResolver.getLocalClaudeDir(cwd2));
|
|
19614
|
-
const globalPath = normalize(PathResolver.getGlobalKitDir());
|
|
19615
|
-
return localPath === globalPath;
|
|
19616
|
-
}
|
|
19617
|
-
static isGlobPattern(pattern) {
|
|
19618
|
-
return pattern.includes("*") || pattern.includes("?") || pattern.includes("{");
|
|
19619
|
-
}
|
|
19620
|
-
static computeProjectHash(projectRoot) {
|
|
19621
|
-
let normalized = resolve4(projectRoot).replace(/[/\\]+$/, "");
|
|
19622
|
-
if (process.platform === "darwin" || process.platform === "win32") {
|
|
19623
|
-
normalized = normalized.toLowerCase();
|
|
19624
|
-
}
|
|
19625
|
-
return createHash3("sha256").update(normalized).digest("hex").slice(0, 12);
|
|
19626
|
-
}
|
|
19627
|
-
static getPlansRegistriesDir() {
|
|
19628
|
-
return join11(PathResolver.getGlobalKitDir(), "plans-registries");
|
|
19629
|
-
}
|
|
19630
|
-
static getPlansRegistryPath(projectRoot) {
|
|
19631
|
-
const hash = PathResolver.computeProjectHash(projectRoot);
|
|
19632
|
-
return join11(PathResolver.getPlansRegistriesDir(), `${hash}.json`);
|
|
19633
|
-
}
|
|
19634
|
-
}
|
|
19635
|
-
var init_path_resolver = () => {};
|
|
19636
|
-
|
|
19637
19636
|
// node_modules/universalify/index.js
|
|
19638
19637
|
var require_universalify = __commonJS((exports) => {
|
|
19639
19638
|
exports.fromCallback = function(fn) {
|
|
@@ -21022,10 +21021,10 @@ var init_safe_prompts = __esm(() => {
|
|
|
21022
21021
|
|
|
21023
21022
|
// src/commands/commands/commands-discovery.ts
|
|
21024
21023
|
import { readdir as readdir4 } from "node:fs/promises";
|
|
21025
|
-
import { homedir as
|
|
21024
|
+
import { homedir as homedir9 } from "node:os";
|
|
21026
21025
|
import { join as join16, relative as relative3 } from "node:path";
|
|
21027
21026
|
function getCommandSourcePath(globalOnly = false) {
|
|
21028
|
-
const globalPath = join16(
|
|
21027
|
+
const globalPath = join16(homedir9(), ".claude/commands");
|
|
21029
21028
|
if (globalOnly) {
|
|
21030
21029
|
return findFirstExistingPath([globalPath]);
|
|
21031
21030
|
}
|
|
@@ -45405,7 +45404,7 @@ __export(exports_ck_config_manager, {
|
|
|
45405
45404
|
});
|
|
45406
45405
|
import { existsSync as existsSync11 } from "node:fs";
|
|
45407
45406
|
import { mkdir as mkdir7, readFile as readFile8, writeFile as writeFile6 } from "node:fs/promises";
|
|
45408
|
-
import { homedir as
|
|
45407
|
+
import { homedir as homedir10 } from "node:os";
|
|
45409
45408
|
import { join as join19 } from "node:path";
|
|
45410
45409
|
function getNestedValue(obj, path4) {
|
|
45411
45410
|
if (!obj || typeof obj !== "object")
|
|
@@ -45480,7 +45479,7 @@ function valuesEqual(a3, b3) {
|
|
|
45480
45479
|
|
|
45481
45480
|
class CkConfigManager {
|
|
45482
45481
|
static getGlobalConfigDir() {
|
|
45483
|
-
return join19(
|
|
45482
|
+
return join19(homedir10(), ".claude");
|
|
45484
45483
|
}
|
|
45485
45484
|
static getGlobalConfigPath() {
|
|
45486
45485
|
return join19(CkConfigManager.getGlobalConfigDir(), CK_CONFIG_FILE);
|
|
@@ -45739,7 +45738,7 @@ function notFoundError(type, name, hint) {
|
|
|
45739
45738
|
}
|
|
45740
45739
|
|
|
45741
45740
|
// src/shared/command-normalizer.ts
|
|
45742
|
-
import { homedir as
|
|
45741
|
+
import { homedir as homedir11 } from "node:os";
|
|
45743
45742
|
import { join as join20 } from "node:path";
|
|
45744
45743
|
function escapeRegex(value) {
|
|
45745
45744
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -45779,7 +45778,7 @@ function resolveClaudePathArg(arg, root) {
|
|
|
45779
45778
|
const isWin2 = process.platform === "win32";
|
|
45780
45779
|
const cmp = (s) => isWin2 ? s.toLowerCase() : s;
|
|
45781
45780
|
const globalRoots = [
|
|
45782
|
-
`${
|
|
45781
|
+
`${homedir11().replace(/\\/g, "/").replace(/\/+$/, "")}/.claude/`,
|
|
45783
45782
|
`${PathResolver.getGlobalKitDir().replace(/\\/g, "/").replace(/\/+$/, "")}/`
|
|
45784
45783
|
];
|
|
45785
45784
|
const isUnderGlobal = globalRoots.some((g2) => cmp(absolutePath).startsWith(cmp(g2)));
|
|
@@ -45856,7 +45855,7 @@ function repairClaudeNodeCommandPath(cmd, root) {
|
|
|
45856
45855
|
const isWin2 = process.platform === "win32";
|
|
45857
45856
|
const cmp = (s) => isWin2 ? s.toLowerCase() : s;
|
|
45858
45857
|
const globalRoots = [
|
|
45859
|
-
`${
|
|
45858
|
+
`${homedir11().replace(/\\/g, "/").replace(/\/+$/, "")}/.claude/`,
|
|
45860
45859
|
`${PathResolver.getGlobalKitDir().replace(/\\/g, "/").replace(/\/+$/, "")}/`
|
|
45861
45860
|
];
|
|
45862
45861
|
const isUnderGlobal = globalRoots.some((g2) => cmp(normalizedAbsPath).startsWith(cmp(g2)));
|
|
@@ -45905,7 +45904,7 @@ function normalizeCommand(cmd) {
|
|
|
45905
45904
|
return "";
|
|
45906
45905
|
let normalized = cmd;
|
|
45907
45906
|
const globalKitDir = PathResolver.getGlobalKitDir().replace(/\\/g, "/").replace(/\/+$/, "");
|
|
45908
|
-
const defaultGlobalKitDir = join20(
|
|
45907
|
+
const defaultGlobalKitDir = join20(homedir11(), ".claude").replace(/\\/g, "/");
|
|
45909
45908
|
normalized = normalized.replace(/"/g, "");
|
|
45910
45909
|
normalized = normalized.replace(/~\//g, "$HOME/");
|
|
45911
45910
|
normalized = normalized.replace(/\$CLAUDE_PROJECT_DIR/g, "$HOME");
|
|
@@ -46103,11 +46102,15 @@ function mergeHookEntries(sourceEntries, destEntries, eventName, result, install
|
|
|
46103
46102
|
const isFullyDuplicated = commands.length > 0 && commands.every((cmd) => existingCommands.has(normalizeCommand(cmd)));
|
|
46104
46103
|
const duplicateCommands = commands.filter((cmd) => existingCommands.has(normalizeCommand(cmd)));
|
|
46105
46104
|
logDuplicates(duplicateCommands, eventName, result);
|
|
46106
|
-
const
|
|
46105
|
+
const newCommands = commands.filter((cmd) => !existingCommands.has(normalizeCommand(cmd)) && !wasCommandInstalled(cmd, installedHooks));
|
|
46106
|
+
const hasNonRemovedCommands = commands.length === 0 || newCommands.length > 0;
|
|
46107
46107
|
if (!isFullyDuplicated && hasNonRemovedCommands) {
|
|
46108
46108
|
let filteredEntry = entry;
|
|
46109
|
-
if ("hooks" in entry && entry.hooks &&
|
|
46110
|
-
const filteredHooks = entry.hooks.filter((h2) => !h2.command || !wasCommandInstalled(h2.command, installedHooks));
|
|
46109
|
+
if ("hooks" in entry && entry.hooks && commands.length > 0) {
|
|
46110
|
+
const filteredHooks = entry.hooks.filter((h2) => !h2.command || !existingCommands.has(normalizeCommand(h2.command)) && !wasCommandInstalled(h2.command, installedHooks));
|
|
46111
|
+
if (filteredHooks.length === 0) {
|
|
46112
|
+
continue;
|
|
46113
|
+
}
|
|
46111
46114
|
filteredEntry = { ...entry, hooks: filteredHooks };
|
|
46112
46115
|
} else if ("command" in entry && wasCommandInstalled(entry.command, installedHooks)) {
|
|
46113
46116
|
continue;
|
|
@@ -46118,16 +46121,12 @@ function mergeHookEntries(sourceEntries, destEntries, eventName, result, install
|
|
|
46118
46121
|
if (sourceMatcher) {
|
|
46119
46122
|
matcherIndex.set(sourceMatcher, merged.length - 1);
|
|
46120
46123
|
}
|
|
46121
|
-
for (const cmd of
|
|
46124
|
+
for (const cmd of newCommands) {
|
|
46122
46125
|
const normalizedCmd = normalizeCommand(cmd);
|
|
46123
|
-
|
|
46124
|
-
|
|
46125
|
-
|
|
46126
|
-
|
|
46127
|
-
trackHookOrigin(result, sourceKit, cmd);
|
|
46128
|
-
}
|
|
46129
|
-
} else if (!existingCommands.has(normalizedCmd)) {
|
|
46130
|
-
existingCommands.add(normalizedCmd);
|
|
46126
|
+
existingCommands.add(normalizedCmd);
|
|
46127
|
+
result.newlyInstalledHooks.push(cmd);
|
|
46128
|
+
if (sourceKit) {
|
|
46129
|
+
trackHookOrigin(result, sourceKit, cmd);
|
|
46131
46130
|
}
|
|
46132
46131
|
}
|
|
46133
46132
|
}
|
|
@@ -48098,7 +48097,7 @@ var init_chokidar = __esm(() => {
|
|
|
48098
48097
|
});
|
|
48099
48098
|
|
|
48100
48099
|
// src/domains/web-server/file-watcher.ts
|
|
48101
|
-
import { homedir as
|
|
48100
|
+
import { homedir as homedir12 } from "node:os";
|
|
48102
48101
|
import { join as join25 } from "node:path";
|
|
48103
48102
|
|
|
48104
48103
|
class FileWatcher {
|
|
@@ -48121,9 +48120,9 @@ class FileWatcher {
|
|
|
48121
48120
|
}
|
|
48122
48121
|
getWatchPaths() {
|
|
48123
48122
|
const paths = [];
|
|
48124
|
-
const globalDir = join25(
|
|
48123
|
+
const globalDir = join25(homedir12(), ".claudekit");
|
|
48125
48124
|
paths.push(join25(globalDir, "config.json"));
|
|
48126
|
-
const globalKitDir = join25(
|
|
48125
|
+
const globalKitDir = join25(homedir12(), ".claude");
|
|
48127
48126
|
paths.push(join25(globalKitDir, ".ck.json"));
|
|
48128
48127
|
paths.push(join25(globalKitDir, "settings.json"));
|
|
48129
48128
|
paths.push(join25(globalKitDir, "settings.local.json"));
|
|
@@ -48173,8 +48172,8 @@ class FileWatcher {
|
|
|
48173
48172
|
return path4.endsWith("config.json") || path4.endsWith(".ck.json") || path4.endsWith("settings.json") || path4.endsWith("settings.local.json");
|
|
48174
48173
|
}
|
|
48175
48174
|
getConfigScope(path4) {
|
|
48176
|
-
const globalDir = join25(
|
|
48177
|
-
const globalKitDir = join25(
|
|
48175
|
+
const globalDir = join25(homedir12(), ".claudekit");
|
|
48176
|
+
const globalKitDir = join25(homedir12(), ".claude");
|
|
48178
48177
|
return path4.startsWith(globalDir) || path4.startsWith(globalKitDir) ? "global" : "local";
|
|
48179
48178
|
}
|
|
48180
48179
|
stop() {
|
|
@@ -48665,7 +48664,7 @@ var init_claudekit_data2 = __esm(() => {
|
|
|
48665
48664
|
// src/domains/web-server/routes/action-routes.ts
|
|
48666
48665
|
import { spawn, spawnSync } from "node:child_process";
|
|
48667
48666
|
import { existsSync as existsSync14 } from "node:fs";
|
|
48668
|
-
import { homedir as
|
|
48667
|
+
import { homedir as homedir13 } from "node:os";
|
|
48669
48668
|
import { join as join27, resolve as resolve12, sep as sep5 } from "node:path";
|
|
48670
48669
|
function getWindowsPaths(...relativePaths) {
|
|
48671
48670
|
const roots = [
|
|
@@ -48942,7 +48941,7 @@ async function isActionPathAllowed(dirPath, projectId) {
|
|
|
48942
48941
|
try {
|
|
48943
48942
|
const encodedPath = projectId.slice("discovered-".length);
|
|
48944
48943
|
const discoveredPath = resolve12(Buffer.from(encodedPath, "base64url").toString("utf-8"));
|
|
48945
|
-
if (discoveredPath === dirPath && (isPathInsideBase(discoveredPath, process.cwd()) || isPathInsideBase(discoveredPath,
|
|
48944
|
+
if (discoveredPath === dirPath && (isPathInsideBase(discoveredPath, process.cwd()) || isPathInsideBase(discoveredPath, homedir13()))) {
|
|
48946
48945
|
return true;
|
|
48947
48946
|
}
|
|
48948
48947
|
} catch {}
|
|
@@ -48954,7 +48953,7 @@ async function isActionPathAllowed(dirPath, projectId) {
|
|
|
48954
48953
|
if (isPathInsideBase(dirPath, process.cwd())) {
|
|
48955
48954
|
return true;
|
|
48956
48955
|
}
|
|
48957
|
-
return isPathInsideBase(dirPath,
|
|
48956
|
+
return isPathInsideBase(dirPath, homedir13());
|
|
48958
48957
|
}
|
|
48959
48958
|
function buildSystemTerminalCommand(dirPath) {
|
|
48960
48959
|
if (isMacOS()) {
|
|
@@ -49293,7 +49292,7 @@ var init_action_routes = __esm(() => {
|
|
|
49293
49292
|
projectId: exports_external.string().min(1).max(256).optional()
|
|
49294
49293
|
}).strict();
|
|
49295
49294
|
WINDOWS_PATHS = {
|
|
49296
|
-
localAppData: process.env.LOCALAPPDATA || join27(
|
|
49295
|
+
localAppData: process.env.LOCALAPPDATA || join27(homedir13(), "AppData", "Local"),
|
|
49297
49296
|
programFiles: process.env.ProgramFiles || "C:\\Program Files",
|
|
49298
49297
|
programFilesX86: process.env["ProgramFiles(x86)"] || "C:\\Program Files (x86)"
|
|
49299
49298
|
};
|
|
@@ -49314,7 +49313,7 @@ var init_action_routes = __esm(() => {
|
|
|
49314
49313
|
openMode: "open-directory",
|
|
49315
49314
|
capabilities: ["open-directory", "run-command"],
|
|
49316
49315
|
macAppName: "iTerm",
|
|
49317
|
-
macAppPaths: ["/Applications/iTerm.app", join27(
|
|
49316
|
+
macAppPaths: ["/Applications/iTerm.app", join27(homedir13(), "Applications", "iTerm.app")]
|
|
49318
49317
|
},
|
|
49319
49318
|
{
|
|
49320
49319
|
id: "warp",
|
|
@@ -49325,7 +49324,7 @@ var init_action_routes = __esm(() => {
|
|
|
49325
49324
|
capabilities: ["open-directory", "uri-scheme"],
|
|
49326
49325
|
commands: ["warp"],
|
|
49327
49326
|
macAppName: "Warp",
|
|
49328
|
-
macAppPaths: ["/Applications/Warp.app", join27(
|
|
49327
|
+
macAppPaths: ["/Applications/Warp.app", join27(homedir13(), "Applications", "Warp.app")],
|
|
49329
49328
|
windowsAppPaths: getWindowsPaths("Warp\\Warp.exe"),
|
|
49330
49329
|
linuxAppPaths: ["/usr/bin/warp", "/usr/local/bin/warp"]
|
|
49331
49330
|
},
|
|
@@ -49348,7 +49347,7 @@ var init_action_routes = __esm(() => {
|
|
|
49348
49347
|
capabilities: ["open-directory"],
|
|
49349
49348
|
commands: ["wezterm"],
|
|
49350
49349
|
macAppName: "WezTerm",
|
|
49351
|
-
macAppPaths: ["/Applications/WezTerm.app", join27(
|
|
49350
|
+
macAppPaths: ["/Applications/WezTerm.app", join27(homedir13(), "Applications", "WezTerm.app")],
|
|
49352
49351
|
windowsAppPaths: getWindowsPaths("WezTerm\\wezterm-gui.exe", "WezTerm\\wezterm.exe"),
|
|
49353
49352
|
linuxAppPaths: ["/usr/bin/wezterm", "/usr/local/bin/wezterm"]
|
|
49354
49353
|
},
|
|
@@ -49361,7 +49360,7 @@ var init_action_routes = __esm(() => {
|
|
|
49361
49360
|
capabilities: ["open-directory"],
|
|
49362
49361
|
commands: ["kitty"],
|
|
49363
49362
|
macAppName: "kitty",
|
|
49364
|
-
macAppPaths: ["/Applications/kitty.app", join27(
|
|
49363
|
+
macAppPaths: ["/Applications/kitty.app", join27(homedir13(), "Applications", "kitty.app")],
|
|
49365
49364
|
windowsAppPaths: getWindowsPaths("kitty\\kitty.exe"),
|
|
49366
49365
|
linuxAppPaths: ["/usr/bin/kitty", "/usr/local/bin/kitty"]
|
|
49367
49366
|
},
|
|
@@ -49374,7 +49373,7 @@ var init_action_routes = __esm(() => {
|
|
|
49374
49373
|
capabilities: ["open-directory"],
|
|
49375
49374
|
commands: ["alacritty"],
|
|
49376
49375
|
macAppName: "Alacritty",
|
|
49377
|
-
macAppPaths: ["/Applications/Alacritty.app", join27(
|
|
49376
|
+
macAppPaths: ["/Applications/Alacritty.app", join27(homedir13(), "Applications", "Alacritty.app")],
|
|
49378
49377
|
windowsAppPaths: getWindowsPaths("Alacritty\\alacritty.exe"),
|
|
49379
49378
|
linuxAppPaths: ["/usr/bin/alacritty", "/usr/local/bin/alacritty"]
|
|
49380
49379
|
},
|
|
@@ -49447,7 +49446,7 @@ var init_action_routes = __esm(() => {
|
|
|
49447
49446
|
capabilities: ["open-app"],
|
|
49448
49447
|
commands: ["termius"],
|
|
49449
49448
|
macAppName: "Termius",
|
|
49450
|
-
macAppPaths: ["/Applications/Termius.app", join27(
|
|
49449
|
+
macAppPaths: ["/Applications/Termius.app", join27(homedir13(), "Applications", "Termius.app")],
|
|
49451
49450
|
windowsAppPaths: getWindowsPaths("Termius\\Termius.exe"),
|
|
49452
49451
|
linuxAppPaths: ["/usr/bin/termius"]
|
|
49453
49452
|
},
|
|
@@ -49470,7 +49469,7 @@ var init_action_routes = __esm(() => {
|
|
|
49470
49469
|
macAppName: "Visual Studio Code",
|
|
49471
49470
|
macAppPaths: [
|
|
49472
49471
|
"/Applications/Visual Studio Code.app",
|
|
49473
|
-
join27(
|
|
49472
|
+
join27(homedir13(), "Applications", "Visual Studio Code.app")
|
|
49474
49473
|
],
|
|
49475
49474
|
windowsAppPaths: getWindowsPaths("Programs\\Microsoft VS Code\\Code.exe", "Microsoft VS Code\\Code.exe"),
|
|
49476
49475
|
linuxAppPaths: ["/usr/bin/code", "/snap/bin/code"]
|
|
@@ -49484,7 +49483,7 @@ var init_action_routes = __esm(() => {
|
|
|
49484
49483
|
capabilities: ["open-directory"],
|
|
49485
49484
|
commands: ["cursor"],
|
|
49486
49485
|
macAppName: "Cursor",
|
|
49487
|
-
macAppPaths: ["/Applications/Cursor.app", join27(
|
|
49486
|
+
macAppPaths: ["/Applications/Cursor.app", join27(homedir13(), "Applications", "Cursor.app")],
|
|
49488
49487
|
windowsAppPaths: getWindowsPaths("Programs\\Cursor\\Cursor.exe", "Cursor\\Cursor.exe"),
|
|
49489
49488
|
linuxAppPaths: ["/usr/bin/cursor"]
|
|
49490
49489
|
},
|
|
@@ -49497,7 +49496,7 @@ var init_action_routes = __esm(() => {
|
|
|
49497
49496
|
capabilities: ["open-directory"],
|
|
49498
49497
|
commands: ["windsurf"],
|
|
49499
49498
|
macAppName: "Windsurf",
|
|
49500
|
-
macAppPaths: ["/Applications/Windsurf.app", join27(
|
|
49499
|
+
macAppPaths: ["/Applications/Windsurf.app", join27(homedir13(), "Applications", "Windsurf.app")],
|
|
49501
49500
|
windowsAppPaths: getWindowsPaths("Programs\\Windsurf\\Windsurf.exe", "Windsurf\\Windsurf.exe"),
|
|
49502
49501
|
linuxAppPaths: ["/usr/bin/windsurf"]
|
|
49503
49502
|
},
|
|
@@ -49512,11 +49511,11 @@ var init_action_routes = __esm(() => {
|
|
|
49512
49511
|
macAppName: "Antigravity",
|
|
49513
49512
|
macAppPaths: [
|
|
49514
49513
|
"/Applications/Antigravity.app",
|
|
49515
|
-
join27(
|
|
49514
|
+
join27(homedir13(), "Applications", "Antigravity.app")
|
|
49516
49515
|
],
|
|
49517
49516
|
windowsAppPaths: getWindowsPaths("Programs\\Antigravity\\Antigravity.exe"),
|
|
49518
49517
|
linuxAppPaths: ["/usr/bin/antigravity"],
|
|
49519
|
-
fallbackDetectionPaths: [join27(
|
|
49518
|
+
fallbackDetectionPaths: [join27(homedir13(), ".gemini", "antigravity")]
|
|
49520
49519
|
},
|
|
49521
49520
|
{
|
|
49522
49521
|
id: "zed",
|
|
@@ -49527,7 +49526,7 @@ var init_action_routes = __esm(() => {
|
|
|
49527
49526
|
capabilities: ["open-directory"],
|
|
49528
49527
|
commands: ["zed"],
|
|
49529
49528
|
macAppName: "Zed",
|
|
49530
|
-
macAppPaths: ["/Applications/Zed.app", join27(
|
|
49529
|
+
macAppPaths: ["/Applications/Zed.app", join27(homedir13(), "Applications", "Zed.app")],
|
|
49531
49530
|
windowsAppPaths: getWindowsPaths("Zed\\Zed.exe"),
|
|
49532
49531
|
linuxAppPaths: ["/usr/bin/zed", "/usr/local/bin/zed"]
|
|
49533
49532
|
},
|
|
@@ -49542,7 +49541,7 @@ var init_action_routes = __esm(() => {
|
|
|
49542
49541
|
macAppName: "Sublime Text",
|
|
49543
49542
|
macAppPaths: [
|
|
49544
49543
|
"/Applications/Sublime Text.app",
|
|
49545
|
-
join27(
|
|
49544
|
+
join27(homedir13(), "Applications", "Sublime Text.app")
|
|
49546
49545
|
],
|
|
49547
49546
|
windowsAppPaths: getWindowsPaths("Sublime Text\\sublime_text.exe"),
|
|
49548
49547
|
linuxAppPaths: ["/usr/bin/subl", "/snap/bin/subl"]
|
|
@@ -49583,7 +49582,7 @@ var init_action_routes = __esm(() => {
|
|
|
49583
49582
|
|
|
49584
49583
|
// src/domains/web-server/routes/agents-routes.ts
|
|
49585
49584
|
import { readdir as readdir7 } from "node:fs/promises";
|
|
49586
|
-
import { homedir as
|
|
49585
|
+
import { homedir as homedir14 } from "node:os";
|
|
49587
49586
|
import { isAbsolute as isAbsolute4, join as join28, relative as relative7 } from "node:path";
|
|
49588
49587
|
function resolveAgentDirs() {
|
|
49589
49588
|
const dirs = [];
|
|
@@ -49628,7 +49627,7 @@ async function scanAgentDir(dirPath, dirLabel) {
|
|
|
49628
49627
|
color: frontmatter.color || null,
|
|
49629
49628
|
skillCount: countSkills(frontmatter.tools),
|
|
49630
49629
|
dirLabel,
|
|
49631
|
-
relativePath: relative7(
|
|
49630
|
+
relativePath: relative7(homedir14(), filePath)
|
|
49632
49631
|
});
|
|
49633
49632
|
} catch {}
|
|
49634
49633
|
}
|
|
@@ -49672,7 +49671,7 @@ function registerAgentsBrowserRoutes(app) {
|
|
|
49672
49671
|
color: frontmatter.color || null,
|
|
49673
49672
|
skillCount: countSkills(frontmatter.tools),
|
|
49674
49673
|
dirLabel: dir.label,
|
|
49675
|
-
relativePath: relative7(
|
|
49674
|
+
relativePath: relative7(homedir14(), filePath),
|
|
49676
49675
|
frontmatter,
|
|
49677
49676
|
body
|
|
49678
49677
|
};
|
|
@@ -49687,7 +49686,7 @@ var home2;
|
|
|
49687
49686
|
var init_agents_routes = __esm(() => {
|
|
49688
49687
|
init_frontmatter_parser();
|
|
49689
49688
|
init_kit_layout();
|
|
49690
|
-
home2 =
|
|
49689
|
+
home2 = homedir14();
|
|
49691
49690
|
});
|
|
49692
49691
|
|
|
49693
49692
|
// src/schemas/ck-config.schema.json
|
|
@@ -50524,7 +50523,7 @@ var init_ck_config_routes = __esm(() => {
|
|
|
50524
50523
|
// src/domains/web-server/routes/command-routes.ts
|
|
50525
50524
|
import { existsSync as existsSync16 } from "node:fs";
|
|
50526
50525
|
import { readFile as readFile12, readdir as readdir8 } from "node:fs/promises";
|
|
50527
|
-
import { homedir as
|
|
50526
|
+
import { homedir as homedir15 } from "node:os";
|
|
50528
50527
|
import { basename as basename9, isAbsolute as isAbsolute5, join as join30, relative as relative8, resolve as resolve13 } from "node:path";
|
|
50529
50528
|
async function buildCommandTree(dir, baseDir) {
|
|
50530
50529
|
let dirents;
|
|
@@ -50566,7 +50565,7 @@ async function buildCommandTree(dir, baseDir) {
|
|
|
50566
50565
|
}
|
|
50567
50566
|
function registerCommandRoutes(app) {
|
|
50568
50567
|
app.get("/api/commands", async (_req, res) => {
|
|
50569
|
-
const commandsDir = join30(
|
|
50568
|
+
const commandsDir = join30(homedir15(), ".claude", "commands");
|
|
50570
50569
|
if (!existsSync16(commandsDir)) {
|
|
50571
50570
|
res.json({ tree: [] });
|
|
50572
50571
|
return;
|
|
@@ -50589,7 +50588,7 @@ function registerCommandRoutes(app) {
|
|
|
50589
50588
|
res.status(400).json({ error: "Invalid path" });
|
|
50590
50589
|
return;
|
|
50591
50590
|
}
|
|
50592
|
-
const commandsDir = join30(
|
|
50591
|
+
const commandsDir = join30(homedir15(), ".claude", "commands");
|
|
50593
50592
|
const safePath = resolve13(commandsDir, rawPath);
|
|
50594
50593
|
const rel = relative8(commandsDir, safePath);
|
|
50595
50594
|
if (rel.startsWith("..") || isAbsolute5(rel)) {
|
|
@@ -50663,11 +50662,11 @@ var init_types5 = __esm(() => {
|
|
|
50663
50662
|
|
|
50664
50663
|
// src/services/claude-data/history-parser.ts
|
|
50665
50664
|
import { createReadStream, statSync as statSync4 } from "node:fs";
|
|
50666
|
-
import { homedir as
|
|
50665
|
+
import { homedir as homedir16 } from "node:os";
|
|
50667
50666
|
import { join as join31 } from "node:path";
|
|
50668
50667
|
import { createInterface as createInterface2 } from "node:readline";
|
|
50669
50668
|
function getHistoryPath() {
|
|
50670
|
-
return process.env.CLAUDE_HISTORY_PATH ?? join31(
|
|
50669
|
+
return process.env.CLAUDE_HISTORY_PATH ?? join31(homedir16(), ".claude", "history.jsonl");
|
|
50671
50670
|
}
|
|
50672
50671
|
function emptyResult(parseTimeMs, error) {
|
|
50673
50672
|
return { projects: [], totalEntries: 0, errorCount: 0, parseTimeMs, error };
|
|
@@ -50865,10 +50864,10 @@ var init_session_parser = () => {};
|
|
|
50865
50864
|
// src/services/claude-data/skill-scanner.ts
|
|
50866
50865
|
import { existsSync as existsSync18 } from "node:fs";
|
|
50867
50866
|
import { readFile as readFile14, readdir as readdir10, stat as stat6 } from "node:fs/promises";
|
|
50868
|
-
import { homedir as
|
|
50867
|
+
import { homedir as homedir17 } from "node:os";
|
|
50869
50868
|
import { join as join33 } from "node:path";
|
|
50870
50869
|
async function getCkSkillMetadata(scope) {
|
|
50871
|
-
const metaPath = scope === "global" ? join33(
|
|
50870
|
+
const metaPath = scope === "global" ? join33(homedir17(), ".claude", "metadata.json") : join33(process.cwd(), ".claude", "metadata.json");
|
|
50872
50871
|
if (!existsSync18(metaPath))
|
|
50873
50872
|
return null;
|
|
50874
50873
|
const result = new Map;
|
|
@@ -50998,14 +50997,14 @@ async function scanSkills() {
|
|
|
50998
50997
|
var import_gray_matter4, skillsDir, SKIP_DIRS2;
|
|
50999
50998
|
var init_skill_scanner = __esm(() => {
|
|
51000
50999
|
import_gray_matter4 = __toESM(require_gray_matter(), 1);
|
|
51001
|
-
skillsDir = join33(
|
|
51000
|
+
skillsDir = join33(homedir17(), ".claude", "skills");
|
|
51002
51001
|
SKIP_DIRS2 = [".venv", "scripts", "__pycache__", "node_modules", ".git", "common"];
|
|
51003
51002
|
});
|
|
51004
51003
|
|
|
51005
51004
|
// src/services/claude-data/settings-reader.ts
|
|
51006
51005
|
import { existsSync as existsSync19 } from "node:fs";
|
|
51007
51006
|
import { copyFile as copyFile2, mkdir as mkdir9, readFile as readFile15, rename as rename5, rm as rm4, writeFile as writeFile10 } from "node:fs/promises";
|
|
51008
|
-
import { homedir as
|
|
51007
|
+
import { homedir as homedir18 } from "node:os";
|
|
51009
51008
|
import { join as join34 } from "node:path";
|
|
51010
51009
|
function getSettingsPath() {
|
|
51011
51010
|
return join34(claudeDir, settingsFilename);
|
|
@@ -51067,7 +51066,7 @@ function countMcpServers(settings) {
|
|
|
51067
51066
|
}
|
|
51068
51067
|
var claudeDir, settingsFilename = "settings.json", settingsBackupDir;
|
|
51069
51068
|
var init_settings_reader = __esm(() => {
|
|
51070
|
-
claudeDir = join34(
|
|
51069
|
+
claudeDir = join34(homedir18(), ".claude");
|
|
51071
51070
|
settingsBackupDir = join34(claudeDir, ".ck-backups", "settings");
|
|
51072
51071
|
});
|
|
51073
51072
|
|
|
@@ -51235,7 +51234,7 @@ var init_hook_log_reader = __esm(() => {
|
|
|
51235
51234
|
});
|
|
51236
51235
|
|
|
51237
51236
|
// src/services/claude-data/project-scanner.ts
|
|
51238
|
-
import { homedir as
|
|
51237
|
+
import { homedir as homedir19 } from "node:os";
|
|
51239
51238
|
import { basename as basename10, join as join36, normalize as normalize4 } from "node:path";
|
|
51240
51239
|
function decodePath(encoded) {
|
|
51241
51240
|
const decoded = encoded.replace(/^-/, "/").replace(/-/g, "/");
|
|
@@ -51250,7 +51249,7 @@ function encodePath(path4) {
|
|
|
51250
51249
|
}
|
|
51251
51250
|
var projectsDir;
|
|
51252
51251
|
var init_project_scanner = __esm(() => {
|
|
51253
|
-
projectsDir = join36(
|
|
51252
|
+
projectsDir = join36(homedir19(), ".claude", "projects");
|
|
51254
51253
|
});
|
|
51255
51254
|
|
|
51256
51255
|
// src/services/claude-data/project-discovery.ts
|
|
@@ -51345,10 +51344,10 @@ var init_project_discovery = __esm(() => {
|
|
|
51345
51344
|
|
|
51346
51345
|
// src/services/claude-data/user-preferences.ts
|
|
51347
51346
|
import { readFile as readFile16, stat as stat7 } from "node:fs/promises";
|
|
51348
|
-
import { homedir as
|
|
51347
|
+
import { homedir as homedir20 } from "node:os";
|
|
51349
51348
|
import { join as join37 } from "node:path";
|
|
51350
51349
|
function getPreferencesPath() {
|
|
51351
|
-
return join37(
|
|
51350
|
+
return join37(homedir20(), ".claude.json");
|
|
51352
51351
|
}
|
|
51353
51352
|
async function readUserPreferences(filePath) {
|
|
51354
51353
|
const path4 = filePath ?? getPreferencesPath();
|
|
@@ -51439,7 +51438,7 @@ var init_claude_data = __esm(() => {
|
|
|
51439
51438
|
// src/domains/web-server/routes/dashboard-routes.ts
|
|
51440
51439
|
import { existsSync as existsSync20 } from "node:fs";
|
|
51441
51440
|
import { readFile as readFile17, readdir as readdir11 } from "node:fs/promises";
|
|
51442
|
-
import { homedir as
|
|
51441
|
+
import { homedir as homedir21 } from "node:os";
|
|
51443
51442
|
import { join as join38 } from "node:path";
|
|
51444
51443
|
async function readAgents() {
|
|
51445
51444
|
const agentsDir = join38(claudeDir2, "agents");
|
|
@@ -51509,7 +51508,7 @@ async function countAllMcpServers() {
|
|
|
51509
51508
|
}
|
|
51510
51509
|
let claudeJsonCount = 0;
|
|
51511
51510
|
try {
|
|
51512
|
-
const claudeJsonPath = join38(
|
|
51511
|
+
const claudeJsonPath = join38(homedir21(), ".claude.json");
|
|
51513
51512
|
if (existsSync20(claudeJsonPath)) {
|
|
51514
51513
|
const content = await readFile17(claudeJsonPath, "utf-8");
|
|
51515
51514
|
const data = JSON.parse(content);
|
|
@@ -51636,7 +51635,7 @@ var claudeDir2;
|
|
|
51636
51635
|
var init_dashboard_routes = __esm(() => {
|
|
51637
51636
|
init_frontmatter_parser();
|
|
51638
51637
|
init_claude_data();
|
|
51639
|
-
claudeDir2 = join38(
|
|
51638
|
+
claudeDir2 = join38(homedir21(), ".claude");
|
|
51640
51639
|
});
|
|
51641
51640
|
|
|
51642
51641
|
// src/domains/web-server/routes/health-routes.ts
|
|
@@ -51710,7 +51709,7 @@ var init_hook_log_routes = __esm(() => {
|
|
|
51710
51709
|
// src/domains/web-server/routes/mcp-routes.ts
|
|
51711
51710
|
import { existsSync as existsSync21 } from "node:fs";
|
|
51712
51711
|
import { readFile as readFile18 } from "node:fs/promises";
|
|
51713
|
-
import { homedir as
|
|
51712
|
+
import { homedir as homedir22 } from "node:os";
|
|
51714
51713
|
import { basename as basename12, join as join39, resolve as resolve14 } from "node:path";
|
|
51715
51714
|
function parseMcpServers(raw, source, sourceLabel) {
|
|
51716
51715
|
const entries = [];
|
|
@@ -51759,7 +51758,7 @@ function mergeServers(lists) {
|
|
|
51759
51758
|
function isSafeProjectPath(projectPath) {
|
|
51760
51759
|
if (projectPath.includes(".."))
|
|
51761
51760
|
return false;
|
|
51762
|
-
const home3 =
|
|
51761
|
+
const home3 = homedir22();
|
|
51763
51762
|
try {
|
|
51764
51763
|
const resolved = resolve14(projectPath);
|
|
51765
51764
|
if (!resolved.startsWith(home3))
|
|
@@ -51772,7 +51771,7 @@ function isSafeProjectPath(projectPath) {
|
|
|
51772
51771
|
function registerMcpRoutes(app) {
|
|
51773
51772
|
app.get("/api/mcp-servers", async (_req, res) => {
|
|
51774
51773
|
try {
|
|
51775
|
-
const claudeDir3 = join39(
|
|
51774
|
+
const claudeDir3 = join39(homedir22(), ".claude");
|
|
51776
51775
|
const allLists = [];
|
|
51777
51776
|
try {
|
|
51778
51777
|
const settings = await readSettings();
|
|
@@ -51782,7 +51781,7 @@ function registerMcpRoutes(app) {
|
|
|
51782
51781
|
}
|
|
51783
51782
|
} catch {}
|
|
51784
51783
|
try {
|
|
51785
|
-
const claudeJsonPath = join39(
|
|
51784
|
+
const claudeJsonPath = join39(homedir22(), ".claude.json");
|
|
51786
51785
|
if (existsSync21(claudeJsonPath)) {
|
|
51787
51786
|
const content = await readFile18(claudeJsonPath, "utf-8");
|
|
51788
51787
|
const parsed = JSON.parse(content);
|
|
@@ -52043,7 +52042,7 @@ var init_skill_directory_installer = __esm(() => {
|
|
|
52043
52042
|
// src/commands/portable/config-discovery.ts
|
|
52044
52043
|
import { existsSync as existsSync23, readFileSync as readFileSync6 } from "node:fs";
|
|
52045
52044
|
import { cp as cp2, mkdir as mkdir11, readFile as readFile19, readdir as readdir12, stat as stat8 } from "node:fs/promises";
|
|
52046
|
-
import { homedir as
|
|
52045
|
+
import { homedir as homedir23 } from "node:os";
|
|
52047
52046
|
import { basename as basename13, dirname as dirname12, extname as extname3, join as join41, relative as relative9, resolve as resolve16, sep as sep6 } from "node:path";
|
|
52048
52047
|
async function copyHooksCompanionDirs(sourceDir, targetDir) {
|
|
52049
52048
|
const result = {
|
|
@@ -52126,7 +52125,7 @@ async function copyHooksCompanionDirs(sourceDir, targetDir) {
|
|
|
52126
52125
|
function resolveSourceOrigin(sourcePath) {
|
|
52127
52126
|
if (!sourcePath)
|
|
52128
52127
|
return "global";
|
|
52129
|
-
const home3 =
|
|
52128
|
+
const home3 = homedir23();
|
|
52130
52129
|
const cwd2 = process.cwd();
|
|
52131
52130
|
if (cwd2 === home3)
|
|
52132
52131
|
return "global";
|
|
@@ -52141,16 +52140,16 @@ function getConfigSourcePath(globalOnly = false) {
|
|
|
52141
52140
|
return findExistingProjectConfigPath(process.cwd()) ?? getGlobalConfigSourcePath();
|
|
52142
52141
|
}
|
|
52143
52142
|
function getGlobalConfigSourcePath() {
|
|
52144
|
-
return join41(
|
|
52143
|
+
return join41(homedir23(), ".claude", "CLAUDE.md");
|
|
52145
52144
|
}
|
|
52146
52145
|
function getRulesSourcePath(globalOnly = false) {
|
|
52147
|
-
const globalPath = join41(
|
|
52146
|
+
const globalPath = join41(homedir23(), ".claude", "rules");
|
|
52148
52147
|
if (globalOnly)
|
|
52149
52148
|
return globalPath;
|
|
52150
52149
|
return findExistingProjectLayoutPath(process.cwd(), "rules") ?? globalPath;
|
|
52151
52150
|
}
|
|
52152
52151
|
function getHooksSourcePath(globalOnly = false) {
|
|
52153
|
-
const globalPath = join41(
|
|
52152
|
+
const globalPath = join41(homedir23(), ".claude", "hooks");
|
|
52154
52153
|
if (globalOnly)
|
|
52155
52154
|
return globalPath;
|
|
52156
52155
|
return findExistingProjectLayoutPath(process.cwd(), "hooks") ?? globalPath;
|
|
@@ -54339,7 +54338,7 @@ var init_codex_capabilities = __esm(() => {
|
|
|
54339
54338
|
// src/commands/portable/codex-path-safety.ts
|
|
54340
54339
|
import { existsSync as existsSync24 } from "node:fs";
|
|
54341
54340
|
import { mkdir as mkdir12, realpath as realpath7 } from "node:fs/promises";
|
|
54342
|
-
import { homedir as
|
|
54341
|
+
import { homedir as homedir24 } from "node:os";
|
|
54343
54342
|
import { dirname as dirname13, join as join42, resolve as resolve17, sep as sep7 } from "node:path";
|
|
54344
54343
|
function isPathWithinBoundary3(targetPath, boundaryPath) {
|
|
54345
54344
|
const resolvedTarget = resolve17(targetPath);
|
|
@@ -54386,7 +54385,7 @@ async function withCodexTargetLock2(targetFilePath, operation) {
|
|
|
54386
54385
|
}
|
|
54387
54386
|
}
|
|
54388
54387
|
function getCodexGlobalBoundary() {
|
|
54389
|
-
return join42(
|
|
54388
|
+
return join42(homedir24(), ".codex");
|
|
54390
54389
|
}
|
|
54391
54390
|
var import_proper_lockfile6;
|
|
54392
54391
|
var init_codex_path_safety = __esm(() => {
|
|
@@ -54781,7 +54780,7 @@ var init_codex_hook_wrapper = __esm(() => {
|
|
|
54781
54780
|
});
|
|
54782
54781
|
|
|
54783
54782
|
// src/commands/portable/converters/claude-to-codex-hooks.ts
|
|
54784
|
-
import { homedir as
|
|
54783
|
+
import { homedir as homedir25 } from "node:os";
|
|
54785
54784
|
function convertClaudeHooksToCodex(sourceHooks, capabilities, pathRewrite) {
|
|
54786
54785
|
const result = {};
|
|
54787
54786
|
for (const [event, groups] of Object.entries(sourceHooks)) {
|
|
@@ -54839,7 +54838,7 @@ function rewriteCommandPath(command, pathRewrite) {
|
|
|
54839
54838
|
const normalizeSlashes = (s) => s.replace(/\\/g, "/");
|
|
54840
54839
|
let rewritten = command;
|
|
54841
54840
|
if (pathRewrite.commandSubstitutions && pathRewrite.commandSubstitutions.size > 0) {
|
|
54842
|
-
const home3 =
|
|
54841
|
+
const home3 = homedir25();
|
|
54843
54842
|
const homeForward = normalizeSlashes(home3);
|
|
54844
54843
|
for (const [originalAbsPath, wrapperAbsPath] of pathRewrite.commandSubstitutions) {
|
|
54845
54844
|
const originalAbsForward = normalizeSlashes(originalAbsPath);
|
|
@@ -54942,7 +54941,7 @@ var init_gemini_hook_event_map = __esm(() => {
|
|
|
54942
54941
|
// src/commands/portable/hooks-settings-merger.ts
|
|
54943
54942
|
import { existsSync as existsSync26 } from "node:fs";
|
|
54944
54943
|
import { mkdir as mkdir13, readFile as readFile21, rename as rename8, rm as rm6, writeFile as writeFile12 } from "node:fs/promises";
|
|
54945
|
-
import { homedir as
|
|
54944
|
+
import { homedir as homedir26 } from "node:os";
|
|
54946
54945
|
import { basename as basename14, dirname as dirname16, extname as extname4, join as join44, resolve as resolve20 } from "node:path";
|
|
54947
54946
|
function isCodexWrappableHookPath(filePath) {
|
|
54948
54947
|
return hookAssetBasename(filePath) !== "node-hook-runner.sh" && CODEX_WRAPPABLE_HOOK_EXTENSIONS.has(extname4(filePath).toLowerCase());
|
|
@@ -55025,7 +55024,7 @@ function normalizeDirPattern(value) {
|
|
|
55025
55024
|
}
|
|
55026
55025
|
function homeRelativeDir(value) {
|
|
55027
55026
|
const normalized = normalizeDirPattern(value);
|
|
55028
|
-
const home3 = normalizeDirPattern(
|
|
55027
|
+
const home3 = normalizeDirPattern(homedir26());
|
|
55029
55028
|
return normalized.startsWith(`${home3}/`) ? normalized.slice(home3.length + 1) : normalized;
|
|
55030
55029
|
}
|
|
55031
55030
|
function buildHookDirRewritePairs(sourceHooksDir, targetHooksDir) {
|
|
@@ -55582,7 +55581,7 @@ async function migrateHooksSettingsForCodex(options2) {
|
|
|
55582
55581
|
}
|
|
55583
55582
|
let featureFlagWritten = false;
|
|
55584
55583
|
if (capabilities.requiresFeatureFlag) {
|
|
55585
|
-
const configTomlPath = isGlobal ? join44(
|
|
55584
|
+
const configTomlPath = isGlobal ? join44(homedir26(), ".codex", "config.toml") : join44(process.cwd(), ".codex", "config.toml");
|
|
55586
55585
|
const flagResult = await ensureCodexHooksFeatureFlag(configTomlPath, isGlobal);
|
|
55587
55586
|
featureFlagWritten = flagResult.status === "written" || flagResult.status === "updated";
|
|
55588
55587
|
}
|
|
@@ -56987,10 +56986,10 @@ __export(exports_skills_discovery, {
|
|
|
56987
56986
|
discoverSkills: () => discoverSkills
|
|
56988
56987
|
});
|
|
56989
56988
|
import { readFile as readFile25, readdir as readdir13, stat as stat9 } from "node:fs/promises";
|
|
56990
|
-
import { homedir as
|
|
56989
|
+
import { homedir as homedir27 } from "node:os";
|
|
56991
56990
|
import { dirname as dirname17, join as join45 } from "node:path";
|
|
56992
56991
|
function getSkillSourcePath(globalOnly = false) {
|
|
56993
|
-
const globalPath = join45(
|
|
56992
|
+
const globalPath = join45(homedir27(), ".claude/skills");
|
|
56994
56993
|
if (globalOnly) {
|
|
56995
56994
|
return findFirstExistingPath([globalPath]);
|
|
56996
56995
|
}
|
|
@@ -57231,7 +57230,7 @@ var init_migration_result_utils = __esm(() => {
|
|
|
57231
57230
|
// src/domains/web-server/routes/migration-routes.ts
|
|
57232
57231
|
import { existsSync as existsSync30 } from "node:fs";
|
|
57233
57232
|
import { readFile as readFile26, rm as rm8 } from "node:fs/promises";
|
|
57234
|
-
import { homedir as
|
|
57233
|
+
import { homedir as homedir28 } from "node:os";
|
|
57235
57234
|
import { basename as basename17, join as join46, resolve as resolve23 } from "node:path";
|
|
57236
57235
|
function resolveRegistryDeps(deps) {
|
|
57237
57236
|
return {
|
|
@@ -57910,7 +57909,7 @@ function registerMigrationRoutes(app, deps) {
|
|
|
57910
57909
|
};
|
|
57911
57910
|
const discovered = await discoverMigrationItems(includeAll);
|
|
57912
57911
|
const cwd2 = process.cwd();
|
|
57913
|
-
const home3 =
|
|
57912
|
+
const home3 = homedir28();
|
|
57914
57913
|
res.status(200).json({
|
|
57915
57914
|
cwd: cwd2,
|
|
57916
57915
|
targetPaths: {
|
|
@@ -59426,7 +59425,7 @@ function scanPlanDir(dir) {
|
|
|
59426
59425
|
var init_plan_scanner = () => {};
|
|
59427
59426
|
|
|
59428
59427
|
// src/domains/plan-parser/plan-scope.ts
|
|
59429
|
-
import { homedir as
|
|
59428
|
+
import { homedir as homedir29 } from "node:os";
|
|
59430
59429
|
import { isAbsolute as isAbsolute8, join as join49, relative as relative12, resolve as resolve25 } from "node:path";
|
|
59431
59430
|
function resolveConfiguredDir(configuredPath, baseDir) {
|
|
59432
59431
|
const trimmed = configuredPath?.trim();
|
|
@@ -59439,7 +59438,7 @@ function resolveProjectPlansDir(projectRoot, config) {
|
|
|
59439
59438
|
return resolveConfiguredDir(config?.paths?.plans, projectRoot);
|
|
59440
59439
|
}
|
|
59441
59440
|
function resolveGlobalPlansDir(config) {
|
|
59442
|
-
return resolveConfiguredDir(config?.paths?.globalPlans, join49(
|
|
59441
|
+
return resolveConfiguredDir(config?.paths?.globalPlans, join49(homedir29(), ".claude"));
|
|
59443
59442
|
}
|
|
59444
59443
|
function resolvePlanDirForScope(scope, projectRoot, config) {
|
|
59445
59444
|
return scope === "global" ? resolveGlobalPlansDir(config) : resolveProjectPlansDir(projectRoot, config);
|
|
@@ -60711,7 +60710,7 @@ var init_p_limit = __esm(() => {
|
|
|
60711
60710
|
|
|
60712
60711
|
// src/domains/web-server/routes/plan-routes.ts
|
|
60713
60712
|
import { existsSync as existsSync36, readFileSync as readFileSync12, realpathSync as realpathSync2 } from "node:fs";
|
|
60714
|
-
import { homedir as
|
|
60713
|
+
import { homedir as homedir30 } from "node:os";
|
|
60715
60714
|
import { basename as basename20, dirname as dirname24, join as join54, relative as relative14, resolve as resolve27, sep as sep8 } from "node:path";
|
|
60716
60715
|
function sanitizeError(err) {
|
|
60717
60716
|
if (err instanceof Error) {
|
|
@@ -60902,7 +60901,7 @@ function withTimeout(promiseFactory, timeoutMs, label) {
|
|
|
60902
60901
|
function isCurrentProjectFallbackCandidate(currentPath, globalProjectKey) {
|
|
60903
60902
|
if (toProjectPathKey(currentPath) === globalProjectKey)
|
|
60904
60903
|
return false;
|
|
60905
|
-
if (toProjectPathKey(currentPath) === toProjectPathKey(
|
|
60904
|
+
if (toProjectPathKey(currentPath) === toProjectPathKey(homedir30()))
|
|
60906
60905
|
return false;
|
|
60907
60906
|
return existsSync36(join54(currentPath, ".git")) || existsSync36(CkConfigManager.getProjectConfigPath(currentPath)) || existsSync36(join54(currentPath, "plans"));
|
|
60908
60907
|
}
|
|
@@ -60967,7 +60966,7 @@ function registerPlanRoutes(app) {
|
|
|
60967
60966
|
});
|
|
60968
60967
|
app.get("/api/plan/list-all", async (_req, res) => {
|
|
60969
60968
|
try {
|
|
60970
|
-
const globalProjectKey = toProjectPathKey(join54(
|
|
60969
|
+
const globalProjectKey = toProjectPathKey(join54(homedir30(), ".claude"));
|
|
60971
60970
|
const seenProjectKeys = new Set;
|
|
60972
60971
|
const scanTargets = [];
|
|
60973
60972
|
for (const project of await ProjectsRegistryManager.listProjects()) {
|
|
@@ -61214,7 +61213,7 @@ var init_project_plan_data = __esm(() => {
|
|
|
61214
61213
|
// src/domains/web-server/routes/project-routes.ts
|
|
61215
61214
|
import { existsSync as existsSync37 } from "node:fs";
|
|
61216
61215
|
import { readFile as readFile27 } from "node:fs/promises";
|
|
61217
|
-
import { homedir as
|
|
61216
|
+
import { homedir as homedir31 } from "node:os";
|
|
61218
61217
|
import { basename as basename21, join as join55, resolve as resolve28 } from "node:path";
|
|
61219
61218
|
function registerProjectRoutes(app) {
|
|
61220
61219
|
app.get("/api/projects", async (req, res) => {
|
|
@@ -61235,7 +61234,7 @@ function registerProjectRoutes(app) {
|
|
|
61235
61234
|
for (const discovered of discoveredProjects) {
|
|
61236
61235
|
if (registeredPaths.has(discovered.path))
|
|
61237
61236
|
continue;
|
|
61238
|
-
if (discovered.path === join55(
|
|
61237
|
+
if (discovered.path === join55(homedir31(), ".claude"))
|
|
61239
61238
|
continue;
|
|
61240
61239
|
const projectInfo = await detectAndBuildProjectInfo(discovered.path, `discovered-${discovered.path}`, cachedSettings, cachedSkills, false);
|
|
61241
61240
|
if (projectInfo) {
|
|
@@ -61251,7 +61250,7 @@ function registerProjectRoutes(app) {
|
|
|
61251
61250
|
if (cwdProject) {
|
|
61252
61251
|
projects.push(cwdProject);
|
|
61253
61252
|
}
|
|
61254
|
-
const globalDir = join55(
|
|
61253
|
+
const globalDir = join55(homedir31(), ".claude");
|
|
61255
61254
|
const globalProject = await detectAndBuildProjectInfo(globalDir, "global", undefined, undefined, false);
|
|
61256
61255
|
if (globalProject) {
|
|
61257
61256
|
projects.push(globalProject);
|
|
@@ -61323,12 +61322,12 @@ function registerProjectRoutes(app) {
|
|
|
61323
61322
|
const body = validation.data;
|
|
61324
61323
|
let projectPath = body.path;
|
|
61325
61324
|
if (projectPath.startsWith("~/") || projectPath === "~") {
|
|
61326
|
-
projectPath = join55(
|
|
61325
|
+
projectPath = join55(homedir31(), projectPath.slice(1));
|
|
61327
61326
|
} else if (projectPath.startsWith("~\\")) {
|
|
61328
|
-
projectPath = join55(
|
|
61327
|
+
projectPath = join55(homedir31(), projectPath.slice(1));
|
|
61329
61328
|
}
|
|
61330
61329
|
projectPath = resolve28(projectPath);
|
|
61331
|
-
const homeDir =
|
|
61330
|
+
const homeDir = homedir31();
|
|
61332
61331
|
if (projectPath.includes("..") || !projectPath.startsWith(homeDir)) {
|
|
61333
61332
|
res.status(400).json({ error: "Invalid path after expansion" });
|
|
61334
61333
|
return;
|
|
@@ -61385,7 +61384,7 @@ function registerProjectRoutes(app) {
|
|
|
61385
61384
|
if (id === "current") {
|
|
61386
61385
|
projectPath = process.cwd();
|
|
61387
61386
|
} else if (id === "global") {
|
|
61388
|
-
projectPath = join55(
|
|
61387
|
+
projectPath = join55(homedir31(), ".claude");
|
|
61389
61388
|
} else {
|
|
61390
61389
|
res.status(404).json({ error: "Project not found" });
|
|
61391
61390
|
return;
|
|
@@ -61465,7 +61464,7 @@ async function buildProjectInfoFromRegistry(registered, cachedSettings, cachedSk
|
|
|
61465
61464
|
const hasLocalConfig = hasClaudeDir && CkConfigManager.projectConfigExists(registered.path, false);
|
|
61466
61465
|
const settings = cachedSettings !== undefined ? cachedSettings : await readSettings();
|
|
61467
61466
|
const skills = cachedSkills !== undefined ? cachedSkills : await scanSkills();
|
|
61468
|
-
const settingsPath = join55(
|
|
61467
|
+
const settingsPath = join55(homedir31(), ".claude", "settings.json");
|
|
61469
61468
|
const health = existsSync37(settingsPath) ? "healthy" : "warning";
|
|
61470
61469
|
const model = getCurrentModel() || settings?.model || "claude-sonnet-4";
|
|
61471
61470
|
const planData = includePlanData ? await buildProjectPlanData(registered.path, "project") : null;
|
|
@@ -61507,7 +61506,7 @@ async function detectAndBuildProjectInfo(path6, id, cachedSettings, cachedSkills
|
|
|
61507
61506
|
const hasLocalConfig = CkConfigManager.projectConfigExists(path6, id === "global");
|
|
61508
61507
|
const settings = cachedSettings !== undefined ? cachedSettings : await readSettings();
|
|
61509
61508
|
const skills = cachedSkills !== undefined ? cachedSkills : await scanSkills();
|
|
61510
|
-
const settingsPath = join55(
|
|
61509
|
+
const settingsPath = join55(homedir31(), ".claude", "settings.json");
|
|
61511
61510
|
const health = existsSync37(settingsPath) ? "healthy" : "warning";
|
|
61512
61511
|
const model = getCurrentModel() || settings?.model || "claude-sonnet-4";
|
|
61513
61512
|
const scope = id === "global" ? "global" : "project";
|
|
@@ -61555,7 +61554,7 @@ var init_project_routes = __esm(() => {
|
|
|
61555
61554
|
// src/domains/web-server/routes/session-routes.ts
|
|
61556
61555
|
import { existsSync as existsSync38 } from "node:fs";
|
|
61557
61556
|
import { readFile as readFile28, readdir as readdir14, stat as stat10 } from "node:fs/promises";
|
|
61558
|
-
import { homedir as
|
|
61557
|
+
import { homedir as homedir32 } from "node:os";
|
|
61559
61558
|
import { basename as basename22, join as join56 } from "node:path";
|
|
61560
61559
|
function toDateStr(d3) {
|
|
61561
61560
|
const y3 = d3.getFullYear();
|
|
@@ -61564,7 +61563,7 @@ function toDateStr(d3) {
|
|
|
61564
61563
|
return `${y3}-${m2}-${day}`;
|
|
61565
61564
|
}
|
|
61566
61565
|
async function scanActivityMetrics(periodDays) {
|
|
61567
|
-
const home3 =
|
|
61566
|
+
const home3 = homedir32();
|
|
61568
61567
|
const projectsDir2 = join56(home3, ".claude", "projects");
|
|
61569
61568
|
const cutoff = new Date;
|
|
61570
61569
|
cutoff.setDate(cutoff.getDate() - periodDays);
|
|
@@ -61635,7 +61634,7 @@ async function scanActivityMetrics(periodDays) {
|
|
|
61635
61634
|
return { totalSessions, projects: projectActivities, dailyCounts };
|
|
61636
61635
|
}
|
|
61637
61636
|
async function resolveSessionDir(projectId) {
|
|
61638
|
-
const home3 =
|
|
61637
|
+
const home3 = homedir32();
|
|
61639
61638
|
if (projectId.startsWith("discovered-")) {
|
|
61640
61639
|
try {
|
|
61641
61640
|
const encodedPathB64 = projectId.slice("discovered-".length);
|
|
@@ -61809,7 +61808,7 @@ async function parseSessionDetail(filePath, limit, offset) {
|
|
|
61809
61808
|
}
|
|
61810
61809
|
function registerSessionRoutes(app) {
|
|
61811
61810
|
app.get("/api/sessions", async (_req, res) => {
|
|
61812
|
-
const home3 =
|
|
61811
|
+
const home3 = homedir32();
|
|
61813
61812
|
const projectsDir2 = join56(home3, ".claude", "projects");
|
|
61814
61813
|
if (!existsSync38(projectsDir2)) {
|
|
61815
61814
|
res.json({ projects: [] });
|
|
@@ -61878,7 +61877,7 @@ function registerSessionRoutes(app) {
|
|
|
61878
61877
|
res.status(404).json({ error: "Project not found" });
|
|
61879
61878
|
return;
|
|
61880
61879
|
}
|
|
61881
|
-
const allowedBase = join56(
|
|
61880
|
+
const allowedBase = join56(homedir32(), ".claude", "projects");
|
|
61882
61881
|
if (!projectDir.startsWith(allowedBase)) {
|
|
61883
61882
|
res.status(403).json({ error: "Access denied" });
|
|
61884
61883
|
return;
|
|
@@ -61908,7 +61907,7 @@ function registerSessionRoutes(app) {
|
|
|
61908
61907
|
res.status(404).json({ error: "Project not found" });
|
|
61909
61908
|
return;
|
|
61910
61909
|
}
|
|
61911
|
-
const allowedBase = join56(
|
|
61910
|
+
const allowedBase = join56(homedir32(), ".claude", "projects");
|
|
61912
61911
|
if (!projectDir.startsWith(allowedBase)) {
|
|
61913
61912
|
res.status(403).json({ error: "Access denied" });
|
|
61914
61913
|
return;
|
|
@@ -61942,7 +61941,7 @@ var init_session_routes = __esm(() => {
|
|
|
61942
61941
|
});
|
|
61943
61942
|
|
|
61944
61943
|
// src/domains/web-server/routes/settings-routes.ts
|
|
61945
|
-
import { homedir as
|
|
61944
|
+
import { homedir as homedir33 } from "node:os";
|
|
61946
61945
|
function registerSettingsRoutes(app) {
|
|
61947
61946
|
app.get("/api/settings", async (_req, res) => {
|
|
61948
61947
|
try {
|
|
@@ -61998,7 +61997,7 @@ function registerSettingsRoutes(app) {
|
|
|
61998
61997
|
res.json({
|
|
61999
61998
|
success: true,
|
|
62000
61999
|
path: "~/.claude/settings.json",
|
|
62001
|
-
backupPath: saveResult.backupPath ? saveResult.backupPath.replace(
|
|
62000
|
+
backupPath: saveResult.backupPath ? saveResult.backupPath.replace(homedir33(), "~") : null,
|
|
62002
62001
|
absolutePath: getSettingsPath()
|
|
62003
62002
|
});
|
|
62004
62003
|
} catch (error) {
|
|
@@ -62032,7 +62031,7 @@ var init_settings_routes = __esm(() => {
|
|
|
62032
62031
|
|
|
62033
62032
|
// src/domains/skills/skill-catalog-generator.ts
|
|
62034
62033
|
import { mkdir as mkdir14, readFile as readFile29, readdir as readdir15, rename as rename10, stat as stat11, writeFile as writeFile14 } from "node:fs/promises";
|
|
62035
|
-
import { homedir as
|
|
62034
|
+
import { homedir as homedir34 } from "node:os";
|
|
62036
62035
|
import { dirname as dirname25, join as join57, relative as relative15 } from "node:path";
|
|
62037
62036
|
async function hasScripts(skillPath) {
|
|
62038
62037
|
try {
|
|
@@ -62175,7 +62174,7 @@ var CATALOG_PATH, CATALOG_VERSION = "1.0.0", SKIP_DIRS4, skillCatalogGenerator;
|
|
|
62175
62174
|
var init_skill_catalog_generator = __esm(() => {
|
|
62176
62175
|
init_skills_discovery();
|
|
62177
62176
|
init_logger();
|
|
62178
|
-
CATALOG_PATH = join57(
|
|
62177
|
+
CATALOG_PATH = join57(homedir34(), ".claude", ".skills-catalog.json");
|
|
62179
62178
|
SKIP_DIRS4 = [".venv", "__pycache__", "node_modules", ".git"];
|
|
62180
62179
|
skillCatalogGenerator = new SkillCatalogGenerator;
|
|
62181
62180
|
});
|
|
@@ -62465,7 +62464,7 @@ var init_skill_browser_routes = __esm(() => {
|
|
|
62465
62464
|
|
|
62466
62465
|
// src/commands/skills/agents.ts
|
|
62467
62466
|
import { existsSync as existsSync39, readdirSync as readdirSync6, statSync as statSync8 } from "node:fs";
|
|
62468
|
-
import { homedir as
|
|
62467
|
+
import { homedir as homedir36, platform as platform5 } from "node:os";
|
|
62469
62468
|
import { join as join59 } from "node:path";
|
|
62470
62469
|
function hasInstallSignal2(path7) {
|
|
62471
62470
|
if (!path7 || !existsSync39(path7)) {
|
|
@@ -62522,7 +62521,7 @@ function isSkillInstalled(skillName, agent, options2) {
|
|
|
62522
62521
|
}
|
|
62523
62522
|
var home3, OPENCODE_BINARY_NAME2, agents;
|
|
62524
62523
|
var init_agents = __esm(() => {
|
|
62525
|
-
home3 =
|
|
62524
|
+
home3 = homedir36();
|
|
62526
62525
|
OPENCODE_BINARY_NAME2 = platform5() === "win32" ? "opencode.exe" : "opencode";
|
|
62527
62526
|
agents = {
|
|
62528
62527
|
"claude-code": {
|
|
@@ -62629,7 +62628,7 @@ var init_agents = __esm(() => {
|
|
|
62629
62628
|
// src/commands/skills/skills-registry.ts
|
|
62630
62629
|
import { existsSync as existsSync40 } from "node:fs";
|
|
62631
62630
|
import { mkdir as mkdir15, readFile as readFile31, writeFile as writeFile15 } from "node:fs/promises";
|
|
62632
|
-
import { homedir as
|
|
62631
|
+
import { homedir as homedir37 } from "node:os";
|
|
62633
62632
|
import { dirname as dirname26, join as join60, sep as sep10 } from "node:path";
|
|
62634
62633
|
function getCliVersion3() {
|
|
62635
62634
|
try {
|
|
@@ -62741,7 +62740,7 @@ async function syncRegistry() {
|
|
|
62741
62740
|
var home4, REGISTRY_PATH, SkillInstallationSchema, SkillRegistrySchema, REGISTRY_PATH_MIGRATIONS;
|
|
62742
62741
|
var init_skills_registry = __esm(() => {
|
|
62743
62742
|
init_zod();
|
|
62744
|
-
home4 =
|
|
62743
|
+
home4 = homedir37();
|
|
62745
62744
|
REGISTRY_PATH = join60(home4, ".claudekit", "skill-registry.json");
|
|
62746
62745
|
SkillInstallationSchema = exports_external.object({
|
|
62747
62746
|
skill: exports_external.string(),
|
|
@@ -62773,7 +62772,7 @@ var init_skills_registry = __esm(() => {
|
|
|
62773
62772
|
// src/commands/skills/skills-installer.ts
|
|
62774
62773
|
import { existsSync as existsSync41 } from "node:fs";
|
|
62775
62774
|
import { cp as cp3, mkdir as mkdir16, rm as rm9, stat as stat12 } from "node:fs/promises";
|
|
62776
|
-
import { homedir as
|
|
62775
|
+
import { homedir as homedir38 } from "node:os";
|
|
62777
62776
|
import { dirname as dirname27, join as join61, resolve as resolve30 } from "node:path";
|
|
62778
62777
|
function isSamePath2(path1, path22) {
|
|
62779
62778
|
try {
|
|
@@ -62904,7 +62903,7 @@ var init_skills_installer = __esm(() => {
|
|
|
62904
62903
|
LEGACY_SKILL_PATHS = {
|
|
62905
62904
|
"gemini-cli": {
|
|
62906
62905
|
project: ".gemini/skills",
|
|
62907
|
-
global: join61(
|
|
62906
|
+
global: join61(homedir38(), ".gemini/skills")
|
|
62908
62907
|
}
|
|
62909
62908
|
};
|
|
62910
62909
|
});
|
|
@@ -63853,7 +63852,7 @@ var package_default;
|
|
|
63853
63852
|
var init_package = __esm(() => {
|
|
63854
63853
|
package_default = {
|
|
63855
63854
|
name: "claudekit-cli",
|
|
63856
|
-
version: "4.3.1-dev.
|
|
63855
|
+
version: "4.3.1-dev.19",
|
|
63857
63856
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
63858
63857
|
type: "module",
|
|
63859
63858
|
repository: {
|
|
@@ -63869,6 +63868,7 @@ var init_package = __esm(() => {
|
|
|
63869
63868
|
},
|
|
63870
63869
|
files: [
|
|
63871
63870
|
"bin/ck.js",
|
|
63871
|
+
"bin/postinstall-hook-restore.cjs",
|
|
63872
63872
|
"bin/postinstall-self-heal.cjs",
|
|
63873
63873
|
"dist/index.js",
|
|
63874
63874
|
"dist/ui/",
|
|
@@ -64335,7 +64335,7 @@ var init_package_manager_runner = __esm(() => {
|
|
|
64335
64335
|
|
|
64336
64336
|
// src/domains/installation/merger/zombie-wirings-pruner.ts
|
|
64337
64337
|
import { existsSync as existsSync44, readdirSync as readdirSync7 } from "node:fs";
|
|
64338
|
-
import { homedir as
|
|
64338
|
+
import { homedir as homedir39 } from "node:os";
|
|
64339
64339
|
import { basename as basename23, dirname as dirname28, isAbsolute as isAbsolute10, resolve as resolve32, sep as sep11 } from "node:path";
|
|
64340
64340
|
function pruneZombieEngineerWirings(settings, hookDir, preserveCommands = new Set) {
|
|
64341
64341
|
const pruned = [];
|
|
@@ -64415,7 +64415,7 @@ function extractHookFilePath(command, hookDir) {
|
|
|
64415
64415
|
return null;
|
|
64416
64416
|
if (/&&|\|\||;|(?<!["|'])\|(?!["|'])/.test(command))
|
|
64417
64417
|
return null;
|
|
64418
|
-
const home5 =
|
|
64418
|
+
const home5 = homedir39().replace(/\\/g, "/");
|
|
64419
64419
|
const hookDirNorm = hookDir.replace(/\\/g, "/");
|
|
64420
64420
|
function resolveEnvPath(prefix, rest) {
|
|
64421
64421
|
const normRest = rest.replace(/\\/g, "/");
|
|
@@ -64495,7 +64495,7 @@ var init_shared2 = __esm(() => {
|
|
|
64495
64495
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
64496
64496
|
import { existsSync as existsSync45, readFileSync as readFileSync13, readdirSync as readdirSync8, statSync as statSync9, writeFileSync as writeFileSync5 } from "node:fs";
|
|
64497
64497
|
import { readdir as readdir17 } from "node:fs/promises";
|
|
64498
|
-
import { homedir as
|
|
64498
|
+
import { homedir as homedir40, tmpdir } from "node:os";
|
|
64499
64499
|
import { join as join64, resolve as resolve33 } from "node:path";
|
|
64500
64500
|
function resolveDoctorCkExecutable(platformName = process.platform) {
|
|
64501
64501
|
return platformName === "win32" ? "ck.cmd" : "ck";
|
|
@@ -64525,12 +64525,12 @@ function isPathWithin2(filePath, parentDir) {
|
|
|
64525
64525
|
}
|
|
64526
64526
|
function getCanonicalGlobalCommandRoot() {
|
|
64527
64527
|
const configuredGlobalDir = PathResolver.getGlobalKitDir().replace(/\\/g, "/").replace(/\/+$/, "");
|
|
64528
|
-
const defaultGlobalDir = join64(
|
|
64528
|
+
const defaultGlobalDir = join64(homedir40(), ".claude").replace(/\\/g, "/");
|
|
64529
64529
|
return configuredGlobalDir === defaultGlobalDir ? "$HOME" : configuredGlobalDir;
|
|
64530
64530
|
}
|
|
64531
64531
|
function getClaudeSettingsFiles(projectDir) {
|
|
64532
64532
|
const globalClaudeDir = PathResolver.getGlobalKitDir();
|
|
64533
|
-
const ccsSettingsDir = join64(process.env.CK_TEST_HOME ??
|
|
64533
|
+
const ccsSettingsDir = join64(process.env.CK_TEST_HOME ?? homedir40(), ".ccs");
|
|
64534
64534
|
const candidates = [
|
|
64535
64535
|
{
|
|
64536
64536
|
path: resolve33(projectDir, ".claude", "settings.json"),
|
|
@@ -65229,7 +65229,7 @@ function extractHookReferencePaths(cmd) {
|
|
|
65229
65229
|
}
|
|
65230
65230
|
function resolveHookScriptPath(scriptPath, projectDir) {
|
|
65231
65231
|
let resolved = scriptPath.replace(/\\/g, "/");
|
|
65232
|
-
const home5 =
|
|
65232
|
+
const home5 = homedir40();
|
|
65233
65233
|
resolved = resolved.replace(/^\$\{?HOME\}?/, home5);
|
|
65234
65234
|
resolved = resolved.replace(/^\$\{?CLAUDE_PROJECT_DIR\}?/, projectDir);
|
|
65235
65235
|
resolved = resolved.replace(/^%USERPROFILE%/, home5);
|
|
@@ -67444,6 +67444,61 @@ async function readMetadataFile(claudeDir3) {
|
|
|
67444
67444
|
return null;
|
|
67445
67445
|
}
|
|
67446
67446
|
}
|
|
67447
|
+
function extractCkHookName(command) {
|
|
67448
|
+
if (!command.trim().startsWith("node "))
|
|
67449
|
+
return null;
|
|
67450
|
+
const normalized = command.replace(/\\/g, "/");
|
|
67451
|
+
const match = normalized.match(/\/hooks\/([^/"'\s]+)\.(?:cjs|mjs|js)(?:["'\s]|$)/);
|
|
67452
|
+
return match?.[1] ?? null;
|
|
67453
|
+
}
|
|
67454
|
+
function collectSettingsHookCommands(settings) {
|
|
67455
|
+
const commands = new Set;
|
|
67456
|
+
for (const entries of Object.values(settings.hooks ?? {})) {
|
|
67457
|
+
for (const entry of entries) {
|
|
67458
|
+
if (typeof entry.command === "string") {
|
|
67459
|
+
commands.add(normalizeCommand(entry.command));
|
|
67460
|
+
}
|
|
67461
|
+
for (const hook of entry.hooks ?? []) {
|
|
67462
|
+
if (typeof hook.command === "string") {
|
|
67463
|
+
commands.add(normalizeCommand(hook.command));
|
|
67464
|
+
}
|
|
67465
|
+
}
|
|
67466
|
+
}
|
|
67467
|
+
}
|
|
67468
|
+
return commands;
|
|
67469
|
+
}
|
|
67470
|
+
function getInstalledHookCommands(config, kit) {
|
|
67471
|
+
const kits = Object.entries(config.kits ?? {});
|
|
67472
|
+
if (kits.length === 0)
|
|
67473
|
+
return [];
|
|
67474
|
+
const kitKey = kit?.toLowerCase();
|
|
67475
|
+
const preferred = kitKey ? kits.filter(([name]) => {
|
|
67476
|
+
const normalizedName = name.toLowerCase();
|
|
67477
|
+
return normalizedName === kitKey || normalizedName.includes(kitKey);
|
|
67478
|
+
}) : [];
|
|
67479
|
+
const candidates = preferred.length > 0 ? preferred : kits;
|
|
67480
|
+
return candidates.flatMap(([, entry]) => entry.installedSettings?.hooks ?? []);
|
|
67481
|
+
}
|
|
67482
|
+
async function countMissingCkHookRegistrations(claudeDir3, kit) {
|
|
67483
|
+
const settingsPath = join68(claudeDir3, "settings.json");
|
|
67484
|
+
const configPath = join68(claudeDir3, ".ck.json");
|
|
67485
|
+
if (!existsSync47(settingsPath) || !existsSync47(configPath))
|
|
67486
|
+
return 0;
|
|
67487
|
+
const settings = parseJsonContent(await import_fs_extra8.readFile(settingsPath, "utf-8"));
|
|
67488
|
+
const config = parseJsonContent(await import_fs_extra8.readFile(configPath, "utf-8"));
|
|
67489
|
+
const existingCommands = collectSettingsHookCommands(settings);
|
|
67490
|
+
const disabledHooks = new Set(Object.entries(config.hooks ?? {}).filter(([, enabled]) => enabled === false).map(([name]) => name));
|
|
67491
|
+
let missing = 0;
|
|
67492
|
+
for (const command of getInstalledHookCommands(config, kit)) {
|
|
67493
|
+
const hookName = extractCkHookName(command);
|
|
67494
|
+
if (hookName && disabledHooks.has(hookName))
|
|
67495
|
+
continue;
|
|
67496
|
+
if (!existingCommands.has(normalizeCommand(command))) {
|
|
67497
|
+
missing++;
|
|
67498
|
+
}
|
|
67499
|
+
}
|
|
67500
|
+
return missing;
|
|
67501
|
+
}
|
|
67447
67502
|
function buildInitCommand(isGlobal, kit, beta, yes, restoreCkHooks) {
|
|
67448
67503
|
const parts = ["ck init"];
|
|
67449
67504
|
if (isGlobal)
|
|
@@ -67565,6 +67620,27 @@ async function promptKitUpdate(beta, yes, deps) {
|
|
|
67565
67620
|
};
|
|
67566
67621
|
}
|
|
67567
67622
|
}
|
|
67623
|
+
const selectedClaudeDir = selection.isGlobal ? setup.global.path : setup.project.path;
|
|
67624
|
+
if (selectedClaudeDir) {
|
|
67625
|
+
try {
|
|
67626
|
+
const missingHookDeps = await findMissingHookDepsFn(selectedClaudeDir);
|
|
67627
|
+
if (missingHookDeps.length > 0) {
|
|
67628
|
+
logger.warning(`Detected ${missingHookDeps.length} ${selection.isGlobal ? "global" : "local"} missing hook dependency(ies); reinstalling kit content`);
|
|
67629
|
+
forceKitReinstall = true;
|
|
67630
|
+
}
|
|
67631
|
+
} catch (error) {
|
|
67632
|
+
logger.verbose(`Selected hook dependency self-heal check skipped: ${error instanceof Error ? error.message : "unknown"}`);
|
|
67633
|
+
}
|
|
67634
|
+
try {
|
|
67635
|
+
const missingHookRegistrations = await countMissingCkHookRegistrations(selectedClaudeDir, selection.kit);
|
|
67636
|
+
if (missingHookRegistrations > 0) {
|
|
67637
|
+
logger.warning(`Detected ${missingHookRegistrations} ${selection.isGlobal ? "global" : "local"} missing hook registration(s); reinstalling kit content`);
|
|
67638
|
+
forceKitReinstall = true;
|
|
67639
|
+
}
|
|
67640
|
+
} catch (error) {
|
|
67641
|
+
logger.verbose(`Selected hook registration self-heal check skipped: ${error instanceof Error ? error.message : "unknown"}`);
|
|
67642
|
+
}
|
|
67643
|
+
}
|
|
67568
67644
|
let kitVersion = selection.kit ? selection.isGlobal ? globalMetadata?.kits?.[selection.kit]?.version : localMetadata?.kits?.[selection.kit]?.version : undefined;
|
|
67569
67645
|
const isBetaInstalled = isBetaVersion(kitVersion);
|
|
67570
67646
|
const promptMessage = selection.promptMessage;
|
|
@@ -67834,6 +67910,7 @@ var init_post_update_handler = __esm(() => {
|
|
|
67834
67910
|
init_metadata_migration();
|
|
67835
67911
|
init_version_utils();
|
|
67836
67912
|
init_claudekit_scanner();
|
|
67913
|
+
init_command_normalizer();
|
|
67837
67914
|
init_logger();
|
|
67838
67915
|
init_safe_prompts();
|
|
67839
67916
|
init_types3();
|
|
@@ -68239,7 +68316,7 @@ import { spawn as spawn3 } from "node:child_process";
|
|
|
68239
68316
|
import { execFile as execFile8 } from "node:child_process";
|
|
68240
68317
|
import { existsSync as existsSync48 } from "node:fs";
|
|
68241
68318
|
import { readFile as readFile38 } from "node:fs/promises";
|
|
68242
|
-
import { cpus, homedir as
|
|
68319
|
+
import { cpus, homedir as homedir41, totalmem } from "node:os";
|
|
68243
68320
|
import { join as join70 } from "node:path";
|
|
68244
68321
|
function runCommand(cmd, args, fallback2) {
|
|
68245
68322
|
return new Promise((resolve34) => {
|
|
@@ -68405,7 +68482,7 @@ function registerSystemRoutes(app) {
|
|
|
68405
68482
|
gitVersion,
|
|
68406
68483
|
ghVersion,
|
|
68407
68484
|
shell: process.env.SHELL ?? process.env.ComSpec ?? "unknown",
|
|
68408
|
-
homeDir:
|
|
68485
|
+
homeDir: homedir41(),
|
|
68409
68486
|
cpuCores: cpus().length,
|
|
68410
68487
|
totalMemoryGb: (totalmem() / 1024 ** 3).toFixed(1)
|
|
68411
68488
|
};
|
|
@@ -74367,10 +74444,10 @@ var init_config_manager2 = __esm(() => {
|
|
|
74367
74444
|
|
|
74368
74445
|
// src/services/package-installer/gemini-mcp/validation.ts
|
|
74369
74446
|
import { existsSync as existsSync63, lstatSync, readlinkSync } from "node:fs";
|
|
74370
|
-
import { homedir as
|
|
74447
|
+
import { homedir as homedir44 } from "node:os";
|
|
74371
74448
|
import { join as join93 } from "node:path";
|
|
74372
74449
|
function getGlobalMcpConfigPath() {
|
|
74373
|
-
return join93(
|
|
74450
|
+
return join93(homedir44(), ".claude", ".mcp.json");
|
|
74374
74451
|
}
|
|
74375
74452
|
function getLocalMcpConfigPath(projectDir) {
|
|
74376
74453
|
return join93(projectDir, ".mcp.json");
|
|
@@ -74391,7 +74468,7 @@ function findMcpConfigPath(projectDir) {
|
|
|
74391
74468
|
}
|
|
74392
74469
|
function getGeminiSettingsPath(projectDir, isGlobal) {
|
|
74393
74470
|
if (isGlobal) {
|
|
74394
|
-
return join93(
|
|
74471
|
+
return join93(homedir44(), ".gemini", "settings.json");
|
|
74395
74472
|
}
|
|
74396
74473
|
return join93(projectDir, ".gemini", "settings.json");
|
|
74397
74474
|
}
|
|
@@ -77019,7 +77096,7 @@ var init_content_validator = __esm(() => {
|
|
|
77019
77096
|
import { createHash as createHash9 } from "node:crypto";
|
|
77020
77097
|
import { existsSync as existsSync79, mkdirSync as mkdirSync5, readFileSync as readFileSync19, readdirSync as readdirSync13, statSync as statSync14 } from "node:fs";
|
|
77021
77098
|
import { rename as rename16, writeFile as writeFile40 } from "node:fs/promises";
|
|
77022
|
-
import { homedir as
|
|
77099
|
+
import { homedir as homedir54 } from "node:os";
|
|
77023
77100
|
import { basename as basename34, join as join160 } from "node:path";
|
|
77024
77101
|
function getCachedContext(repoPath) {
|
|
77025
77102
|
const cachePath = getCacheFilePath(repoPath);
|
|
@@ -77094,7 +77171,7 @@ function getCacheFilePath(repoPath) {
|
|
|
77094
77171
|
}
|
|
77095
77172
|
var CACHE_DIR, CACHE_TTL_MS5;
|
|
77096
77173
|
var init_context_cache_manager = __esm(() => {
|
|
77097
|
-
CACHE_DIR = join160(
|
|
77174
|
+
CACHE_DIR = join160(homedir54(), ".claudekit", "cache");
|
|
77098
77175
|
CACHE_TTL_MS5 = 24 * 60 * 60 * 1000;
|
|
77099
77176
|
});
|
|
77100
77177
|
|
|
@@ -77548,10 +77625,10 @@ IMPORTANT: Generate the image and output the path as JSON: {"imagePath": "/path/
|
|
|
77548
77625
|
// src/commands/content/phases/photo-generator.ts
|
|
77549
77626
|
import { execSync as execSync8 } from "node:child_process";
|
|
77550
77627
|
import { existsSync as existsSync81, mkdirSync as mkdirSync6, readdirSync as readdirSync15 } from "node:fs";
|
|
77551
|
-
import { homedir as
|
|
77628
|
+
import { homedir as homedir55 } from "node:os";
|
|
77552
77629
|
import { join as join162 } from "node:path";
|
|
77553
77630
|
async function generatePhoto(_content, context, config, platform18, contentId, contentLogger) {
|
|
77554
|
-
const mediaDir = join162(config.contentDir.replace(/^~/,
|
|
77631
|
+
const mediaDir = join162(config.contentDir.replace(/^~/, homedir55()), "media", String(contentId));
|
|
77555
77632
|
if (!existsSync81(mediaDir)) {
|
|
77556
77633
|
mkdirSync6(mediaDir, { recursive: true });
|
|
77557
77634
|
}
|
|
@@ -77665,7 +77742,7 @@ var init_content_creator = __esm(() => {
|
|
|
77665
77742
|
|
|
77666
77743
|
// src/commands/content/phases/content-logger.ts
|
|
77667
77744
|
import { createWriteStream as createWriteStream4, existsSync as existsSync82, mkdirSync as mkdirSync7, statSync as statSync15 } from "node:fs";
|
|
77668
|
-
import { homedir as
|
|
77745
|
+
import { homedir as homedir56 } from "node:os";
|
|
77669
77746
|
import { join as join163 } from "node:path";
|
|
77670
77747
|
|
|
77671
77748
|
class ContentLogger {
|
|
@@ -77674,7 +77751,7 @@ class ContentLogger {
|
|
|
77674
77751
|
logDir;
|
|
77675
77752
|
maxBytes;
|
|
77676
77753
|
constructor(maxBytes = 0) {
|
|
77677
|
-
this.logDir = join163(
|
|
77754
|
+
this.logDir = join163(homedir56(), ".claudekit", "logs");
|
|
77678
77755
|
this.maxBytes = maxBytes;
|
|
77679
77756
|
}
|
|
77680
77757
|
init() {
|
|
@@ -79285,11 +79362,11 @@ var init_setup_wizard = __esm(() => {
|
|
|
79285
79362
|
|
|
79286
79363
|
// src/commands/content/content-review-commands.ts
|
|
79287
79364
|
import { existsSync as existsSync86 } from "node:fs";
|
|
79288
|
-
import { homedir as
|
|
79365
|
+
import { homedir as homedir57 } from "node:os";
|
|
79289
79366
|
async function queueContent() {
|
|
79290
79367
|
const cwd2 = process.cwd();
|
|
79291
79368
|
const config = await loadContentConfig(cwd2);
|
|
79292
|
-
const dbPath = config.dbPath.replace(/^~/,
|
|
79369
|
+
const dbPath = config.dbPath.replace(/^~/, homedir57());
|
|
79293
79370
|
if (!existsSync86(dbPath)) {
|
|
79294
79371
|
logger.info("No content database found. Run 'ck content setup' first.");
|
|
79295
79372
|
return;
|
|
@@ -79316,7 +79393,7 @@ async function queueContent() {
|
|
|
79316
79393
|
async function approveContentCmd(id) {
|
|
79317
79394
|
const cwd2 = process.cwd();
|
|
79318
79395
|
const config = await loadContentConfig(cwd2);
|
|
79319
|
-
const dbPath = config.dbPath.replace(/^~/,
|
|
79396
|
+
const dbPath = config.dbPath.replace(/^~/, homedir57());
|
|
79320
79397
|
const db = initDatabase(dbPath);
|
|
79321
79398
|
try {
|
|
79322
79399
|
approveContent(db, Number.parseInt(id, 10));
|
|
@@ -79328,7 +79405,7 @@ async function approveContentCmd(id) {
|
|
|
79328
79405
|
async function rejectContentCmd(id, reason) {
|
|
79329
79406
|
const cwd2 = process.cwd();
|
|
79330
79407
|
const config = await loadContentConfig(cwd2);
|
|
79331
|
-
const dbPath = config.dbPath.replace(/^~/,
|
|
79408
|
+
const dbPath = config.dbPath.replace(/^~/, homedir57());
|
|
79332
79409
|
const db = initDatabase(dbPath);
|
|
79333
79410
|
try {
|
|
79334
79411
|
rejectContent(db, Number.parseInt(id, 10), reason);
|
|
@@ -79359,7 +79436,7 @@ __export(exports_content_subcommands, {
|
|
|
79359
79436
|
approveContentCmd: () => approveContentCmd
|
|
79360
79437
|
});
|
|
79361
79438
|
import { existsSync as existsSync87, readFileSync as readFileSync22, unlinkSync as unlinkSync6 } from "node:fs";
|
|
79362
|
-
import { homedir as
|
|
79439
|
+
import { homedir as homedir58 } from "node:os";
|
|
79363
79440
|
import { join as join168 } from "node:path";
|
|
79364
79441
|
function isDaemonRunning() {
|
|
79365
79442
|
const lockFile = join168(LOCK_DIR, `${LOCK_NAME2}.lock`);
|
|
@@ -79433,7 +79510,7 @@ async function statusContent() {
|
|
|
79433
79510
|
} catch {}
|
|
79434
79511
|
}
|
|
79435
79512
|
async function logsContent(options2) {
|
|
79436
|
-
const logDir = join168(
|
|
79513
|
+
const logDir = join168(homedir58(), ".claudekit", "logs");
|
|
79437
79514
|
const dateStr = new Date().toISOString().slice(0, 10).replace(/-/g, "");
|
|
79438
79515
|
const logPath = join168(logDir, `content-${dateStr}.log`);
|
|
79439
79516
|
if (!existsSync87(logPath)) {
|
|
@@ -79467,12 +79544,12 @@ var init_content_subcommands = __esm(() => {
|
|
|
79467
79544
|
init_setup_wizard();
|
|
79468
79545
|
init_state_manager();
|
|
79469
79546
|
init_content_review_commands();
|
|
79470
|
-
LOCK_DIR = join168(
|
|
79547
|
+
LOCK_DIR = join168(homedir58(), ".claudekit", "locks");
|
|
79471
79548
|
});
|
|
79472
79549
|
|
|
79473
79550
|
// src/commands/content/content-command.ts
|
|
79474
79551
|
import { existsSync as existsSync88, mkdirSync as mkdirSync9, unlinkSync as unlinkSync7, writeFileSync as writeFileSync7 } from "node:fs";
|
|
79475
|
-
import { homedir as
|
|
79552
|
+
import { homedir as homedir59 } from "node:os";
|
|
79476
79553
|
import { join as join169 } from "node:path";
|
|
79477
79554
|
async function contentCommand(options2) {
|
|
79478
79555
|
const cwd2 = process.cwd();
|
|
@@ -79505,7 +79582,7 @@ async function contentCommand(options2) {
|
|
|
79505
79582
|
if (!existsSync88(LOCK_DIR2))
|
|
79506
79583
|
mkdirSync9(LOCK_DIR2, { recursive: true });
|
|
79507
79584
|
writeFileSync7(LOCK_FILE, String(process.pid), "utf-8");
|
|
79508
|
-
const dbPath = config.dbPath.replace(/^~/,
|
|
79585
|
+
const dbPath = config.dbPath.replace(/^~/, homedir59());
|
|
79509
79586
|
const db = initDatabase(dbPath);
|
|
79510
79587
|
contentLogger.info(`Database initialised at ${dbPath}`);
|
|
79511
79588
|
const adapters = initializeAdapters(config);
|
|
@@ -79651,7 +79728,7 @@ var init_content_command = __esm(() => {
|
|
|
79651
79728
|
init_publisher();
|
|
79652
79729
|
init_review_manager();
|
|
79653
79730
|
init_state_manager();
|
|
79654
|
-
LOCK_DIR2 = join169(
|
|
79731
|
+
LOCK_DIR2 = join169(homedir59(), ".claudekit", "locks");
|
|
79655
79732
|
LOCK_FILE = join169(LOCK_DIR2, "ck-content.lock");
|
|
79656
79733
|
});
|
|
79657
79734
|
|
|
@@ -82872,9 +82949,9 @@ var import_picocolors6 = __toESM(require_picocolors(), 1);
|
|
|
82872
82949
|
init_fm_to_json();
|
|
82873
82950
|
init_portable_registry();
|
|
82874
82951
|
init_provider_registry();
|
|
82875
|
-
import { existsSync as
|
|
82952
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
82876
82953
|
import { readFile as readFile6, rm, writeFile as writeFile4 } from "node:fs/promises";
|
|
82877
|
-
import { dirname as dirname4, join as
|
|
82954
|
+
import { dirname as dirname4, join as join8 } from "node:path";
|
|
82878
82955
|
function toSlug3(name) {
|
|
82879
82956
|
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
82880
82957
|
}
|
|
@@ -82994,7 +83071,7 @@ async function removeFromJsonMerge(agentName, filePath) {
|
|
|
82994
83071
|
const rulesDir = dirname4(filePath);
|
|
82995
83072
|
const ruleNames = new Set([`${agentName}.md`, `${slug}.md`]);
|
|
82996
83073
|
for (const ruleName of ruleNames) {
|
|
82997
|
-
await rm(
|
|
83074
|
+
await rm(join8(rulesDir, ruleName), { force: true });
|
|
82998
83075
|
}
|
|
82999
83076
|
if (filtered.length === 0) {
|
|
83000
83077
|
await rm(filePath, { force: true });
|
|
@@ -83024,7 +83101,7 @@ async function uninstallAgentFromProvider(agentName, provider, global2) {
|
|
|
83024
83101
|
};
|
|
83025
83102
|
}
|
|
83026
83103
|
const installation = installations[0];
|
|
83027
|
-
const fileExists =
|
|
83104
|
+
const fileExists = existsSync7(installation.path);
|
|
83028
83105
|
try {
|
|
83029
83106
|
const config = providers[provider];
|
|
83030
83107
|
const pathConfig = config.agents;
|
|
@@ -83113,8 +83190,8 @@ async function forceUninstallAgentFromProvider(agentName, provider, global2) {
|
|
|
83113
83190
|
};
|
|
83114
83191
|
}
|
|
83115
83192
|
const writeStrategy = pathConfig.writeStrategy;
|
|
83116
|
-
const targetPath = writeStrategy === "json-merge" ?
|
|
83117
|
-
const fileExists =
|
|
83193
|
+
const targetPath = writeStrategy === "json-merge" ? join8(basePath, "cline_custom_modes.json") : writeStrategy === "merge-single" || writeStrategy === "yaml-merge" || writeStrategy === "single-file" ? basePath : join8(basePath, `${agentName}${pathConfig.fileExtension}`);
|
|
83194
|
+
const fileExists = existsSync7(targetPath);
|
|
83118
83195
|
try {
|
|
83119
83196
|
if (!fileExists) {
|
|
83120
83197
|
return {
|
|
@@ -83633,7 +83710,7 @@ var import_picocolors8 = __toESM(require_picocolors(), 1);
|
|
|
83633
83710
|
|
|
83634
83711
|
// src/domains/claudekit-api/index.ts
|
|
83635
83712
|
import { homedir as homedir7 } from "node:os";
|
|
83636
|
-
import { join as
|
|
83713
|
+
import { join as join10 } from "node:path";
|
|
83637
83714
|
|
|
83638
83715
|
// src/domains/api-key/validator.ts
|
|
83639
83716
|
var API_BASE_URL = "https://claudekit.cc/api";
|
|
@@ -83680,20 +83757,20 @@ function isValidKeyFormat(key) {
|
|
|
83680
83757
|
return /^ck_live_[A-Za-z0-9_-]{32}$/.test(key);
|
|
83681
83758
|
}
|
|
83682
83759
|
// src/domains/api-key/storage.ts
|
|
83683
|
-
import { existsSync as
|
|
83684
|
-
import { join as
|
|
83760
|
+
import { existsSync as existsSync8, readFileSync as readFileSync4, writeFileSync } from "node:fs";
|
|
83761
|
+
import { join as join9 } from "node:path";
|
|
83685
83762
|
var ENV_FILE = ".env";
|
|
83686
83763
|
var API_KEY_VAR = "CLAUDEKIT_API_KEY";
|
|
83687
83764
|
function getEnvFilePath(claudeDir) {
|
|
83688
|
-
return
|
|
83765
|
+
return join9(claudeDir, ENV_FILE);
|
|
83689
83766
|
}
|
|
83690
83767
|
function readExistingApiKey(claudeDir) {
|
|
83691
83768
|
const envPath = getEnvFilePath(claudeDir);
|
|
83692
|
-
if (!
|
|
83769
|
+
if (!existsSync8(envPath)) {
|
|
83693
83770
|
return null;
|
|
83694
83771
|
}
|
|
83695
83772
|
try {
|
|
83696
|
-
const content =
|
|
83773
|
+
const content = readFileSync4(envPath, "utf-8");
|
|
83697
83774
|
const match = content.match(new RegExp(`^${API_KEY_VAR}=(.+)$`, "m"));
|
|
83698
83775
|
return match?.[1]?.trim() ?? null;
|
|
83699
83776
|
} catch {
|
|
@@ -83703,8 +83780,8 @@ function readExistingApiKey(claudeDir) {
|
|
|
83703
83780
|
function saveApiKey(claudeDir, apiKey) {
|
|
83704
83781
|
const envPath = getEnvFilePath(claudeDir);
|
|
83705
83782
|
let content = "";
|
|
83706
|
-
if (
|
|
83707
|
-
content =
|
|
83783
|
+
if (existsSync8(envPath)) {
|
|
83784
|
+
content = readFileSync4(envPath, "utf-8");
|
|
83708
83785
|
if (content.includes(`${API_KEY_VAR}=`)) {
|
|
83709
83786
|
content = content.replace(new RegExp(`^${API_KEY_VAR}=.*$`, "m"), `${API_KEY_VAR}=${apiKey}`);
|
|
83710
83787
|
} else {
|
|
@@ -83860,7 +83937,7 @@ class ClaudekitHttpClient {
|
|
|
83860
83937
|
} catch (error) {
|
|
83861
83938
|
if (error instanceof CkApiError && error.code === "RATE_LIMIT_EXCEEDED" && error.retryAfter) {
|
|
83862
83939
|
const delayMs = error.retryAfter * 1000;
|
|
83863
|
-
await new Promise((
|
|
83940
|
+
await new Promise((resolve5) => setTimeout(resolve5, delayMs));
|
|
83864
83941
|
return fn();
|
|
83865
83942
|
}
|
|
83866
83943
|
throw error;
|
|
@@ -83870,7 +83947,7 @@ class ClaudekitHttpClient {
|
|
|
83870
83947
|
|
|
83871
83948
|
// src/domains/claudekit-api/index.ts
|
|
83872
83949
|
function createApiClient(claudeDir) {
|
|
83873
|
-
const dir = claudeDir ??
|
|
83950
|
+
const dir = claudeDir ?? join10(homedir7(), ".claude");
|
|
83874
83951
|
const apiKey = readExistingApiKey(dir);
|
|
83875
83952
|
if (!apiKey) {
|
|
83876
83953
|
throw new CkApiError("MISSING_API_KEY", "No API key found. Run `ck api setup` to configure your ClaudeKit API key.", 401);
|
|
@@ -84301,13 +84378,13 @@ async function handleApiServices(options2) {
|
|
|
84301
84378
|
|
|
84302
84379
|
// src/commands/api/subcommands/api-setup-handler.ts
|
|
84303
84380
|
import { homedir as homedir8 } from "node:os";
|
|
84304
|
-
import { join as
|
|
84381
|
+
import { join as join11 } from "node:path";
|
|
84305
84382
|
init_logger();
|
|
84306
84383
|
init_dist2();
|
|
84307
84384
|
var DASHBOARD_URL = "https://claudekit.cc/api-keys";
|
|
84308
84385
|
var MAX_ATTEMPTS = 3;
|
|
84309
84386
|
async function handleApiSetup(options2) {
|
|
84310
|
-
const claudeDir =
|
|
84387
|
+
const claudeDir = join11(homedir8(), ".claude");
|
|
84311
84388
|
const existing = readExistingApiKey(claudeDir);
|
|
84312
84389
|
if (existing && !options2.force) {
|
|
84313
84390
|
const masked = `${existing.slice(0, 15)}...`;
|
|
@@ -88291,7 +88368,7 @@ init_logger();
|
|
|
88291
88368
|
init_path_resolver();
|
|
88292
88369
|
import { existsSync as existsSync58 } from "node:fs";
|
|
88293
88370
|
import { readFile as readFile42 } from "node:fs/promises";
|
|
88294
|
-
import { homedir as
|
|
88371
|
+
import { homedir as homedir42 } from "node:os";
|
|
88295
88372
|
import { dirname as dirname31, join as join80, normalize as normalize6, resolve as resolve36 } from "node:path";
|
|
88296
88373
|
async function checkPathRefsValid(projectDir) {
|
|
88297
88374
|
const globalClaudeMd = join80(PathResolver.getGlobalKitDir(), "CLAUDE.md");
|
|
@@ -88324,7 +88401,7 @@ async function checkPathRefsValid(projectDir) {
|
|
|
88324
88401
|
};
|
|
88325
88402
|
}
|
|
88326
88403
|
const baseDir = dirname31(claudeMdPath);
|
|
88327
|
-
const home5 =
|
|
88404
|
+
const home5 = homedir42();
|
|
88328
88405
|
const broken = [];
|
|
88329
88406
|
for (const ref of refs) {
|
|
88330
88407
|
let refPath;
|
|
@@ -89328,7 +89405,7 @@ import { platform as platform8 } from "node:os";
|
|
|
89328
89405
|
init_environment();
|
|
89329
89406
|
init_path_resolver();
|
|
89330
89407
|
import { constants as constants3, access as access4, mkdir as mkdir21, readFile as readFile44, unlink as unlink11, writeFile as writeFile21 } from "node:fs/promises";
|
|
89331
|
-
import { arch as arch2, homedir as
|
|
89408
|
+
import { arch as arch2, homedir as homedir43, platform as platform7 } from "node:os";
|
|
89332
89409
|
import { join as join85, normalize as normalize7 } from "node:path";
|
|
89333
89410
|
function shouldSkipExpensiveOperations4() {
|
|
89334
89411
|
return shouldSkipExpensiveOperations();
|
|
@@ -89351,7 +89428,7 @@ async function checkPlatformDetect() {
|
|
|
89351
89428
|
};
|
|
89352
89429
|
}
|
|
89353
89430
|
async function checkHomeDirResolution() {
|
|
89354
|
-
const nodeHome = normalize7(
|
|
89431
|
+
const nodeHome = normalize7(homedir43());
|
|
89355
89432
|
const rawEnvHome = getHomeDirectoryFromEnv(platform7());
|
|
89356
89433
|
const envHome = rawEnvHome ? normalize7(rawEnvHome) : "";
|
|
89357
89434
|
const match = nodeHome === envHome && envHome !== "";
|
|
@@ -103436,7 +103513,7 @@ class FileScanner {
|
|
|
103436
103513
|
|
|
103437
103514
|
// src/domains/installation/merger/settings-processor.ts
|
|
103438
103515
|
import { execSync as execSync5 } from "node:child_process";
|
|
103439
|
-
import { homedir as
|
|
103516
|
+
import { homedir as homedir45 } from "node:os";
|
|
103440
103517
|
import { dirname as dirname39, join as join109 } from "node:path";
|
|
103441
103518
|
|
|
103442
103519
|
// src/domains/config/installed-settings-tracker.ts
|
|
@@ -104053,7 +104130,7 @@ class SettingsProcessor {
|
|
|
104053
104130
|
return false;
|
|
104054
104131
|
}
|
|
104055
104132
|
const configuredGlobalDir = PathResolver.getGlobalKitDir().replace(/\\/g, "/").replace(/\/+$/, "");
|
|
104056
|
-
const defaultGlobalDir = join109(
|
|
104133
|
+
const defaultGlobalDir = join109(homedir45(), ".claude").replace(/\\/g, "/");
|
|
104057
104134
|
return configuredGlobalDir !== defaultGlobalDir;
|
|
104058
104135
|
}
|
|
104059
104136
|
getClaudeCommandRoot() {
|
|
@@ -107750,7 +107827,7 @@ async function handleFreshInstallation(claudeDir3, prompts) {
|
|
|
107750
107827
|
// src/domains/installation/global-kit-legacy-repair.ts
|
|
107751
107828
|
var import_fs_extra35 = __toESM(require_lib(), 1);
|
|
107752
107829
|
import { cp as cp5, mkdir as mkdir35, readdir as readdir42, rename as rename11, rm as rm16, stat as stat22 } from "node:fs/promises";
|
|
107753
|
-
import { homedir as
|
|
107830
|
+
import { homedir as homedir46 } from "node:os";
|
|
107754
107831
|
import { dirname as dirname42, join as join133, normalize as normalize11, resolve as resolve46 } from "node:path";
|
|
107755
107832
|
var LEGACY_KIT_MARKERS = [
|
|
107756
107833
|
"metadata.json",
|
|
@@ -107785,7 +107862,7 @@ function uniqueNormalizedPaths(paths) {
|
|
|
107785
107862
|
}
|
|
107786
107863
|
return result;
|
|
107787
107864
|
}
|
|
107788
|
-
function getLegacyWindowsGlobalKitDirCandidates(env2 = process.env, homeDir =
|
|
107865
|
+
function getLegacyWindowsGlobalKitDirCandidates(env2 = process.env, homeDir = homedir46()) {
|
|
107789
107866
|
const candidates = [];
|
|
107790
107867
|
const localAppData = safeEnvPath(env2.LOCALAPPDATA);
|
|
107791
107868
|
const appData = safeEnvPath(env2.APPDATA);
|
|
@@ -108918,7 +108995,7 @@ async function transformFolderPaths(extractDir, folders, options2 = {}) {
|
|
|
108918
108995
|
// src/services/transformers/global-path-transformer.ts
|
|
108919
108996
|
init_logger();
|
|
108920
108997
|
import { readFile as readFile61, readdir as readdir44, writeFile as writeFile35 } from "node:fs/promises";
|
|
108921
|
-
import { homedir as
|
|
108998
|
+
import { homedir as homedir47, platform as platform15 } from "node:os";
|
|
108922
108999
|
import { extname as extname7, join as join138 } from "node:path";
|
|
108923
109000
|
var IS_WINDOWS3 = platform15() === "win32";
|
|
108924
109001
|
var HOME_PREFIX = "$HOME";
|
|
@@ -108929,7 +109006,7 @@ function normalizeInstallPath(path17) {
|
|
|
108929
109006
|
return path17.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
108930
109007
|
}
|
|
108931
109008
|
function getDefaultGlobalClaudeDir() {
|
|
108932
|
-
return normalizeInstallPath(join138(
|
|
109009
|
+
return normalizeInstallPath(join138(homedir47(), ".claude"));
|
|
108933
109010
|
}
|
|
108934
109011
|
function getCustomGlobalClaudeDir(targetClaudeDir) {
|
|
108935
109012
|
if (!targetClaudeDir)
|
|
@@ -109361,13 +109438,13 @@ init_dist2();
|
|
|
109361
109438
|
var import_picocolors30 = __toESM(require_picocolors(), 1);
|
|
109362
109439
|
import { existsSync as existsSync68 } from "node:fs";
|
|
109363
109440
|
import { readFile as readFile65, rm as rm18, unlink as unlink14 } from "node:fs/promises";
|
|
109364
|
-
import { homedir as
|
|
109441
|
+
import { homedir as homedir52 } from "node:os";
|
|
109365
109442
|
import { basename as basename30, join as join143, resolve as resolve50 } from "node:path";
|
|
109366
109443
|
init_logger();
|
|
109367
109444
|
|
|
109368
109445
|
// src/ui/ck-cli-design/tokens.ts
|
|
109369
109446
|
var import_picocolors27 = __toESM(require_picocolors(), 1);
|
|
109370
|
-
import { homedir as
|
|
109447
|
+
import { homedir as homedir48, platform as platform16 } from "node:os";
|
|
109371
109448
|
import { resolve as resolve49, win32 as win322 } from "node:path";
|
|
109372
109449
|
var PANEL_MIN_WIDTH = 60;
|
|
109373
109450
|
var PANEL_MAX_WIDTH = 72;
|
|
@@ -109525,7 +109602,7 @@ function wrapText(value, width) {
|
|
|
109525
109602
|
}
|
|
109526
109603
|
function formatDisplayPath(value) {
|
|
109527
109604
|
const normalized = value.replace(/\\/g, "/");
|
|
109528
|
-
const home5 =
|
|
109605
|
+
const home5 = homedir48().replace(/\\/g, "/");
|
|
109529
109606
|
if (normalized === home5)
|
|
109530
109607
|
return "~";
|
|
109531
109608
|
if (normalized.startsWith(`${home5}/`)) {
|
|
@@ -109839,13 +109916,13 @@ init_logger();
|
|
|
109839
109916
|
init_dist2();
|
|
109840
109917
|
init_model_taxonomy();
|
|
109841
109918
|
import { mkdir as mkdir39, readFile as readFile64, writeFile as writeFile37 } from "node:fs/promises";
|
|
109842
|
-
import { homedir as
|
|
109919
|
+
import { homedir as homedir51 } from "node:os";
|
|
109843
109920
|
import { dirname as dirname44, join as join142 } from "node:path";
|
|
109844
109921
|
|
|
109845
109922
|
// src/commands/portable/models-dev-cache.ts
|
|
109846
109923
|
init_logger();
|
|
109847
109924
|
import { mkdir as mkdir38, readFile as readFile62, rename as rename14, writeFile as writeFile36 } from "node:fs/promises";
|
|
109848
|
-
import { homedir as
|
|
109925
|
+
import { homedir as homedir49 } from "node:os";
|
|
109849
109926
|
import { join as join140 } from "node:path";
|
|
109850
109927
|
|
|
109851
109928
|
class ModelsDevUnavailableError extends Error {
|
|
@@ -109858,7 +109935,7 @@ var MODELS_DEV_URL = "https://models.dev/api.json";
|
|
|
109858
109935
|
var CACHE_TTL_MS3 = 24 * 60 * 60 * 1000;
|
|
109859
109936
|
var FETCH_TIMEOUT_MS = 1e4;
|
|
109860
109937
|
function defaultCacheDir() {
|
|
109861
|
-
return join140(
|
|
109938
|
+
return join140(homedir49(), ".config", "claudekit", "cache");
|
|
109862
109939
|
}
|
|
109863
109940
|
function cacheFilePath(cacheDir) {
|
|
109864
109941
|
return join140(cacheDir, "models-dev.json");
|
|
@@ -109938,7 +110015,7 @@ async function getModelsDevCatalog(opts = {}) {
|
|
|
109938
110015
|
// src/commands/portable/opencode-model-discovery.ts
|
|
109939
110016
|
init_logger();
|
|
109940
110017
|
import { readFile as readFile63 } from "node:fs/promises";
|
|
109941
|
-
import { homedir as
|
|
110018
|
+
import { homedir as homedir50, platform as platform17 } from "node:os";
|
|
109942
110019
|
import { join as join141 } from "node:path";
|
|
109943
110020
|
function resolveOpenCodeAuthPath(homeDir) {
|
|
109944
110021
|
if (platform17() === "win32") {
|
|
@@ -109984,7 +110061,7 @@ function pickGenericModel(models) {
|
|
|
109984
110061
|
return sorted[0] ?? null;
|
|
109985
110062
|
}
|
|
109986
110063
|
async function resolveOpenCodeDefaultModel(opts = {}) {
|
|
109987
|
-
const home5 = opts.homeDir ??
|
|
110064
|
+
const home5 = opts.homeDir ?? homedir50();
|
|
109988
110065
|
const authedProviders = await readAuthedProviders(home5);
|
|
109989
110066
|
if (authedProviders.length === 0) {
|
|
109990
110067
|
return { ok: false, reason: "no-auth", authedProviders: [] };
|
|
@@ -110048,7 +110125,7 @@ function messageForReason(reason) {
|
|
|
110048
110125
|
}
|
|
110049
110126
|
function getOpenCodeConfigPath(options2) {
|
|
110050
110127
|
if (options2.global) {
|
|
110051
|
-
return join142(options2.homeDir ??
|
|
110128
|
+
return join142(options2.homeDir ?? homedir51(), ".config", "opencode", "opencode.json");
|
|
110052
110129
|
}
|
|
110053
110130
|
return join142(options2.cwd ?? process.cwd(), "opencode.json");
|
|
110054
110131
|
}
|
|
@@ -111055,7 +111132,7 @@ async function processMetadataDeletions(skillSourcePath, installGlobally) {
|
|
|
111055
111132
|
}
|
|
111056
111133
|
if (!sourceMetadata.deletions || sourceMetadata.deletions.length === 0)
|
|
111057
111134
|
return;
|
|
111058
|
-
const claudeDir3 = installGlobally ? join143(
|
|
111135
|
+
const claudeDir3 = installGlobally ? join143(homedir52(), ".claude") : join143(process.cwd(), ".claude");
|
|
111059
111136
|
if (!existsSync68(claudeDir3))
|
|
111060
111137
|
return;
|
|
111061
111138
|
try {
|
|
@@ -111184,7 +111261,7 @@ async function migrateCommand(options2) {
|
|
|
111184
111261
|
let installGlobally = requestedGlobal;
|
|
111185
111262
|
if (options2.global === undefined && !options2.yes) {
|
|
111186
111263
|
const projectTarget = join143(process.cwd(), ".claude");
|
|
111187
|
-
const globalTarget = join143(
|
|
111264
|
+
const globalTarget = join143(homedir52(), ".claude");
|
|
111188
111265
|
const scopeChoice = await ie({
|
|
111189
111266
|
message: "Installation scope",
|
|
111190
111267
|
options: [
|
|
@@ -111257,7 +111334,7 @@ async function migrateCommand(options2) {
|
|
|
111257
111334
|
}).join(`
|
|
111258
111335
|
`));
|
|
111259
111336
|
if (sourceGlobalOnly) {
|
|
111260
|
-
f2.info(import_picocolors30.default.dim(` Scope: global (--global / -g) - reading from ${formatDisplayPath(join143(
|
|
111337
|
+
f2.info(import_picocolors30.default.dim(` Scope: global (--global / -g) - reading from ${formatDisplayPath(join143(homedir52(), ".claude"))}`));
|
|
111261
111338
|
} else {
|
|
111262
111339
|
f2.info(import_picocolors30.default.dim(` CWD: ${process.cwd()}`));
|
|
111263
111340
|
}
|
|
@@ -116286,7 +116363,7 @@ async function scanForRepos(parentDir) {
|
|
|
116286
116363
|
init_logger();
|
|
116287
116364
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
116288
116365
|
import { existsSync as existsSync76 } from "node:fs";
|
|
116289
|
-
import { homedir as
|
|
116366
|
+
import { homedir as homedir53 } from "node:os";
|
|
116290
116367
|
import { join as join157 } from "node:path";
|
|
116291
116368
|
async function validateSetup(cwd2) {
|
|
116292
116369
|
const workDir = cwd2 ?? process.cwd();
|
|
@@ -116318,7 +116395,7 @@ Run this command from a directory with a GitHub remote.`);
|
|
|
116318
116395
|
} catch {
|
|
116319
116396
|
throw new Error(`Failed to parse repository info: ${ghRepo.stdout}`);
|
|
116320
116397
|
}
|
|
116321
|
-
const skillsPath = join157(
|
|
116398
|
+
const skillsPath = join157(homedir53(), ".claude", "skills");
|
|
116322
116399
|
const skillsAvailable = existsSync76(skillsPath);
|
|
116323
116400
|
if (!skillsAvailable) {
|
|
116324
116401
|
logger.warning(`ClaudeKit Engineer skills not found at ${skillsPath}`);
|