@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 +340 -299
- package/dist/bootstrap.js.map +1 -1
- package/package.json +1 -1
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.
|
|
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
|
|
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 (!
|
|
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
|
-
|
|
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 (!
|
|
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
|
|
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
|
|
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(
|
|
1834
|
-
resolve(
|
|
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
|
|
1855
|
-
import { homedir as
|
|
1856
|
-
import { dirname as dirname3, join as
|
|
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 (!
|
|
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 =
|
|
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 (!
|
|
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 (!
|
|
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 =
|
|
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 (!
|
|
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
|
|
1981
|
-
|
|
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 (!
|
|
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 (!
|
|
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:
|
|
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 (!
|
|
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 =
|
|
2049
|
-
CURSOR_MCP_PATH =
|
|
2050
|
-
CLAUDE_DESKTOP_CONFIG_PATH =
|
|
2051
|
-
|
|
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 =
|
|
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
|
|
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) =>
|
|
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
|
|
2725
|
-
import { homedir as
|
|
2726
|
-
import { join as
|
|
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 (!
|
|
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 (!
|
|
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 (
|
|
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 ||
|
|
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
|
|
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
|
|
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 =
|
|
3289
|
+
const workflowDir = join11(repoRootPath, ".github", "workflows");
|
|
3249
3290
|
mkdirSync8(workflowDir, { recursive: true });
|
|
3250
|
-
const workflowFile =
|
|
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 (
|
|
3258
|
-
const parent =
|
|
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
|
|
3609
|
-
import { join as
|
|
3610
|
-
import { homedir as
|
|
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" &&
|
|
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 =
|
|
3788
|
+
const cdRoot = join12(homedir12(), ".synkro", "cd-sessions");
|
|
3748
3789
|
mkdirSync9(cdRoot, { recursive: true });
|
|
3749
|
-
const sessionDir = mkdtempSync(
|
|
3750
|
-
writeFileSync11(
|
|
3751
|
-
writeFileSync11(
|
|
3752
|
-
writeFileSync11(
|
|
3753
|
-
const runnerPath =
|
|
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 =
|
|
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
|
|
4904
|
-
import { homedir as
|
|
4905
|
-
import { join as
|
|
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 (
|
|
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
|
|
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 (!
|
|
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(
|
|
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 (
|
|
5077
|
-
if (
|
|
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 =
|
|
5097
|
-
CLAUDE_CREDS_DIR =
|
|
5098
|
-
CLAUDE_CREDS_FILE =
|
|
5099
|
-
CURSOR_CREDS_DIR =
|
|
5100
|
-
CURSOR_API_KEY_FILE =
|
|
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 =
|
|
5104
|
-
REFRESH_SCRIPT =
|
|
5105
|
-
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
|
|
5145
|
-
import { homedir as
|
|
5146
|
-
import { join as
|
|
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 =
|
|
5242
|
-
if (!
|
|
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
|
|
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 =
|
|
5375
|
-
if (
|
|
5415
|
+
const hostClaudeJson = join14(homedir14(), ".claude.json");
|
|
5416
|
+
if (existsSync18(hostClaudeJson)) {
|
|
5376
5417
|
copyFileSync(hostClaudeJson, CLAUDE_HOST_STATE_FILE);
|
|
5377
5418
|
}
|
|
5378
|
-
if (!
|
|
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(
|
|
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
|
-
`${
|
|
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 (
|
|
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 (!
|
|
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 =
|
|
5713
|
-
MCP_JWT_PATH =
|
|
5714
|
-
PGDATA_PATH =
|
|
5715
|
-
CLAUDE_HOST_STATE_DIR =
|
|
5716
|
-
CLAUDE_HOST_STATE_FILE =
|
|
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 =
|
|
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
|
|
5739
|
-
import { join as
|
|
5779
|
+
import { homedir as homedir15, platform as platform4 } from "os";
|
|
5780
|
+
import { join as join15 } from "path";
|
|
5740
5781
|
function captureClaudeSetupToken() {
|
|
5741
|
-
const tmpFile =
|
|
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 =
|
|
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
|
|
5832
|
-
import { homedir as
|
|
5833
|
-
import { join as
|
|
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 =
|
|
5863
|
-
if (!
|
|
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 =
|
|
5902
|
-
CODEX_CLOUD_HOME =
|
|
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
|
|
5916
|
-
import { homedir as
|
|
5917
|
-
import { join as
|
|
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 (!
|
|
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 =
|
|
6230
|
-
CONFIG_PATH3 =
|
|
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
|
|
6250
|
-
import { homedir as
|
|
6251
|
-
import { join as
|
|
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(
|
|
6441
|
+
mkdirSync13(join18(SYNKRO_DIR11, "sessions"), { recursive: true });
|
|
6401
6442
|
}
|
|
6402
6443
|
function writeHookScripts() {
|
|
6403
|
-
const installExtractCorePath =
|
|
6404
|
-
const bashScriptPath =
|
|
6405
|
-
const skillJudgeScriptPath =
|
|
6406
|
-
const cursorSkillJudgePath =
|
|
6407
|
-
const bashFollowupScriptPath =
|
|
6408
|
-
const editPrecheckScriptPath =
|
|
6409
|
-
const cwePrecheckScriptPath =
|
|
6410
|
-
const cvePrecheckScriptPath =
|
|
6411
|
-
const planJudgeScriptPath =
|
|
6412
|
-
const agentJudgeScriptPath =
|
|
6413
|
-
const stopSummaryScriptPath =
|
|
6414
|
-
const sessionStartScriptPath =
|
|
6415
|
-
const transcriptSyncScriptPath =
|
|
6416
|
-
const userPromptSubmitScriptPath =
|
|
6417
|
-
const commonScriptPath =
|
|
6418
|
-
const commonBashScriptPath =
|
|
6419
|
-
const installScanScriptPath =
|
|
6420
|
-
const cursorBashJudgePath =
|
|
6421
|
-
const cursorEditCapturePath =
|
|
6422
|
-
const cursorAgentCapturePath =
|
|
6423
|
-
const mcpStdioProxyPath =
|
|
6424
|
-
const taskActivateIntentScriptPath =
|
|
6425
|
-
const mcpGateScriptPath =
|
|
6426
|
-
const stubCommonPath =
|
|
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(
|
|
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 &&
|
|
6533
|
+
if (scriptPath && existsSync21(scriptPath)) return scriptPath;
|
|
6493
6534
|
return null;
|
|
6494
6535
|
}
|
|
6495
6536
|
function writeConfigEnv(opts) {
|
|
6496
|
-
const credsPath =
|
|
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.
|
|
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(
|
|
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 (
|
|
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 (!
|
|
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(
|
|
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 (
|
|
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 =
|
|
6973
|
+
const claudeDir = join18(homedir18(), ".claude");
|
|
6933
6974
|
try {
|
|
6934
|
-
const settings = JSON.parse(readFileSync18(
|
|
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(
|
|
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 =
|
|
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(
|
|
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.
|
|
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 =
|
|
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(
|
|
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(
|
|
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 =
|
|
7297
|
-
if (!
|
|
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(
|
|
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(
|
|
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(
|
|
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 ===
|
|
7603
|
-
const fp =
|
|
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 =
|
|
7649
|
-
if (!
|
|
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 =
|
|
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(
|
|
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 =
|
|
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 &&
|
|
7866
|
+
if (p && existsSync21(p) && statSync2(p).isDirectory()) roots.push(p);
|
|
7826
7867
|
} catch {
|
|
7827
7868
|
}
|
|
7828
7869
|
};
|
|
7829
|
-
add(
|
|
7830
|
-
add(
|
|
7870
|
+
add(join18(homedir18(), ".claude", "skills"));
|
|
7871
|
+
add(join18(homedir18(), ".agents", "skills"));
|
|
7831
7872
|
if (repoRoot) {
|
|
7832
|
-
add(
|
|
7833
|
-
add(
|
|
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 =
|
|
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 =
|
|
7873
|
-
if (
|
|
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 =
|
|
7994
|
-
return
|
|
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 =
|
|
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 =
|
|
8083
|
-
return
|
|
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 =
|
|
8122
|
-
if (!
|
|
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(
|
|
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 =
|
|
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(
|
|
8264
|
+
const content = readFileSync18(join18(projectsDir, file), "utf-8");
|
|
8224
8265
|
const lineCount = content.split("\n").filter(Boolean).length;
|
|
8225
|
-
writeFileSync13(
|
|
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 =
|
|
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 =
|
|
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(
|
|
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 =
|
|
8305
|
-
HOOKS_DIR =
|
|
8306
|
-
BIN_DIR =
|
|
8307
|
-
CONFIG_PATH4 =
|
|
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 =
|
|
8419
|
-
CLOUD_JWT_PATH =
|
|
8420
|
-
SKILLS_DISCOVERED_PATH =
|
|
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
|
|
8426
|
-
import { join as
|
|
8427
|
-
import { homedir as
|
|
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 (!
|
|
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 =
|
|
8614
|
-
SESSION_DIR =
|
|
8615
|
-
PLUGIN_PATH =
|
|
8616
|
-
PLUGIN_PKG_PATH =
|
|
8617
|
-
PLUGIN_SETTINGS_DIR =
|
|
8618
|
-
PLUGIN_SETTINGS_PATH =
|
|
8619
|
-
PROJECT_MCP_PATH =
|
|
8620
|
-
CLAUDE_JSON_PATH =
|
|
8621
|
-
RUN_SCRIPT_PATH =
|
|
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 =
|
|
8625
|
-
PLUGIN_PATH_2 =
|
|
8626
|
-
PLUGIN_PKG_PATH_2 =
|
|
8627
|
-
PLUGIN_SETTINGS_DIR_2 =
|
|
8628
|
-
PLUGIN_SETTINGS_PATH_2 =
|
|
8629
|
-
PROJECT_MCP_PATH_2 =
|
|
8630
|
-
RUN_SCRIPT_PATH_2 =
|
|
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 =
|
|
8634
|
-
PLUGIN_PATH_3 =
|
|
8635
|
-
PLUGIN_PKG_PATH_3 =
|
|
8636
|
-
PLUGIN_SETTINGS_DIR_3 =
|
|
8637
|
-
PLUGIN_SETTINGS_PATH_3 =
|
|
8638
|
-
PROJECT_MCP_PATH_3 =
|
|
8639
|
-
RUN_SCRIPT_PATH_3 =
|
|
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 =
|
|
8643
|
-
PLUGIN_PATH_4 =
|
|
8644
|
-
PLUGIN_PKG_PATH_4 =
|
|
8645
|
-
PLUGIN_SETTINGS_DIR_4 =
|
|
8646
|
-
PLUGIN_SETTINGS_PATH_4 =
|
|
8647
|
-
PROJECT_MCP_PATH_4 =
|
|
8648
|
-
RUN_SCRIPT_PATH_4 =
|
|
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
|
|
8923
|
-
import { homedir as
|
|
8924
|
-
import { join as
|
|
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 (
|
|
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
|
-
|
|
9025
|
-
|
|
9026
|
-
|
|
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 =
|
|
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 =
|
|
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
|
|
9071
|
-
import { dirname as dirname6, join as
|
|
9072
|
-
import { homedir as
|
|
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 (!
|
|
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 (!
|
|
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 =
|
|
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
|
|
9342
|
-
import { join as
|
|
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 =
|
|
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 =
|
|
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 =
|
|
9542
|
-
SESSION_DIR_32 =
|
|
9543
|
-
SESSION_DIR_42 =
|
|
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
|
|
9559
|
-
import { homedir as
|
|
9560
|
-
import { join as
|
|
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 (!
|
|
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 =
|
|
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
|
|
9586
|
-
import { join as
|
|
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
|
|
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 (
|
|
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 (!
|
|
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 =
|
|
10144
|
-
CONFIG_PATH6 =
|
|
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
|
|
10154
|
-
import { homedir as
|
|
10155
|
-
import { join as
|
|
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 =
|
|
10174
|
-
return
|
|
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(
|
|
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 =
|
|
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
|
|
10373
|
-
import { join as
|
|
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
|
|
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
|
|
10409
|
-
import { homedir as
|
|
10410
|
-
import { join as
|
|
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 =
|
|
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(
|
|
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 &&
|
|
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(
|
|
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
|
|
10623
|
-
import { join as
|
|
10624
|
-
import { homedir as
|
|
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 (!
|
|
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 (!
|
|
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 =
|
|
10811
|
-
CONFIG_PATH8 =
|
|
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
|
|
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 (!
|
|
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.
|
|
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
|