@synkro-sh/cli 1.7.62 → 1.7.63

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/bootstrap.js CHANGED
@@ -132,7 +132,7 @@ function getIdentity() {
132
132
  if (cached2) return cached2;
133
133
  let cliVersion = "0.0.0";
134
134
  try {
135
- cliVersion = "1.7.62";
135
+ cliVersion = "1.7.63";
136
136
  } catch {
137
137
  }
138
138
  const creds = loadCredentialsIdentity();
@@ -1388,11 +1388,45 @@ var init_agentDetect = __esm({
1388
1388
  }
1389
1389
  });
1390
1390
 
1391
+ // cli/installer/platform.ts
1392
+ import { existsSync as existsSync10 } from "fs";
1393
+ import { homedir as homedir8 } from "os";
1394
+ import { join as join8 } from "path";
1395
+ import { spawnSync } from "child_process";
1396
+ function resolveBunBin() {
1397
+ const finder = IS_WINDOWS ? "where" : "which";
1398
+ const r = spawnSync(finder, ["bun"], { encoding: "utf-8", timeout: 5e3 });
1399
+ const resolved = (r.stdout || "").split(/\r?\n/).map((s) => s.trim()).find(Boolean);
1400
+ if (resolved) return resolved;
1401
+ const home = process.env.USERPROFILE || homedir8();
1402
+ const candidates = IS_WINDOWS ? [join8(home, ".bun", "bin", "bun.exe"), "C:\\Program Files\\bun\\bin\\bun.exe"] : ["/opt/homebrew/bin/bun", "/usr/local/bin/bun", join8(home, ".bun", "bin", "bun")];
1403
+ for (const p of candidates) if (existsSync10(p)) return p;
1404
+ return IS_WINDOWS ? "bun.exe" : "bun";
1405
+ }
1406
+ function quoteArg(s) {
1407
+ return IS_WINDOWS ? `"${s}"` : "'" + s.replace(/'/g, "'\\''") + "'";
1408
+ }
1409
+ function ccHookCommand(scriptPath) {
1410
+ if (!IS_WINDOWS) return scriptPath;
1411
+ return `${quoteArg(resolveBunBin())} ${quoteArg(scriptPath)}`;
1412
+ }
1413
+ function isSynkroHookCommand(command) {
1414
+ if (typeof command !== "string") return false;
1415
+ return command.replace(/\\/g, "/").includes("/.synkro/hooks/");
1416
+ }
1417
+ var IS_WINDOWS;
1418
+ var init_platform = __esm({
1419
+ "cli/installer/platform.ts"() {
1420
+ "use strict";
1421
+ IS_WINDOWS = process.platform === "win32";
1422
+ }
1423
+ });
1424
+
1391
1425
  // cli/installer/ccHookConfig.ts
1392
- import { existsSync as existsSync10, readFileSync as readFileSync8, writeFileSync as writeFileSync6, renameSync as renameSync3, mkdirSync as mkdirSync4 } from "fs";
1426
+ import { existsSync as existsSync11, readFileSync as readFileSync8, writeFileSync as writeFileSync6, renameSync as renameSync3, mkdirSync as mkdirSync4 } from "fs";
1393
1427
  import { dirname } from "path";
1394
1428
  function readSettings(path) {
1395
- if (!existsSync10(path)) return {};
1429
+ if (!existsSync11(path)) return {};
1396
1430
  try {
1397
1431
  const raw = readFileSync8(path, "utf-8");
1398
1432
  return JSON.parse(raw);
@@ -1409,9 +1443,19 @@ function writeSettingsAtomic(path, settings) {
1409
1443
  function isSynkroEntry(entry) {
1410
1444
  if (entry?.[SYNKRO_MARKER]) return true;
1411
1445
  const hooks = Array.isArray(entry?.hooks) ? entry.hooks : [];
1412
- return hooks.some(
1413
- (h) => typeof h?.command === "string" && h.command.includes("/.synkro/hooks/")
1414
- );
1446
+ return hooks.some((h) => isSynkroHookCommand(h?.command));
1447
+ }
1448
+ function finalizeHookCommands(hooks) {
1449
+ for (const evt of Object.keys(hooks)) {
1450
+ const arr = hooks[evt];
1451
+ if (!Array.isArray(arr)) continue;
1452
+ for (const entry of arr) {
1453
+ if (!entry?.[SYNKRO_MARKER] || !Array.isArray(entry.hooks)) continue;
1454
+ for (const h of entry.hooks) {
1455
+ if (typeof h?.command === "string") h.command = ccHookCommand(h.command);
1456
+ }
1457
+ }
1458
+ }
1415
1459
  }
1416
1460
  function removeSynkroEntries(events, eventName) {
1417
1461
  if (!events) return;
@@ -1592,10 +1636,11 @@ function installCCHooks(settingsPath, config) {
1592
1636
  delete settings.env.ANTHROPIC_BASE_URL;
1593
1637
  if (Object.keys(settings.env).length === 0) delete settings.env;
1594
1638
  }
1639
+ finalizeHookCommands(settings.hooks);
1595
1640
  writeSettingsAtomic(settingsPath, settings);
1596
1641
  }
1597
1642
  function uninstallCCHooks(settingsPath) {
1598
- if (!existsSync10(settingsPath)) return false;
1643
+ if (!existsSync11(settingsPath)) return false;
1599
1644
  const settings = readSettings(settingsPath);
1600
1645
  if (!settings.hooks) return false;
1601
1646
  const events = ["PreToolUse", "PostToolUse", "SessionEnd", "SessionStart", "Stop", "UserPromptSubmit"];
@@ -1621,6 +1666,7 @@ var SYNKRO_MARKER, USAGE_PROXY_URL;
1621
1666
  var init_ccHookConfig = __esm({
1622
1667
  "cli/installer/ccHookConfig.ts"() {
1623
1668
  "use strict";
1669
+ init_platform();
1624
1670
  SYNKRO_MARKER = "__synkro_managed__";
1625
1671
  USAGE_PROXY_URL = `http://127.0.0.1:${process.env.SYNKRO_HOST_USAGE_PROXY_PORT || "18927"}`;
1626
1672
  }
@@ -1629,7 +1675,7 @@ var init_ccHookConfig = __esm({
1629
1675
  // cli/installer/cursorHookConfig.ts
1630
1676
  import { readFileSync as readFileSync9, writeFileSync as writeFileSync7, renameSync as renameSync4, mkdirSync as mkdirSync5 } from "fs";
1631
1677
  import { dirname as dirname2, resolve, normalize } from "path";
1632
- import { homedir as homedir8 } from "os";
1678
+ import { homedir as homedir9 } from "os";
1633
1679
  function shellQuote(s) {
1634
1680
  return "'" + s.replace(/'/g, "'\\''") + "'";
1635
1681
  }
@@ -1665,7 +1711,7 @@ function writeHooksFileAtomic(rawPath, data) {
1665
1711
  }
1666
1712
  function isSynkroEntry2(entry) {
1667
1713
  if (entry?.[SYNKRO_MARKER2]) return true;
1668
- return typeof entry?.command === "string" && entry.command.includes("/.synkro/hooks/");
1714
+ return isSynkroHookCommand(entry?.command);
1669
1715
  }
1670
1716
  function removeSynkroEntries2(hooks, event) {
1671
1717
  if (!hooks) return;
@@ -1828,10 +1874,11 @@ var SYNKRO_MARKER2, ALLOWED_PARENT_DIRS, ALL_EVENTS;
1828
1874
  var init_cursorHookConfig = __esm({
1829
1875
  "cli/installer/cursorHookConfig.ts"() {
1830
1876
  "use strict";
1877
+ init_platform();
1831
1878
  SYNKRO_MARKER2 = "__synkro_managed__";
1832
1879
  ALLOWED_PARENT_DIRS = [
1833
- resolve(homedir8(), ".cursor"),
1834
- resolve(homedir8(), ".config", "cursor")
1880
+ resolve(homedir9(), ".cursor"),
1881
+ resolve(homedir9(), ".config", "cursor")
1835
1882
  ];
1836
1883
  ALL_EVENTS = [
1837
1884
  "sessionStart",
@@ -1851,13 +1898,12 @@ var init_cursorHookConfig = __esm({
1851
1898
  });
1852
1899
 
1853
1900
  // cli/installer/mcpConfig.ts
1854
- import { existsSync as existsSync11, readFileSync as readFileSync10, writeFileSync as writeFileSync8, renameSync as renameSync5, mkdirSync as mkdirSync6 } from "fs";
1855
- import { homedir as homedir9 } from "os";
1856
- import { dirname as dirname3, join as join8 } from "path";
1857
- import { spawnSync } from "child_process";
1901
+ import { existsSync as existsSync12, readFileSync as readFileSync10, writeFileSync as writeFileSync8, renameSync as renameSync5, mkdirSync as mkdirSync6 } from "fs";
1902
+ import { homedir as homedir10 } from "os";
1903
+ import { dirname as dirname3, join as join9 } from "path";
1858
1904
  import { randomBytes } from "crypto";
1859
1905
  function readClaudeJson() {
1860
- if (!existsSync11(CC_CONFIG_PATH)) return {};
1906
+ if (!existsSync12(CC_CONFIG_PATH)) return {};
1861
1907
  try {
1862
1908
  const raw = readFileSync10(CC_CONFIG_PATH, "utf-8");
1863
1909
  return JSON.parse(raw);
@@ -1878,7 +1924,7 @@ function installMcpConfig(opts) {
1878
1924
  if (entry?.[SYNKRO_MARKER3] === true) delete config.mcpServers[name];
1879
1925
  }
1880
1926
  if (opts.local) {
1881
- const proxyScript = join8(homedir9(), ".synkro", "hooks", "mcp-stdio-proxy.ts");
1927
+ const proxyScript = join9(homedir10(), ".synkro", "hooks", "mcp-stdio-proxy.ts");
1882
1928
  config.mcpServers[SYNKRO_SERVER_NAME] = {
1883
1929
  type: "stdio",
1884
1930
  command: "bun",
@@ -1899,7 +1945,7 @@ function installMcpConfig(opts) {
1899
1945
  return { path: CC_CONFIG_PATH, url };
1900
1946
  }
1901
1947
  function uninstallMcpConfig() {
1902
- if (!existsSync11(CC_CONFIG_PATH)) return false;
1948
+ if (!existsSync12(CC_CONFIG_PATH)) return false;
1903
1949
  const config = readClaudeJson();
1904
1950
  if (!config.mcpServers || Object.keys(config.mcpServers).length === 0) return false;
1905
1951
  let removed = false;
@@ -1915,7 +1961,7 @@ function uninstallMcpConfig() {
1915
1961
  return true;
1916
1962
  }
1917
1963
  function readCursorMcpJson() {
1918
- if (!existsSync11(CURSOR_MCP_PATH)) return {};
1964
+ if (!existsSync12(CURSOR_MCP_PATH)) return {};
1919
1965
  try {
1920
1966
  const raw = readFileSync10(CURSOR_MCP_PATH, "utf-8");
1921
1967
  return JSON.parse(raw);
@@ -1938,7 +1984,7 @@ function installCursorMcpConfig(opts) {
1938
1984
  if (opts.local) {
1939
1985
  const port = process.env.SYNKRO_MCP_PORT || "18931";
1940
1986
  const url2 = `http://127.0.0.1:${port}/`;
1941
- const jwtPath = join8(homedir9(), ".synkro", ".mcp-jwt");
1987
+ const jwtPath = join9(homedir10(), ".synkro", ".mcp-jwt");
1942
1988
  let jwt2 = "";
1943
1989
  try {
1944
1990
  jwt2 = readFileSync10(jwtPath, "utf-8").trim();
@@ -1962,7 +2008,7 @@ function installCursorMcpConfig(opts) {
1962
2008
  return { path: CURSOR_MCP_PATH, url };
1963
2009
  }
1964
2010
  function uninstallCursorMcpConfig() {
1965
- if (!existsSync11(CURSOR_MCP_PATH)) return false;
2011
+ if (!existsSync12(CURSOR_MCP_PATH)) return false;
1966
2012
  const config = readCursorMcpJson();
1967
2013
  if (!config.mcpServers || Object.keys(config.mcpServers).length === 0) return false;
1968
2014
  let removed = false;
@@ -1977,17 +2023,11 @@ function uninstallCursorMcpConfig() {
1977
2023
  writeCursorMcpJsonAtomic(config);
1978
2024
  return true;
1979
2025
  }
1980
- function resolveBunBin() {
1981
- const r = spawnSync("which", ["bun"], { encoding: "utf-8", timeout: 5e3 });
1982
- const resolved = (r.stdout || "").split("\n")[0].trim();
1983
- if (resolved) return resolved;
1984
- for (const p of ["/opt/homebrew/bin/bun", "/usr/local/bin/bun", join8(homedir9(), ".bun", "bin", "bun")]) {
1985
- if (existsSync11(p)) return p;
1986
- }
1987
- return "bun";
2026
+ function resolveBunBin2() {
2027
+ return resolveBunBin();
1988
2028
  }
1989
2029
  function readDesktopJson() {
1990
- if (!existsSync11(CLAUDE_DESKTOP_CONFIG_PATH)) return {};
2030
+ if (!existsSync12(CLAUDE_DESKTOP_CONFIG_PATH)) return {};
1991
2031
  try {
1992
2032
  return JSON.parse(readFileSync10(CLAUDE_DESKTOP_CONFIG_PATH, "utf-8"));
1993
2033
  } catch (err) {
@@ -2001,7 +2041,7 @@ function writeDesktopJsonAtomic(config) {
2001
2041
  renameSync5(tmpPath, CLAUDE_DESKTOP_CONFIG_PATH);
2002
2042
  }
2003
2043
  function installClaudeDesktopMcpConfig() {
2004
- if (!existsSync11(MCP_STDIO_PROXY_PATH)) {
2044
+ if (!existsSync12(MCP_STDIO_PROXY_PATH)) {
2005
2045
  return {
2006
2046
  ok: false,
2007
2047
  path: CLAUDE_DESKTOP_CONFIG_PATH,
@@ -2015,7 +2055,7 @@ function installClaudeDesktopMcpConfig() {
2015
2055
  if (entry?.[SYNKRO_MARKER3] === true) delete config.mcpServers[name];
2016
2056
  }
2017
2057
  config.mcpServers[SYNKRO_SERVER_NAME] = {
2018
- command: resolveBunBin(),
2058
+ command: resolveBunBin2(),
2019
2059
  args: ["run", MCP_STDIO_PROXY_PATH],
2020
2060
  env: { SYNKRO_MCP_PORT: process.env.SYNKRO_MCP_PORT || "18931" },
2021
2061
  [SYNKRO_MARKER3]: true
@@ -2024,7 +2064,7 @@ function installClaudeDesktopMcpConfig() {
2024
2064
  return { ok: true, path: CLAUDE_DESKTOP_CONFIG_PATH, proxy: MCP_STDIO_PROXY_PATH };
2025
2065
  }
2026
2066
  function uninstallClaudeDesktopMcpConfig() {
2027
- if (!existsSync11(CLAUDE_DESKTOP_CONFIG_PATH)) return false;
2067
+ if (!existsSync12(CLAUDE_DESKTOP_CONFIG_PATH)) return false;
2028
2068
  const config = readDesktopJson();
2029
2069
  if (!config.mcpServers || Object.keys(config.mcpServers).length === 0) return false;
2030
2070
  let removed = false;
@@ -2043,26 +2083,27 @@ var SYNKRO_MARKER3, SYNKRO_SERVER_NAME, CC_CONFIG_PATH, CURSOR_MCP_PATH, CLAUDE_
2043
2083
  var init_mcpConfig = __esm({
2044
2084
  "cli/installer/mcpConfig.ts"() {
2045
2085
  "use strict";
2086
+ init_platform();
2046
2087
  SYNKRO_MARKER3 = "__synkro_managed__";
2047
2088
  SYNKRO_SERVER_NAME = "synkro-guardrails";
2048
- CC_CONFIG_PATH = join8(homedir9(), ".claude.json");
2049
- CURSOR_MCP_PATH = join8(homedir9(), ".cursor", "mcp.json");
2050
- CLAUDE_DESKTOP_CONFIG_PATH = join8(
2051
- homedir9(),
2089
+ CC_CONFIG_PATH = join9(homedir10(), ".claude.json");
2090
+ CURSOR_MCP_PATH = join9(homedir10(), ".cursor", "mcp.json");
2091
+ CLAUDE_DESKTOP_CONFIG_PATH = join9(
2092
+ homedir10(),
2052
2093
  "Library",
2053
2094
  "Application Support",
2054
2095
  "Claude",
2055
2096
  "claude_desktop_config.json"
2056
2097
  );
2057
- MCP_STDIO_PROXY_PATH = join8(homedir9(), ".synkro", "hooks", "mcp-stdio-proxy.ts");
2098
+ MCP_STDIO_PROXY_PATH = join9(homedir10(), ".synkro", "hooks", "mcp-stdio-proxy.ts");
2058
2099
  }
2059
2100
  });
2060
2101
 
2061
2102
  // cli/installer/skillParser.ts
2062
- import { existsSync as existsSync12 } from "fs";
2103
+ import { existsSync as existsSync13 } from "fs";
2063
2104
  import { resolve as resolve2 } from "path";
2064
2105
  function resolveSkillPaths(skills, repoRoot) {
2065
- return skills.filter((s) => s.endsWith(".md")).map((s) => resolve2(repoRoot, s)).filter((p) => existsSync12(p));
2106
+ return skills.filter((s) => s.endsWith(".md")).map((s) => resolve2(repoRoot, s)).filter((p) => existsSync13(p));
2066
2107
  }
2067
2108
  var init_skillParser = __esm({
2068
2109
  "cli/installer/skillParser.ts"() {
@@ -2721,9 +2762,9 @@ __export(stub_exports, {
2721
2762
  saveCredentials: () => saveCredentials
2722
2763
  });
2723
2764
  import { createServer } from "http";
2724
- import { writeFileSync as writeFileSync9, readFileSync as readFileSync11, existsSync as existsSync13, mkdirSync as mkdirSync7, unlinkSync as unlinkSync4 } from "fs";
2725
- import { homedir as homedir10, platform as platform2 } from "os";
2726
- import { join as join9, dirname as dirname4 } from "path";
2765
+ import { writeFileSync as writeFileSync9, readFileSync as readFileSync11, existsSync as existsSync14, mkdirSync as mkdirSync7, unlinkSync as unlinkSync4 } from "fs";
2766
+ import { homedir as homedir11, platform as platform2 } from "os";
2767
+ import { join as join10, dirname as dirname4 } from "path";
2727
2768
  import { execFile } from "child_process";
2728
2769
  import jwt from "jsonwebtoken";
2729
2770
  function openBrowser(url) {
@@ -2752,13 +2793,13 @@ function openBrowser(url) {
2752
2793
  }
2753
2794
  function saveCredentials(data) {
2754
2795
  const dir = dirname4(AUTH_FILE);
2755
- if (!existsSync13(dir)) {
2796
+ if (!existsSync14(dir)) {
2756
2797
  mkdirSync7(dir, { recursive: true, mode: 448 });
2757
2798
  }
2758
2799
  writeFileSync9(AUTH_FILE, JSON.stringify(data, null, 2), { mode: 384 });
2759
2800
  }
2760
2801
  function loadCredentials() {
2761
- if (!existsSync13(AUTH_FILE)) {
2802
+ if (!existsSync14(AUTH_FILE)) {
2762
2803
  return null;
2763
2804
  }
2764
2805
  try {
@@ -3017,7 +3058,7 @@ async function ensureValidToken() {
3017
3058
  return true;
3018
3059
  }
3019
3060
  function clearCredentials() {
3020
- if (existsSync13(AUTH_FILE)) {
3061
+ if (existsSync14(AUTH_FILE)) {
3021
3062
  unlinkSync4(AUTH_FILE);
3022
3063
  }
3023
3064
  }
@@ -3037,7 +3078,7 @@ var init_stub = __esm({
3037
3078
  PORT = 8100;
3038
3079
  RAW_WEB_AUTH_URL = process.env.SYNKRO_WEB_AUTH_URL;
3039
3080
  SYNKRO_WEB_AUTH_URL = RAW_WEB_AUTH_URL && /^https?:\/\//.test(RAW_WEB_AUTH_URL) ? RAW_WEB_AUTH_URL : "https://app.synkro.sh";
3040
- AUTH_FILE = process.env.SYNKRO_AUTH_FILE || join9(homedir10(), ".synkro", "credentials.json");
3081
+ AUTH_FILE = process.env.SYNKRO_AUTH_FILE || join10(homedir11(), ".synkro", "credentials.json");
3041
3082
  RAW_API_URL = process.env.SYNKRO_CRUD_URL || process.env.SYNKRO_API_URL;
3042
3083
  SYNKRO_API_URL = RAW_API_URL && /^https?:\/\//.test(RAW_API_URL) ? RAW_API_URL : "https://api.synkro.sh";
3043
3084
  ERROR_HTML = `
@@ -3197,9 +3238,9 @@ jobs:
3197
3238
  });
3198
3239
 
3199
3240
  // cli/installer/githubSetup.ts
3200
- import { existsSync as existsSync14, mkdirSync as mkdirSync8, writeFileSync as writeFileSync10 } from "fs";
3241
+ import { existsSync as existsSync15, mkdirSync as mkdirSync8, writeFileSync as writeFileSync10 } from "fs";
3201
3242
  import { execSync as execSync2 } from "child_process";
3202
- import { join as join10 } from "path";
3243
+ import { join as join11 } from "path";
3203
3244
  function ghSecretSet(token, owner, repo, name, value) {
3204
3245
  execSync2(`gh secret set ${name} --repo ${owner}/${repo} --body -`, {
3205
3246
  input: value,
@@ -3245,17 +3286,17 @@ async function pushSecretsToRepo(opts, owner, repo, secrets) {
3245
3286
  ghSecretSet(opts.token, owner, repo, "SYNKRO_API_KEY", secrets.synkroApiKey);
3246
3287
  }
3247
3288
  function writeWorkflowFile(repoRootPath) {
3248
- const workflowDir = join10(repoRootPath, ".github", "workflows");
3289
+ const workflowDir = join11(repoRootPath, ".github", "workflows");
3249
3290
  mkdirSync8(workflowDir, { recursive: true });
3250
- const workflowFile = join10(workflowDir, "synkro.yml");
3291
+ const workflowFile = join11(workflowDir, "synkro.yml");
3251
3292
  writeFileSync10(workflowFile, SYNKRO_WORKFLOW_YAML, "utf-8");
3252
3293
  return workflowFile;
3253
3294
  }
3254
3295
  function findGitRoot(startCwd) {
3255
3296
  let cur = startCwd;
3256
3297
  while (cur && cur !== "/") {
3257
- if (existsSync14(join10(cur, ".git"))) return cur;
3258
- const parent = join10(cur, "..");
3298
+ if (existsSync15(join11(cur, ".git"))) return cur;
3299
+ const parent = join11(cur, "..");
3259
3300
  if (parent === cur) break;
3260
3301
  cur = parent;
3261
3302
  }
@@ -3605,11 +3646,11 @@ __export(claudeDesktopTap_exports, {
3605
3646
  runClaudeDesktopTap: () => runClaudeDesktopTap
3606
3647
  });
3607
3648
  import { spawn as spawn2 } from "child_process";
3608
- import { writeFileSync as writeFileSync11, mkdtempSync, mkdirSync as mkdirSync9, readFileSync as readFileSync12, existsSync as existsSync15 } from "fs";
3609
- import { join as join11 } from "path";
3610
- import { homedir as homedir11 } from "os";
3649
+ import { writeFileSync as writeFileSync11, mkdtempSync, mkdirSync as mkdirSync9, readFileSync as readFileSync12, existsSync as existsSync16 } from "fs";
3650
+ import { join as join12 } from "path";
3651
+ import { homedir as homedir12 } from "os";
3611
3652
  function claudeDesktopInstalled() {
3612
- return process.platform === "darwin" && existsSync15("/Applications/Claude.app/Contents/MacOS/Claude");
3653
+ return process.platform === "darwin" && existsSync16("/Applications/Claude.app/Contents/MacOS/Claude");
3613
3654
  }
3614
3655
  function buildRunner(sessionDir) {
3615
3656
  return `#!/bin/bash
@@ -3744,13 +3785,13 @@ async function runClaudeDesktopTap(opts = {}) {
3744
3785
  } catch (err) {
3745
3786
  console.log(` \u26A0 Could not register Claude Desktop MCP: ${err.message}`);
3746
3787
  }
3747
- const cdRoot = join11(homedir11(), ".synkro", "cd-sessions");
3788
+ const cdRoot = join12(homedir12(), ".synkro", "cd-sessions");
3748
3789
  mkdirSync9(cdRoot, { recursive: true });
3749
- const sessionDir = mkdtempSync(join11(cdRoot, "synkro-cd-"));
3750
- writeFileSync11(join11(sessionDir, "tap.py"), ADDON_PY, "utf-8");
3751
- writeFileSync11(join11(sessionDir, "mcp_proxy.py"), MCP_PROXY_PY, { mode: 493 });
3752
- writeFileSync11(join11(sessionDir, "mcp_patch.py"), MCP_PATCH_PY, "utf-8");
3753
- const runnerPath = join11(sessionDir, "run.sh");
3790
+ const sessionDir = mkdtempSync(join12(cdRoot, "synkro-cd-"));
3791
+ writeFileSync11(join12(sessionDir, "tap.py"), ADDON_PY, "utf-8");
3792
+ writeFileSync11(join12(sessionDir, "mcp_proxy.py"), MCP_PROXY_PY, { mode: 493 });
3793
+ writeFileSync11(join12(sessionDir, "mcp_patch.py"), MCP_PATCH_PY, "utf-8");
3794
+ const runnerPath = join12(sessionDir, "run.sh");
3754
3795
  writeFileSync11(runnerPath, buildRunner(sessionDir), { mode: 493 });
3755
3796
  await new Promise((resolve4) => {
3756
3797
  const child = spawn2("bash", [runnerPath], {
@@ -3784,7 +3825,7 @@ var init_claudeDesktopTap = __esm({
3784
3825
  TURN_VERDICTS_URL = "http://127.0.0.1:18931/api/local/turn-verdicts";
3785
3826
  TURN_VERDICT_URL = "http://127.0.0.1:18931/api/local/turn-verdict";
3786
3827
  MCP_EVENT_URL = "http://127.0.0.1:18931/api/local/mcp/event";
3787
- JWT_PATH = join11(homedir11(), ".synkro", ".mcp-jwt");
3828
+ JWT_PATH = join12(homedir12(), ".synkro", ".mcp-jwt");
3788
3829
  ADDON_PY = `import os, json, threading, urllib.request, urllib.error, re, base64, time, hashlib
3789
3830
  from mitmproxy import http
3790
3831
 
@@ -4900,9 +4941,9 @@ __export(macKeychain_exports, {
4900
4941
  writeCursorApiKey: () => writeCursorApiKey,
4901
4942
  writeRefreshAgent: () => writeRefreshAgent
4902
4943
  });
4903
- import { existsSync as existsSync16, mkdirSync as mkdirSync10, writeFileSync as writeFileSync12, chmodSync as chmodSync2, readFileSync as readFileSync13 } from "fs";
4904
- import { homedir as homedir12, platform as platform3 } from "os";
4905
- import { join as join12 } from "path";
4944
+ import { existsSync as existsSync17, mkdirSync as mkdirSync10, writeFileSync as writeFileSync12, chmodSync as chmodSync2, readFileSync as readFileSync13 } from "fs";
4945
+ import { homedir as homedir13, platform as platform3 } from "os";
4946
+ import { join as join13 } from "path";
4906
4947
  import { spawnSync as spawnSync2 } from "child_process";
4907
4948
  function needsKeychainBridge() {
4908
4949
  return platform3() === "darwin";
@@ -4924,7 +4965,7 @@ function exportKeychainCreds() {
4924
4965
  chmodSync2(CLAUDE_CREDS_DIR, 448);
4925
4966
  let changed = true;
4926
4967
  try {
4927
- if (existsSync16(CLAUDE_CREDS_FILE)) {
4968
+ if (existsSync17(CLAUDE_CREDS_FILE)) {
4928
4969
  changed = readFileSync13(CLAUDE_CREDS_FILE, "utf-8") !== blob;
4929
4970
  }
4930
4971
  } catch {
@@ -4935,7 +4976,7 @@ function exportKeychainCreds() {
4935
4976
  }
4936
4977
  function cursorApiKeyConfigured() {
4937
4978
  try {
4938
- return existsSync16(CURSOR_API_KEY_FILE) && readFileSync13(CURSOR_API_KEY_FILE, "utf-8").trim().length > 0;
4979
+ return existsSync17(CURSOR_API_KEY_FILE) && readFileSync13(CURSOR_API_KEY_FILE, "utf-8").trim().length > 0;
4939
4980
  } catch {
4940
4981
  return false;
4941
4982
  }
@@ -4970,7 +5011,7 @@ async function validateCursorApiKey() {
4970
5011
  }
4971
5012
  }
4972
5013
  function credsAreStale() {
4973
- if (!existsSync16(CLAUDE_CREDS_FILE)) return true;
5014
+ if (!existsSync17(CLAUDE_CREDS_FILE)) return true;
4974
5015
  try {
4975
5016
  const raw = readFileSync13(CLAUDE_CREDS_FILE, "utf-8");
4976
5017
  const exp = JSON.parse(raw)?.claudeAiOauth?.expiresAt ?? 0;
@@ -4987,7 +5028,7 @@ function writeRefreshAgent(synkroBinPath) {
4987
5028
  if (platform3() !== "darwin") {
4988
5029
  throw new KeychainExportError("writeRefreshAgent is darwin-only");
4989
5030
  }
4990
- mkdirSync10(join12(homedir12(), "Library", "LaunchAgents"), { recursive: true });
5031
+ mkdirSync10(join13(homedir13(), "Library", "LaunchAgents"), { recursive: true });
4991
5032
  mkdirSync10(SYNKRO_DIR6, { recursive: true });
4992
5033
  const script = `#!/bin/bash
4993
5034
  # Generated by synkro (writeRefreshAgent). Expiry-aware Claude creds refresher.
@@ -5073,8 +5114,8 @@ function uninstallRefreshAgent() {
5073
5114
  });
5074
5115
  try {
5075
5116
  const fs = __require("fs");
5076
- if (existsSync16(LAUNCHD_PLIST)) fs.unlinkSync(LAUNCHD_PLIST);
5077
- if (existsSync16(REFRESH_SCRIPT)) fs.unlinkSync(REFRESH_SCRIPT);
5117
+ if (existsSync17(LAUNCHD_PLIST)) fs.unlinkSync(LAUNCHD_PLIST);
5118
+ if (existsSync17(REFRESH_SCRIPT)) fs.unlinkSync(REFRESH_SCRIPT);
5078
5119
  } catch {
5079
5120
  }
5080
5121
  }
@@ -5093,16 +5134,16 @@ var SYNKRO_DIR6, CLAUDE_CREDS_DIR, CLAUDE_CREDS_FILE, CURSOR_CREDS_DIR, CURSOR_A
5093
5134
  var init_macKeychain = __esm({
5094
5135
  "cli/local-cc/macKeychain.ts"() {
5095
5136
  "use strict";
5096
- SYNKRO_DIR6 = join12(homedir12(), ".synkro");
5097
- CLAUDE_CREDS_DIR = join12(SYNKRO_DIR6, "claude-creds");
5098
- CLAUDE_CREDS_FILE = join12(CLAUDE_CREDS_DIR, ".credentials.json");
5099
- CURSOR_CREDS_DIR = join12(SYNKRO_DIR6, "cursor-creds");
5100
- CURSOR_API_KEY_FILE = join12(CURSOR_CREDS_DIR, "api-key");
5137
+ SYNKRO_DIR6 = join13(homedir13(), ".synkro");
5138
+ CLAUDE_CREDS_DIR = join13(SYNKRO_DIR6, "claude-creds");
5139
+ CLAUDE_CREDS_FILE = join13(CLAUDE_CREDS_DIR, ".credentials.json");
5140
+ CURSOR_CREDS_DIR = join13(SYNKRO_DIR6, "cursor-creds");
5141
+ CURSOR_API_KEY_FILE = join13(CURSOR_CREDS_DIR, "api-key");
5101
5142
  KEYCHAIN_SERVICE = "Claude Code-credentials";
5102
5143
  LAUNCHD_LABEL = "com.synkro.cli.claude-creds-refresh";
5103
- LAUNCHD_PLIST = join12(homedir12(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
5104
- REFRESH_SCRIPT = join12(SYNKRO_DIR6, "claude-creds-refresh-loop.sh");
5105
- REFRESH_LOG = join12(SYNKRO_DIR6, "claude-creds-refresh.log");
5144
+ LAUNCHD_PLIST = join13(homedir13(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
5145
+ REFRESH_SCRIPT = join13(SYNKRO_DIR6, "claude-creds-refresh-loop.sh");
5146
+ REFRESH_LOG = join13(SYNKRO_DIR6, "claude-creds-refresh.log");
5106
5147
  REFRESH_EXPIRY_BUFFER_SECONDS = 120;
5107
5148
  MIN_REFRESH_INTERVAL_SECONDS = 30;
5108
5149
  MAX_REFRESH_INTERVAL_SECONDS = 5 * 60;
@@ -5141,9 +5182,9 @@ __export(dockerInstall_exports, {
5141
5182
  waitForContainerReady: () => waitForContainerReady,
5142
5183
  waitForWorkersReady: () => waitForWorkersReady
5143
5184
  });
5144
- import { copyFileSync, existsSync as existsSync17, mkdirSync as mkdirSync11, readFileSync as readFileSync14, readdirSync as readdirSync2 } from "fs";
5145
- import { homedir as homedir13 } from "os";
5146
- import { join as join13 } from "path";
5185
+ import { copyFileSync, existsSync as existsSync18, mkdirSync as mkdirSync11, readFileSync as readFileSync14, readdirSync as readdirSync2 } from "fs";
5186
+ import { homedir as homedir14 } from "os";
5187
+ import { join as join14 } from "path";
5147
5188
  import { execSync as execSync4, spawnSync as spawnSync3 } from "child_process";
5148
5189
  function splitWorkers(total, providers) {
5149
5190
  const t = Math.max(0, Math.floor(total));
@@ -5238,8 +5279,8 @@ function readSynkroFileConfig() {
5238
5279
  try {
5239
5280
  const root = execSync4("git rev-parse --show-toplevel 2>/dev/null", { encoding: "utf-8", timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
5240
5281
  if (!root) return { pool: "auto", warnings: [] };
5241
- const fp = join13(root, "synkro.toml");
5242
- if (!existsSync17(fp)) return { pool: "auto", warnings: [] };
5282
+ const fp = join14(root, "synkro.toml");
5283
+ if (!existsSync18(fp)) return { pool: "auto", warnings: [] };
5243
5284
  const parsed = parseSynkroToml(readFileSync14(fp, "utf-8"));
5244
5285
  return resolveGraderPool(parsed);
5245
5286
  } catch {
@@ -5315,7 +5356,7 @@ function assertDockerAvailable() {
5315
5356
  }
5316
5357
  function claudeCredsHostDir() {
5317
5358
  if (needsKeychainBridge()) return CLAUDE_CREDS_DIR;
5318
- return join13(homedir13(), ".claude");
5359
+ return join14(homedir14(), ".claude");
5319
5360
  }
5320
5361
  function resolveSynkroBin() {
5321
5362
  const which2 = spawnSync3("which", ["synkro"], { encoding: "utf-8", timeout: 5e3 });
@@ -5371,11 +5412,11 @@ async function dockerInstall(opts = {}) {
5371
5412
  mkdirSync11(PGDATA_PATH, { recursive: true });
5372
5413
  mkdirSync11(BACKUP_DIR, { recursive: true });
5373
5414
  mkdirSync11(CLAUDE_HOST_STATE_DIR, { recursive: true });
5374
- const hostClaudeJson = join13(homedir13(), ".claude.json");
5375
- if (existsSync17(hostClaudeJson)) {
5415
+ const hostClaudeJson = join14(homedir14(), ".claude.json");
5416
+ if (existsSync18(hostClaudeJson)) {
5376
5417
  copyFileSync(hostClaudeJson, CLAUDE_HOST_STATE_FILE);
5377
5418
  }
5378
- if (!existsSync17(MCP_JWT_PATH)) {
5419
+ if (!existsSync18(MCP_JWT_PATH)) {
5379
5420
  throw new DockerInstallError(
5380
5421
  `MCP JWT missing at ${MCP_JWT_PATH}. The installer should mint this before calling dockerInstall.`
5381
5422
  );
@@ -5404,7 +5445,7 @@ async function dockerInstall(opts = {}) {
5404
5445
  console.warn(` Plist written to ${plist} \u2014 load manually with launchctl bootstrap when ready.`);
5405
5446
  }
5406
5447
  } else {
5407
- mkdirSync11(join13(homedir13(), ".claude"), { recursive: true });
5448
+ mkdirSync11(join14(homedir14(), ".claude"), { recursive: true });
5408
5449
  }
5409
5450
  const imageExistsLocally = () => spawnSync3("docker", ["image", "inspect", image], { stdio: "ignore", timeout: 3e4 }).status === 0;
5410
5451
  const skipPull = process.env.SYNKRO_SKIP_PULL === "1" || process.env.SYNKRO_SKIP_PULL === "true";
@@ -5457,7 +5498,7 @@ async function dockerInstall(opts = {}) {
5457
5498
  "-v",
5458
5499
  `${credsDir}:/home/synkro/.claude:rw`,
5459
5500
  "-v",
5460
- `${join13(homedir13(), ".claude")}:/data/claude-host:ro`,
5501
+ `${join14(homedir14(), ".claude")}:/data/claude-host:ro`,
5461
5502
  "-v",
5462
5503
  `${CLAUDE_HOST_STATE_DIR}:/data/claude-host-state:ro`,
5463
5504
  // Cursor creds — mounted RW so the in-container refresher can rotate the
@@ -5652,7 +5693,7 @@ async function dockerSafeStart() {
5652
5693
  return { ok: false, pgdataState: "no_container", error: "No synkro-server container found. Run `synkro install` first." };
5653
5694
  }
5654
5695
  const pgCheck = checkPgdata();
5655
- if (existsSync17(PGDATA_PATH) && readdirSync2(PGDATA_PATH).length > 0) {
5696
+ if (existsSync18(PGDATA_PATH) && readdirSync2(PGDATA_PATH).length > 0) {
5656
5697
  if (pgCheck.healthy) {
5657
5698
  console.log(` pgdata: existing data found \u2014 ${pgCheck.details}`);
5658
5699
  } else {
@@ -5692,7 +5733,7 @@ async function dockerSafeRestart() {
5692
5733
  return { ok: startResult.ok, stop: stopResult, start: startResult };
5693
5734
  }
5694
5735
  function checkPgdata() {
5695
- if (!existsSync17(PGDATA_PATH)) return { healthy: false, details: "pgdata directory does not exist" };
5736
+ if (!existsSync18(PGDATA_PATH)) return { healthy: false, details: "pgdata directory does not exist" };
5696
5737
  const entries = readdirSync2(PGDATA_PATH);
5697
5738
  if (entries.length === 0) return { healthy: true, details: "empty (fresh start)" };
5698
5739
  const hasPidFile = entries.includes("postmaster.pid");
@@ -5709,11 +5750,11 @@ var init_dockerInstall = __esm({
5709
5750
  "use strict";
5710
5751
  init_agentDetect();
5711
5752
  init_macKeychain();
5712
- SYNKRO_DIR7 = join13(homedir13(), ".synkro");
5713
- MCP_JWT_PATH = join13(SYNKRO_DIR7, ".mcp-jwt");
5714
- PGDATA_PATH = join13(SYNKRO_DIR7, "pgdata");
5715
- CLAUDE_HOST_STATE_DIR = join13(SYNKRO_DIR7, "claude-host-state");
5716
- CLAUDE_HOST_STATE_FILE = join13(CLAUDE_HOST_STATE_DIR, ".claude.json");
5753
+ SYNKRO_DIR7 = join14(homedir14(), ".synkro");
5754
+ MCP_JWT_PATH = join14(SYNKRO_DIR7, ".mcp-jwt");
5755
+ PGDATA_PATH = join14(SYNKRO_DIR7, "pgdata");
5756
+ CLAUDE_HOST_STATE_DIR = join14(SYNKRO_DIR7, "claude-host-state");
5757
+ CLAUDE_HOST_STATE_FILE = join14(CLAUDE_HOST_STATE_DIR, ".claude.json");
5717
5758
  HOST_MCP_PORT = parseInt(process.env.SYNKRO_HOST_MCP_PORT || "18931", 10);
5718
5759
  HOST_GRADER_PORT = parseInt(process.env.SYNKRO_HOST_GRADER_PORT || "18929", 10);
5719
5760
  HOST_CWE_PORT = parseInt(process.env.SYNKRO_HOST_CWE_PORT || "18930", 10);
@@ -5728,17 +5769,17 @@ var init_dockerInstall = __esm({
5728
5769
  }
5729
5770
  cause;
5730
5771
  };
5731
- BACKUP_DIR = join13(SYNKRO_DIR7, "pgdata-backups");
5772
+ BACKUP_DIR = join14(SYNKRO_DIR7, "pgdata-backups");
5732
5773
  }
5733
5774
  });
5734
5775
 
5735
5776
  // cli/local-cc/setupToken.ts
5736
5777
  import { spawn as nodeSpawn } from "child_process";
5737
5778
  import { readFileSync as readFileSync15, unlinkSync as unlinkSync5 } from "fs";
5738
- import { homedir as homedir14, platform as platform4 } from "os";
5739
- import { join as join14 } from "path";
5779
+ import { homedir as homedir15, platform as platform4 } from "os";
5780
+ import { join as join15 } from "path";
5740
5781
  function captureClaudeSetupToken() {
5741
- const tmpFile = join14(SYNKRO_DIR8, `token-capture-${Date.now()}.raw`);
5782
+ const tmpFile = join15(SYNKRO_DIR8, `token-capture-${Date.now()}.raw`);
5742
5783
  const isMac = platform4() === "darwin";
5743
5784
  const bin = "script";
5744
5785
  const args2 = isMac ? ["-q", tmpFile, "claude", "setup-token"] : ["-qec", "claude setup-token", tmpFile];
@@ -5818,7 +5859,7 @@ var SYNKRO_DIR8;
5818
5859
  var init_setupToken = __esm({
5819
5860
  "cli/local-cc/setupToken.ts"() {
5820
5861
  "use strict";
5821
- SYNKRO_DIR8 = join14(homedir14(), ".synkro");
5862
+ SYNKRO_DIR8 = join15(homedir15(), ".synkro");
5822
5863
  }
5823
5864
  });
5824
5865
 
@@ -5828,9 +5869,9 @@ __export(codexCloudSetup_exports, {
5828
5869
  setupCodexCloud: () => setupCodexCloud
5829
5870
  });
5830
5871
  import { spawn as nodeSpawn2, spawnSync as spawnSync4 } from "child_process";
5831
- import { readFileSync as readFileSync16, mkdirSync as mkdirSync12, rmSync, existsSync as existsSync18 } from "fs";
5832
- import { homedir as homedir15 } from "os";
5833
- import { join as join15 } from "path";
5872
+ import { readFileSync as readFileSync16, mkdirSync as mkdirSync12, rmSync, existsSync as existsSync19 } from "fs";
5873
+ import { homedir as homedir16 } from "os";
5874
+ import { join as join16 } from "path";
5834
5875
  function findCodexBinary() {
5835
5876
  if (process.env.SYNKRO_CODEX_BIN) return process.env.SYNKRO_CODEX_BIN;
5836
5877
  const r = spawnSync4("which", ["codex"], { encoding: "utf-8" });
@@ -5859,8 +5900,8 @@ async function setupCodexCloud(gatewayUrl, bearerToken, onStatus) {
5859
5900
  } catch (e) {
5860
5901
  return { ok: false, error: `Codex login failed: ${e.message}` };
5861
5902
  }
5862
- const authPath = join15(CODEX_CLOUD_HOME, "auth.json");
5863
- if (!existsSync18(authPath)) {
5903
+ const authPath = join16(CODEX_CLOUD_HOME, "auth.json");
5904
+ if (!existsSync19(authPath)) {
5864
5905
  return { ok: false, error: "codex login completed but no auth.json was written \u2014 did the browser approval finish?" };
5865
5906
  }
5866
5907
  let auth;
@@ -5898,8 +5939,8 @@ var SYNKRO_DIR9, CODEX_CLOUD_HOME;
5898
5939
  var init_codexCloudSetup = __esm({
5899
5940
  "cli/local-cc/codexCloudSetup.ts"() {
5900
5941
  "use strict";
5901
- SYNKRO_DIR9 = join15(homedir15(), ".synkro");
5902
- CODEX_CLOUD_HOME = join15(SYNKRO_DIR9, "codex-cloud-session");
5942
+ SYNKRO_DIR9 = join16(homedir16(), ".synkro");
5943
+ CODEX_CLOUD_HOME = join16(SYNKRO_DIR9, "codex-cloud-session");
5903
5944
  }
5904
5945
  });
5905
5946
 
@@ -5912,12 +5953,12 @@ __export(setupGithub_exports, {
5912
5953
  import { createInterface as createInterface2 } from "readline/promises";
5913
5954
  import { stdin as input, stdout as output } from "process";
5914
5955
  import { execSync as execSync5 } from "child_process";
5915
- import { existsSync as existsSync19, readFileSync as readFileSync17 } from "fs";
5916
- import { homedir as homedir16, platform as platform5 } from "os";
5917
- import { join as join16 } from "path";
5956
+ import { existsSync as existsSync20, readFileSync as readFileSync17 } from "fs";
5957
+ import { homedir as homedir17, platform as platform5 } from "os";
5958
+ import { join as join17 } from "path";
5918
5959
  import { execFile as execFile2 } from "child_process";
5919
5960
  function readConfig() {
5920
- if (!existsSync19(CONFIG_PATH3)) return {};
5961
+ if (!existsSync20(CONFIG_PATH3)) return {};
5921
5962
  const out = {};
5922
5963
  for (const line of readFileSync17(CONFIG_PATH3, "utf-8").split("\n")) {
5923
5964
  const t = line.trim();
@@ -6226,8 +6267,8 @@ var init_setupGithub = __esm({
6226
6267
  init_githubSetup();
6227
6268
  init_stub();
6228
6269
  init_setupToken();
6229
- SYNKRO_DIR10 = join16(homedir16(), ".synkro");
6230
- CONFIG_PATH3 = join16(SYNKRO_DIR10, "config.env");
6270
+ SYNKRO_DIR10 = join17(homedir17(), ".synkro");
6271
+ CONFIG_PATH3 = join17(SYNKRO_DIR10, "config.env");
6231
6272
  }
6232
6273
  });
6233
6274
 
@@ -6246,9 +6287,9 @@ __export(install_exports, {
6246
6287
  syncSkillFiles: () => syncSkillFiles,
6247
6288
  writeHookScripts: () => writeHookScripts
6248
6289
  });
6249
- import { existsSync as existsSync20, mkdirSync as mkdirSync13, writeFileSync as writeFileSync13, chmodSync as chmodSync3, readFileSync as readFileSync18, readdirSync as readdirSync3, unlinkSync as unlinkSync6, statSync as statSync2 } from "fs";
6250
- import { homedir as homedir17 } from "os";
6251
- import { join as join17 } from "path";
6290
+ import { existsSync as existsSync21, mkdirSync as mkdirSync13, writeFileSync as writeFileSync13, chmodSync as chmodSync3, readFileSync as readFileSync18, readdirSync as readdirSync3, unlinkSync as unlinkSync6, statSync as statSync2 } from "fs";
6291
+ import { homedir as homedir18 } from "os";
6292
+ import { join as join18 } from "path";
6252
6293
  import { execSync as execSync6 } from "child_process";
6253
6294
  import { createInterface as createInterface3 } from "readline";
6254
6295
  import { createHash as createHash2 } from "crypto";
@@ -6397,33 +6438,33 @@ function ensureSynkroDir() {
6397
6438
  mkdirSync13(HOOKS_DIR, { recursive: true });
6398
6439
  mkdirSync13(BIN_DIR, { recursive: true });
6399
6440
  mkdirSync13(OFFSETS_DIR, { recursive: true });
6400
- mkdirSync13(join17(SYNKRO_DIR11, "sessions"), { recursive: true });
6441
+ mkdirSync13(join18(SYNKRO_DIR11, "sessions"), { recursive: true });
6401
6442
  }
6402
6443
  function writeHookScripts() {
6403
- const installExtractCorePath = join17(HOOKS_DIR, "installExtractCore.ts");
6404
- const bashScriptPath = join17(HOOKS_DIR, "cc-bash-judge.ts");
6405
- const skillJudgeScriptPath = join17(HOOKS_DIR, "cc-skill-judge.ts");
6406
- const cursorSkillJudgePath = join17(HOOKS_DIR, "cursor-skill-judge.ts");
6407
- const bashFollowupScriptPath = join17(HOOKS_DIR, "cc-bash-followup.ts");
6408
- const editPrecheckScriptPath = join17(HOOKS_DIR, "cc-edit-precheck.ts");
6409
- const cwePrecheckScriptPath = join17(HOOKS_DIR, "cc-cwe-precheck.ts");
6410
- const cvePrecheckScriptPath = join17(HOOKS_DIR, "cc-cve-precheck.ts");
6411
- const planJudgeScriptPath = join17(HOOKS_DIR, "cc-plan-judge.ts");
6412
- const agentJudgeScriptPath = join17(HOOKS_DIR, "cc-agent-judge.ts");
6413
- const stopSummaryScriptPath = join17(HOOKS_DIR, "cc-stop-summary.ts");
6414
- const sessionStartScriptPath = join17(HOOKS_DIR, "cc-session-start.ts");
6415
- const transcriptSyncScriptPath = join17(HOOKS_DIR, "cc-transcript-sync.ts");
6416
- const userPromptSubmitScriptPath = join17(HOOKS_DIR, "cc-user-prompt-submit.ts");
6417
- const commonScriptPath = join17(HOOKS_DIR, "_synkro-common.ts");
6418
- const commonBashScriptPath = join17(HOOKS_DIR, "_synkro-common.sh");
6419
- const installScanScriptPath = join17(HOOKS_DIR, "cc-install-scan.ts");
6420
- const cursorBashJudgePath = join17(HOOKS_DIR, "cursor-bash-judge.ts");
6421
- const cursorEditCapturePath = join17(HOOKS_DIR, "cursor-edit-capture.ts");
6422
- const cursorAgentCapturePath = join17(HOOKS_DIR, "cursor-agent-capture.ts");
6423
- const mcpStdioProxyPath = join17(HOOKS_DIR, "mcp-stdio-proxy.ts");
6424
- const taskActivateIntentScriptPath = join17(HOOKS_DIR, "cc-task-activate-intent.ts");
6425
- const mcpGateScriptPath = join17(HOOKS_DIR, "cc-mcp-gate.ts");
6426
- const stubCommonPath = join17(HOOKS_DIR, "_synkro-stub-common.ts");
6444
+ const installExtractCorePath = join18(HOOKS_DIR, "installExtractCore.ts");
6445
+ const bashScriptPath = join18(HOOKS_DIR, "cc-bash-judge.ts");
6446
+ const skillJudgeScriptPath = join18(HOOKS_DIR, "cc-skill-judge.ts");
6447
+ const cursorSkillJudgePath = join18(HOOKS_DIR, "cursor-skill-judge.ts");
6448
+ const bashFollowupScriptPath = join18(HOOKS_DIR, "cc-bash-followup.ts");
6449
+ const editPrecheckScriptPath = join18(HOOKS_DIR, "cc-edit-precheck.ts");
6450
+ const cwePrecheckScriptPath = join18(HOOKS_DIR, "cc-cwe-precheck.ts");
6451
+ const cvePrecheckScriptPath = join18(HOOKS_DIR, "cc-cve-precheck.ts");
6452
+ const planJudgeScriptPath = join18(HOOKS_DIR, "cc-plan-judge.ts");
6453
+ const agentJudgeScriptPath = join18(HOOKS_DIR, "cc-agent-judge.ts");
6454
+ const stopSummaryScriptPath = join18(HOOKS_DIR, "cc-stop-summary.ts");
6455
+ const sessionStartScriptPath = join18(HOOKS_DIR, "cc-session-start.ts");
6456
+ const transcriptSyncScriptPath = join18(HOOKS_DIR, "cc-transcript-sync.ts");
6457
+ const userPromptSubmitScriptPath = join18(HOOKS_DIR, "cc-user-prompt-submit.ts");
6458
+ const commonScriptPath = join18(HOOKS_DIR, "_synkro-common.ts");
6459
+ const commonBashScriptPath = join18(HOOKS_DIR, "_synkro-common.sh");
6460
+ const installScanScriptPath = join18(HOOKS_DIR, "cc-install-scan.ts");
6461
+ const cursorBashJudgePath = join18(HOOKS_DIR, "cursor-bash-judge.ts");
6462
+ const cursorEditCapturePath = join18(HOOKS_DIR, "cursor-edit-capture.ts");
6463
+ const cursorAgentCapturePath = join18(HOOKS_DIR, "cursor-agent-capture.ts");
6464
+ const mcpStdioProxyPath = join18(HOOKS_DIR, "mcp-stdio-proxy.ts");
6465
+ const taskActivateIntentScriptPath = join18(HOOKS_DIR, "cc-task-activate-intent.ts");
6466
+ const mcpGateScriptPath = join18(HOOKS_DIR, "cc-mcp-gate.ts");
6467
+ const stubCommonPath = join18(HOOKS_DIR, "_synkro-stub-common.ts");
6427
6468
  const stubFiles = [
6428
6469
  [stubCommonPath, STUB_COMMON_TS],
6429
6470
  [bashScriptPath, STUB_BASH_JUDGE_TS],
@@ -6454,7 +6495,7 @@ function writeHookScripts() {
6454
6495
  chmodSync3(mcpStdioProxyPath, 493);
6455
6496
  for (const stale of ["_synkro-common.ts", "_synkro-common.sh", "installExtractCore.ts"]) {
6456
6497
  try {
6457
- unlinkSync6(join17(HOOKS_DIR, stale));
6498
+ unlinkSync6(join18(HOOKS_DIR, stale));
6458
6499
  } catch {
6459
6500
  }
6460
6501
  }
@@ -6489,11 +6530,11 @@ function shellQuoteSingle2(value) {
6489
6530
  }
6490
6531
  function resolveSynkroBundle() {
6491
6532
  const scriptPath = process.argv[1];
6492
- if (scriptPath && existsSync20(scriptPath)) return scriptPath;
6533
+ if (scriptPath && existsSync21(scriptPath)) return scriptPath;
6493
6534
  return null;
6494
6535
  }
6495
6536
  function writeConfigEnv(opts) {
6496
- const credsPath = join17(SYNKRO_DIR11, "credentials.json");
6537
+ const credsPath = join18(SYNKRO_DIR11, "credentials.json");
6497
6538
  const safeGateway = sanitizeConfigValue(opts.gatewayUrl);
6498
6539
  const safeUserId = sanitizeConfigValue(opts.userId);
6499
6540
  const safeOrgId = sanitizeConfigValue(opts.orgId);
@@ -6509,7 +6550,7 @@ function writeConfigEnv(opts) {
6509
6550
  `SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle2(credsPath)}`,
6510
6551
  `SYNKRO_TIER=${shellQuoteSingle2(safeTier)}`,
6511
6552
  `SYNKRO_INFERENCE=${shellQuoteSingle2(safeInference)}`,
6512
- `SYNKRO_VERSION=${shellQuoteSingle2("1.7.62")}`
6553
+ `SYNKRO_VERSION=${shellQuoteSingle2("1.7.63")}`
6513
6554
  ];
6514
6555
  if (safeSynkroBin) lines.push(`SYNKRO_CLI_BIN=${shellQuoteSingle2(safeSynkroBin)}`);
6515
6556
  if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle2(safeUserId)}`);
@@ -6601,7 +6642,7 @@ async function provisionCloudContainer(opts) {
6601
6642
  let cursorApiKey = "";
6602
6643
  if (cursorTotal > 0) {
6603
6644
  try {
6604
- cursorApiKey = readFileSync18(join17(SYNKRO_DIR11, "cursor-creds", "api-key"), "utf-8").trim();
6645
+ cursorApiKey = readFileSync18(join18(SYNKRO_DIR11, "cursor-creds", "api-key"), "utf-8").trim();
6605
6646
  } catch {
6606
6647
  }
6607
6648
  }
@@ -6758,7 +6799,7 @@ async function verifyCloudGrader(jwt2) {
6758
6799
  }
6759
6800
  function readPersistedDeployLocation() {
6760
6801
  try {
6761
- if (existsSync20(CONFIG_PATH4)) {
6802
+ if (existsSync21(CONFIG_PATH4)) {
6762
6803
  const m = readFileSync18(CONFIG_PATH4, "utf-8").match(/^SYNKRO_DEPLOY_LOCATION='([^']*)'/m);
6763
6804
  if (m?.[1] === "cloud") return "cloud";
6764
6805
  }
@@ -6767,7 +6808,7 @@ function readPersistedDeployLocation() {
6767
6808
  return "local";
6768
6809
  }
6769
6810
  function updateConfigEnvLocation(location) {
6770
- if (!existsSync20(CONFIG_PATH4)) return;
6811
+ if (!existsSync21(CONFIG_PATH4)) return;
6771
6812
  let env = readFileSync18(CONFIG_PATH4, "utf-8");
6772
6813
  const set = (k, v) => {
6773
6814
  const re = new RegExp(`^${k}=.*$`, "m");
@@ -6783,7 +6824,7 @@ async function applyMcpConfig(opts) {
6783
6824
  if (!opts.hasClaudeCode && !opts.hasCursor) return;
6784
6825
  let mcpJwt = "";
6785
6826
  try {
6786
- mcpJwt = readFileSync18(join17(SYNKRO_DIR11, ".mcp-jwt"), "utf-8").trim();
6827
+ mcpJwt = readFileSync18(join18(SYNKRO_DIR11, ".mcp-jwt"), "utf-8").trim();
6787
6828
  } catch {
6788
6829
  }
6789
6830
  if (!mcpJwt) {
@@ -6901,7 +6942,7 @@ function resolveDeploymentMode() {
6901
6942
  const envOverride = process.env.SYNKRO_DEPLOYMENT_MODE?.toLowerCase();
6902
6943
  if (envOverride === "bare-host" || envOverride === "docker") return envOverride;
6903
6944
  try {
6904
- if (existsSync20(CONFIG_PATH4)) {
6945
+ if (existsSync21(CONFIG_PATH4)) {
6905
6946
  const m = readFileSync18(CONFIG_PATH4, "utf-8").match(/^SYNKRO_DEPLOYMENT_MODE='([^']*)'/m);
6906
6947
  const val = m?.[1]?.toLowerCase();
6907
6948
  if (val === "bare-host" || val === "docker") return val;
@@ -6929,16 +6970,16 @@ function collectLocalMetadata(includeClaudeCode = true) {
6929
6970
  meta.cc_version = execSync6("claude --version", { encoding: "utf-8", timeout: 5e3 }).trim().split("\n")[0];
6930
6971
  } catch {
6931
6972
  }
6932
- const claudeDir = join17(homedir17(), ".claude");
6973
+ const claudeDir = join18(homedir18(), ".claude");
6933
6974
  try {
6934
- const settings = JSON.parse(readFileSync18(join17(claudeDir, "settings.json"), "utf-8"));
6975
+ const settings = JSON.parse(readFileSync18(join18(claudeDir, "settings.json"), "utf-8"));
6935
6976
  const plugins = Object.keys(settings.enabledPlugins ?? {}).filter((k) => settings.enabledPlugins[k]);
6936
6977
  if (plugins.length) meta.enabled_plugins = plugins;
6937
6978
  if (settings.permissions?.defaultMode) meta.permissions_mode = settings.permissions.defaultMode;
6938
6979
  } catch {
6939
6980
  }
6940
6981
  try {
6941
- const mcpCache = JSON.parse(readFileSync18(join17(claudeDir, "mcp-needs-auth-cache.json"), "utf-8"));
6982
+ const mcpCache = JSON.parse(readFileSync18(join18(claudeDir, "mcp-needs-auth-cache.json"), "utf-8"));
6942
6983
  const mcpNames = Object.keys(mcpCache);
6943
6984
  if (mcpNames.length) meta.mcp_servers = mcpNames;
6944
6985
  } catch {
@@ -6950,10 +6991,10 @@ function collectLocalMetadata(includeClaudeCode = true) {
6950
6991
  } catch {
6951
6992
  }
6952
6993
  try {
6953
- const sessionsDir = join17(claudeDir, "sessions");
6994
+ const sessionsDir = join18(claudeDir, "sessions");
6954
6995
  const files = readdirSync3(sessionsDir).filter((f) => f.endsWith(".json")).slice(-5);
6955
6996
  for (const f of files) {
6956
- const s = JSON.parse(readFileSync18(join17(sessionsDir, f), "utf-8"));
6997
+ const s = JSON.parse(readFileSync18(join18(sessionsDir, f), "utf-8"));
6957
6998
  if (s.version) {
6958
6999
  meta.cc_version = meta.cc_version || s.version;
6959
7000
  break;
@@ -7149,7 +7190,7 @@ async function installCommand(opts = {}) {
7149
7190
  await setTelemetryState({ enabled: true, remoteFlushEnabled: telemetryConsent });
7150
7191
  emit("install", {
7151
7192
  phase: "started",
7152
- cli_version_to: "1.7.62",
7193
+ cli_version_to: "1.7.63",
7153
7194
  agents_detected: agents.map((a) => a.kind),
7154
7195
  with_github: false,
7155
7196
  with_local_cc: false,
@@ -7161,7 +7202,7 @@ async function installCommand(opts = {}) {
7161
7202
  const scripts = writeHookScripts();
7162
7203
  console.log("Wrote hook scripts to ~/.synkro/hooks/\n");
7163
7204
  for (const mode of ["edit", "bash"]) {
7164
- const pidFile = join17(SYNKRO_DIR11, "daemon", mode, "daemon.pid");
7205
+ const pidFile = join18(SYNKRO_DIR11, "daemon", mode, "daemon.pid");
7165
7206
  try {
7166
7207
  const pid = parseInt(readFileSync18(pidFile, "utf-8").trim(), 10);
7167
7208
  if (pid > 0) {
@@ -7248,7 +7289,7 @@ async function installCommand(opts = {}) {
7248
7289
  if (mintResp.ok) {
7249
7290
  const minted = await mintResp.json();
7250
7291
  mcpJwt = minted.token;
7251
- writeFileSync13(join17(SYNKRO_DIR11, ".mcp-jwt"), mcpJwt + "\n", { mode: 384 });
7292
+ writeFileSync13(join18(SYNKRO_DIR11, ".mcp-jwt"), mcpJwt + "\n", { mode: 384 });
7252
7293
  } else {
7253
7294
  console.warn(" \u26A0 Could not mint MCP token \u2014 local server will reject requests until re-installed.");
7254
7295
  }
@@ -7276,7 +7317,7 @@ async function installCommand(opts = {}) {
7276
7317
  throw new Error(`mcp-token mint failed (${mintResp.status}): ${errText.slice(0, 200)}`);
7277
7318
  }
7278
7319
  const minted = await mintResp.json();
7279
- writeFileSync13(join17(SYNKRO_DIR11, ".mcp-jwt"), minted.token + "\n", { mode: 384 });
7320
+ writeFileSync13(join18(SYNKRO_DIR11, ".mcp-jwt"), minted.token + "\n", { mode: 384 });
7280
7321
  const mcp = installMcpConfig({ gatewayUrl, bearerToken: minted.token });
7281
7322
  console.log(`Registered Synkro guardrails MCP server in ${mcp.path}`);
7282
7323
  console.log(` url: ${mcp.url}`);
@@ -7293,8 +7334,8 @@ async function installCommand(opts = {}) {
7293
7334
  if (hasCursor && !opts.noMcp) {
7294
7335
  try {
7295
7336
  if (useLocalMcp) {
7296
- const jwtPath = join17(SYNKRO_DIR11, ".mcp-jwt");
7297
- if (!existsSync20(jwtPath)) {
7337
+ const jwtPath = join18(SYNKRO_DIR11, ".mcp-jwt");
7338
+ if (!existsSync21(jwtPath)) {
7298
7339
  const mintResp = await fetch(`${gatewayUrl}/api/v1/cli/mcp-token`, {
7299
7340
  method: "POST",
7300
7341
  headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" },
@@ -7322,7 +7363,7 @@ async function installCommand(opts = {}) {
7322
7363
  throw new Error(`mcp-token mint failed (${mintResp.status}): ${errText.slice(0, 200)}`);
7323
7364
  }
7324
7365
  const minted = await mintResp.json();
7325
- writeFileSync13(join17(SYNKRO_DIR11, ".mcp-jwt"), minted.token + "\n", { mode: 384 });
7366
+ writeFileSync13(join18(SYNKRO_DIR11, ".mcp-jwt"), minted.token + "\n", { mode: 384 });
7326
7367
  const mcp = installCursorMcpConfig({ gatewayUrl, bearerToken: minted.token });
7327
7368
  console.log(`Registered Synkro guardrails MCP server in ${mcp.path}`);
7328
7369
  console.log(` url: ${mcp.url}`);
@@ -7415,7 +7456,7 @@ async function installCommand(opts = {}) {
7415
7456
  const ready = await waitForContainerReady(6e4);
7416
7457
  if (ready) {
7417
7458
  console.log(" \u2713 container ready");
7418
- const mcpJwt = readFileSync18(join17(SYNKRO_DIR11, ".mcp-jwt"), "utf-8").trim();
7459
+ const mcpJwt = readFileSync18(join18(SYNKRO_DIR11, ".mcp-jwt"), "utf-8").trim();
7419
7460
  try {
7420
7461
  const ingestResp = await fetch(`http://127.0.0.1:${hostMcpPort}/api/ingest`, {
7421
7462
  method: "POST",
@@ -7463,7 +7504,7 @@ async function installCommand(opts = {}) {
7463
7504
  try {
7464
7505
  let mcpToken = "";
7465
7506
  try {
7466
- mcpToken = readFileSync18(join17(SYNKRO_DIR11, ".mcp-jwt"), "utf-8").trim();
7507
+ mcpToken = readFileSync18(join18(SYNKRO_DIR11, ".mcp-jwt"), "utf-8").trim();
7467
7508
  } catch {
7468
7509
  }
7469
7510
  if (mcpToken) {
@@ -7599,8 +7640,8 @@ function writeSynkroFileIfMissing(opts) {
7599
7640
  try {
7600
7641
  const root = execSync6("git rev-parse --show-toplevel", { encoding: "utf-8", timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
7601
7642
  if (!root) return;
7602
- if (root === homedir17()) return;
7603
- const fp = join17(root, "synkro.toml");
7643
+ if (root === homedir18()) return;
7644
+ const fp = join18(root, "synkro.toml");
7604
7645
  let hasFile = false;
7605
7646
  try {
7606
7647
  hasFile = statSync2(fp).isFile();
@@ -7645,8 +7686,8 @@ function readFullSynkroFile() {
7645
7686
  try {
7646
7687
  const root = execSync6("git rev-parse --show-toplevel", { encoding: "utf-8", timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
7647
7688
  if (!root) return null;
7648
- const fp = join17(root, "synkro.toml");
7649
- if (!existsSync20(fp)) return null;
7689
+ const fp = join18(root, "synkro.toml");
7690
+ if (!existsSync21(fp)) return null;
7650
7691
  const parsed = parseSynkroToml2(readFileSync18(fp, "utf-8"));
7651
7692
  const valid = ["claude-code", "cursor"];
7652
7693
  const harness = Array.isArray(parsed.harness) ? parsed.harness.filter((h) => valid.includes(h)) : ["claude-code", "cursor"];
@@ -7685,7 +7726,7 @@ function reconcileHarness() {
7685
7726
  console.log(`synkro.toml: harness=[${sf.harness.join(", ")}] pool=${poolLabel(sf.grader.pool)} mode=${sf.grader.mode}`);
7686
7727
  const scripts = writeHookScripts();
7687
7728
  console.log("Wrote hook scripts to ~/.synkro/hooks/");
7688
- const ccSettings = join17(homedir17(), ".claude", "settings.json");
7729
+ const ccSettings = join18(homedir18(), ".claude", "settings.json");
7689
7730
  if (wantCC) {
7690
7731
  installCCHooks(ccSettings, {
7691
7732
  bashJudgeScriptPath: scripts.bashScript,
@@ -7706,7 +7747,7 @@ function reconcileHarness() {
7706
7747
  });
7707
7748
  console.log(" \u2713 Claude Code hooks registered");
7708
7749
  try {
7709
- const mcpJwt = readFileSync18(join17(SYNKRO_DIR11, ".mcp-jwt"), "utf-8").trim();
7750
+ const mcpJwt = readFileSync18(join18(SYNKRO_DIR11, ".mcp-jwt"), "utf-8").trim();
7710
7751
  if (mcpJwt) {
7711
7752
  installMcpConfig({ gatewayUrl: "", bearerToken: mcpJwt, local: true });
7712
7753
  console.log(" \u2713 Claude Code MCP registered");
@@ -7718,7 +7759,7 @@ function reconcileHarness() {
7718
7759
  if (uninstallMcpConfig()) console.log(" \u2717 Claude Code MCP removed");
7719
7760
  if (uninstallClaudeDesktopMcpConfig()) console.log(" \u2717 Claude Desktop MCP removed");
7720
7761
  }
7721
- const cursorHooks = join17(homedir17(), ".cursor", "hooks.json");
7762
+ const cursorHooks = join18(homedir18(), ".cursor", "hooks.json");
7722
7763
  if (wantCursor) {
7723
7764
  installCursorHooks(cursorHooks, {
7724
7765
  bashJudgeScriptPath: scripts.cursorBashJudgeScript,
@@ -7822,15 +7863,15 @@ function discoverSkillFiles(repoRoot, excludeHashes, ingestedHashes, ingestedNam
7822
7863
  const roots = [];
7823
7864
  const add = (p) => {
7824
7865
  try {
7825
- if (p && existsSync20(p) && statSync2(p).isDirectory()) roots.push(p);
7866
+ if (p && existsSync21(p) && statSync2(p).isDirectory()) roots.push(p);
7826
7867
  } catch {
7827
7868
  }
7828
7869
  };
7829
- add(join17(homedir17(), ".claude", "skills"));
7830
- add(join17(homedir17(), ".agents", "skills"));
7870
+ add(join18(homedir18(), ".claude", "skills"));
7871
+ add(join18(homedir18(), ".agents", "skills"));
7831
7872
  if (repoRoot) {
7832
- add(join17(repoRoot, ".claude", "skills"));
7833
- add(join17(repoRoot, ".agents", "skills"));
7873
+ add(join18(repoRoot, ".claude", "skills"));
7874
+ add(join18(repoRoot, ".agents", "skills"));
7834
7875
  }
7835
7876
  const out = [];
7836
7877
  const seen = /* @__PURE__ */ new Set();
@@ -7861,7 +7902,7 @@ function discoverSkillFiles(repoRoot, excludeHashes, ingestedHashes, ingestedNam
7861
7902
  }
7862
7903
  for (const entry of entries) {
7863
7904
  if (entry.startsWith(".")) continue;
7864
- const full = join17(root, entry);
7905
+ const full = join18(root, entry);
7865
7906
  let st;
7866
7907
  try {
7867
7908
  st = statSync2(full);
@@ -7869,8 +7910,8 @@ function discoverSkillFiles(repoRoot, excludeHashes, ingestedHashes, ingestedNam
7869
7910
  continue;
7870
7911
  }
7871
7912
  if (st.isDirectory()) {
7872
- const skillMd = join17(full, "SKILL.md");
7873
- if (existsSync20(skillMd)) consider(skillMd, entry);
7913
+ const skillMd = join18(full, "SKILL.md");
7914
+ if (existsSync21(skillMd)) consider(skillMd, entry);
7874
7915
  } else if (/\.mdx?$/i.test(entry) && entry.toUpperCase() !== "README.MD") {
7875
7916
  consider(full, entry.replace(/\.mdx?$/i, ""));
7876
7917
  }
@@ -7990,15 +8031,15 @@ function detectGitRepo2() {
7990
8031
  function getClaudeProjectsFolder() {
7991
8032
  const cwd = process.cwd();
7992
8033
  const sanitized = "-" + cwd.replace(/\//g, "-");
7993
- const projectsDir = join17(homedir17(), ".claude", "projects", sanitized);
7994
- return existsSync20(projectsDir) ? projectsDir : null;
8034
+ const projectsDir = join18(homedir18(), ".claude", "projects", sanitized);
8035
+ return existsSync21(projectsDir) ? projectsDir : null;
7995
8036
  }
7996
8037
  function extractSessionInsights(projectsDir) {
7997
8038
  const insights = [];
7998
8039
  const files = readdirSync3(projectsDir).filter((f) => f.endsWith(".jsonl"));
7999
8040
  for (const file of files) {
8000
8041
  const sessionId = file.replace(".jsonl", "");
8001
- const filePath = join17(projectsDir, file);
8042
+ const filePath = join18(projectsDir, file);
8002
8043
  try {
8003
8044
  const content = readFileSync18(filePath, "utf-8");
8004
8045
  const lines = content.split("\n").filter(Boolean);
@@ -8079,8 +8120,8 @@ function cursorProjectSlug(workspaceRoot) {
8079
8120
  return workspaceRoot.replace(/^[/]+/, "").replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "");
8080
8121
  }
8081
8122
  function getCursorTranscriptsDir() {
8082
- const dir = join17(homedir17(), ".cursor", "projects", cursorProjectSlug(process.cwd()), "agent-transcripts");
8083
- return existsSync20(dir) ? dir : null;
8123
+ const dir = join18(homedir18(), ".cursor", "projects", cursorProjectSlug(process.cwd()), "agent-transcripts");
8124
+ return existsSync21(dir) ? dir : null;
8084
8125
  }
8085
8126
  function isSafeConvId(id) {
8086
8127
  return /^[A-Za-z0-9_-]+$/.test(id);
@@ -8118,8 +8159,8 @@ async function syncCursorTranscriptsLocal(mcpPort, mcpToken, repo) {
8118
8159
  for (let i = 0; i < convDirs.length; i++) {
8119
8160
  const convId = convDirs[i];
8120
8161
  if (!isSafeConvId(convId)) continue;
8121
- const filePath = join17(dir, convId, `${convId}.jsonl`);
8122
- if (!existsSync20(filePath)) continue;
8162
+ const filePath = join18(dir, convId, `${convId}.jsonl`);
8163
+ if (!existsSync21(filePath)) continue;
8123
8164
  try {
8124
8165
  const all = parseCursorTranscriptFile(filePath);
8125
8166
  const messages = all.length > 500 ? all.slice(-500) : all;
@@ -8142,7 +8183,7 @@ async function syncCursorTranscriptsLocal(mcpPort, mcpToken, repo) {
8142
8183
  }
8143
8184
  try {
8144
8185
  const lc = readFileSync18(filePath, "utf-8").split("\n").filter(Boolean).length;
8145
- writeFileSync13(join17(OFFSETS_DIR, convId), String(lc), "utf-8");
8186
+ writeFileSync13(join18(OFFSETS_DIR, convId), String(lc), "utf-8");
8146
8187
  } catch {
8147
8188
  }
8148
8189
  }
@@ -8198,7 +8239,7 @@ async function syncTranscriptsLocal(mcpPort, mcpToken, repo) {
8198
8239
  for (let i = 0; i < files.length; i++) {
8199
8240
  const file = files[i];
8200
8241
  const sessionId = file.replace(".jsonl", "");
8201
- const filePath = join17(projectsDir, file);
8242
+ const filePath = join18(projectsDir, file);
8202
8243
  try {
8203
8244
  const allMessages = parseTranscriptFile(filePath);
8204
8245
  const messages = allMessages.length > 500 ? allMessages.slice(-500) : allMessages;
@@ -8220,9 +8261,9 @@ async function syncTranscriptsLocal(mcpPort, mcpToken, repo) {
8220
8261
  process.stdout.write(`\r Progress: ${i + 1}/${files.length} sessions (${totalMessages} messages embedded) `);
8221
8262
  }
8222
8263
  try {
8223
- const content = readFileSync18(join17(projectsDir, file), "utf-8");
8264
+ const content = readFileSync18(join18(projectsDir, file), "utf-8");
8224
8265
  const lineCount = content.split("\n").filter(Boolean).length;
8225
- writeFileSync13(join17(OFFSETS_DIR, sessionId), String(lineCount), "utf-8");
8266
+ writeFileSync13(join18(OFFSETS_DIR, sessionId), String(lineCount), "utf-8");
8226
8267
  } catch {
8227
8268
  }
8228
8269
  }
@@ -8243,7 +8284,7 @@ async function syncTranscriptsBulk(gatewayUrl, token, repo) {
8243
8284
  const sessions = [];
8244
8285
  for (const file of batch) {
8245
8286
  const sessionId = file.replace(".jsonl", "");
8246
- const filePath = join17(projectsDir, file);
8287
+ const filePath = join18(projectsDir, file);
8247
8288
  try {
8248
8289
  const allMessages = parseTranscriptFile(filePath);
8249
8290
  const messages = allMessages.length > maxMessagesPerSession ? allMessages.slice(-maxMessagesPerSession) : allMessages;
@@ -8272,11 +8313,11 @@ async function syncTranscriptsBulk(gatewayUrl, token, repo) {
8272
8313
  }
8273
8314
  for (const file of batch) {
8274
8315
  const sessionId = file.replace(".jsonl", "");
8275
- const filePath = join17(projectsDir, file);
8316
+ const filePath = join18(projectsDir, file);
8276
8317
  try {
8277
8318
  const content = readFileSync18(filePath, "utf-8");
8278
8319
  const lineCount = content.split("\n").filter(Boolean).length;
8279
- writeFileSync13(join17(OFFSETS_DIR, sessionId), String(lineCount), "utf-8");
8320
+ writeFileSync13(join18(OFFSETS_DIR, sessionId), String(lineCount), "utf-8");
8280
8321
  } catch {
8281
8322
  }
8282
8323
  }
@@ -8301,10 +8342,10 @@ var init_install = __esm({
8301
8342
  init_claudeDesktopTap();
8302
8343
  init_dockerInstall();
8303
8344
  init_setupToken();
8304
- SYNKRO_DIR11 = join17(homedir17(), ".synkro");
8305
- HOOKS_DIR = join17(SYNKRO_DIR11, "hooks");
8306
- BIN_DIR = join17(SYNKRO_DIR11, "bin");
8307
- CONFIG_PATH4 = join17(SYNKRO_DIR11, "config.env");
8345
+ SYNKRO_DIR11 = join18(homedir18(), ".synkro");
8346
+ HOOKS_DIR = join18(SYNKRO_DIR11, "hooks");
8347
+ BIN_DIR = join18(SYNKRO_DIR11, "bin");
8348
+ CONFIG_PATH4 = join18(SYNKRO_DIR11, "config.env");
8308
8349
  MCP_STDIO_PROXY_SRC = `#!/usr/bin/env bun
8309
8350
  import { readFileSync } from 'node:fs';
8310
8351
  import { homedir } from 'node:os';
@@ -8415,16 +8456,16 @@ rl.on('line', async (line) => {
8415
8456
  }
8416
8457
  });
8417
8458
  `;
8418
- OFFSETS_DIR = join17(SYNKRO_DIR11, ".transcript-offsets");
8419
- CLOUD_JWT_PATH = join17(SYNKRO_DIR11, ".cloud-jwt");
8420
- SKILLS_DISCOVERED_PATH = join17(SYNKRO_DIR11, ".skills-discovered");
8459
+ OFFSETS_DIR = join18(SYNKRO_DIR11, ".transcript-offsets");
8460
+ CLOUD_JWT_PATH = join18(SYNKRO_DIR11, ".cloud-jwt");
8461
+ SKILLS_DISCOVERED_PATH = join18(SYNKRO_DIR11, ".skills-discovered");
8421
8462
  }
8422
8463
  });
8423
8464
 
8424
8465
  // cli/local-cc/install.ts
8425
- import { existsSync as existsSync21, mkdirSync as mkdirSync14, writeFileSync as writeFileSync14, readFileSync as readFileSync19, chmodSync as chmodSync4, copyFileSync as copyFileSync2, renameSync as renameSync6, unlinkSync as unlinkSync7, openSync as openSync2, fsyncSync, closeSync as closeSync2 } from "fs";
8426
- import { join as join18 } from "path";
8427
- import { homedir as homedir18 } from "os";
8466
+ import { existsSync as existsSync22, mkdirSync as mkdirSync14, writeFileSync as writeFileSync14, readFileSync as readFileSync19, chmodSync as chmodSync4, copyFileSync as copyFileSync2, renameSync as renameSync6, unlinkSync as unlinkSync7, openSync as openSync2, fsyncSync, closeSync as closeSync2 } from "fs";
8467
+ import { join as join19 } from "path";
8468
+ import { homedir as homedir19 } from "os";
8428
8469
  import { spawnSync as spawnSync6 } from "child_process";
8429
8470
  function writePluginFiles() {
8430
8471
  for (const c of CHANNELS) {
@@ -8465,7 +8506,7 @@ function runBunInstall() {
8465
8506
  }
8466
8507
  }
8467
8508
  function safelyMutateClaudeJson(mutator) {
8468
- if (!existsSync21(CLAUDE_JSON_PATH)) {
8509
+ if (!existsSync22(CLAUDE_JSON_PATH)) {
8469
8510
  return;
8470
8511
  }
8471
8512
  const originalText = readFileSync19(CLAUDE_JSON_PATH, "utf-8");
@@ -8610,42 +8651,42 @@ var CLAUDE_JSON_BACKUP_PATH, SESSION_DIR, PLUGIN_PATH, PLUGIN_PKG_PATH, PLUGIN_S
8610
8651
  var init_install2 = __esm({
8611
8652
  "cli/local-cc/install.ts"() {
8612
8653
  "use strict";
8613
- CLAUDE_JSON_BACKUP_PATH = join18(homedir18(), ".claude.json.synkro-bak");
8614
- SESSION_DIR = join18(homedir18(), ".synkro", "cc_sessions");
8615
- PLUGIN_PATH = join18(SESSION_DIR, "synkro-channel.ts");
8616
- PLUGIN_PKG_PATH = join18(SESSION_DIR, "package.json");
8617
- PLUGIN_SETTINGS_DIR = join18(SESSION_DIR, ".claude");
8618
- PLUGIN_SETTINGS_PATH = join18(PLUGIN_SETTINGS_DIR, "settings.json");
8619
- PROJECT_MCP_PATH = join18(SESSION_DIR, ".mcp.json");
8620
- CLAUDE_JSON_PATH = join18(homedir18(), ".claude.json");
8621
- RUN_SCRIPT_PATH = join18(SESSION_DIR, "run-claude.sh");
8654
+ CLAUDE_JSON_BACKUP_PATH = join19(homedir19(), ".claude.json.synkro-bak");
8655
+ SESSION_DIR = join19(homedir19(), ".synkro", "cc_sessions");
8656
+ PLUGIN_PATH = join19(SESSION_DIR, "synkro-channel.ts");
8657
+ PLUGIN_PKG_PATH = join19(SESSION_DIR, "package.json");
8658
+ PLUGIN_SETTINGS_DIR = join19(SESSION_DIR, ".claude");
8659
+ PLUGIN_SETTINGS_PATH = join19(PLUGIN_SETTINGS_DIR, "settings.json");
8660
+ PROJECT_MCP_PATH = join19(SESSION_DIR, ".mcp.json");
8661
+ CLAUDE_JSON_PATH = join19(homedir19(), ".claude.json");
8662
+ RUN_SCRIPT_PATH = join19(SESSION_DIR, "run-claude.sh");
8622
8663
  TMUX_SESSION_NAME = "synkro-local-cc";
8623
8664
  CHANNEL_1_PORT = 8941;
8624
- SESSION_DIR_2 = join18(homedir18(), ".synkro", "cc_sessions_2");
8625
- PLUGIN_PATH_2 = join18(SESSION_DIR_2, "synkro-channel.ts");
8626
- PLUGIN_PKG_PATH_2 = join18(SESSION_DIR_2, "package.json");
8627
- PLUGIN_SETTINGS_DIR_2 = join18(SESSION_DIR_2, ".claude");
8628
- PLUGIN_SETTINGS_PATH_2 = join18(PLUGIN_SETTINGS_DIR_2, "settings.json");
8629
- PROJECT_MCP_PATH_2 = join18(SESSION_DIR_2, ".mcp.json");
8630
- RUN_SCRIPT_PATH_2 = join18(SESSION_DIR_2, "run-claude.sh");
8665
+ SESSION_DIR_2 = join19(homedir19(), ".synkro", "cc_sessions_2");
8666
+ PLUGIN_PATH_2 = join19(SESSION_DIR_2, "synkro-channel.ts");
8667
+ PLUGIN_PKG_PATH_2 = join19(SESSION_DIR_2, "package.json");
8668
+ PLUGIN_SETTINGS_DIR_2 = join19(SESSION_DIR_2, ".claude");
8669
+ PLUGIN_SETTINGS_PATH_2 = join19(PLUGIN_SETTINGS_DIR_2, "settings.json");
8670
+ PROJECT_MCP_PATH_2 = join19(SESSION_DIR_2, ".mcp.json");
8671
+ RUN_SCRIPT_PATH_2 = join19(SESSION_DIR_2, "run-claude.sh");
8631
8672
  TMUX_SESSION_NAME_2 = "synkro-local-cc-2";
8632
8673
  CHANNEL_2_PORT = 8951;
8633
- SESSION_DIR_3 = join18(homedir18(), ".synkro", "cc_sessions_3");
8634
- PLUGIN_PATH_3 = join18(SESSION_DIR_3, "synkro-channel.ts");
8635
- PLUGIN_PKG_PATH_3 = join18(SESSION_DIR_3, "package.json");
8636
- PLUGIN_SETTINGS_DIR_3 = join18(SESSION_DIR_3, ".claude");
8637
- PLUGIN_SETTINGS_PATH_3 = join18(PLUGIN_SETTINGS_DIR_3, "settings.json");
8638
- PROJECT_MCP_PATH_3 = join18(SESSION_DIR_3, ".mcp.json");
8639
- RUN_SCRIPT_PATH_3 = join18(SESSION_DIR_3, "run-claude.sh");
8674
+ SESSION_DIR_3 = join19(homedir19(), ".synkro", "cc_sessions_3");
8675
+ PLUGIN_PATH_3 = join19(SESSION_DIR_3, "synkro-channel.ts");
8676
+ PLUGIN_PKG_PATH_3 = join19(SESSION_DIR_3, "package.json");
8677
+ PLUGIN_SETTINGS_DIR_3 = join19(SESSION_DIR_3, ".claude");
8678
+ PLUGIN_SETTINGS_PATH_3 = join19(PLUGIN_SETTINGS_DIR_3, "settings.json");
8679
+ PROJECT_MCP_PATH_3 = join19(SESSION_DIR_3, ".mcp.json");
8680
+ RUN_SCRIPT_PATH_3 = join19(SESSION_DIR_3, "run-claude.sh");
8640
8681
  TMUX_SESSION_NAME_3 = "synkro-local-cc-3";
8641
8682
  CHANNEL_3_PORT = 8942;
8642
- SESSION_DIR_4 = join18(homedir18(), ".synkro", "cc_sessions_4");
8643
- PLUGIN_PATH_4 = join18(SESSION_DIR_4, "synkro-channel.ts");
8644
- PLUGIN_PKG_PATH_4 = join18(SESSION_DIR_4, "package.json");
8645
- PLUGIN_SETTINGS_DIR_4 = join18(SESSION_DIR_4, ".claude");
8646
- PLUGIN_SETTINGS_PATH_4 = join18(PLUGIN_SETTINGS_DIR_4, "settings.json");
8647
- PROJECT_MCP_PATH_4 = join18(SESSION_DIR_4, ".mcp.json");
8648
- RUN_SCRIPT_PATH_4 = join18(SESSION_DIR_4, "run-claude.sh");
8683
+ SESSION_DIR_4 = join19(homedir19(), ".synkro", "cc_sessions_4");
8684
+ PLUGIN_PATH_4 = join19(SESSION_DIR_4, "synkro-channel.ts");
8685
+ PLUGIN_PKG_PATH_4 = join19(SESSION_DIR_4, "package.json");
8686
+ PLUGIN_SETTINGS_DIR_4 = join19(SESSION_DIR_4, ".claude");
8687
+ PLUGIN_SETTINGS_PATH_4 = join19(PLUGIN_SETTINGS_DIR_4, "settings.json");
8688
+ PROJECT_MCP_PATH_4 = join19(SESSION_DIR_4, ".mcp.json");
8689
+ RUN_SCRIPT_PATH_4 = join19(SESSION_DIR_4, "run-claude.sh");
8649
8690
  TMUX_SESSION_NAME_4 = "synkro-local-cc-4";
8650
8691
  CHANNEL_4_PORT = 8952;
8651
8692
  RUN_SCRIPT_SOURCE = `#!/usr/bin/env bash
@@ -8919,9 +8960,9 @@ var disconnect_exports = {};
8919
8960
  __export(disconnect_exports, {
8920
8961
  disconnectCommand: () => disconnectCommand
8921
8962
  });
8922
- import { existsSync as existsSync22, rmSync as rmSync2, readdirSync as readdirSync4 } from "fs";
8923
- import { homedir as homedir19 } from "os";
8924
- import { join as join19 } from "path";
8963
+ import { existsSync as existsSync23, rmSync as rmSync2, readdirSync as readdirSync4 } from "fs";
8964
+ import { homedir as homedir20 } from "os";
8965
+ import { join as join20 } from "path";
8925
8966
  import { spawnSync as spawnSync7 } from "child_process";
8926
8967
  import { createInterface as createInterface4 } from "readline";
8927
8968
  async function tearDownLocalCC() {
@@ -9007,7 +9048,7 @@ async function disconnectCommand(args2 = [], opts = {}) {
9007
9048
  if (desktopMcpRemoved) removed.mcp = true;
9008
9049
  console.log(`${desktopMcpRemoved ? "\u2713" : "\xB7"} MCP guardrails (Claude Desktop): ${desktopMcpRemoved ? "removed from claude_desktop_config.json" : "no entry found"}`);
9009
9050
  }
9010
- if (existsSync22(SYNKRO_DIR12)) {
9051
+ if (existsSync23(SYNKRO_DIR12)) {
9011
9052
  if (purge2) {
9012
9053
  emit("uninstall", {
9013
9054
  flavor,
@@ -9021,13 +9062,13 @@ async function disconnectCommand(args2 = [], opts = {}) {
9021
9062
  console.log(`\u2713 wiped ${SYNKRO_DIR12} entirely \u2014 including all scan data and backups`);
9022
9063
  } else {
9023
9064
  const keep = /* @__PURE__ */ new Set([
9024
- join19(SYNKRO_DIR12, "pgdata"),
9025
- join19(SYNKRO_DIR12, "pgdata-backups"),
9026
- join19(SYNKRO_DIR12, ".transcript-offsets")
9065
+ join20(SYNKRO_DIR12, "pgdata"),
9066
+ join20(SYNKRO_DIR12, "pgdata-backups"),
9067
+ join20(SYNKRO_DIR12, ".transcript-offsets")
9027
9068
  ]);
9028
9069
  const preserved = [];
9029
9070
  for (const entry of readdirSync4(SYNKRO_DIR12)) {
9030
- const full = join19(SYNKRO_DIR12, entry);
9071
+ const full = join20(SYNKRO_DIR12, entry);
9031
9072
  if (keep.has(full)) {
9032
9073
  preserved.push(entry);
9033
9074
  continue;
@@ -9062,14 +9103,14 @@ var init_disconnect = __esm({
9062
9103
  init_dockerInstall();
9063
9104
  init_macKeychain();
9064
9105
  init_telemetry();
9065
- SYNKRO_DIR12 = join19(homedir19(), ".synkro");
9106
+ SYNKRO_DIR12 = join20(homedir20(), ".synkro");
9066
9107
  }
9067
9108
  });
9068
9109
 
9069
9110
  // cli/local-cc/turnLog.ts
9070
- import { appendFileSync as appendFileSync3, existsSync as existsSync23, mkdirSync as mkdirSync15, openSync as openSync3, readFileSync as readFileSync20, readSync, closeSync as closeSync3, statSync as statSync3, watchFile, unwatchFile } from "fs";
9071
- import { dirname as dirname6, join as join20 } from "path";
9072
- import { homedir as homedir20 } from "os";
9111
+ import { appendFileSync as appendFileSync3, existsSync as existsSync24, mkdirSync as mkdirSync15, openSync as openSync3, readFileSync as readFileSync20, readSync, closeSync as closeSync3, statSync as statSync3, watchFile, unwatchFile } from "fs";
9112
+ import { dirname as dirname6, join as join21 } from "path";
9113
+ import { homedir as homedir21 } from "os";
9073
9114
  function truncate(s, max = PREVIEW_MAX) {
9074
9115
  if (s.length <= max) return s;
9075
9116
  return s.slice(0, max) + "\u2026 [+" + (s.length - max) + " chars]";
@@ -9105,7 +9146,7 @@ function appendTurn(args2) {
9105
9146
  }
9106
9147
  }
9107
9148
  function readRecentTurns(n = 20) {
9108
- if (!existsSync23(TURN_LOG_PATH)) return [];
9149
+ if (!existsSync24(TURN_LOG_PATH)) return [];
9109
9150
  try {
9110
9151
  const size = statSync3(TURN_LOG_PATH).size;
9111
9152
  if (size === 0) return [];
@@ -9126,7 +9167,7 @@ function readRecentTurns(n = 20) {
9126
9167
  function followTurns(onEntry) {
9127
9168
  try {
9128
9169
  mkdirSync15(dirname6(TURN_LOG_PATH), { recursive: true });
9129
- if (!existsSync23(TURN_LOG_PATH)) {
9170
+ if (!existsSync24(TURN_LOG_PATH)) {
9130
9171
  appendFileSync3(TURN_LOG_PATH, "", "utf-8");
9131
9172
  }
9132
9173
  } catch {
@@ -9188,7 +9229,7 @@ var TURN_LOG_PATH, PREVIEW_MAX;
9188
9229
  var init_turnLog = __esm({
9189
9230
  "cli/local-cc/turnLog.ts"() {
9190
9231
  "use strict";
9191
- TURN_LOG_PATH = join20(homedir20(), ".synkro", "cc_sessions", "turns.log");
9232
+ TURN_LOG_PATH = join21(homedir21(), ".synkro", "cc_sessions", "turns.log");
9192
9233
  PREVIEW_MAX = 400;
9193
9234
  }
9194
9235
  });
@@ -9338,8 +9379,8 @@ var init_grade = __esm({
9338
9379
 
9339
9380
  // cli/local-cc/pueue.ts
9340
9381
  import { execFileSync as execFileSync4, spawnSync as spawnSync8, spawn as spawn3 } from "child_process";
9341
- import { homedir as homedir21 } from "os";
9342
- import { join as join21 } from "path";
9382
+ import { homedir as homedir22 } from "os";
9383
+ import { join as join22 } from "path";
9343
9384
  import { connect as connect2 } from "net";
9344
9385
  function pueueAvailable() {
9345
9386
  const r = spawnSync8("pueue", ["--version"], { encoding: "utf-8" });
@@ -9405,7 +9446,7 @@ function startTask(opts = {}) {
9405
9446
  spawnSync8("pueue", ["remove", String(existing.id)], { encoding: "utf-8" });
9406
9447
  existing = findTask(ch);
9407
9448
  }
9408
- const runScript = join21(cwd, "run-claude.sh");
9449
+ const runScript = join22(cwd, "run-claude.sh");
9409
9450
  const args2 = [
9410
9451
  "add",
9411
9452
  "--label",
@@ -9535,12 +9576,12 @@ var init_pueue = __esm({
9535
9576
  "use strict";
9536
9577
  TASK_LABEL = "synkro-local-cc";
9537
9578
  TMUX_SESSION = "synkro-local-cc";
9538
- SESSION_DIR2 = join21(homedir21(), ".synkro", "cc_sessions");
9579
+ SESSION_DIR2 = join22(homedir22(), ".synkro", "cc_sessions");
9539
9580
  TASK_LABEL_2 = "synkro-local-cc-2";
9540
9581
  TMUX_SESSION_2 = "synkro-local-cc-2";
9541
- SESSION_DIR_22 = join21(homedir21(), ".synkro", "cc_sessions_2");
9542
- SESSION_DIR_32 = join21(homedir21(), ".synkro", "cc_sessions_3");
9543
- SESSION_DIR_42 = join21(homedir21(), ".synkro", "cc_sessions_4");
9582
+ SESSION_DIR_22 = join22(homedir22(), ".synkro", "cc_sessions_2");
9583
+ SESSION_DIR_32 = join22(homedir22(), ".synkro", "cc_sessions_3");
9584
+ SESSION_DIR_42 = join22(homedir22(), ".synkro", "cc_sessions_4");
9544
9585
  PueueError = class extends Error {
9545
9586
  constructor(message, cause) {
9546
9587
  super(message);
@@ -9555,11 +9596,11 @@ var init_pueue = __esm({
9555
9596
  });
9556
9597
 
9557
9598
  // cli/local-cc/settings.ts
9558
- import { existsSync as existsSync24, readFileSync as readFileSync21 } from "fs";
9559
- import { homedir as homedir22 } from "os";
9560
- import { join as join22 } from "path";
9599
+ import { existsSync as existsSync25, readFileSync as readFileSync21 } from "fs";
9600
+ import { homedir as homedir23 } from "os";
9601
+ import { join as join23 } from "path";
9561
9602
  function isLocalCCEnabled() {
9562
- if (!existsSync24(CONFIG_PATH5)) return false;
9603
+ if (!existsSync25(CONFIG_PATH5)) return false;
9563
9604
  try {
9564
9605
  const content = readFileSync21(CONFIG_PATH5, "utf-8");
9565
9606
  const match = content.match(/^SYNKRO_LOCAL_INFERENCE='([^']*)'/m);
@@ -9572,7 +9613,7 @@ var CONFIG_PATH5;
9572
9613
  var init_settings = __esm({
9573
9614
  "cli/local-cc/settings.ts"() {
9574
9615
  "use strict";
9575
- CONFIG_PATH5 = join22(homedir22(), ".synkro", "config.env");
9616
+ CONFIG_PATH5 = join23(homedir23(), ".synkro", "config.env");
9576
9617
  }
9577
9618
  });
9578
9619
 
@@ -9582,10 +9623,10 @@ __export(localCc_exports, {
9582
9623
  localCcCommand: () => localCcCommand
9583
9624
  });
9584
9625
  import { spawnSync as spawnSync9 } from "child_process";
9585
- import { homedir as homedir23 } from "os";
9586
- import { join as join23 } from "path";
9626
+ import { homedir as homedir24 } from "os";
9627
+ import { join as join24 } from "path";
9587
9628
  import { readFileSync as fsReadFileSync, existsSync as fsExistsSync } from "fs";
9588
- import { existsSync as existsSync25, readFileSync as readFileSync22, writeFileSync as writeFileSync15 } from "fs";
9629
+ import { existsSync as existsSync26, readFileSync as readFileSync22, writeFileSync as writeFileSync15 } from "fs";
9589
9630
  function deploymentMode() {
9590
9631
  const env = (process.env.SYNKRO_DEPLOYMENT_MODE || "").toLowerCase();
9591
9632
  if (env === "docker") return "docker";
@@ -9691,14 +9732,14 @@ TROUBLESHOOTING
9691
9732
  `);
9692
9733
  }
9693
9734
  function readGatewayUrl() {
9694
- if (existsSync25(CONFIG_PATH6)) {
9735
+ if (existsSync26(CONFIG_PATH6)) {
9695
9736
  const m = readFileSync22(CONFIG_PATH6, "utf-8").match(/^SYNKRO_GATEWAY_URL='([^']*)'/m);
9696
9737
  if (m) return m[1];
9697
9738
  }
9698
9739
  return "https://api.synkro.sh";
9699
9740
  }
9700
9741
  function updateLocalInferenceFlag(enabled) {
9701
- if (!existsSync25(CONFIG_PATH6)) return;
9742
+ if (!existsSync26(CONFIG_PATH6)) return;
9702
9743
  let content = readFileSync22(CONFIG_PATH6, "utf-8");
9703
9744
  const flag = enabled ? "yes" : "no";
9704
9745
  if (content.includes("SYNKRO_LOCAL_INFERENCE=")) {
@@ -10140,8 +10181,8 @@ var init_localCc = __esm({
10140
10181
  init_install();
10141
10182
  init_client2();
10142
10183
  init_stub();
10143
- SYNKRO_CONFIG_PATH = join23(homedir23(), ".synkro", "config.env");
10144
- CONFIG_PATH6 = join23(homedir23(), ".synkro", "config.env");
10184
+ SYNKRO_CONFIG_PATH = join24(homedir24(), ".synkro", "config.env");
10185
+ CONFIG_PATH6 = join24(homedir24(), ".synkro", "config.env");
10145
10186
  }
10146
10187
  });
10147
10188
 
@@ -10150,9 +10191,9 @@ var import_exports = {};
10150
10191
  __export(import_exports, {
10151
10192
  importCommand: () => importCommand
10152
10193
  });
10153
- import { existsSync as existsSync26, readFileSync as readFileSync23, readdirSync as readdirSync5 } from "fs";
10154
- import { homedir as homedir24 } from "os";
10155
- import { join as join24 } from "path";
10194
+ import { existsSync as existsSync27, readFileSync as readFileSync23, readdirSync as readdirSync5 } from "fs";
10195
+ import { homedir as homedir25 } from "os";
10196
+ import { join as join25 } from "path";
10156
10197
  import { execSync as execSync7 } from "child_process";
10157
10198
  import { createInterface as createInterface5 } from "readline";
10158
10199
  function readConfigEnv2() {
@@ -10170,8 +10211,8 @@ function readConfigEnv2() {
10170
10211
  }
10171
10212
  function projectsFolder() {
10172
10213
  const sanitized = process.cwd().replace(/\//g, "-");
10173
- const dir = join24(homedir24(), ".claude", "projects", sanitized);
10174
- return existsSync26(dir) ? dir : null;
10214
+ const dir = join25(homedir25(), ".claude", "projects", sanitized);
10215
+ return existsSync27(dir) ? dir : null;
10175
10216
  }
10176
10217
  function repoName() {
10177
10218
  try {
@@ -10267,7 +10308,7 @@ async function importCommand() {
10267
10308
  return;
10268
10309
  }
10269
10310
  }
10270
- const sessions = files.map((f) => parseSession(join24(dir, f), f.replace(".jsonl", ""))).filter((s) => s.messages.length > 0);
10311
+ const sessions = files.map((f) => parseSession(join25(dir, f), f.replace(".jsonl", ""))).filter((s) => s.messages.length > 0);
10271
10312
  const totalMsgs = sessions.reduce((n, s) => n + s.messages.length, 0);
10272
10313
  let ok = 0, fail = 0;
10273
10314
  if (isCloud) {
@@ -10327,7 +10368,7 @@ var init_import = __esm({
10327
10368
  "cli/commands/import.ts"() {
10328
10369
  "use strict";
10329
10370
  init_stub();
10330
- CONFIG_PATH7 = join24(homedir24(), ".synkro", "config.env");
10371
+ CONFIG_PATH7 = join25(homedir25(), ".synkro", "config.env");
10331
10372
  }
10332
10373
  });
10333
10374
 
@@ -10369,10 +10410,10 @@ var init_packVerify = __esm({
10369
10410
  });
10370
10411
 
10371
10412
  // cli/installer/lockfile.ts
10372
- import { existsSync as existsSync27, readFileSync as readFileSync24, writeFileSync as writeFileSync16 } from "fs";
10373
- import { join as join25 } from "path";
10413
+ import { existsSync as existsSync28, readFileSync as readFileSync24, writeFileSync as writeFileSync16 } from "fs";
10414
+ import { join as join26 } from "path";
10374
10415
  function lockPath(repoRoot) {
10375
- return join25(repoRoot, LOCK_FILE);
10416
+ return join26(repoRoot, LOCK_FILE);
10376
10417
  }
10377
10418
  function writeLockfile(repoRoot, entries) {
10378
10419
  const sorted = [...entries].sort((a, b) => a.ref.localeCompare(b.ref));
@@ -10405,9 +10446,9 @@ var sync_exports = {};
10405
10446
  __export(sync_exports, {
10406
10447
  syncCommand: () => syncCommand
10407
10448
  });
10408
- import { existsSync as existsSync28, mkdirSync as mkdirSync16, readdirSync as readdirSync6, rmSync as rmSync3, writeFileSync as writeFileSync17 } from "fs";
10409
- import { homedir as homedir25 } from "os";
10410
- import { join as join26 } from "path";
10449
+ import { existsSync as existsSync29, mkdirSync as mkdirSync16, readdirSync as readdirSync6, rmSync as rmSync3, writeFileSync as writeFileSync17 } from "fs";
10450
+ import { homedir as homedir26 } from "os";
10451
+ import { join as join27 } from "path";
10411
10452
  function cacheKey(ref, version) {
10412
10453
  return ref.replace(/\//g, "__").replace(/[^\w.@-]/g, "_") + "@" + version + ".json";
10413
10454
  }
@@ -10438,7 +10479,7 @@ async function syncCommand(_args = []) {
10438
10479
  }
10439
10480
  const gateway = (process.env.SYNKRO_GATEWAY_URL || "https://api.synkro.sh").replace(/\/$/, "");
10440
10481
  const cloud = process.env.SYNKRO_DEPLOY_LOCATION === "cloud";
10441
- const cacheDir = join26(homedir25(), ".synkro", "cache", "packs");
10482
+ const cacheDir = join27(homedir26(), ".synkro", "cache", "packs");
10442
10483
  if (!cloud) mkdirSync16(cacheDir, { recursive: true });
10443
10484
  console.log(`Syncing ${refs.length} standard(s) from the registry\u2026`);
10444
10485
  const lock = [];
@@ -10467,7 +10508,7 @@ async function syncCommand(_args = []) {
10467
10508
  if (!cloud) {
10468
10509
  const fname = cacheKey(ref, data.version);
10469
10510
  keptCacheFiles.add(fname);
10470
- writeFileSync17(join26(cacheDir, fname), JSON.stringify({
10511
+ writeFileSync17(join27(cacheDir, fname), JSON.stringify({
10471
10512
  ref,
10472
10513
  version: data.version,
10473
10514
  digest: data.digest,
@@ -10479,11 +10520,11 @@ async function syncCommand(_args = []) {
10479
10520
  const ruleCount = Array.isArray(pack.rules) ? pack.rules.length : 0;
10480
10521
  console.log(` \u2713 ${ref}:${data.version} \u2014 verified (${ruleCount} rule${ruleCount === 1 ? "" : "s"})`);
10481
10522
  }
10482
- if (!cloud && existsSync28(cacheDir)) {
10523
+ if (!cloud && existsSync29(cacheDir)) {
10483
10524
  for (const f of readdirSync6(cacheDir)) {
10484
10525
  if (f.endsWith(".json") && !keptCacheFiles.has(f)) {
10485
10526
  try {
10486
- rmSync3(join26(cacheDir, f));
10527
+ rmSync3(join27(cacheDir, f));
10487
10528
  } catch {
10488
10529
  }
10489
10530
  }
@@ -10619,11 +10660,11 @@ var config_exports = {};
10619
10660
  __export(config_exports, {
10620
10661
  configCommand: () => configCommand
10621
10662
  });
10622
- import { readFileSync as readFileSync25, writeFileSync as writeFileSync18, existsSync as existsSync29 } from "fs";
10623
- import { join as join27 } from "path";
10624
- import { homedir as homedir26 } from "os";
10663
+ import { readFileSync as readFileSync25, writeFileSync as writeFileSync18, existsSync as existsSync30 } from "fs";
10664
+ import { join as join28 } from "path";
10665
+ import { homedir as homedir27 } from "os";
10625
10666
  function readConfigEnv3() {
10626
- if (!existsSync29(CONFIG_PATH8)) return {};
10667
+ if (!existsSync30(CONFIG_PATH8)) return {};
10627
10668
  const out = {};
10628
10669
  for (const line of readFileSync25(CONFIG_PATH8, "utf-8").split("\n")) {
10629
10670
  const t = line.trim();
@@ -10634,7 +10675,7 @@ function readConfigEnv3() {
10634
10675
  return out;
10635
10676
  }
10636
10677
  function updateConfigValue(key, value) {
10637
- if (!existsSync29(CONFIG_PATH8)) {
10678
+ if (!existsSync30(CONFIG_PATH8)) {
10638
10679
  console.error("No config found. Run `synkro install` first.");
10639
10680
  process.exit(1);
10640
10681
  }
@@ -10807,8 +10848,8 @@ var init_config = __esm({
10807
10848
  "use strict";
10808
10849
  init_stub();
10809
10850
  init_optout();
10810
- SYNKRO_DIR13 = join27(homedir26(), ".synkro");
10811
- CONFIG_PATH8 = join27(SYNKRO_DIR13, "config.env");
10851
+ SYNKRO_DIR13 = join28(homedir27(), ".synkro");
10852
+ CONFIG_PATH8 = join28(SYNKRO_DIR13, "config.env");
10812
10853
  }
10813
10854
  });
10814
10855
 
@@ -10997,13 +11038,13 @@ Usage:
10997
11038
  });
10998
11039
 
10999
11040
  // cli/bootstrap.js
11000
- import { readFileSync as readFileSync26, existsSync as existsSync30 } from "fs";
11041
+ import { readFileSync as readFileSync26, existsSync as existsSync31 } from "fs";
11001
11042
  import { resolve as resolve3 } from "path";
11002
11043
  var envCandidates = [
11003
11044
  resolve3(process.env.HOME ?? "", ".synkro", "config.env")
11004
11045
  ];
11005
11046
  for (const envPath of envCandidates) {
11006
- if (!existsSync30(envPath)) continue;
11047
+ if (!existsSync31(envPath)) continue;
11007
11048
  const envContent = readFileSync26(envPath, "utf-8");
11008
11049
  for (const line of envContent.split("\n")) {
11009
11050
  const trimmed = line.trim();
@@ -11021,7 +11062,7 @@ var subArgs = args.slice(1);
11021
11062
  var isDetachedChild = process.env.SYNKRO_TELEMETRY_DETACHED === "1";
11022
11063
  var FLUSH_SKIP = /* @__PURE__ */ new Set(["grade", "version", "--version", "-v", "help", "--help", "-h", ""]);
11023
11064
  function printVersion() {
11024
- console.log("1.7.62");
11065
+ console.log("1.7.63");
11025
11066
  }
11026
11067
  function printHelp2() {
11027
11068
  console.log(`Synkro CLI \u2014 runtime safety for AI coding agents