claudekit-cli 3.34.1-dev.5 → 3.34.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js
CHANGED
|
@@ -29190,10 +29190,8 @@ var init_ck_config = __esm(() => {
|
|
|
29190
29190
|
CkHooksConfigSchema = exports_external.object({
|
|
29191
29191
|
"session-init": exports_external.boolean().optional(),
|
|
29192
29192
|
"subagent-init": exports_external.boolean().optional(),
|
|
29193
|
-
"descriptive-name": exports_external.boolean().optional(),
|
|
29194
29193
|
"dev-rules-reminder": exports_external.boolean().optional(),
|
|
29195
29194
|
"usage-context-awareness": exports_external.boolean().optional(),
|
|
29196
|
-
"context-tracking": exports_external.boolean().optional(),
|
|
29197
29195
|
"scout-block": exports_external.boolean().optional(),
|
|
29198
29196
|
"privacy-block": exports_external.boolean().optional(),
|
|
29199
29197
|
"post-edit-simplify-reminder": exports_external.boolean().optional()
|
|
@@ -29266,10 +29264,8 @@ var init_ck_config = __esm(() => {
|
|
|
29266
29264
|
hooks: {
|
|
29267
29265
|
"session-init": true,
|
|
29268
29266
|
"subagent-init": true,
|
|
29269
|
-
"descriptive-name": true,
|
|
29270
29267
|
"dev-rules-reminder": true,
|
|
29271
29268
|
"usage-context-awareness": true,
|
|
29272
|
-
"context-tracking": true,
|
|
29273
29269
|
"scout-block": true,
|
|
29274
29270
|
"privacy-block": true,
|
|
29275
29271
|
"post-edit-simplify-reminder": true
|
|
@@ -29278,10 +29274,8 @@ var init_ck_config = __esm(() => {
|
|
|
29278
29274
|
CK_HOOK_NAMES = [
|
|
29279
29275
|
"session-init",
|
|
29280
29276
|
"subagent-init",
|
|
29281
|
-
"descriptive-name",
|
|
29282
29277
|
"dev-rules-reminder",
|
|
29283
29278
|
"usage-context-awareness",
|
|
29284
|
-
"context-tracking",
|
|
29285
29279
|
"scout-block",
|
|
29286
29280
|
"privacy-block",
|
|
29287
29281
|
"post-edit-simplify-reminder"
|
|
@@ -29562,9 +29556,6 @@ function getNestedValue(obj, path2) {
|
|
|
29562
29556
|
}
|
|
29563
29557
|
function setNestedValue(obj, path2, value) {
|
|
29564
29558
|
const keys = path2.split(".");
|
|
29565
|
-
if (keys.some((k) => DANGEROUS_KEYS.includes(k))) {
|
|
29566
|
-
throw new Error("Invalid field path: dangerous key detected");
|
|
29567
|
-
}
|
|
29568
29559
|
let current = obj;
|
|
29569
29560
|
for (let i = 0;i < keys.length - 1; i++) {
|
|
29570
29561
|
const key = keys[i];
|
|
@@ -29578,8 +29569,6 @@ function setNestedValue(obj, path2, value) {
|
|
|
29578
29569
|
function deepMerge(target, source) {
|
|
29579
29570
|
const result = { ...target };
|
|
29580
29571
|
for (const key of Object.keys(source)) {
|
|
29581
|
-
if (DANGEROUS_KEYS.includes(key))
|
|
29582
|
-
continue;
|
|
29583
29572
|
const sourceVal = source[key];
|
|
29584
29573
|
const targetVal = result[key];
|
|
29585
29574
|
if (sourceVal !== null && typeof sourceVal === "object" && !Array.isArray(sourceVal) && targetVal !== null && typeof targetVal === "object" && !Array.isArray(targetVal)) {
|
|
@@ -29718,10 +29707,6 @@ class CkConfigManager {
|
|
|
29718
29707
|
return null;
|
|
29719
29708
|
return CkConfigManager.loadConfigFile(CkConfigManager.getProjectConfigPath(projectDir));
|
|
29720
29709
|
}
|
|
29721
|
-
static projectConfigExists(dir, isGlobal) {
|
|
29722
|
-
const configPath = isGlobal ? join3(dir, ".ck.json") : CkConfigManager.getProjectConfigPath(dir);
|
|
29723
|
-
return existsSync3(configPath);
|
|
29724
|
-
}
|
|
29725
29710
|
static configExists(scope, projectDir) {
|
|
29726
29711
|
if (scope === "global") {
|
|
29727
29712
|
return existsSync3(CkConfigManager.getGlobalConfigPath());
|
|
@@ -29742,11 +29727,10 @@ class CkConfigManager {
|
|
|
29742
29727
|
await CkConfigManager.saveFull(existing, scope, projectDir);
|
|
29743
29728
|
}
|
|
29744
29729
|
}
|
|
29745
|
-
var CK_CONFIG_FILE = ".ck.json"
|
|
29730
|
+
var CK_CONFIG_FILE = ".ck.json";
|
|
29746
29731
|
var init_ck_config_manager = __esm(() => {
|
|
29747
29732
|
init_logger();
|
|
29748
29733
|
init_types2();
|
|
29749
|
-
DANGEROUS_KEYS = ["__proto__", "constructor", "prototype"];
|
|
29750
29734
|
});
|
|
29751
29735
|
|
|
29752
29736
|
// src/shared/environment.ts
|
|
@@ -38125,12 +38109,17 @@ class FileWatcher {
|
|
|
38125
38109
|
if (this.isConfigFile(path2)) {
|
|
38126
38110
|
try {
|
|
38127
38111
|
const scope = this.getConfigScope(path2);
|
|
38128
|
-
|
|
38129
|
-
|
|
38130
|
-
|
|
38112
|
+
let config;
|
|
38113
|
+
if (scope === "global") {
|
|
38114
|
+
ConfigManager.setGlobalFlag(true);
|
|
38115
|
+
config = await ConfigManager.load();
|
|
38116
|
+
} else {
|
|
38117
|
+
const projectConfig = await ConfigManager.loadProjectConfig(process.cwd(), false);
|
|
38118
|
+
config = projectConfig ? { paths: projectConfig } : {};
|
|
38119
|
+
}
|
|
38131
38120
|
this.wsManager.broadcast({
|
|
38132
38121
|
type: "config:updated",
|
|
38133
|
-
payload: { scope, config
|
|
38122
|
+
payload: { scope, config }
|
|
38134
38123
|
});
|
|
38135
38124
|
} catch (error) {
|
|
38136
38125
|
logger.error(`Failed to reload config: ${error}`);
|
|
@@ -38888,9 +38877,6 @@ var init_projects_registry = __esm(() => {
|
|
|
38888
38877
|
});
|
|
38889
38878
|
|
|
38890
38879
|
// src/domains/web-server/routes/ck-config-routes.ts
|
|
38891
|
-
import { existsSync as existsSync6 } from "node:fs";
|
|
38892
|
-
import { readFile as readFile5 } from "node:fs/promises";
|
|
38893
|
-
import { join as join9 } from "node:path";
|
|
38894
38880
|
async function resolveProjectDir(projectId) {
|
|
38895
38881
|
if (!projectId)
|
|
38896
38882
|
return null;
|
|
@@ -39013,6 +38999,92 @@ function registerCkConfigRoutes(app) {
|
|
|
39013
38999
|
res.status(500).json({ error: "Failed to update field" });
|
|
39014
39000
|
}
|
|
39015
39001
|
});
|
|
39002
|
+
}
|
|
39003
|
+
var init_ck_config_routes = __esm(() => {
|
|
39004
|
+
init_config();
|
|
39005
|
+
init_ck_config_schema();
|
|
39006
|
+
init_logger();
|
|
39007
|
+
init_types2();
|
|
39008
|
+
});
|
|
39009
|
+
|
|
39010
|
+
// src/domains/web-server/routes/config-routes.ts
|
|
39011
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
39012
|
+
import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile6 } from "node:fs/promises";
|
|
39013
|
+
import { join as join9 } from "node:path";
|
|
39014
|
+
function registerConfigRoutes(app) {
|
|
39015
|
+
app.get("/api/config", async (_req, res) => {
|
|
39016
|
+
try {
|
|
39017
|
+
const projectDir = process.cwd();
|
|
39018
|
+
const globalConfigPath = getEngineerKitConfigPath();
|
|
39019
|
+
let globalConfig = {};
|
|
39020
|
+
if (existsSync6(globalConfigPath)) {
|
|
39021
|
+
const content = await readFile5(globalConfigPath, "utf-8");
|
|
39022
|
+
try {
|
|
39023
|
+
globalConfig = JSON.parse(content);
|
|
39024
|
+
} catch {}
|
|
39025
|
+
}
|
|
39026
|
+
const localConfig = await ConfigManager.loadProjectConfig(projectDir, false);
|
|
39027
|
+
const merged = deepMerge2(globalConfig, localConfig ? { paths: localConfig } : {});
|
|
39028
|
+
const response = {
|
|
39029
|
+
global: globalConfig,
|
|
39030
|
+
local: localConfig ? { paths: localConfig } : null,
|
|
39031
|
+
merged
|
|
39032
|
+
};
|
|
39033
|
+
res.json(response);
|
|
39034
|
+
} catch (error) {
|
|
39035
|
+
logger.error(`Failed to load config: ${error}`);
|
|
39036
|
+
res.status(500).json({ error: "Failed to load configuration" });
|
|
39037
|
+
}
|
|
39038
|
+
});
|
|
39039
|
+
app.get("/api/config/global", async (_req, res) => {
|
|
39040
|
+
try {
|
|
39041
|
+
const globalConfigPath = getEngineerKitConfigPath();
|
|
39042
|
+
let config = {};
|
|
39043
|
+
if (existsSync6(globalConfigPath)) {
|
|
39044
|
+
const content = await readFile5(globalConfigPath, "utf-8");
|
|
39045
|
+
try {
|
|
39046
|
+
config = JSON.parse(content);
|
|
39047
|
+
} catch {}
|
|
39048
|
+
}
|
|
39049
|
+
res.json(config);
|
|
39050
|
+
} catch (error) {
|
|
39051
|
+
res.status(500).json({ error: "Failed to load global config" });
|
|
39052
|
+
}
|
|
39053
|
+
});
|
|
39054
|
+
app.get("/api/config/local", async (_req, res) => {
|
|
39055
|
+
try {
|
|
39056
|
+
const projectDir = process.cwd();
|
|
39057
|
+
const config = await ConfigManager.loadProjectConfig(projectDir, false);
|
|
39058
|
+
res.json(config ? { paths: config } : {});
|
|
39059
|
+
} catch (error) {
|
|
39060
|
+
res.status(500).json({ error: "Failed to load local config" });
|
|
39061
|
+
}
|
|
39062
|
+
});
|
|
39063
|
+
app.post("/api/config", async (req, res) => {
|
|
39064
|
+
try {
|
|
39065
|
+
const { scope = "local", config } = req.body;
|
|
39066
|
+
if (!config || typeof config !== "object") {
|
|
39067
|
+
res.status(400).json({ error: "Invalid config payload" });
|
|
39068
|
+
return;
|
|
39069
|
+
}
|
|
39070
|
+
if (scope === "global") {
|
|
39071
|
+
const globalConfigPath = getEngineerKitConfigPath();
|
|
39072
|
+
const globalDir = PathResolver.getGlobalKitDir();
|
|
39073
|
+
if (!existsSync6(globalDir)) {
|
|
39074
|
+
await mkdir4(globalDir, { recursive: true });
|
|
39075
|
+
}
|
|
39076
|
+
await writeFile6(globalConfigPath, JSON.stringify(config, null, 2), "utf-8");
|
|
39077
|
+
logger.debug(`Engineer kit config saved to ${globalConfigPath}`);
|
|
39078
|
+
} else {
|
|
39079
|
+
const projectDir = process.cwd();
|
|
39080
|
+
await ConfigManager.saveProjectConfig(projectDir, config.paths || config, false);
|
|
39081
|
+
}
|
|
39082
|
+
res.json({ success: true, scope });
|
|
39083
|
+
} catch (error) {
|
|
39084
|
+
logger.error(`Failed to save config: ${error}`);
|
|
39085
|
+
res.status(500).json({ error: "Failed to save configuration" });
|
|
39086
|
+
}
|
|
39087
|
+
});
|
|
39016
39088
|
app.get("/api/metadata/global", async (_req, res) => {
|
|
39017
39089
|
try {
|
|
39018
39090
|
const metadataPath = join9(PathResolver.getGlobalKitDir(), "metadata.json");
|
|
@@ -39021,9 +39093,7 @@ function registerCkConfigRoutes(app) {
|
|
|
39021
39093
|
const content = await readFile5(metadataPath, "utf-8");
|
|
39022
39094
|
try {
|
|
39023
39095
|
metadata = JSON.parse(content);
|
|
39024
|
-
} catch
|
|
39025
|
-
logger.warning(`Invalid JSON in metadata.json: ${err}`);
|
|
39026
|
-
}
|
|
39096
|
+
} catch {}
|
|
39027
39097
|
}
|
|
39028
39098
|
res.json(metadata);
|
|
39029
39099
|
} catch (error) {
|
|
@@ -39031,13 +39101,92 @@ function registerCkConfigRoutes(app) {
|
|
|
39031
39101
|
res.status(500).json({ error: "Failed to load metadata" });
|
|
39032
39102
|
}
|
|
39033
39103
|
});
|
|
39104
|
+
app.get("/api/config/project/:id", async (req, res) => {
|
|
39105
|
+
try {
|
|
39106
|
+
const id = String(req.params.id);
|
|
39107
|
+
let projectDir;
|
|
39108
|
+
if (id.startsWith("discovered-")) {
|
|
39109
|
+
const encodedPath = id.slice("discovered-".length);
|
|
39110
|
+
projectDir = Buffer.from(encodedPath, "base64url").toString("utf-8");
|
|
39111
|
+
} else {
|
|
39112
|
+
const { ProjectsRegistryManager: ProjectsRegistryManager2 } = await Promise.resolve().then(() => (init_projects_registry(), exports_projects_registry));
|
|
39113
|
+
const project = await ProjectsRegistryManager2.getProject(id);
|
|
39114
|
+
if (!project) {
|
|
39115
|
+
res.status(404).json({ error: "Project not found" });
|
|
39116
|
+
return;
|
|
39117
|
+
}
|
|
39118
|
+
projectDir = project.path;
|
|
39119
|
+
}
|
|
39120
|
+
const globalConfigPath = getEngineerKitConfigPath();
|
|
39121
|
+
let globalConfig = {};
|
|
39122
|
+
if (existsSync6(globalConfigPath)) {
|
|
39123
|
+
const content = await readFile5(globalConfigPath, "utf-8");
|
|
39124
|
+
try {
|
|
39125
|
+
globalConfig = JSON.parse(content);
|
|
39126
|
+
} catch {}
|
|
39127
|
+
}
|
|
39128
|
+
const localConfig = await ConfigManager.loadProjectConfig(projectDir, false);
|
|
39129
|
+
const merged = deepMerge2(globalConfig, localConfig ? { paths: localConfig } : {});
|
|
39130
|
+
const response = {
|
|
39131
|
+
global: globalConfig,
|
|
39132
|
+
local: localConfig ? { paths: localConfig } : null,
|
|
39133
|
+
merged
|
|
39134
|
+
};
|
|
39135
|
+
res.json(response);
|
|
39136
|
+
} catch (error) {
|
|
39137
|
+
logger.error(`Failed to load project config: ${error}`);
|
|
39138
|
+
res.status(500).json({ error: "Failed to load project configuration" });
|
|
39139
|
+
}
|
|
39140
|
+
});
|
|
39141
|
+
app.post("/api/config/project/:id", async (req, res) => {
|
|
39142
|
+
try {
|
|
39143
|
+
const id = String(req.params.id);
|
|
39144
|
+
const { config } = req.body;
|
|
39145
|
+
if (!config || typeof config !== "object") {
|
|
39146
|
+
res.status(400).json({ error: "Invalid config payload" });
|
|
39147
|
+
return;
|
|
39148
|
+
}
|
|
39149
|
+
let projectDir;
|
|
39150
|
+
if (id.startsWith("discovered-")) {
|
|
39151
|
+
const encodedPath = id.slice("discovered-".length);
|
|
39152
|
+
projectDir = Buffer.from(encodedPath, "base64url").toString("utf-8");
|
|
39153
|
+
} else {
|
|
39154
|
+
const { ProjectsRegistryManager: ProjectsRegistryManager2 } = await Promise.resolve().then(() => (init_projects_registry(), exports_projects_registry));
|
|
39155
|
+
const project = await ProjectsRegistryManager2.getProject(id);
|
|
39156
|
+
if (!project) {
|
|
39157
|
+
res.status(404).json({ error: "Project not found" });
|
|
39158
|
+
return;
|
|
39159
|
+
}
|
|
39160
|
+
projectDir = project.path;
|
|
39161
|
+
}
|
|
39162
|
+
await ConfigManager.saveProjectConfig(projectDir, config.paths || config, false);
|
|
39163
|
+
res.json({ success: true });
|
|
39164
|
+
} catch (error) {
|
|
39165
|
+
logger.error(`Failed to save project config: ${error}`);
|
|
39166
|
+
res.status(500).json({ error: "Failed to save project configuration" });
|
|
39167
|
+
}
|
|
39168
|
+
});
|
|
39034
39169
|
}
|
|
39035
|
-
|
|
39170
|
+
function deepMerge2(target, source) {
|
|
39171
|
+
const result = { ...target };
|
|
39172
|
+
const dangerousKeys = ["__proto__", "constructor", "prototype"];
|
|
39173
|
+
for (const key of Object.keys(source)) {
|
|
39174
|
+
if (dangerousKeys.includes(key))
|
|
39175
|
+
continue;
|
|
39176
|
+
const sourceVal = source[key];
|
|
39177
|
+
if (sourceVal && typeof sourceVal === "object" && !Array.isArray(sourceVal)) {
|
|
39178
|
+
result[key] = deepMerge2(result[key] || {}, sourceVal);
|
|
39179
|
+
} else {
|
|
39180
|
+
result[key] = sourceVal;
|
|
39181
|
+
}
|
|
39182
|
+
}
|
|
39183
|
+
return result;
|
|
39184
|
+
}
|
|
39185
|
+
var getEngineerKitConfigPath = () => join9(PathResolver.getGlobalKitDir(), ".ck.json");
|
|
39186
|
+
var init_config_routes = __esm(() => {
|
|
39036
39187
|
init_config();
|
|
39037
|
-
init_ck_config_schema();
|
|
39038
39188
|
init_logger();
|
|
39039
39189
|
init_path_resolver();
|
|
39040
|
-
init_types2();
|
|
39041
39190
|
});
|
|
39042
39191
|
|
|
39043
39192
|
// src/domains/web-server/routes/health-routes.ts
|
|
@@ -43459,7 +43608,7 @@ async function buildProjectInfoFromRegistry(registered) {
|
|
|
43459
43608
|
} catch {}
|
|
43460
43609
|
}
|
|
43461
43610
|
} catch {}
|
|
43462
|
-
const hasLocalConfig = hasClaudeDir &&
|
|
43611
|
+
const hasLocalConfig = hasClaudeDir && ConfigManager.projectConfigExists(registered.path, false);
|
|
43463
43612
|
const settings = await readSettings();
|
|
43464
43613
|
const skills = await scanSkills();
|
|
43465
43614
|
const settingsPath = join17(homedir10(), ".claude", "settings.json");
|
|
@@ -43500,7 +43649,7 @@ async function detectAndBuildProjectInfo(path2, id) {
|
|
|
43500
43649
|
} catch {}
|
|
43501
43650
|
}
|
|
43502
43651
|
} catch {}
|
|
43503
|
-
const hasLocalConfig =
|
|
43652
|
+
const hasLocalConfig = ConfigManager.projectConfigExists(path2, id === "global");
|
|
43504
43653
|
const settings = await readSettings();
|
|
43505
43654
|
const skills = await scanSkills();
|
|
43506
43655
|
const settingsPath = join17(homedir10(), ".claude", "settings.json");
|
|
@@ -43849,7 +43998,7 @@ var init_skills_discovery = __esm(() => {
|
|
|
43849
43998
|
|
|
43850
43999
|
// src/commands/skills/skills-registry.ts
|
|
43851
44000
|
import { existsSync as existsSync14 } from "node:fs";
|
|
43852
|
-
import { mkdir as
|
|
44001
|
+
import { mkdir as mkdir5, readFile as readFile12, writeFile as writeFile7 } from "node:fs/promises";
|
|
43853
44002
|
import { homedir as homedir14 } from "node:os";
|
|
43854
44003
|
import { dirname as dirname6, join as join21 } from "node:path";
|
|
43855
44004
|
function getCliVersion() {
|
|
@@ -43886,9 +44035,9 @@ async function readRegistry() {
|
|
|
43886
44035
|
async function writeRegistry(registry) {
|
|
43887
44036
|
const dir = dirname6(REGISTRY_PATH);
|
|
43888
44037
|
if (!existsSync14(dir)) {
|
|
43889
|
-
await
|
|
44038
|
+
await mkdir5(dir, { recursive: true });
|
|
43890
44039
|
}
|
|
43891
|
-
await
|
|
44040
|
+
await writeFile7(REGISTRY_PATH, JSON.stringify(registry, null, 2), "utf-8");
|
|
43892
44041
|
}
|
|
43893
44042
|
async function addInstallation(skill, agent, global3, path2, sourcePath) {
|
|
43894
44043
|
const registry = await readRegistry();
|
|
@@ -43962,7 +44111,7 @@ var init_skills_registry = __esm(() => {
|
|
|
43962
44111
|
|
|
43963
44112
|
// src/commands/skills/skills-installer.ts
|
|
43964
44113
|
import { existsSync as existsSync15 } from "node:fs";
|
|
43965
|
-
import { cp, mkdir as
|
|
44114
|
+
import { cp, mkdir as mkdir6, stat as stat7 } from "node:fs/promises";
|
|
43966
44115
|
import { dirname as dirname7, resolve as resolve6 } from "node:path";
|
|
43967
44116
|
function isSamePath(path1, path2) {
|
|
43968
44117
|
try {
|
|
@@ -44007,7 +44156,7 @@ async function installSkillForAgent(skill, agent, options2) {
|
|
|
44007
44156
|
try {
|
|
44008
44157
|
const parentDir = dirname7(targetPath);
|
|
44009
44158
|
if (!existsSync15(parentDir)) {
|
|
44010
|
-
await
|
|
44159
|
+
await mkdir6(parentDir, { recursive: true });
|
|
44011
44160
|
}
|
|
44012
44161
|
if (existsSync15(targetPath)) {
|
|
44013
44162
|
const stats = await stat7(targetPath);
|
|
@@ -44585,38 +44734,10 @@ var init_pnpm_detector = __esm(() => {
|
|
|
44585
44734
|
});
|
|
44586
44735
|
|
|
44587
44736
|
// src/domains/installation/package-managers/detection-core.ts
|
|
44588
|
-
import { existsSync as existsSync17
|
|
44589
|
-
import { chmod as chmod2, mkdir as
|
|
44737
|
+
import { existsSync as existsSync17 } from "node:fs";
|
|
44738
|
+
import { chmod as chmod2, mkdir as mkdir7, readFile as readFile13, writeFile as writeFile8 } from "node:fs/promises";
|
|
44590
44739
|
import { platform as platform4 } from "node:os";
|
|
44591
|
-
import { join as join23
|
|
44592
|
-
function detectFromBinaryPath() {
|
|
44593
|
-
try {
|
|
44594
|
-
const scriptPath = process.argv[1];
|
|
44595
|
-
if (!scriptPath)
|
|
44596
|
-
return "unknown";
|
|
44597
|
-
let resolvedPath;
|
|
44598
|
-
try {
|
|
44599
|
-
resolvedPath = realpathSync(scriptPath);
|
|
44600
|
-
} catch {
|
|
44601
|
-
resolvedPath = scriptPath;
|
|
44602
|
-
}
|
|
44603
|
-
const normalized = resolvedPath.split(sep).join("/").toLowerCase();
|
|
44604
|
-
logger.verbose(`Binary path resolved: ${normalized}`);
|
|
44605
|
-
if (normalized.includes("/.bun/install/") || normalized.includes("/bun/install/global/")) {
|
|
44606
|
-
return "bun";
|
|
44607
|
-
}
|
|
44608
|
-
if (normalized.includes("/pnpm/global/") || normalized.includes("/.local/share/pnpm/")) {
|
|
44609
|
-
return "pnpm";
|
|
44610
|
-
}
|
|
44611
|
-
if (normalized.includes("/yarn/global/") || normalized.includes("/.config/yarn/")) {
|
|
44612
|
-
return "yarn";
|
|
44613
|
-
}
|
|
44614
|
-
if (normalized.includes("/npm/node_modules/") || normalized.includes("/usr/local/lib/node_modules/") || normalized.includes("/usr/lib/node_modules/") || normalized.includes("/opt/homebrew/lib/node_modules/") || normalized.includes("/.nvm/versions/node/") || normalized.includes("/n/versions/node/") || normalized.includes("/appdata/roaming/npm/")) {
|
|
44615
|
-
return "npm";
|
|
44616
|
-
}
|
|
44617
|
-
} catch {}
|
|
44618
|
-
return "unknown";
|
|
44619
|
-
}
|
|
44740
|
+
import { join as join23 } from "node:path";
|
|
44620
44741
|
function detectFromEnv() {
|
|
44621
44742
|
const userAgent = process.env.npm_config_user_agent;
|
|
44622
44743
|
if (userAgent) {
|
|
@@ -44633,14 +44754,13 @@ function detectFromEnv() {
|
|
|
44633
44754
|
const execPath = process.env.npm_execpath;
|
|
44634
44755
|
if (execPath) {
|
|
44635
44756
|
logger.debug(`Detected exec path: ${execPath}`);
|
|
44636
|
-
|
|
44637
|
-
if (/\/bun([/.]|$)/.test(normalizedExec) || normalizedExec.startsWith("bun"))
|
|
44757
|
+
if (execPath.includes("bun"))
|
|
44638
44758
|
return "bun";
|
|
44639
|
-
if (
|
|
44759
|
+
if (execPath.includes("yarn"))
|
|
44640
44760
|
return "yarn";
|
|
44641
|
-
if (
|
|
44761
|
+
if (execPath.includes("pnpm"))
|
|
44642
44762
|
return "pnpm";
|
|
44643
|
-
if (
|
|
44763
|
+
if (execPath.includes("npm"))
|
|
44644
44764
|
return "npm";
|
|
44645
44765
|
}
|
|
44646
44766
|
return "unknown";
|
|
@@ -44658,8 +44778,8 @@ async function readCachedPm() {
|
|
|
44658
44778
|
return null;
|
|
44659
44779
|
}
|
|
44660
44780
|
const age = Date.now() - data.detectedAt;
|
|
44661
|
-
if (age
|
|
44662
|
-
logger.debug(
|
|
44781
|
+
if (age > CACHE_TTL) {
|
|
44782
|
+
logger.debug("Cache expired, will re-detect");
|
|
44663
44783
|
return null;
|
|
44664
44784
|
}
|
|
44665
44785
|
const validPms = ["npm", "bun", "yarn", "pnpm"];
|
|
@@ -44680,7 +44800,7 @@ async function saveCachedPm(pm, getVersion) {
|
|
|
44680
44800
|
const configDir = PathResolver.getConfigDir(false);
|
|
44681
44801
|
const cacheFile = join23(configDir, CACHE_FILE);
|
|
44682
44802
|
if (!existsSync17(configDir)) {
|
|
44683
|
-
await
|
|
44803
|
+
await mkdir7(configDir, { recursive: true });
|
|
44684
44804
|
if (platform4() !== "win32") {
|
|
44685
44805
|
await chmod2(configDir, 448);
|
|
44686
44806
|
}
|
|
@@ -44691,7 +44811,7 @@ async function saveCachedPm(pm, getVersion) {
|
|
|
44691
44811
|
detectedAt: Date.now(),
|
|
44692
44812
|
version: version ?? undefined
|
|
44693
44813
|
};
|
|
44694
|
-
await
|
|
44814
|
+
await writeFile8(cacheFile, JSON.stringify(data, null, 2), "utf-8");
|
|
44695
44815
|
if (platform4() !== "win32") {
|
|
44696
44816
|
await chmod2(cacheFile, 384);
|
|
44697
44817
|
}
|
|
@@ -44768,18 +44888,6 @@ var init_package_manager_detector = __esm(() => {
|
|
|
44768
44888
|
PackageManagerDetector = class PackageManagerDetector {
|
|
44769
44889
|
static async detect() {
|
|
44770
44890
|
logger.verbose("PackageManagerDetector: Starting detection");
|
|
44771
|
-
const binaryPm = detectFromBinaryPath();
|
|
44772
|
-
if (binaryPm !== "unknown") {
|
|
44773
|
-
logger.verbose(`PackageManagerDetector: Detected from binary path: ${binaryPm}`);
|
|
44774
|
-
const cachedPm2 = await readCachedPm();
|
|
44775
|
-
if (cachedPm2 && cachedPm2 !== binaryPm) {
|
|
44776
|
-
logger.verbose(`PackageManagerDetector: Cache says ${cachedPm2}, binary says ${binaryPm} — updating cache`);
|
|
44777
|
-
await saveCachedPm(binaryPm, PackageManagerDetector.getVersion);
|
|
44778
|
-
} else if (!cachedPm2) {
|
|
44779
|
-
await saveCachedPm(binaryPm, PackageManagerDetector.getVersion);
|
|
44780
|
-
}
|
|
44781
|
-
return binaryPm;
|
|
44782
|
-
}
|
|
44783
44891
|
const envPm = detectFromEnv();
|
|
44784
44892
|
if (envPm !== "unknown") {
|
|
44785
44893
|
logger.verbose(`PackageManagerDetector: Detected from env: ${envPm}`);
|
|
@@ -45277,7 +45385,7 @@ var package_default;
|
|
|
45277
45385
|
var init_package = __esm(() => {
|
|
45278
45386
|
package_default = {
|
|
45279
45387
|
name: "claudekit-cli",
|
|
45280
|
-
version: "3.34.
|
|
45388
|
+
version: "3.34.2",
|
|
45281
45389
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
45282
45390
|
type: "module",
|
|
45283
45391
|
repository: {
|
|
@@ -45376,6 +45484,7 @@ var init_package = __esm(() => {
|
|
|
45376
45484
|
"@types/tar": "^6.1.13",
|
|
45377
45485
|
"@types/tmp": "^0.2.6",
|
|
45378
45486
|
"@types/ws": "^8.18.1",
|
|
45487
|
+
"conventional-changelog-conventionalcommits": "^9.1.0",
|
|
45379
45488
|
"semantic-release": "^24.2.0",
|
|
45380
45489
|
typescript: "^5.7.2"
|
|
45381
45490
|
}
|
|
@@ -45592,15 +45701,12 @@ Run 'ck update' to install`, "Update Check");
|
|
|
45592
45701
|
s.stop("Update failed");
|
|
45593
45702
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
45594
45703
|
if (errorMessage.includes("EACCES") || errorMessage.includes("EPERM") || errorMessage.includes("permission") || errorMessage.includes("Access is denied")) {
|
|
45595
|
-
|
|
45704
|
+
throw new CliUpdateError(`Permission denied. Try: sudo ${updateCmd}
|
|
45596
45705
|
|
|
45597
|
-
Or fix npm permissions: https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally`
|
|
45598
|
-
const isWindows3 = process.platform === "win32";
|
|
45599
|
-
const elevationHint = isWindows3 ? `Run your terminal as Administrator and retry: ${updateCmd}` : `sudo ${updateCmd}`;
|
|
45600
|
-
throw new CliUpdateError(`Permission denied. Try: ${elevationHint}${permHint}`);
|
|
45706
|
+
Or fix npm permissions: https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally`);
|
|
45601
45707
|
}
|
|
45602
45708
|
logger.error(`Update failed: ${errorMessage}`);
|
|
45603
|
-
logger.info(
|
|
45709
|
+
logger.info("Try running: npm install -g claudekit-cli@latest");
|
|
45604
45710
|
throw new CliUpdateError(`Update failed: ${errorMessage}
|
|
45605
45711
|
|
|
45606
45712
|
Manual update: ${updateCmd}`);
|
|
@@ -46094,7 +46200,7 @@ var init_error_handler2 = __esm(() => {
|
|
|
46094
46200
|
|
|
46095
46201
|
// src/domains/versioning/release-cache.ts
|
|
46096
46202
|
import { existsSync as existsSync18 } from "node:fs";
|
|
46097
|
-
import { mkdir as
|
|
46203
|
+
import { mkdir as mkdir8, readFile as readFile17, unlink as unlink3, writeFile as writeFile10 } from "node:fs/promises";
|
|
46098
46204
|
import { join as join27 } from "node:path";
|
|
46099
46205
|
var ReleaseCacheEntrySchema, ReleaseCache;
|
|
46100
46206
|
var init_release_cache = __esm(() => {
|
|
@@ -46140,12 +46246,12 @@ var init_release_cache = __esm(() => {
|
|
|
46140
46246
|
async set(key, releases) {
|
|
46141
46247
|
const cacheFile = this.getCachePath(key);
|
|
46142
46248
|
try {
|
|
46143
|
-
await
|
|
46249
|
+
await mkdir8(this.cacheDir, { recursive: true, mode: 448 });
|
|
46144
46250
|
const cacheEntry = {
|
|
46145
46251
|
timestamp: Date.now(),
|
|
46146
46252
|
releases
|
|
46147
46253
|
};
|
|
46148
|
-
await
|
|
46254
|
+
await writeFile10(cacheFile, JSON.stringify(cacheEntry, null, 2), "utf-8");
|
|
46149
46255
|
logger.debug(`Release cache set for key: ${key}, cached ${releases.length} releases`);
|
|
46150
46256
|
} catch (error) {
|
|
46151
46257
|
logger.debug(`Failed to set release cache for key ${key}: ${error}`);
|
|
@@ -46856,7 +46962,7 @@ var init_version_utils = __esm(() => {
|
|
|
46856
46962
|
|
|
46857
46963
|
// src/domains/versioning/version-cache.ts
|
|
46858
46964
|
import { existsSync as existsSync19 } from "node:fs";
|
|
46859
|
-
import { mkdir as
|
|
46965
|
+
import { mkdir as mkdir9, readFile as readFile18, writeFile as writeFile11 } from "node:fs/promises";
|
|
46860
46966
|
import { join as join28 } from "node:path";
|
|
46861
46967
|
var VersionCacheManager;
|
|
46862
46968
|
var init_version_cache = __esm(() => {
|
|
@@ -46894,9 +47000,9 @@ var init_version_cache = __esm(() => {
|
|
|
46894
47000
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
46895
47001
|
try {
|
|
46896
47002
|
if (!existsSync19(cacheDir)) {
|
|
46897
|
-
await
|
|
47003
|
+
await mkdir9(cacheDir, { recursive: true, mode: 448 });
|
|
46898
47004
|
}
|
|
46899
|
-
await
|
|
47005
|
+
await writeFile11(cacheFile, JSON.stringify(cache3, null, 2), "utf-8");
|
|
46900
47006
|
logger.debug(`Version check cache saved to ${cacheFile}`);
|
|
46901
47007
|
} catch (error) {
|
|
46902
47008
|
logger.debug(`Failed to save version check cache: ${error}`);
|
|
@@ -47476,6 +47582,7 @@ var init_user_routes = __esm(() => {
|
|
|
47476
47582
|
function registerRoutes(app) {
|
|
47477
47583
|
registerHealthRoutes(app);
|
|
47478
47584
|
registerActionRoutes(app);
|
|
47585
|
+
registerConfigRoutes(app);
|
|
47479
47586
|
registerCkConfigRoutes(app);
|
|
47480
47587
|
registerProjectRoutes(app);
|
|
47481
47588
|
registerSkillRoutes(app);
|
|
@@ -47487,6 +47594,7 @@ function registerRoutes(app) {
|
|
|
47487
47594
|
var init_routes = __esm(() => {
|
|
47488
47595
|
init_action_routes();
|
|
47489
47596
|
init_ck_config_routes();
|
|
47597
|
+
init_config_routes();
|
|
47490
47598
|
init_project_routes();
|
|
47491
47599
|
init_session_routes();
|
|
47492
47600
|
init_settings_routes();
|
|
@@ -52939,7 +53047,7 @@ var init_skills_installer2 = __esm(() => {
|
|
|
52939
53047
|
|
|
52940
53048
|
// src/services/package-installer/gemini-mcp/config-manager.ts
|
|
52941
53049
|
import { existsSync as existsSync32 } from "node:fs";
|
|
52942
|
-
import { mkdir as
|
|
53050
|
+
import { mkdir as mkdir13, readFile as readFile26, writeFile as writeFile16 } from "node:fs/promises";
|
|
52943
53051
|
import { dirname as dirname11, join as join50 } from "node:path";
|
|
52944
53052
|
async function readJsonFile(filePath) {
|
|
52945
53053
|
try {
|
|
@@ -52970,7 +53078,7 @@ async function addGeminiToGitignore(projectDir) {
|
|
|
52970
53078
|
`) || content === "" ? "" : `
|
|
52971
53079
|
`;
|
|
52972
53080
|
const comment = "# Gemini CLI settings (contains user-specific config)";
|
|
52973
|
-
await
|
|
53081
|
+
await writeFile16(gitignorePath, `${content}${newLine}${comment}
|
|
52974
53082
|
${geminiPattern}
|
|
52975
53083
|
`, "utf-8");
|
|
52976
53084
|
logger.debug(`Added ${geminiPattern} to .gitignore`);
|
|
@@ -52982,7 +53090,7 @@ ${geminiPattern}
|
|
|
52982
53090
|
async function createNewSettingsWithMerge(geminiSettingsPath, mcpConfigPath) {
|
|
52983
53091
|
const linkDir = dirname11(geminiSettingsPath);
|
|
52984
53092
|
if (!existsSync32(linkDir)) {
|
|
52985
|
-
await
|
|
53093
|
+
await mkdir13(linkDir, { recursive: true });
|
|
52986
53094
|
logger.debug(`Created directory: ${linkDir}`);
|
|
52987
53095
|
}
|
|
52988
53096
|
const mcpConfig = await readJsonFile(mcpConfigPath);
|
|
@@ -52995,7 +53103,7 @@ async function createNewSettingsWithMerge(geminiSettingsPath, mcpConfigPath) {
|
|
|
52995
53103
|
}
|
|
52996
53104
|
const newSettings = { mcpServers };
|
|
52997
53105
|
try {
|
|
52998
|
-
await
|
|
53106
|
+
await writeFile16(geminiSettingsPath, JSON.stringify(newSettings, null, 2), "utf-8");
|
|
52999
53107
|
logger.debug(`Created new Gemini settings with mcpServers: ${geminiSettingsPath}`);
|
|
53000
53108
|
return { success: true, method: "merge", targetPath: mcpConfigPath };
|
|
53001
53109
|
} catch (error) {
|
|
@@ -53025,7 +53133,7 @@ async function mergeGeminiSettings(geminiSettingsPath, mcpConfigPath) {
|
|
|
53025
53133
|
mcpServers
|
|
53026
53134
|
};
|
|
53027
53135
|
try {
|
|
53028
|
-
await
|
|
53136
|
+
await writeFile16(geminiSettingsPath, JSON.stringify(mergedSettings, null, 2), "utf-8");
|
|
53029
53137
|
logger.debug(`Merged mcpServers into: ${geminiSettingsPath}`);
|
|
53030
53138
|
return { success: true, method: "merge", targetPath: mcpConfigPath };
|
|
53031
53139
|
} catch (error) {
|
|
@@ -53098,12 +53206,12 @@ var init_validation = __esm(() => {
|
|
|
53098
53206
|
|
|
53099
53207
|
// src/services/package-installer/gemini-mcp/linker-core.ts
|
|
53100
53208
|
import { existsSync as existsSync34 } from "node:fs";
|
|
53101
|
-
import { mkdir as
|
|
53209
|
+
import { mkdir as mkdir14, symlink as symlink2 } from "node:fs/promises";
|
|
53102
53210
|
import { dirname as dirname12, join as join52 } from "node:path";
|
|
53103
53211
|
async function createSymlink(targetPath, linkPath, projectDir, isGlobal) {
|
|
53104
53212
|
const linkDir = dirname12(linkPath);
|
|
53105
53213
|
if (!existsSync34(linkDir)) {
|
|
53106
|
-
await
|
|
53214
|
+
await mkdir14(linkDir, { recursive: true });
|
|
53107
53215
|
logger.debug(`Created directory: ${linkDir}`);
|
|
53108
53216
|
}
|
|
53109
53217
|
let symlinkTarget;
|
|
@@ -60907,7 +61015,7 @@ function checkComponentCounts(setup) {
|
|
|
60907
61015
|
// src/domains/health-checks/checkers/permissions-checker.ts
|
|
60908
61016
|
init_logger();
|
|
60909
61017
|
init_path_resolver();
|
|
60910
|
-
import { constants as constants2, access as access2, unlink as unlink4, writeFile as
|
|
61018
|
+
import { constants as constants2, access as access2, unlink as unlink4, writeFile as writeFile12 } from "node:fs/promises";
|
|
60911
61019
|
import { join as join34 } from "node:path";
|
|
60912
61020
|
|
|
60913
61021
|
// src/domains/health-checks/checkers/shared.ts
|
|
@@ -60978,7 +61086,7 @@ async function checkGlobalDirWritable() {
|
|
|
60978
61086
|
const random = Math.random().toString(36).substring(2);
|
|
60979
61087
|
const testFile = join34(globalDir, `.ck-write-test-${timestamp}-${random}`);
|
|
60980
61088
|
try {
|
|
60981
|
-
await
|
|
61089
|
+
await writeFile12(testFile, "test", { encoding: "utf-8", flag: "wx" });
|
|
60982
61090
|
} catch (error) {
|
|
60983
61091
|
return {
|
|
60984
61092
|
id: "ck-global-dir-writable",
|
|
@@ -62008,7 +62116,7 @@ import { platform as platform6 } from "node:os";
|
|
|
62008
62116
|
|
|
62009
62117
|
// src/domains/health-checks/platform/environment-checker.ts
|
|
62010
62118
|
init_path_resolver();
|
|
62011
|
-
import { constants as constants3, access as access3, mkdir as
|
|
62119
|
+
import { constants as constants3, access as access3, mkdir as mkdir10, readFile as readFile23, unlink as unlink5, writeFile as writeFile13 } from "node:fs/promises";
|
|
62012
62120
|
import { arch as arch2, homedir as homedir16, platform as platform5 } from "node:os";
|
|
62013
62121
|
import { join as join42, normalize as normalize6 } from "node:path";
|
|
62014
62122
|
var IS_WINDOWS = platform5() === "win32";
|
|
@@ -62106,8 +62214,8 @@ async function checkGlobalDirAccess() {
|
|
|
62106
62214
|
}
|
|
62107
62215
|
const testFile = join42(globalDir, ".ck-doctor-access-test");
|
|
62108
62216
|
try {
|
|
62109
|
-
await
|
|
62110
|
-
await
|
|
62217
|
+
await mkdir10(globalDir, { recursive: true });
|
|
62218
|
+
await writeFile13(testFile, "test", "utf-8");
|
|
62111
62219
|
const content = await readFile23(testFile, "utf-8");
|
|
62112
62220
|
await unlink5(testFile);
|
|
62113
62221
|
if (content !== "test")
|
|
@@ -62181,7 +62289,7 @@ async function checkWSLBoundary() {
|
|
|
62181
62289
|
|
|
62182
62290
|
// src/domains/health-checks/platform/windows-checker.ts
|
|
62183
62291
|
init_path_resolver();
|
|
62184
|
-
import { mkdir as
|
|
62292
|
+
import { mkdir as mkdir11, symlink, unlink as unlink6, writeFile as writeFile14 } from "node:fs/promises";
|
|
62185
62293
|
import { join as join43 } from "node:path";
|
|
62186
62294
|
async function checkLongPathSupport() {
|
|
62187
62295
|
if (shouldSkipExpensiveOperations4()) {
|
|
@@ -62237,8 +62345,8 @@ async function checkSymlinkSupport() {
|
|
|
62237
62345
|
const target = join43(testDir, ".ck-symlink-test-target");
|
|
62238
62346
|
const link = join43(testDir, ".ck-symlink-test-link");
|
|
62239
62347
|
try {
|
|
62240
|
-
await
|
|
62241
|
-
await
|
|
62348
|
+
await mkdir11(testDir, { recursive: true });
|
|
62349
|
+
await writeFile14(target, "test", "utf-8");
|
|
62242
62350
|
await symlink(target, link);
|
|
62243
62351
|
await unlink6(link);
|
|
62244
62352
|
await unlink6(target);
|
|
@@ -62992,7 +63100,7 @@ init_github_client();
|
|
|
62992
63100
|
init_logger();
|
|
62993
63101
|
init_path_resolver();
|
|
62994
63102
|
var import_compare_versions5 = __toESM(require_umd(), 1);
|
|
62995
|
-
import { mkdir as
|
|
63103
|
+
import { mkdir as mkdir12, readFile as readFile24, unlink as unlink7, writeFile as writeFile15 } from "node:fs/promises";
|
|
62996
63104
|
import { join as join45 } from "node:path";
|
|
62997
63105
|
var CACHE_TTL_HOURS = 24;
|
|
62998
63106
|
var DEFAULT_CACHE_TTL_MS = CACHE_TTL_HOURS * 60 * 60 * 1000;
|
|
@@ -63050,8 +63158,8 @@ class ConfigVersionChecker {
|
|
|
63050
63158
|
try {
|
|
63051
63159
|
const cachePath = ConfigVersionChecker.getCacheFilePath(kitType, global3);
|
|
63052
63160
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
63053
|
-
await
|
|
63054
|
-
await
|
|
63161
|
+
await mkdir12(cacheDir, { recursive: true });
|
|
63162
|
+
await writeFile15(cachePath, JSON.stringify(cache3, null, 2));
|
|
63055
63163
|
} catch (error) {
|
|
63056
63164
|
logger.debug(`Cache write failed: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
63057
63165
|
}
|
|
@@ -65712,7 +65820,7 @@ init_logger();
|
|
|
65712
65820
|
// src/shared/process-lock.ts
|
|
65713
65821
|
init_logger();
|
|
65714
65822
|
var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
|
|
65715
|
-
import { mkdir as
|
|
65823
|
+
import { mkdir as mkdir15 } from "node:fs/promises";
|
|
65716
65824
|
import os5 from "node:os";
|
|
65717
65825
|
import { join as join53 } from "node:path";
|
|
65718
65826
|
var LOCK_CONFIG = {
|
|
@@ -65745,7 +65853,7 @@ function registerCleanupHandlers() {
|
|
|
65745
65853
|
}
|
|
65746
65854
|
async function ensureLocksDir() {
|
|
65747
65855
|
const lockDir = getLocksDir();
|
|
65748
|
-
await
|
|
65856
|
+
await mkdir15(lockDir, { recursive: true });
|
|
65749
65857
|
}
|
|
65750
65858
|
async function withProcessLock(lockName, fn) {
|
|
65751
65859
|
registerCleanupHandlers();
|
|
@@ -65900,7 +66008,7 @@ init_github_client();
|
|
|
65900
66008
|
init_environment();
|
|
65901
66009
|
init_logger();
|
|
65902
66010
|
init_safe_spinner();
|
|
65903
|
-
import { mkdir as
|
|
66011
|
+
import { mkdir as mkdir21, stat as stat12 } from "node:fs/promises";
|
|
65904
66012
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
65905
66013
|
import { join as join61 } from "node:path";
|
|
65906
66014
|
|
|
@@ -65920,7 +66028,7 @@ var import_ignore = __toESM(require_ignore(), 1);
|
|
|
65920
66028
|
init_logger();
|
|
65921
66029
|
init_output_manager();
|
|
65922
66030
|
import { createWriteStream as createWriteStream2, rmSync } from "node:fs";
|
|
65923
|
-
import { mkdir as
|
|
66031
|
+
import { mkdir as mkdir16 } from "node:fs/promises";
|
|
65924
66032
|
import { join as join55 } from "node:path";
|
|
65925
66033
|
|
|
65926
66034
|
// src/shared/progress-bar.ts
|
|
@@ -66085,7 +66193,7 @@ init_types2();
|
|
|
66085
66193
|
|
|
66086
66194
|
// src/domains/installation/utils/path-security.ts
|
|
66087
66195
|
init_types2();
|
|
66088
|
-
import { lstatSync as lstatSync2, realpathSync
|
|
66196
|
+
import { lstatSync as lstatSync2, realpathSync } from "node:fs";
|
|
66089
66197
|
import { relative as relative5, resolve as resolve10 } from "node:path";
|
|
66090
66198
|
var MAX_EXTRACTION_SIZE = 500 * 1024 * 1024;
|
|
66091
66199
|
function isPathSafe(basePath, targetPath) {
|
|
@@ -66093,7 +66201,7 @@ function isPathSafe(basePath, targetPath) {
|
|
|
66093
66201
|
try {
|
|
66094
66202
|
const stat10 = lstatSync2(targetPath);
|
|
66095
66203
|
if (stat10.isSymbolicLink()) {
|
|
66096
|
-
const realTarget =
|
|
66204
|
+
const realTarget = realpathSync(targetPath);
|
|
66097
66205
|
if (!realTarget.startsWith(resolvedBase)) {
|
|
66098
66206
|
return false;
|
|
66099
66207
|
}
|
|
@@ -66132,7 +66240,7 @@ class FileDownloader {
|
|
|
66132
66240
|
async downloadAsset(asset, destDir) {
|
|
66133
66241
|
try {
|
|
66134
66242
|
const destPath = join55(destDir, asset.name);
|
|
66135
|
-
await
|
|
66243
|
+
await mkdir16(destDir, { recursive: true });
|
|
66136
66244
|
output.info(`Downloading ${asset.name} (${formatBytes(asset.size)})...`);
|
|
66137
66245
|
logger.verbose("Download details", {
|
|
66138
66246
|
url: asset.browser_download_url,
|
|
@@ -66217,7 +66325,7 @@ class FileDownloader {
|
|
|
66217
66325
|
async downloadFile(params) {
|
|
66218
66326
|
const { url, name, size, destDir, token } = params;
|
|
66219
66327
|
const destPath = join55(destDir, name);
|
|
66220
|
-
await
|
|
66328
|
+
await mkdir16(destDir, { recursive: true });
|
|
66221
66329
|
output.info(`Downloading ${name}${size ? ` (${formatBytes(size)})` : ""}...`);
|
|
66222
66330
|
const headers = {};
|
|
66223
66331
|
if (token && url.includes("api.github.com")) {
|
|
@@ -66335,7 +66443,7 @@ async function validateExtraction(extractDir) {
|
|
|
66335
66443
|
|
|
66336
66444
|
// src/domains/installation/extraction/tar-extractor.ts
|
|
66337
66445
|
init_logger();
|
|
66338
|
-
import { copyFile as copyFile3, mkdir as
|
|
66446
|
+
import { copyFile as copyFile3, mkdir as mkdir19, readdir as readdir11, rm as rm3, stat as stat10 } from "node:fs/promises";
|
|
66339
66447
|
import { join as join59 } from "node:path";
|
|
66340
66448
|
|
|
66341
66449
|
// node_modules/@isaacs/fs-minipass/dist/esm/index.js
|
|
@@ -71965,7 +72073,7 @@ var checkCwd = (dir, cb) => {
|
|
|
71965
72073
|
cb(er);
|
|
71966
72074
|
});
|
|
71967
72075
|
};
|
|
71968
|
-
var
|
|
72076
|
+
var mkdir17 = (dir, opt, cb) => {
|
|
71969
72077
|
dir = normalizeWindowsPath(dir);
|
|
71970
72078
|
const umask = opt.umask ?? 18;
|
|
71971
72079
|
const mode = opt.mode | 448;
|
|
@@ -72488,7 +72596,7 @@ class Unpack extends Parser {
|
|
|
72488
72596
|
}
|
|
72489
72597
|
}
|
|
72490
72598
|
[MKDIR](dir, mode, cb) {
|
|
72491
|
-
|
|
72599
|
+
mkdir17(normalizeWindowsPath(dir), {
|
|
72492
72600
|
uid: this.uid,
|
|
72493
72601
|
gid: this.gid,
|
|
72494
72602
|
processUid: this.processUid,
|
|
@@ -73204,7 +73312,7 @@ function decodeFilePath(path10) {
|
|
|
73204
73312
|
// src/domains/installation/utils/file-utils.ts
|
|
73205
73313
|
init_logger();
|
|
73206
73314
|
init_types2();
|
|
73207
|
-
import { copyFile as copyFile2, lstat as lstat4, mkdir as
|
|
73315
|
+
import { copyFile as copyFile2, lstat as lstat4, mkdir as mkdir18, readdir as readdir10 } from "node:fs/promises";
|
|
73208
73316
|
import { join as join58, relative as relative6 } from "node:path";
|
|
73209
73317
|
async function withRetry(fn, retries = 3) {
|
|
73210
73318
|
for (let i = 0;i < retries; i++) {
|
|
@@ -73224,7 +73332,7 @@ var isRetryable = (e2) => {
|
|
|
73224
73332
|
};
|
|
73225
73333
|
var delay = (ms) => new Promise((r2) => setTimeout(r2, ms));
|
|
73226
73334
|
async function moveDirectoryContents(sourceDir, destDir, shouldExclude, sizeTracker) {
|
|
73227
|
-
await
|
|
73335
|
+
await mkdir18(destDir, { recursive: true });
|
|
73228
73336
|
const entries = await readdir10(sourceDir, { encoding: "utf8" });
|
|
73229
73337
|
for (const entry of entries) {
|
|
73230
73338
|
const sourcePath = join58(sourceDir, entry);
|
|
@@ -73252,7 +73360,7 @@ async function moveDirectoryContents(sourceDir, destDir, shouldExclude, sizeTrac
|
|
|
73252
73360
|
}
|
|
73253
73361
|
}
|
|
73254
73362
|
async function copyDirectory(sourceDir, destDir, shouldExclude, sizeTracker) {
|
|
73255
|
-
await
|
|
73363
|
+
await mkdir18(destDir, { recursive: true });
|
|
73256
73364
|
const entries = await readdir10(sourceDir, { encoding: "utf8" });
|
|
73257
73365
|
for (const entry of entries) {
|
|
73258
73366
|
const sourcePath = join58(sourceDir, entry);
|
|
@@ -73284,7 +73392,7 @@ async function copyDirectory(sourceDir, destDir, shouldExclude, sizeTracker) {
|
|
|
73284
73392
|
class TarExtractor {
|
|
73285
73393
|
async extract(archivePath, destDir, shouldExclude, sizeTracker) {
|
|
73286
73394
|
const tempExtractDir = `${destDir}-temp`;
|
|
73287
|
-
await
|
|
73395
|
+
await mkdir19(tempExtractDir, { recursive: true });
|
|
73288
73396
|
try {
|
|
73289
73397
|
await extract({
|
|
73290
73398
|
file: archivePath,
|
|
@@ -73319,7 +73427,7 @@ class TarExtractor {
|
|
|
73319
73427
|
await moveDirectoryContents(tempExtractDir, destDir, shouldExclude, sizeTracker);
|
|
73320
73428
|
}
|
|
73321
73429
|
} else {
|
|
73322
|
-
await
|
|
73430
|
+
await mkdir19(destDir, { recursive: true });
|
|
73323
73431
|
await copyFile3(rootPath, join59(destDir, rootEntry));
|
|
73324
73432
|
}
|
|
73325
73433
|
} else {
|
|
@@ -73342,7 +73450,7 @@ init_environment();
|
|
|
73342
73450
|
init_logger();
|
|
73343
73451
|
var import_extract_zip = __toESM(require_extract_zip(), 1);
|
|
73344
73452
|
import { execFile as execFile8 } from "node:child_process";
|
|
73345
|
-
import { copyFile as copyFile4, mkdir as
|
|
73453
|
+
import { copyFile as copyFile4, mkdir as mkdir20, readdir as readdir12, rm as rm4, stat as stat11 } from "node:fs/promises";
|
|
73346
73454
|
import { join as join60 } from "node:path";
|
|
73347
73455
|
class ZipExtractor {
|
|
73348
73456
|
async tryNativeUnzip(archivePath, destDir) {
|
|
@@ -73350,7 +73458,7 @@ class ZipExtractor {
|
|
|
73350
73458
|
return false;
|
|
73351
73459
|
}
|
|
73352
73460
|
return new Promise((resolve11) => {
|
|
73353
|
-
|
|
73461
|
+
mkdir20(destDir, { recursive: true }).then(() => {
|
|
73354
73462
|
execFile8("unzip", ["-o", "-q", archivePath, "-d", destDir], (error, _stdout, stderr) => {
|
|
73355
73463
|
if (error) {
|
|
73356
73464
|
logger.debug(`Native unzip failed: ${stderr || error.message}`);
|
|
@@ -73368,7 +73476,7 @@ class ZipExtractor {
|
|
|
73368
73476
|
}
|
|
73369
73477
|
async extract(archivePath, destDir, shouldExclude, sizeTracker) {
|
|
73370
73478
|
const tempExtractDir = `${destDir}-temp`;
|
|
73371
|
-
await
|
|
73479
|
+
await mkdir20(tempExtractDir, { recursive: true });
|
|
73372
73480
|
try {
|
|
73373
73481
|
const nativeSuccess = await this.tryNativeUnzip(archivePath, tempExtractDir);
|
|
73374
73482
|
if (!nativeSuccess) {
|
|
@@ -73406,7 +73514,7 @@ class ZipExtractor {
|
|
|
73406
73514
|
await moveDirectoryContents(tempExtractDir, destDir, shouldExclude, sizeTracker);
|
|
73407
73515
|
}
|
|
73408
73516
|
} else {
|
|
73409
|
-
await
|
|
73517
|
+
await mkdir20(destDir, { recursive: true });
|
|
73410
73518
|
await copyFile4(rootPath, join60(destDir, rootEntry));
|
|
73411
73519
|
}
|
|
73412
73520
|
} else {
|
|
@@ -73481,7 +73589,7 @@ class DownloadManager {
|
|
|
73481
73589
|
try {
|
|
73482
73590
|
this.sizeTracker.reset();
|
|
73483
73591
|
const detectedType = archiveType || detectArchiveType(archivePath);
|
|
73484
|
-
await
|
|
73592
|
+
await mkdir21(destDir, { recursive: true });
|
|
73485
73593
|
if (detectedType === "tar.gz") {
|
|
73486
73594
|
await this.tarExtractor.extract(archivePath, destDir, this.shouldExclude, this.sizeTracker);
|
|
73487
73595
|
} else if (detectedType === "zip") {
|
|
@@ -73508,7 +73616,7 @@ class DownloadManager {
|
|
|
73508
73616
|
const counter = DownloadManager.tempDirCounter++;
|
|
73509
73617
|
const primaryTempDir = join61(tmpdir3(), `claudekit-${timestamp}-${counter}`);
|
|
73510
73618
|
try {
|
|
73511
|
-
await
|
|
73619
|
+
await mkdir21(primaryTempDir, { recursive: true });
|
|
73512
73620
|
logger.debug(`Created temp directory: ${primaryTempDir}`);
|
|
73513
73621
|
registerTempDir(primaryTempDir);
|
|
73514
73622
|
return primaryTempDir;
|
|
@@ -73525,7 +73633,7 @@ Solutions:
|
|
|
73525
73633
|
}
|
|
73526
73634
|
const fallbackTempDir = join61(homeDir, ".claudekit", "tmp", `claudekit-${timestamp}-${counter}`);
|
|
73527
73635
|
try {
|
|
73528
|
-
await
|
|
73636
|
+
await mkdir21(fallbackTempDir, { recursive: true });
|
|
73529
73637
|
logger.debug(`Created temp directory (fallback): ${fallbackTempDir}`);
|
|
73530
73638
|
logger.warning(`Using fallback temp directory: ${fallbackTempDir}
|
|
73531
73639
|
(OS temp directory was not accessible)`);
|
|
@@ -73876,7 +73984,7 @@ import { join as join77 } from "node:path";
|
|
|
73876
73984
|
|
|
73877
73985
|
// src/domains/installation/deletion-handler.ts
|
|
73878
73986
|
import { existsSync as existsSync35, lstatSync as lstatSync3, readdirSync as readdirSync2, rmSync as rmSync2, rmdirSync, unlinkSync as unlinkSync3 } from "node:fs";
|
|
73879
|
-
import { dirname as dirname14, join as join64, relative as relative7, resolve as resolve12, sep
|
|
73987
|
+
import { dirname as dirname14, join as join64, relative as relative7, resolve as resolve12, sep } from "node:path";
|
|
73880
73988
|
|
|
73881
73989
|
// src/services/file-operations/manifest/manifest-reader.ts
|
|
73882
73990
|
init_metadata_migration();
|
|
@@ -74115,7 +74223,7 @@ function cleanupEmptyDirectories(filePath, claudeDir2) {
|
|
|
74115
74223
|
function deletePath(fullPath, claudeDir2) {
|
|
74116
74224
|
const normalizedPath = resolve12(fullPath);
|
|
74117
74225
|
const normalizedClaudeDir = resolve12(claudeDir2);
|
|
74118
|
-
if (!normalizedPath.startsWith(`${normalizedClaudeDir}${
|
|
74226
|
+
if (!normalizedPath.startsWith(`${normalizedClaudeDir}${sep}`) && normalizedPath !== normalizedClaudeDir) {
|
|
74119
74227
|
throw new Error(`Path traversal detected: ${fullPath}`);
|
|
74120
74228
|
}
|
|
74121
74229
|
try {
|
|
@@ -74189,7 +74297,7 @@ async function handleDeletions(sourceMetadata, claudeDir2) {
|
|
|
74189
74297
|
const fullPath = join64(claudeDir2, path11);
|
|
74190
74298
|
const normalizedPath = resolve12(fullPath);
|
|
74191
74299
|
const normalizedClaudeDir = resolve12(claudeDir2);
|
|
74192
|
-
if (!normalizedPath.startsWith(`${normalizedClaudeDir}${
|
|
74300
|
+
if (!normalizedPath.startsWith(`${normalizedClaudeDir}${sep}`)) {
|
|
74193
74301
|
logger.warning(`Skipping invalid path: ${path11}`);
|
|
74194
74302
|
result.errors.push(path11);
|
|
74195
74303
|
continue;
|
|
@@ -75212,8 +75320,8 @@ var path11 = {
|
|
|
75212
75320
|
win32: { sep: "\\" },
|
|
75213
75321
|
posix: { sep: "/" }
|
|
75214
75322
|
};
|
|
75215
|
-
var
|
|
75216
|
-
minimatch.sep =
|
|
75323
|
+
var sep2 = defaultPlatform === "win32" ? path11.win32.sep : path11.posix.sep;
|
|
75324
|
+
minimatch.sep = sep2;
|
|
75217
75325
|
var GLOBSTAR = Symbol("globstar **");
|
|
75218
75326
|
minimatch.GLOBSTAR = GLOBSTAR;
|
|
75219
75327
|
var qmark2 = "[^/]";
|
|
@@ -75894,13 +76002,10 @@ class FileScanner {
|
|
|
75894
76002
|
}
|
|
75895
76003
|
}
|
|
75896
76004
|
|
|
75897
|
-
// src/domains/installation/merger/settings-processor.ts
|
|
75898
|
-
import { execSync as execSync4 } from "node:child_process";
|
|
75899
|
-
|
|
75900
76005
|
// src/domains/config/installed-settings-tracker.ts
|
|
75901
76006
|
init_shared();
|
|
75902
76007
|
import { existsSync as existsSync36 } from "node:fs";
|
|
75903
|
-
import { mkdir as
|
|
76008
|
+
import { mkdir as mkdir22, readFile as readFile29, writeFile as writeFile18 } from "node:fs/promises";
|
|
75904
76009
|
import { dirname as dirname15, join as join66 } from "node:path";
|
|
75905
76010
|
var CK_JSON_FILE = ".ck.json";
|
|
75906
76011
|
|
|
@@ -75952,8 +76057,8 @@ class InstalledSettingsTracker {
|
|
|
75952
76057
|
data.kits[this.kitName] = {};
|
|
75953
76058
|
}
|
|
75954
76059
|
data.kits[this.kitName].installedSettings = settings;
|
|
75955
|
-
await
|
|
75956
|
-
await
|
|
76060
|
+
await mkdir22(dirname15(ckJsonPath), { recursive: true });
|
|
76061
|
+
await writeFile18(ckJsonPath, JSON.stringify(data, null, 2), "utf-8");
|
|
75957
76062
|
logger.debug(`Saved installed settings to ${ckJsonPath}`);
|
|
75958
76063
|
} catch (error) {
|
|
75959
76064
|
logger.warning(`Failed to save installed settings: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -75995,17 +76100,14 @@ init_settings_merger();
|
|
|
75995
76100
|
init_environment();
|
|
75996
76101
|
init_logger();
|
|
75997
76102
|
var import_fs_extra11 = __toESM(require_lib3(), 1);
|
|
75998
|
-
var import_semver2 = __toESM(require_semver2(), 1);
|
|
75999
76103
|
|
|
76000
76104
|
class SettingsProcessor {
|
|
76001
|
-
static MIN_TEAM_HOOKS_VERSION = "2.1.33";
|
|
76002
76105
|
isGlobal = false;
|
|
76003
76106
|
forceOverwriteSettings = false;
|
|
76004
76107
|
projectDir = "";
|
|
76005
76108
|
kitName = "engineer";
|
|
76006
76109
|
tracker = null;
|
|
76007
76110
|
installingKit;
|
|
76008
|
-
cachedVersion = undefined;
|
|
76009
76111
|
setGlobalFlag(isGlobal) {
|
|
76010
76112
|
this.isGlobal = isGlobal;
|
|
76011
76113
|
}
|
|
@@ -76051,9 +76153,8 @@ class SettingsProcessor {
|
|
|
76051
76153
|
} else {
|
|
76052
76154
|
const formattedContent = this.formatJsonContent(transformedSource);
|
|
76053
76155
|
await import_fs_extra11.writeFile(destFile, formattedContent, "utf-8");
|
|
76054
|
-
let parsedSettings;
|
|
76055
76156
|
try {
|
|
76056
|
-
parsedSettings = JSON.parse(formattedContent);
|
|
76157
|
+
const parsedSettings = JSON.parse(formattedContent);
|
|
76057
76158
|
if (this.forceOverwriteSettings && destExists) {
|
|
76058
76159
|
logger.debug("Force overwrite enabled, replaced settings.json completely");
|
|
76059
76160
|
if (this.tracker) {
|
|
@@ -76062,7 +76163,6 @@ class SettingsProcessor {
|
|
|
76062
76163
|
}
|
|
76063
76164
|
await this.trackInstalledSettings(parsedSettings);
|
|
76064
76165
|
} catch {}
|
|
76065
|
-
await this.injectTeamHooksIfSupported(destFile, parsedSettings);
|
|
76066
76166
|
}
|
|
76067
76167
|
} catch (error) {
|
|
76068
76168
|
logger.error(`Failed to process settings.json: ${error}`);
|
|
@@ -76090,6 +76190,7 @@ class SettingsProcessor {
|
|
|
76090
76190
|
await this.trackInstalledSettings(sourceSettings);
|
|
76091
76191
|
return;
|
|
76092
76192
|
}
|
|
76193
|
+
this.migrateDeprecatedMatchers(destSettings, sourceSettings);
|
|
76093
76194
|
let installedSettings = { hooks: [], mcpServers: [] };
|
|
76094
76195
|
if (this.tracker) {
|
|
76095
76196
|
installedSettings = await this.tracker.loadInstalledSettings();
|
|
@@ -76123,7 +76224,46 @@ class SettingsProcessor {
|
|
|
76123
76224
|
}
|
|
76124
76225
|
await SettingsMerger.writeSettingsFile(destFile, mergeResult.merged);
|
|
76125
76226
|
logger.success("Merged settings.json (user customizations preserved)");
|
|
76126
|
-
|
|
76227
|
+
}
|
|
76228
|
+
migrateDeprecatedMatchers(destSettings, sourceSettings) {
|
|
76229
|
+
if (!destSettings.hooks || !sourceSettings.hooks)
|
|
76230
|
+
return;
|
|
76231
|
+
for (const [eventName, sourceEntries] of Object.entries(sourceSettings.hooks)) {
|
|
76232
|
+
const destEntries = destSettings.hooks[eventName];
|
|
76233
|
+
if (!destEntries)
|
|
76234
|
+
continue;
|
|
76235
|
+
for (const sourceEntry of sourceEntries) {
|
|
76236
|
+
if (!("matcher" in sourceEntry) || !sourceEntry.matcher)
|
|
76237
|
+
continue;
|
|
76238
|
+
if (!("hooks" in sourceEntry) || !sourceEntry.hooks)
|
|
76239
|
+
continue;
|
|
76240
|
+
const sourceCommands = new Set(sourceEntry.hooks.map((h2) => normalizeCommand(h2.command)).filter((c2) => c2.length > 0));
|
|
76241
|
+
if (sourceCommands.size === 0)
|
|
76242
|
+
continue;
|
|
76243
|
+
for (const destEntry of destEntries) {
|
|
76244
|
+
if (!("matcher" in destEntry))
|
|
76245
|
+
continue;
|
|
76246
|
+
if (destEntry.matcher === sourceEntry.matcher)
|
|
76247
|
+
continue;
|
|
76248
|
+
if (!("hooks" in destEntry) || !destEntry.hooks)
|
|
76249
|
+
continue;
|
|
76250
|
+
const destCommands = destEntry.hooks.map((h2) => normalizeCommand(h2.command)).filter((c2) => c2.length > 0);
|
|
76251
|
+
const hasOverlap = destCommands.some((cmd) => sourceCommands.has(cmd));
|
|
76252
|
+
if (!hasOverlap)
|
|
76253
|
+
continue;
|
|
76254
|
+
const oldMatcher = destEntry.matcher;
|
|
76255
|
+
destEntry.matcher = sourceEntry.matcher;
|
|
76256
|
+
for (const destHook of destEntry.hooks) {
|
|
76257
|
+
const normalizedDest = normalizeCommand(destHook.command);
|
|
76258
|
+
const matchingSource = sourceEntry.hooks.find((sh) => normalizeCommand(sh.command) === normalizedDest);
|
|
76259
|
+
if (matchingSource?.timeout !== undefined) {
|
|
76260
|
+
destHook.timeout = matchingSource.timeout;
|
|
76261
|
+
}
|
|
76262
|
+
}
|
|
76263
|
+
logger.info(`Migrated ${eventName} matcher: "${oldMatcher}" -> "${sourceEntry.matcher}"`);
|
|
76264
|
+
}
|
|
76265
|
+
}
|
|
76266
|
+
}
|
|
76127
76267
|
}
|
|
76128
76268
|
async trackInstalledSettings(settings) {
|
|
76129
76269
|
if (!this.tracker)
|
|
@@ -76195,80 +76335,6 @@ class SettingsProcessor {
|
|
|
76195
76335
|
}
|
|
76196
76336
|
return transformed;
|
|
76197
76337
|
}
|
|
76198
|
-
detectClaudeCodeVersion() {
|
|
76199
|
-
if (this.cachedVersion !== undefined)
|
|
76200
|
-
return this.cachedVersion;
|
|
76201
|
-
try {
|
|
76202
|
-
const output2 = execSync4("claude --version", {
|
|
76203
|
-
encoding: "utf-8",
|
|
76204
|
-
timeout: 5000,
|
|
76205
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
76206
|
-
});
|
|
76207
|
-
const match2 = output2.match(/(\d+\.\d+\.\d+)/);
|
|
76208
|
-
this.cachedVersion = match2 ? match2[1] : null;
|
|
76209
|
-
} catch {
|
|
76210
|
-
this.cachedVersion = null;
|
|
76211
|
-
}
|
|
76212
|
-
return this.cachedVersion;
|
|
76213
|
-
}
|
|
76214
|
-
isVersionAtLeast(version, minimum) {
|
|
76215
|
-
const coerced = import_semver2.default.coerce(version);
|
|
76216
|
-
if (!coerced)
|
|
76217
|
-
return false;
|
|
76218
|
-
return import_semver2.default.gte(coerced, minimum);
|
|
76219
|
-
}
|
|
76220
|
-
async injectTeamHooksIfSupported(destFile, existingSettings) {
|
|
76221
|
-
const version = this.detectClaudeCodeVersion();
|
|
76222
|
-
if (!version) {
|
|
76223
|
-
logger.debug("Claude Code version not detected, skipping team hooks injection");
|
|
76224
|
-
return;
|
|
76225
|
-
}
|
|
76226
|
-
if (!this.isVersionAtLeast(version, SettingsProcessor.MIN_TEAM_HOOKS_VERSION)) {
|
|
76227
|
-
logger.debug(`Claude Code ${version} does not support team hooks (requires >= 2.1.33), skipping injection`);
|
|
76228
|
-
return;
|
|
76229
|
-
}
|
|
76230
|
-
logger.debug(`Claude Code ${version} detected, checking team hooks`);
|
|
76231
|
-
const settings = existingSettings ?? await SettingsMerger.readSettingsFile(destFile);
|
|
76232
|
-
if (!settings) {
|
|
76233
|
-
logger.warning("Failed to read settings file for team hooks injection");
|
|
76234
|
-
return;
|
|
76235
|
-
}
|
|
76236
|
-
const prefix = this.isGlobal ? isWindows() ? "%USERPROFILE%" : "$HOME" : isWindows() ? "%CLAUDE_PROJECT_DIR%" : "$CLAUDE_PROJECT_DIR";
|
|
76237
|
-
if (!settings.hooks) {
|
|
76238
|
-
settings.hooks = {};
|
|
76239
|
-
}
|
|
76240
|
-
let injected = false;
|
|
76241
|
-
const installedSettings = this.tracker ? await this.tracker.loadInstalledSettings() : { hooks: [], mcpServers: [] };
|
|
76242
|
-
const teamHooks = [
|
|
76243
|
-
{ event: "TaskCompleted", handler: "task-completed-handler.cjs" },
|
|
76244
|
-
{ event: "TeammateIdle", handler: "teammate-idle-handler.cjs" }
|
|
76245
|
-
];
|
|
76246
|
-
for (const { event, handler } of teamHooks) {
|
|
76247
|
-
const hookCommand = `node ${prefix}/.claude/hooks/${handler}`;
|
|
76248
|
-
const eventHooks = settings.hooks[event];
|
|
76249
|
-
if (eventHooks && eventHooks.length > 0)
|
|
76250
|
-
continue;
|
|
76251
|
-
if (this.tracker?.wasHookInstalled(hookCommand, installedSettings)) {
|
|
76252
|
-
logger.debug(`Skipping ${event} hook injection (previously removed by user)`);
|
|
76253
|
-
continue;
|
|
76254
|
-
}
|
|
76255
|
-
settings.hooks[event] = [{ hooks: [{ type: "command", command: hookCommand }] }];
|
|
76256
|
-
logger.info(`Injected ${event} hook`);
|
|
76257
|
-
injected = true;
|
|
76258
|
-
if (this.tracker) {
|
|
76259
|
-
this.tracker.trackHook(hookCommand, installedSettings);
|
|
76260
|
-
}
|
|
76261
|
-
}
|
|
76262
|
-
if (injected) {
|
|
76263
|
-
await SettingsMerger.writeSettingsFile(destFile, settings);
|
|
76264
|
-
if (this.tracker) {
|
|
76265
|
-
await this.tracker.saveInstalledSettings(installedSettings);
|
|
76266
|
-
}
|
|
76267
|
-
logger.success("Team hooks injected successfully");
|
|
76268
|
-
} else {
|
|
76269
|
-
logger.debug("Team hooks already present, no injection needed");
|
|
76270
|
-
}
|
|
76271
|
-
}
|
|
76272
76338
|
}
|
|
76273
76339
|
|
|
76274
76340
|
// src/domains/installation/merger/copy-executor.ts
|
|
@@ -77205,12 +77271,12 @@ class FileScanner2 {
|
|
|
77205
77271
|
// src/services/transformers/commands-prefix/prefix-applier.ts
|
|
77206
77272
|
init_logger();
|
|
77207
77273
|
var import_fs_extra17 = __toESM(require_lib3(), 1);
|
|
77208
|
-
import { lstat as lstat7, mkdir as
|
|
77274
|
+
import { lstat as lstat7, mkdir as mkdir23, readdir as readdir17, stat as stat15 } from "node:fs/promises";
|
|
77209
77275
|
import { join as join74 } from "node:path";
|
|
77210
77276
|
|
|
77211
77277
|
// src/services/transformers/commands-prefix/content-transformer.ts
|
|
77212
77278
|
init_logger();
|
|
77213
|
-
import { readFile as readFile33, readdir as readdir16, writeFile as
|
|
77279
|
+
import { readFile as readFile33, readdir as readdir16, writeFile as writeFile22 } from "node:fs/promises";
|
|
77214
77280
|
import { join as join73 } from "node:path";
|
|
77215
77281
|
var TRANSFORMABLE_EXTENSIONS = new Set([
|
|
77216
77282
|
".md",
|
|
@@ -77286,7 +77352,7 @@ async function transformCommandReferences(directory, options2 = {}) {
|
|
|
77286
77352
|
if (options2.dryRun) {
|
|
77287
77353
|
logger.debug(`[dry-run] Would transform ${changes} command ref(s) in ${fullPath}`);
|
|
77288
77354
|
} else {
|
|
77289
|
-
await
|
|
77355
|
+
await writeFile22(fullPath, transformed, "utf-8");
|
|
77290
77356
|
if (options2.verbose) {
|
|
77291
77357
|
logger.verbose(`Transformed ${changes} command ref(s) in ${fullPath}`);
|
|
77292
77358
|
}
|
|
@@ -77371,9 +77437,9 @@ async function applyPrefix(extractDir) {
|
|
|
77371
77437
|
}
|
|
77372
77438
|
await import_fs_extra17.copy(commandsDir, backupDir);
|
|
77373
77439
|
logger.verbose("Created backup of commands directory");
|
|
77374
|
-
await
|
|
77440
|
+
await mkdir23(tempDir, { recursive: true });
|
|
77375
77441
|
const ckDir = join74(tempDir, "ck");
|
|
77376
|
-
await
|
|
77442
|
+
await mkdir23(ckDir, { recursive: true });
|
|
77377
77443
|
let processedCount = 0;
|
|
77378
77444
|
for (const entry of entries) {
|
|
77379
77445
|
const sourcePath = join74(commandsDir, entry);
|
|
@@ -77811,7 +77877,7 @@ init_skip_directories();
|
|
|
77811
77877
|
init_types2();
|
|
77812
77878
|
var import_fs_extra21 = __toESM(require_lib3(), 1);
|
|
77813
77879
|
import { createHash as createHash2 } from "node:crypto";
|
|
77814
|
-
import { readFile as readFile35, readdir as readdir20, writeFile as
|
|
77880
|
+
import { readFile as readFile35, readdir as readdir20, writeFile as writeFile23 } from "node:fs/promises";
|
|
77815
77881
|
import { join as join78, relative as relative12 } from "node:path";
|
|
77816
77882
|
|
|
77817
77883
|
class SkillsManifestManager {
|
|
@@ -77835,7 +77901,7 @@ class SkillsManifestManager {
|
|
|
77835
77901
|
}
|
|
77836
77902
|
static async writeManifest(skillsDir2, manifest) {
|
|
77837
77903
|
const manifestPath = join78(skillsDir2, SkillsManifestManager.MANIFEST_FILENAME);
|
|
77838
|
-
await
|
|
77904
|
+
await writeFile23(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
77839
77905
|
logger.debug(`Wrote manifest to: ${manifestPath}`);
|
|
77840
77906
|
}
|
|
77841
77907
|
static async readManifest(skillsDir2) {
|
|
@@ -78228,7 +78294,7 @@ import { join as join84 } from "node:path";
|
|
|
78228
78294
|
|
|
78229
78295
|
// src/domains/skills/migrator/migration-executor.ts
|
|
78230
78296
|
init_logger();
|
|
78231
|
-
import { copyFile as copyFile5, mkdir as
|
|
78297
|
+
import { copyFile as copyFile5, mkdir as mkdir24, readdir as readdir22, rm as rm5 } from "node:fs/promises";
|
|
78232
78298
|
import { join as join80 } from "node:path";
|
|
78233
78299
|
var import_fs_extra24 = __toESM(require_lib3(), 1);
|
|
78234
78300
|
|
|
@@ -78391,7 +78457,7 @@ Detected changes:`;
|
|
|
78391
78457
|
|
|
78392
78458
|
// src/domains/skills/migrator/migration-executor.ts
|
|
78393
78459
|
async function copySkillDirectory(sourceDir, destDir) {
|
|
78394
|
-
await
|
|
78460
|
+
await mkdir24(destDir, { recursive: true });
|
|
78395
78461
|
const entries = await readdir22(sourceDir, { withFileTypes: true });
|
|
78396
78462
|
for (const entry of entries) {
|
|
78397
78463
|
const sourcePath = join80(sourceDir, entry.name);
|
|
@@ -78411,7 +78477,7 @@ async function executeInternal(mappings, customizations, currentSkillsDir, inter
|
|
|
78411
78477
|
const preserved = [];
|
|
78412
78478
|
const errors2 = [];
|
|
78413
78479
|
const tempDir = join80(currentSkillsDir, "..", ".skills-migration-temp");
|
|
78414
|
-
await
|
|
78480
|
+
await mkdir24(tempDir, { recursive: true });
|
|
78415
78481
|
try {
|
|
78416
78482
|
for (const mapping of mappings) {
|
|
78417
78483
|
try {
|
|
@@ -78433,7 +78499,7 @@ async function executeInternal(mappings, customizations, currentSkillsDir, inter
|
|
|
78433
78499
|
const category = mapping.category;
|
|
78434
78500
|
const targetPath = category ? join80(tempDir, category, skillName) : join80(tempDir, skillName);
|
|
78435
78501
|
if (category) {
|
|
78436
|
-
await
|
|
78502
|
+
await mkdir24(join80(tempDir, category), { recursive: true });
|
|
78437
78503
|
}
|
|
78438
78504
|
await copySkillDirectory(currentSkillPath, targetPath);
|
|
78439
78505
|
migrated.push(skillName);
|
|
@@ -78452,7 +78518,7 @@ async function executeInternal(mappings, customizations, currentSkillsDir, inter
|
|
|
78452
78518
|
}
|
|
78453
78519
|
}
|
|
78454
78520
|
await rm5(currentSkillsDir, { recursive: true, force: true });
|
|
78455
|
-
await
|
|
78521
|
+
await mkdir24(currentSkillsDir, { recursive: true });
|
|
78456
78522
|
await copySkillDirectory(tempDir, currentSkillsDir);
|
|
78457
78523
|
await rm5(tempDir, { recursive: true, force: true });
|
|
78458
78524
|
return { migrated, preserved, errors: errors2 };
|
|
@@ -78499,7 +78565,7 @@ function validateMigrationPath(path12, paramName) {
|
|
|
78499
78565
|
init_logger();
|
|
78500
78566
|
init_types2();
|
|
78501
78567
|
var import_fs_extra25 = __toESM(require_lib3(), 1);
|
|
78502
|
-
import { copyFile as copyFile6, mkdir as
|
|
78568
|
+
import { copyFile as copyFile6, mkdir as mkdir25, readdir as readdir23, rm as rm6, stat as stat16 } from "node:fs/promises";
|
|
78503
78569
|
import { basename as basename8, join as join81, normalize as normalize8 } from "node:path";
|
|
78504
78570
|
function validatePath2(path12, paramName) {
|
|
78505
78571
|
if (!path12 || typeof path12 !== "string") {
|
|
@@ -78529,7 +78595,7 @@ class SkillsBackupManager {
|
|
|
78529
78595
|
const backupDir = parentDir ? join81(parentDir, backupDirName) : join81(skillsDir2, "..", backupDirName);
|
|
78530
78596
|
logger.info(`Creating backup at: ${backupDir}`);
|
|
78531
78597
|
try {
|
|
78532
|
-
await
|
|
78598
|
+
await mkdir25(backupDir, { recursive: true });
|
|
78533
78599
|
await SkillsBackupManager.copyDirectory(skillsDir2, backupDir);
|
|
78534
78600
|
logger.success("Backup created successfully");
|
|
78535
78601
|
return backupDir;
|
|
@@ -78551,7 +78617,7 @@ class SkillsBackupManager {
|
|
|
78551
78617
|
if (await import_fs_extra25.pathExists(targetDir)) {
|
|
78552
78618
|
await rm6(targetDir, { recursive: true, force: true });
|
|
78553
78619
|
}
|
|
78554
|
-
await
|
|
78620
|
+
await mkdir25(targetDir, { recursive: true });
|
|
78555
78621
|
await SkillsBackupManager.copyDirectory(backupDir, targetDir);
|
|
78556
78622
|
logger.success("Backup restored successfully");
|
|
78557
78623
|
} catch (error) {
|
|
@@ -78611,7 +78677,7 @@ class SkillsBackupManager {
|
|
|
78611
78677
|
continue;
|
|
78612
78678
|
}
|
|
78613
78679
|
if (entry.isDirectory()) {
|
|
78614
|
-
await
|
|
78680
|
+
await mkdir25(destPath, { recursive: true });
|
|
78615
78681
|
await SkillsBackupManager.copyDirectory(sourcePath, destPath);
|
|
78616
78682
|
} else if (entry.isFile()) {
|
|
78617
78683
|
await copyFile6(sourcePath, destPath);
|
|
@@ -79030,7 +79096,7 @@ import { join as join87 } from "node:path";
|
|
|
79030
79096
|
|
|
79031
79097
|
// src/services/transformers/opencode-path-transformer.ts
|
|
79032
79098
|
init_logger();
|
|
79033
|
-
import { readFile as readFile37, readdir as readdir26, writeFile as
|
|
79099
|
+
import { readFile as readFile37, readdir as readdir26, writeFile as writeFile24 } from "node:fs/promises";
|
|
79034
79100
|
import { platform as platform12 } from "node:os";
|
|
79035
79101
|
import { extname as extname3, join as join86 } from "node:path";
|
|
79036
79102
|
var IS_WINDOWS3 = platform12() === "win32";
|
|
@@ -79104,7 +79170,7 @@ async function transformPathsForGlobalOpenCode(directory, options2 = {}) {
|
|
|
79104
79170
|
const content = await readFile37(fullPath, "utf-8");
|
|
79105
79171
|
const { transformed, changes } = transformOpenCodeContent(content);
|
|
79106
79172
|
if (changes > 0) {
|
|
79107
|
-
await
|
|
79173
|
+
await writeFile24(fullPath, transformed, "utf-8");
|
|
79108
79174
|
filesTransformed++;
|
|
79109
79175
|
totalChanges += changes;
|
|
79110
79176
|
if (options2.verbose) {
|
|
@@ -79325,7 +79391,7 @@ async function handlePostInstall(ctx) {
|
|
|
79325
79391
|
// src/commands/init/phases/selection-handler.ts
|
|
79326
79392
|
init_config_manager();
|
|
79327
79393
|
init_github_client();
|
|
79328
|
-
import { mkdir as
|
|
79394
|
+
import { mkdir as mkdir26 } from "node:fs/promises";
|
|
79329
79395
|
import { join as join90, resolve as resolve15 } from "node:path";
|
|
79330
79396
|
|
|
79331
79397
|
// src/domains/github/kit-access-checker.ts
|
|
@@ -79848,7 +79914,7 @@ async function handleSelection(ctx) {
|
|
|
79848
79914
|
}
|
|
79849
79915
|
if (!await import_fs_extra32.pathExists(resolvedDir)) {
|
|
79850
79916
|
if (ctx.options.global) {
|
|
79851
|
-
await
|
|
79917
|
+
await mkdir26(resolvedDir, { recursive: true });
|
|
79852
79918
|
logger.info(`Created global directory: ${resolvedDir}`);
|
|
79853
79919
|
} else {
|
|
79854
79920
|
logger.error(`Directory does not exist: ${resolvedDir}`);
|
|
@@ -79983,7 +80049,7 @@ async function handleSelection(ctx) {
|
|
|
79983
80049
|
};
|
|
79984
80050
|
}
|
|
79985
80051
|
// src/commands/init/phases/sync-handler.ts
|
|
79986
|
-
import { copyFile as copyFile7, mkdir as
|
|
80052
|
+
import { copyFile as copyFile7, mkdir as mkdir27, open as open4, readFile as readFile39, rename as rename3, stat as stat17, unlink as unlink8, writeFile as writeFile26 } from "node:fs/promises";
|
|
79987
80053
|
import { dirname as dirname18, join as join91, resolve as resolve16 } from "node:path";
|
|
79988
80054
|
init_logger();
|
|
79989
80055
|
init_path_resolver();
|
|
@@ -80103,7 +80169,7 @@ async function acquireSyncLock(global3) {
|
|
|
80103
80169
|
const lockPath = join91(cacheDir, ".sync-lock");
|
|
80104
80170
|
const startTime = Date.now();
|
|
80105
80171
|
const lockTimeout = getLockTimeout();
|
|
80106
|
-
await
|
|
80172
|
+
await mkdir27(dirname18(lockPath), { recursive: true });
|
|
80107
80173
|
while (Date.now() - startTime < lockTimeout) {
|
|
80108
80174
|
try {
|
|
80109
80175
|
const handle = await open4(lockPath, "wx");
|
|
@@ -80183,7 +80249,7 @@ async function executeSyncMerge(ctx) {
|
|
|
80183
80249
|
const targetPath = await validateSyncPath(ctx.claudeDir, file.path);
|
|
80184
80250
|
const targetDir = join91(targetPath, "..");
|
|
80185
80251
|
try {
|
|
80186
|
-
await
|
|
80252
|
+
await mkdir27(targetDir, { recursive: true });
|
|
80187
80253
|
} catch (mkdirError) {
|
|
80188
80254
|
const errCode = mkdirError.code;
|
|
80189
80255
|
if (errCode === "ENOSPC") {
|
|
@@ -80262,7 +80328,7 @@ async function executeSyncMerge(ctx) {
|
|
|
80262
80328
|
try {
|
|
80263
80329
|
const tempPath = `${currentPath}.tmp.${Date.now()}`;
|
|
80264
80330
|
try {
|
|
80265
|
-
await
|
|
80331
|
+
await writeFile26(tempPath, result.result, "utf-8");
|
|
80266
80332
|
await rename3(tempPath, currentPath);
|
|
80267
80333
|
} catch (atomicError) {
|
|
80268
80334
|
await unlink8(tempPath).catch(() => {});
|
|
@@ -80346,14 +80412,14 @@ function displaySyncPlan(plan) {
|
|
|
80346
80412
|
console.log(import_picocolors21.default.dim("─".repeat(40)));
|
|
80347
80413
|
}
|
|
80348
80414
|
async function createBackup(claudeDir2, files, backupDir) {
|
|
80349
|
-
await
|
|
80415
|
+
await mkdir27(backupDir, { recursive: true });
|
|
80350
80416
|
for (const file of files) {
|
|
80351
80417
|
try {
|
|
80352
80418
|
const sourcePath = await validateSyncPath(claudeDir2, file.path);
|
|
80353
80419
|
if (await import_fs_extra33.pathExists(sourcePath)) {
|
|
80354
80420
|
const targetPath = await validateSyncPath(backupDir, file.path);
|
|
80355
80421
|
const targetDir = join91(targetPath, "..");
|
|
80356
|
-
await
|
|
80422
|
+
await mkdir27(targetDir, { recursive: true });
|
|
80357
80423
|
await copyFile7(sourcePath, targetPath);
|
|
80358
80424
|
}
|
|
80359
80425
|
} catch (error) {
|
|
@@ -80449,7 +80515,7 @@ async function renameFolders(dirsToRename, extractDir, options2) {
|
|
|
80449
80515
|
// src/services/transformers/folder-transform/path-replacer.ts
|
|
80450
80516
|
init_logger();
|
|
80451
80517
|
init_types2();
|
|
80452
|
-
import { readFile as readFile40, readdir as readdir28, writeFile as
|
|
80518
|
+
import { readFile as readFile40, readdir as readdir28, writeFile as writeFile27 } from "node:fs/promises";
|
|
80453
80519
|
import { join as join93, relative as relative16 } from "node:path";
|
|
80454
80520
|
var TRANSFORMABLE_FILE_PATTERNS = [
|
|
80455
80521
|
".md",
|
|
@@ -80532,7 +80598,7 @@ async function transformFileContents(dir, compiledReplacements, options2) {
|
|
|
80532
80598
|
if (options2.dryRun) {
|
|
80533
80599
|
logger.debug(`[dry-run] Would update ${relative16(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
80534
80600
|
} else {
|
|
80535
|
-
await
|
|
80601
|
+
await writeFile27(fullPath, newContent, "utf-8");
|
|
80536
80602
|
logger.debug(`Updated ${relative16(dir, fullPath)}: ${changeCount} replacement(s)`);
|
|
80537
80603
|
}
|
|
80538
80604
|
filesChanged++;
|
|
@@ -80638,7 +80704,7 @@ async function transformFolderPaths(extractDir, folders, options2 = {}) {
|
|
|
80638
80704
|
|
|
80639
80705
|
// src/services/transformers/global-path-transformer.ts
|
|
80640
80706
|
init_logger();
|
|
80641
|
-
import { readFile as readFile41, readdir as readdir29, writeFile as
|
|
80707
|
+
import { readFile as readFile41, readdir as readdir29, writeFile as writeFile28 } from "node:fs/promises";
|
|
80642
80708
|
import { platform as platform13 } from "node:os";
|
|
80643
80709
|
import { extname as extname4, join as join94 } from "node:path";
|
|
80644
80710
|
var IS_WINDOWS4 = platform13() === "win32";
|
|
@@ -80761,7 +80827,7 @@ async function transformPathsForGlobalInstall(directory, options2 = {}) {
|
|
|
80761
80827
|
const content = await readFile41(fullPath, "utf-8");
|
|
80762
80828
|
const { transformed, changes } = transformContent(content);
|
|
80763
80829
|
if (changes > 0) {
|
|
80764
|
-
await
|
|
80830
|
+
await writeFile28(fullPath, transformed, "utf-8");
|
|
80765
80831
|
filesTransformed++;
|
|
80766
80832
|
totalChanges += changes;
|
|
80767
80833
|
if (options2.verbose) {
|
|
@@ -81619,10 +81685,10 @@ init_dist2();
|
|
|
81619
81685
|
|
|
81620
81686
|
// src/commands/setup/phases/preflight-check.ts
|
|
81621
81687
|
init_dist2();
|
|
81622
|
-
import { execSync as
|
|
81688
|
+
import { execSync as execSync4 } from "node:child_process";
|
|
81623
81689
|
function isGhInstalled() {
|
|
81624
81690
|
try {
|
|
81625
|
-
|
|
81691
|
+
execSync4("gh --version", { stdio: "pipe" });
|
|
81626
81692
|
return true;
|
|
81627
81693
|
} catch {
|
|
81628
81694
|
return false;
|
|
@@ -81630,7 +81696,7 @@ function isGhInstalled() {
|
|
|
81630
81696
|
}
|
|
81631
81697
|
function checkGhAuth() {
|
|
81632
81698
|
try {
|
|
81633
|
-
|
|
81699
|
+
execSync4("gh auth status", { stdio: "pipe" });
|
|
81634
81700
|
return true;
|
|
81635
81701
|
} catch {
|
|
81636
81702
|
return false;
|
|
@@ -81647,11 +81713,11 @@ function checkNodeVersion() {
|
|
|
81647
81713
|
}
|
|
81648
81714
|
function checkPython() {
|
|
81649
81715
|
try {
|
|
81650
|
-
|
|
81716
|
+
execSync4("python3 --version", { stdio: "pipe" });
|
|
81651
81717
|
return true;
|
|
81652
81718
|
} catch {
|
|
81653
81719
|
try {
|
|
81654
|
-
|
|
81720
|
+
execSync4("python --version", { stdio: "pipe" });
|
|
81655
81721
|
return true;
|
|
81656
81722
|
} catch {
|
|
81657
81723
|
return false;
|
|
@@ -82374,7 +82440,7 @@ async function detectInstallations() {
|
|
|
82374
82440
|
|
|
82375
82441
|
// src/commands/uninstall/removal-handler.ts
|
|
82376
82442
|
import { readdirSync as readdirSync5, rmSync as rmSync5 } from "node:fs";
|
|
82377
|
-
import { join as join99, resolve as resolve19, sep as
|
|
82443
|
+
import { join as join99, resolve as resolve19, sep as sep3 } from "node:path";
|
|
82378
82444
|
init_logger();
|
|
82379
82445
|
init_safe_prompts();
|
|
82380
82446
|
init_safe_spinner();
|
|
@@ -82517,7 +82583,7 @@ async function isPathSafeToRemove(filePath, baseDir) {
|
|
|
82517
82583
|
try {
|
|
82518
82584
|
const resolvedPath = resolve19(filePath);
|
|
82519
82585
|
const resolvedBase = resolve19(baseDir);
|
|
82520
|
-
if (!resolvedPath.startsWith(resolvedBase +
|
|
82586
|
+
if (!resolvedPath.startsWith(resolvedBase + sep3) && resolvedPath !== resolvedBase) {
|
|
82521
82587
|
logger.debug(`Path outside installation directory: ${filePath}`);
|
|
82522
82588
|
return false;
|
|
82523
82589
|
}
|
|
@@ -82525,7 +82591,7 @@ async function isPathSafeToRemove(filePath, baseDir) {
|
|
|
82525
82591
|
if (stats.isSymbolicLink()) {
|
|
82526
82592
|
const realPath = await import_fs_extra37.realpath(filePath);
|
|
82527
82593
|
const resolvedReal = resolve19(realPath);
|
|
82528
|
-
if (!resolvedReal.startsWith(resolvedBase +
|
|
82594
|
+
if (!resolvedReal.startsWith(resolvedBase + sep3) && resolvedReal !== resolvedBase) {
|
|
82529
82595
|
logger.debug(`Symlink points outside installation directory: ${filePath} -> ${realPath}`);
|
|
82530
82596
|
return false;
|
|
82531
82597
|
}
|