@synkro-sh/cli 1.4.89 → 1.4.91
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 +114 -217
- package/dist/bootstrap.js.map +1 -1
- package/package.json +1 -1
package/dist/bootstrap.js
CHANGED
|
@@ -508,7 +508,7 @@ function installCursorMcpConfig(opts) {
|
|
|
508
508
|
if (entry?.[SYNKRO_MARKER3] === true) delete config.mcpServers[name];
|
|
509
509
|
}
|
|
510
510
|
if (opts.local) {
|
|
511
|
-
const port = process.env.SYNKRO_MCP_PORT || "
|
|
511
|
+
const port = process.env.SYNKRO_MCP_PORT || "18931";
|
|
512
512
|
const url2 = `http://127.0.0.1:${port}/`;
|
|
513
513
|
const jwtPath = join2(homedir3(), ".synkro", ".mcp-jwt");
|
|
514
514
|
let jwt2 = "";
|
|
@@ -986,7 +986,7 @@ export function detectRepo(cwd: string, transcriptPath?: string): string {
|
|
|
986
986
|
|
|
987
987
|
// \u2500\u2500\u2500 Channel Health \u2500\u2500\u2500
|
|
988
988
|
|
|
989
|
-
export async function channelUp(port =
|
|
989
|
+
export async function channelUp(port = 18929): Promise<boolean> {
|
|
990
990
|
return new Promise(resolve => {
|
|
991
991
|
const sock = require('node:net').connect(port, '127.0.0.1');
|
|
992
992
|
const done = (ok: boolean) => { try { sock.destroy(); } catch {} resolve(ok); };
|
|
@@ -997,7 +997,7 @@ export async function channelUp(port = 8929): Promise<boolean> {
|
|
|
997
997
|
}
|
|
998
998
|
|
|
999
999
|
export async function cweChannelUp(): Promise<boolean> {
|
|
1000
|
-
return channelUp(
|
|
1000
|
+
return channelUp(18930);
|
|
1001
1001
|
}
|
|
1002
1002
|
|
|
1003
1003
|
// \u2500\u2500\u2500 Config Loading \u2500\u2500\u2500
|
|
@@ -1030,7 +1030,7 @@ export async function loadConfig(jwt: string, query?: string): Promise<HookConfi
|
|
|
1030
1030
|
};
|
|
1031
1031
|
|
|
1032
1032
|
// Local-first: fetch from the local MCP server (PGLite-backed) \u2014 zero network egress.
|
|
1033
|
-
const mcpPort = process.env.SYNKRO_MCP_PORT || '
|
|
1033
|
+
const mcpPort = process.env.SYNKRO_MCP_PORT || '18931';
|
|
1034
1034
|
try {
|
|
1035
1035
|
const resp = await fetch('http://127.0.0.1:' + mcpPort + '/api/local/hook-config', {
|
|
1036
1036
|
signal: AbortSignal.timeout(1500),
|
|
@@ -1146,13 +1146,13 @@ export async function localGrade(surface: string, prompt: string, timeoutMs = 20
|
|
|
1146
1146
|
if (!(await channelUp())) throw new Error('SYNKRO_CHANNEL_DOWN');
|
|
1147
1147
|
const jwt = loadJwt();
|
|
1148
1148
|
if (!jwt) throw new Error('NO_JWT');
|
|
1149
|
-
return channelGrade(ROLE_MAP[surface] || 'grade-edit', prompt, jwt,
|
|
1149
|
+
return channelGrade(ROLE_MAP[surface] || 'grade-edit', prompt, jwt, 18929, timeoutMs);
|
|
1150
1150
|
}
|
|
1151
1151
|
|
|
1152
1152
|
export async function localGradeCwe(prompt: string): Promise<string> {
|
|
1153
1153
|
const jwt = loadJwt();
|
|
1154
1154
|
if (!jwt) throw new Error('NO_JWT');
|
|
1155
|
-
return channelGrade('grade-cwe', prompt, jwt,
|
|
1155
|
+
return channelGrade('grade-cwe', prompt, jwt, 18930, 45000);
|
|
1156
1156
|
}
|
|
1157
1157
|
|
|
1158
1158
|
// \u2500\u2500\u2500 Session Action Log \u2500\u2500\u2500
|
|
@@ -1273,6 +1273,13 @@ export function parseVerdict(resp: string): Verdict {
|
|
|
1273
1273
|
const okMatch = inner.match(/<ok>(.*?)<\\/ok>/);
|
|
1274
1274
|
if (okMatch) verdict.ok = okMatch[1].trim() !== 'false';
|
|
1275
1275
|
|
|
1276
|
+
const decisionMatch = inner.match(/<decision>(.*?)<\\/decision>/) || inner.match(/<overall>(.*?)<\\/overall>/);
|
|
1277
|
+
if (decisionMatch) {
|
|
1278
|
+
const d = decisionMatch[1].trim().toLowerCase();
|
|
1279
|
+
if (d === 'block' || d === 'blocking' || d === 'deny' || d === 'fail') verdict.ok = false;
|
|
1280
|
+
else if (d === 'allow' || d === 'pass' || d === 'approve') verdict.ok = true;
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1276
1283
|
const reasonMatch = inner.match(/<reason>(.*?)<\\/reason>/) || inner.match(/<reasoning>(.*?)<\\/reasoning>/);
|
|
1277
1284
|
if (reasonMatch) verdict.reason = reasonMatch[1].trim();
|
|
1278
1285
|
|
|
@@ -1401,7 +1408,7 @@ export function dispatchCapture(
|
|
|
1401
1408
|
|
|
1402
1409
|
export function appendLocalTelemetry(body: Record<string, any>): void {
|
|
1403
1410
|
const event = { ...body, _ts: new Date().toISOString() };
|
|
1404
|
-
const mcpPort = process.env.SYNKRO_MCP_PORT || '
|
|
1411
|
+
const mcpPort = process.env.SYNKRO_MCP_PORT || '18931';
|
|
1405
1412
|
let mcpToken = '';
|
|
1406
1413
|
try { mcpToken = readFileSync(join(HOME, '.synkro', '.mcp-jwt'), 'utf-8').trim(); } catch {}
|
|
1407
1414
|
if (!mcpToken) return;
|
|
@@ -1992,7 +1999,7 @@ async function main() {
|
|
|
1992
1999
|
}
|
|
1993
2000
|
|
|
1994
2001
|
if (rt === 'local') {
|
|
1995
|
-
// \u2500\u2500\u2500 Local grading: org rules ONLY (channel 1, port
|
|
2002
|
+
// \u2500\u2500\u2500 Local grading: org rules ONLY (channel 1, port 18929) \u2500\u2500\u2500
|
|
1996
2003
|
const proposedShort = proposed.slice(0, 4000);
|
|
1997
2004
|
const sessionLog = compressSessionLog(readSessionLog(sessionId));
|
|
1998
2005
|
const graderPrompt = [
|
|
@@ -3481,7 +3488,7 @@ async function main() {
|
|
|
3481
3488
|
|
|
3482
3489
|
const fakeConfig: HookConfig = { captureDepth: 'local_only', tier: 'standard', silent, policyName, rules: [] };
|
|
3483
3490
|
const tagStr = tag(rt, fakeConfig);
|
|
3484
|
-
const routeLine = tagStr + ' inference: ' + (isChannelUp ? 'local-cc (channel reachable on 127.0.0.1:
|
|
3491
|
+
const routeLine = tagStr + ' inference: ' + (isChannelUp ? 'local-cc (channel reachable on 127.0.0.1:18929)' : 'cloud (local-cc channel not reachable)');
|
|
3485
3492
|
|
|
3486
3493
|
if (!jwt) {
|
|
3487
3494
|
outputJson({ systemMessage: routeLine });
|
|
@@ -5275,6 +5282,7 @@ function writeRefreshAgent(synkroBinPath) {
|
|
|
5275
5282
|
throw new KeychainExportError("writeRefreshAgent is darwin-only");
|
|
5276
5283
|
}
|
|
5277
5284
|
mkdirSync6(join6(homedir6(), "Library", "LaunchAgents"), { recursive: true });
|
|
5285
|
+
const shellCmd = `export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH" && "${synkroBinPath}" local-cc refresh-creds`;
|
|
5278
5286
|
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
5279
5287
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
5280
5288
|
<plist version="1.0">
|
|
@@ -5283,9 +5291,9 @@ function writeRefreshAgent(synkroBinPath) {
|
|
|
5283
5291
|
<string>${LAUNCHD_LABEL}</string>
|
|
5284
5292
|
<key>ProgramArguments</key>
|
|
5285
5293
|
<array>
|
|
5286
|
-
<string
|
|
5287
|
-
<string
|
|
5288
|
-
<string
|
|
5294
|
+
<string>/bin/bash</string>
|
|
5295
|
+
<string>-c</string>
|
|
5296
|
+
<string>${shellCmd}</string>
|
|
5289
5297
|
</array>
|
|
5290
5298
|
<key>StartInterval</key>
|
|
5291
5299
|
<integer>${REFRESH_INTERVAL_SECONDS}</integer>
|
|
@@ -5340,7 +5348,7 @@ var init_macKeychain = __esm({
|
|
|
5340
5348
|
KEYCHAIN_SERVICE = "Claude Code-credentials";
|
|
5341
5349
|
LAUNCHD_LABEL = "com.synkro.cli.claude-creds-refresh";
|
|
5342
5350
|
LAUNCHD_PLIST = join6(homedir6(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
|
|
5343
|
-
REFRESH_INTERVAL_SECONDS =
|
|
5351
|
+
REFRESH_INTERVAL_SECONDS = 45 * 60;
|
|
5344
5352
|
KeychainExportError = class extends Error {
|
|
5345
5353
|
constructor(message, cause) {
|
|
5346
5354
|
super(message);
|
|
@@ -5443,7 +5451,13 @@ async function dockerInstall(opts = {}) {
|
|
|
5443
5451
|
"-v",
|
|
5444
5452
|
`${MCP_JWT_PATH}:/data/.mcp-jwt:ro`,
|
|
5445
5453
|
"-v",
|
|
5454
|
+
`${SYNKRO_CREDS_PATH}:/data/credentials.json:ro`,
|
|
5455
|
+
"-v",
|
|
5446
5456
|
`${credsDir}:/home/synkro/.claude:rw`,
|
|
5457
|
+
"-v",
|
|
5458
|
+
`${join7(homedir7(), ".claude")}:/data/claude-host:ro`,
|
|
5459
|
+
"-v",
|
|
5460
|
+
`${join7(homedir7(), ".claude.json")}:/home/synkro/.claude.json:rw`,
|
|
5447
5461
|
"-e",
|
|
5448
5462
|
`WORKERS_PER_POOL=${workers}`,
|
|
5449
5463
|
image
|
|
@@ -5488,13 +5502,14 @@ function dockerStatus() {
|
|
|
5488
5502
|
healthz: `http://127.0.0.1:${HOST_MCP_PORT}/`
|
|
5489
5503
|
};
|
|
5490
5504
|
}
|
|
5491
|
-
var SYNKRO_DIR3, MCP_JWT_PATH, PGDATA_PATH, HOST_MCP_PORT, HOST_GRADER_PORT, HOST_CWE_PORT, HOST_PG_PORT, CONTAINER_NAME, DEFAULT_IMAGE, DockerInstallError;
|
|
5505
|
+
var SYNKRO_DIR3, MCP_JWT_PATH, SYNKRO_CREDS_PATH, PGDATA_PATH, HOST_MCP_PORT, HOST_GRADER_PORT, HOST_CWE_PORT, HOST_PG_PORT, CONTAINER_NAME, DEFAULT_IMAGE, DockerInstallError;
|
|
5492
5506
|
var init_dockerInstall = __esm({
|
|
5493
5507
|
"cli/local-cc/dockerInstall.ts"() {
|
|
5494
5508
|
"use strict";
|
|
5495
5509
|
init_macKeychain();
|
|
5496
5510
|
SYNKRO_DIR3 = join7(homedir7(), ".synkro");
|
|
5497
5511
|
MCP_JWT_PATH = join7(SYNKRO_DIR3, ".mcp-jwt");
|
|
5512
|
+
SYNKRO_CREDS_PATH = join7(SYNKRO_DIR3, "credentials.json");
|
|
5498
5513
|
PGDATA_PATH = join7(SYNKRO_DIR3, "pgdata");
|
|
5499
5514
|
HOST_MCP_PORT = parseInt(process.env.SYNKRO_HOST_MCP_PORT || "18931", 10);
|
|
5500
5515
|
HOST_GRADER_PORT = parseInt(process.env.SYNKRO_HOST_GRADER_PORT || "18929", 10);
|
|
@@ -5544,19 +5559,6 @@ function parseArgs(argv) {
|
|
|
5544
5559
|
}
|
|
5545
5560
|
return opts;
|
|
5546
5561
|
}
|
|
5547
|
-
async function promptTranscriptConsent() {
|
|
5548
|
-
const rl = createInterface3({ input: process.stdin, output: process.stdout });
|
|
5549
|
-
return new Promise((resolve3) => {
|
|
5550
|
-
rl.question(
|
|
5551
|
-
"Would you like Synkro to use Claude Code session transcripts\nto generate guardrail rules and policies for your team? (Y/n) ",
|
|
5552
|
-
(answer) => {
|
|
5553
|
-
rl.close();
|
|
5554
|
-
const trimmed = answer.trim().toLowerCase();
|
|
5555
|
-
resolve3(trimmed === "" || trimmed === "y" || trimmed === "yes");
|
|
5556
|
-
}
|
|
5557
|
-
);
|
|
5558
|
-
});
|
|
5559
|
-
}
|
|
5560
5562
|
function ensureSynkroDir() {
|
|
5561
5563
|
mkdirSync8(SYNKRO_DIR4, { recursive: true });
|
|
5562
5564
|
mkdirSync8(HOOKS_DIR, { recursive: true });
|
|
@@ -5658,7 +5660,7 @@ function writeConfigEnv(opts) {
|
|
|
5658
5660
|
`SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
|
|
5659
5661
|
`SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
|
|
5660
5662
|
`SYNKRO_INFERENCE=${shellQuoteSingle(safeInference)}`,
|
|
5661
|
-
`SYNKRO_VERSION=${shellQuoteSingle("1.4.
|
|
5663
|
+
`SYNKRO_VERSION=${shellQuoteSingle("1.4.91")}`
|
|
5662
5664
|
];
|
|
5663
5665
|
if (safeSynkroBin) lines.push(`SYNKRO_CLI_BIN=${shellQuoteSingle(safeSynkroBin)}`);
|
|
5664
5666
|
if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
|
|
@@ -5874,16 +5876,29 @@ async function installCommand(opts = {}) {
|
|
|
5874
5876
|
console.error("No access token available after auth.");
|
|
5875
5877
|
process.exit(1);
|
|
5876
5878
|
}
|
|
5877
|
-
console.log("\nConnecting to GitHub (optional \u2014 for PR scanning)...");
|
|
5878
5879
|
let ghToken = null;
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
|
|
5880
|
+
if (process.stdin.isTTY) {
|
|
5881
|
+
const rl = createInterface3({ input: process.stdin, output: process.stdout });
|
|
5882
|
+
const wantsPR = await new Promise((resolve3) => {
|
|
5883
|
+
rl.question("Would you like to enable GitHub PR scanning? (y/N) ", (answer) => {
|
|
5884
|
+
rl.close();
|
|
5885
|
+
const trimmed = answer.trim().toLowerCase();
|
|
5886
|
+
resolve3(trimmed === "y" || trimmed === "yes");
|
|
5887
|
+
});
|
|
5888
|
+
});
|
|
5889
|
+
if (wantsPR) {
|
|
5890
|
+
try {
|
|
5891
|
+
ghToken = await connectGitHub(gatewayUrl, token);
|
|
5892
|
+
} catch {
|
|
5893
|
+
}
|
|
5894
|
+
if (ghToken) {
|
|
5895
|
+
console.log();
|
|
5896
|
+
} else {
|
|
5897
|
+
console.log(" Skipped. Run `synkro install` again to enable PR scanning.\n");
|
|
5898
|
+
}
|
|
5899
|
+
} else {
|
|
5900
|
+
console.log(" Skipped PR scanning.\n");
|
|
5901
|
+
}
|
|
5887
5902
|
}
|
|
5888
5903
|
setApiBaseUrl(`${gatewayUrl}/api`);
|
|
5889
5904
|
await promptRepoConnection({ linkRepo: opts.linkRepo });
|
|
@@ -5922,15 +5937,7 @@ async function installCommand(opts = {}) {
|
|
|
5922
5937
|
} catch {
|
|
5923
5938
|
}
|
|
5924
5939
|
}
|
|
5925
|
-
|
|
5926
|
-
if (process.stdin.isTTY) {
|
|
5927
|
-
transcriptConsent = await promptTranscriptConsent();
|
|
5928
|
-
if (transcriptConsent) {
|
|
5929
|
-
console.log(" \u2713 Transcript collection enabled\n");
|
|
5930
|
-
} else {
|
|
5931
|
-
console.log(" \u2717 Transcript collection disabled \u2014 skipping transcript sync\n");
|
|
5932
|
-
}
|
|
5933
|
-
}
|
|
5940
|
+
const transcriptConsent = false;
|
|
5934
5941
|
let hasClaudeCode = false;
|
|
5935
5942
|
let hasCursor = false;
|
|
5936
5943
|
for (const agent of agents) {
|
|
@@ -6373,7 +6380,7 @@ import { createInterface } from 'node:readline';
|
|
|
6373
6380
|
|
|
6374
6381
|
const HOME = homedir();
|
|
6375
6382
|
const TOKEN_PATH = join(HOME, '.synkro', '.mcp-jwt');
|
|
6376
|
-
const PORT = parseInt(process.env.SYNKRO_MCP_PORT || '
|
|
6383
|
+
const PORT = parseInt(process.env.SYNKRO_MCP_PORT || '18931', 10);
|
|
6377
6384
|
const URL = \`http://127.0.0.1:\${PORT}\`;
|
|
6378
6385
|
|
|
6379
6386
|
let token = '';
|
|
@@ -6415,117 +6422,11 @@ rl.on('line', async (line) => {
|
|
|
6415
6422
|
}
|
|
6416
6423
|
});
|
|
6417
6424
|
|
|
6418
|
-
// cli/local-cc/pueue.ts
|
|
6419
|
-
import { execFileSync, spawnSync as spawnSync3, spawn } from "child_process";
|
|
6420
|
-
import { homedir as homedir9 } from "os";
|
|
6421
|
-
import { join as join9 } from "path";
|
|
6422
|
-
import { connect } from "net";
|
|
6423
|
-
function pueueAvailable() {
|
|
6424
|
-
const r = spawnSync3("pueue", ["--version"], { encoding: "utf-8" });
|
|
6425
|
-
if (r.status !== 0) {
|
|
6426
|
-
throw new PueueError("pueue CLI not found on PATH. Install pueue (https://github.com/Nukesor/pueue) and start `pueued`.");
|
|
6427
|
-
}
|
|
6428
|
-
}
|
|
6429
|
-
function statusJson() {
|
|
6430
|
-
pueueAvailable();
|
|
6431
|
-
const r = spawnSync3("pueue", ["status", "--json"], { encoding: "utf-8" });
|
|
6432
|
-
if (r.status !== 0) {
|
|
6433
|
-
throw new PueueError(`pueue status failed: ${r.stderr || r.stdout || "unknown error"} \u2014 is pueued running?`);
|
|
6434
|
-
}
|
|
6435
|
-
try {
|
|
6436
|
-
return JSON.parse(r.stdout);
|
|
6437
|
-
} catch (err) {
|
|
6438
|
-
throw new PueueError(`pueue status returned non-JSON output: ${r.stdout.slice(0, 200)}`, err);
|
|
6439
|
-
}
|
|
6440
|
-
}
|
|
6441
|
-
function statusName(s) {
|
|
6442
|
-
if (typeof s === "string") return s;
|
|
6443
|
-
if (s && typeof s === "object") {
|
|
6444
|
-
if ("Running" in s) return "Running";
|
|
6445
|
-
if ("Done" in s) {
|
|
6446
|
-
const result = s.Done?.result;
|
|
6447
|
-
if (typeof result === "string") return `Done (${result})`;
|
|
6448
|
-
if (result && typeof result === "object") return `Done (${Object.keys(result)[0] ?? "unknown"})`;
|
|
6449
|
-
return "Done";
|
|
6450
|
-
}
|
|
6451
|
-
return Object.keys(s)[0] ?? "unknown";
|
|
6452
|
-
}
|
|
6453
|
-
return "unknown";
|
|
6454
|
-
}
|
|
6455
|
-
function findTask(channel = CHANNEL_PRIMARY) {
|
|
6456
|
-
const data = statusJson();
|
|
6457
|
-
for (const [id, t] of Object.entries(data.tasks)) {
|
|
6458
|
-
if (t.label === channel.taskLabel) {
|
|
6459
|
-
return {
|
|
6460
|
-
id: Number(id),
|
|
6461
|
-
label: t.label,
|
|
6462
|
-
status: statusName(t.status),
|
|
6463
|
-
command: t.command,
|
|
6464
|
-
cwd: t.path
|
|
6465
|
-
};
|
|
6466
|
-
}
|
|
6467
|
-
}
|
|
6468
|
-
return null;
|
|
6469
|
-
}
|
|
6470
|
-
function stopTask(channel = CHANNEL_PRIMARY) {
|
|
6471
|
-
spawnSync3("tmux", ["kill-session", "-t", `=${channel.tmuxSession}`], { encoding: "utf-8" });
|
|
6472
|
-
let t = findTask(channel);
|
|
6473
|
-
while (t) {
|
|
6474
|
-
if (t.status === "Running" || t.status === "Queued") {
|
|
6475
|
-
spawnSync3("pueue", ["kill", String(t.id)], { encoding: "utf-8" });
|
|
6476
|
-
for (let i = 0; i < 10; i++) {
|
|
6477
|
-
const check = findTask(channel);
|
|
6478
|
-
if (!check || check.id !== t.id || check.status !== "Running" && check.status !== "Queued") break;
|
|
6479
|
-
spawnSync3("sleep", ["0.5"], { encoding: "utf-8" });
|
|
6480
|
-
}
|
|
6481
|
-
}
|
|
6482
|
-
spawnSync3("pueue", ["remove", String(t.id)], { encoding: "utf-8" });
|
|
6483
|
-
t = findTask(channel);
|
|
6484
|
-
}
|
|
6485
|
-
}
|
|
6486
|
-
var TASK_LABEL, TMUX_SESSION, SESSION_DIR, TASK_LABEL_2, TMUX_SESSION_2, SESSION_DIR_2, TASK_LABEL_3, TMUX_SESSION_3, SESSION_DIR_3, TASK_LABEL_4, TMUX_SESSION_4, SESSION_DIR_4, PueueError, CHANNEL_PRIMARY, CHANNEL_SECONDARY, CHANNEL_TERTIARY, CHANNEL_QUATERNARY;
|
|
6487
|
-
var init_pueue = __esm({
|
|
6488
|
-
"cli/local-cc/pueue.ts"() {
|
|
6489
|
-
"use strict";
|
|
6490
|
-
TASK_LABEL = "synkro-local-cc";
|
|
6491
|
-
TMUX_SESSION = "synkro-local-cc";
|
|
6492
|
-
SESSION_DIR = join9(homedir9(), ".synkro", "cc_sessions");
|
|
6493
|
-
TASK_LABEL_2 = "synkro-local-cc-2";
|
|
6494
|
-
TMUX_SESSION_2 = "synkro-local-cc-2";
|
|
6495
|
-
SESSION_DIR_2 = join9(homedir9(), ".synkro", "cc_sessions_2");
|
|
6496
|
-
TASK_LABEL_3 = "synkro-local-cc-3";
|
|
6497
|
-
TMUX_SESSION_3 = "synkro-local-cc-3";
|
|
6498
|
-
SESSION_DIR_3 = join9(homedir9(), ".synkro", "cc_sessions_3");
|
|
6499
|
-
TASK_LABEL_4 = "synkro-local-cc-4";
|
|
6500
|
-
TMUX_SESSION_4 = "synkro-local-cc-4";
|
|
6501
|
-
SESSION_DIR_4 = join9(homedir9(), ".synkro", "cc_sessions_4");
|
|
6502
|
-
PueueError = class extends Error {
|
|
6503
|
-
constructor(message, cause) {
|
|
6504
|
-
super(message);
|
|
6505
|
-
this.cause = cause;
|
|
6506
|
-
this.name = "PueueError";
|
|
6507
|
-
}
|
|
6508
|
-
cause;
|
|
6509
|
-
};
|
|
6510
|
-
CHANNEL_PRIMARY = { taskLabel: TASK_LABEL, tmuxSession: TMUX_SESSION, sessionDir: SESSION_DIR };
|
|
6511
|
-
CHANNEL_SECONDARY = { taskLabel: TASK_LABEL_2, tmuxSession: TMUX_SESSION_2, sessionDir: SESSION_DIR_2 };
|
|
6512
|
-
CHANNEL_TERTIARY = { taskLabel: TASK_LABEL_3, tmuxSession: TMUX_SESSION_3, sessionDir: SESSION_DIR_3 };
|
|
6513
|
-
CHANNEL_QUATERNARY = { taskLabel: TASK_LABEL_4, tmuxSession: TMUX_SESSION_4, sessionDir: SESSION_DIR_4 };
|
|
6514
|
-
}
|
|
6515
|
-
});
|
|
6516
|
-
|
|
6517
|
-
// cli/local-cc/channelSource.ts
|
|
6518
|
-
var init_channelSource = __esm({
|
|
6519
|
-
"cli/local-cc/channelSource.ts"() {
|
|
6520
|
-
"use strict";
|
|
6521
|
-
}
|
|
6522
|
-
});
|
|
6523
|
-
|
|
6524
6425
|
// cli/local-cc/install.ts
|
|
6525
6426
|
import { existsSync as existsSync10, mkdirSync as mkdirSync9, writeFileSync as writeFileSync8, readFileSync as readFileSync8, chmodSync as chmodSync3, copyFileSync, renameSync as renameSync4, unlinkSync as unlinkSync4, openSync, fsyncSync, closeSync } from "fs";
|
|
6526
|
-
import { join as
|
|
6527
|
-
import { homedir as
|
|
6528
|
-
import { spawnSync as
|
|
6427
|
+
import { join as join9 } from "path";
|
|
6428
|
+
import { homedir as homedir9 } from "os";
|
|
6429
|
+
import { spawnSync as spawnSync3 } from "child_process";
|
|
6529
6430
|
function safelyMutateClaudeJson(mutator) {
|
|
6530
6431
|
if (!existsSync10(CLAUDE_JSON_PATH)) {
|
|
6531
6432
|
return;
|
|
@@ -6601,47 +6502,46 @@ function uninstallLocalCC() {
|
|
|
6601
6502
|
return dirty;
|
|
6602
6503
|
});
|
|
6603
6504
|
}
|
|
6604
|
-
var CLAUDE_JSON_BACKUP_PATH,
|
|
6505
|
+
var CLAUDE_JSON_BACKUP_PATH, SESSION_DIR, PLUGIN_PATH, PLUGIN_PKG_PATH, PLUGIN_SETTINGS_DIR, PLUGIN_SETTINGS_PATH, PROJECT_MCP_PATH, CLAUDE_JSON_PATH, RUN_SCRIPT_PATH, TMUX_SESSION_NAME, CHANNEL_1_PORT, SESSION_DIR_2, PLUGIN_PATH_2, PLUGIN_PKG_PATH_2, PLUGIN_SETTINGS_DIR_2, PLUGIN_SETTINGS_PATH_2, PROJECT_MCP_PATH_2, RUN_SCRIPT_PATH_2, TMUX_SESSION_NAME_2, CHANNEL_2_PORT, SESSION_DIR_3, PLUGIN_PATH_3, PLUGIN_PKG_PATH_3, PLUGIN_SETTINGS_DIR_3, PLUGIN_SETTINGS_PATH_3, PROJECT_MCP_PATH_3, RUN_SCRIPT_PATH_3, TMUX_SESSION_NAME_3, CHANNEL_3_PORT, SESSION_DIR_4, PLUGIN_PATH_4, PLUGIN_PKG_PATH_4, PLUGIN_SETTINGS_DIR_4, PLUGIN_SETTINGS_PATH_4, PROJECT_MCP_PATH_4, RUN_SCRIPT_PATH_4, TMUX_SESSION_NAME_4, CHANNEL_4_PORT, RUN_SCRIPT_SOURCE, RUN_SCRIPT_SOURCE_2, RUN_SCRIPT_SOURCE_3, RUN_SCRIPT_SOURCE_4, MCP_SERVER_NAME, PLUGIN_PACKAGE_JSON, LocalCCInstallError, CHANNELS;
|
|
6605
6506
|
var init_install2 = __esm({
|
|
6606
6507
|
"cli/local-cc/install.ts"() {
|
|
6607
6508
|
"use strict";
|
|
6608
|
-
|
|
6609
|
-
|
|
6610
|
-
|
|
6611
|
-
|
|
6612
|
-
|
|
6613
|
-
|
|
6614
|
-
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
RUN_SCRIPT_PATH = join10(SESSION_DIR2, "run-claude.sh");
|
|
6509
|
+
CLAUDE_JSON_BACKUP_PATH = join9(homedir9(), ".claude.json.synkro-bak");
|
|
6510
|
+
SESSION_DIR = join9(homedir9(), ".synkro", "cc_sessions");
|
|
6511
|
+
PLUGIN_PATH = join9(SESSION_DIR, "synkro-channel.ts");
|
|
6512
|
+
PLUGIN_PKG_PATH = join9(SESSION_DIR, "package.json");
|
|
6513
|
+
PLUGIN_SETTINGS_DIR = join9(SESSION_DIR, ".claude");
|
|
6514
|
+
PLUGIN_SETTINGS_PATH = join9(PLUGIN_SETTINGS_DIR, "settings.json");
|
|
6515
|
+
PROJECT_MCP_PATH = join9(SESSION_DIR, ".mcp.json");
|
|
6516
|
+
CLAUDE_JSON_PATH = join9(homedir9(), ".claude.json");
|
|
6517
|
+
RUN_SCRIPT_PATH = join9(SESSION_DIR, "run-claude.sh");
|
|
6618
6518
|
TMUX_SESSION_NAME = "synkro-local-cc";
|
|
6619
6519
|
CHANNEL_1_PORT = 8941;
|
|
6620
|
-
|
|
6621
|
-
PLUGIN_PATH_2 =
|
|
6622
|
-
PLUGIN_PKG_PATH_2 =
|
|
6623
|
-
PLUGIN_SETTINGS_DIR_2 =
|
|
6624
|
-
PLUGIN_SETTINGS_PATH_2 =
|
|
6625
|
-
PROJECT_MCP_PATH_2 =
|
|
6626
|
-
RUN_SCRIPT_PATH_2 =
|
|
6520
|
+
SESSION_DIR_2 = join9(homedir9(), ".synkro", "cc_sessions_2");
|
|
6521
|
+
PLUGIN_PATH_2 = join9(SESSION_DIR_2, "synkro-channel.ts");
|
|
6522
|
+
PLUGIN_PKG_PATH_2 = join9(SESSION_DIR_2, "package.json");
|
|
6523
|
+
PLUGIN_SETTINGS_DIR_2 = join9(SESSION_DIR_2, ".claude");
|
|
6524
|
+
PLUGIN_SETTINGS_PATH_2 = join9(PLUGIN_SETTINGS_DIR_2, "settings.json");
|
|
6525
|
+
PROJECT_MCP_PATH_2 = join9(SESSION_DIR_2, ".mcp.json");
|
|
6526
|
+
RUN_SCRIPT_PATH_2 = join9(SESSION_DIR_2, "run-claude.sh");
|
|
6627
6527
|
TMUX_SESSION_NAME_2 = "synkro-local-cc-2";
|
|
6628
6528
|
CHANNEL_2_PORT = 8951;
|
|
6629
|
-
|
|
6630
|
-
PLUGIN_PATH_3 =
|
|
6631
|
-
PLUGIN_PKG_PATH_3 =
|
|
6632
|
-
PLUGIN_SETTINGS_DIR_3 =
|
|
6633
|
-
PLUGIN_SETTINGS_PATH_3 =
|
|
6634
|
-
PROJECT_MCP_PATH_3 =
|
|
6635
|
-
RUN_SCRIPT_PATH_3 =
|
|
6529
|
+
SESSION_DIR_3 = join9(homedir9(), ".synkro", "cc_sessions_3");
|
|
6530
|
+
PLUGIN_PATH_3 = join9(SESSION_DIR_3, "synkro-channel.ts");
|
|
6531
|
+
PLUGIN_PKG_PATH_3 = join9(SESSION_DIR_3, "package.json");
|
|
6532
|
+
PLUGIN_SETTINGS_DIR_3 = join9(SESSION_DIR_3, ".claude");
|
|
6533
|
+
PLUGIN_SETTINGS_PATH_3 = join9(PLUGIN_SETTINGS_DIR_3, "settings.json");
|
|
6534
|
+
PROJECT_MCP_PATH_3 = join9(SESSION_DIR_3, ".mcp.json");
|
|
6535
|
+
RUN_SCRIPT_PATH_3 = join9(SESSION_DIR_3, "run-claude.sh");
|
|
6636
6536
|
TMUX_SESSION_NAME_3 = "synkro-local-cc-3";
|
|
6637
6537
|
CHANNEL_3_PORT = 8942;
|
|
6638
|
-
|
|
6639
|
-
PLUGIN_PATH_4 =
|
|
6640
|
-
PLUGIN_PKG_PATH_4 =
|
|
6641
|
-
PLUGIN_SETTINGS_DIR_4 =
|
|
6642
|
-
PLUGIN_SETTINGS_PATH_4 =
|
|
6643
|
-
PROJECT_MCP_PATH_4 =
|
|
6644
|
-
RUN_SCRIPT_PATH_4 =
|
|
6538
|
+
SESSION_DIR_4 = join9(homedir9(), ".synkro", "cc_sessions_4");
|
|
6539
|
+
PLUGIN_PATH_4 = join9(SESSION_DIR_4, "synkro-channel.ts");
|
|
6540
|
+
PLUGIN_PKG_PATH_4 = join9(SESSION_DIR_4, "package.json");
|
|
6541
|
+
PLUGIN_SETTINGS_DIR_4 = join9(SESSION_DIR_4, ".claude");
|
|
6542
|
+
PLUGIN_SETTINGS_PATH_4 = join9(PLUGIN_SETTINGS_DIR_4, "settings.json");
|
|
6543
|
+
PROJECT_MCP_PATH_4 = join9(SESSION_DIR_4, ".mcp.json");
|
|
6544
|
+
RUN_SCRIPT_PATH_4 = join9(SESSION_DIR_4, "run-claude.sh");
|
|
6645
6545
|
TMUX_SESSION_NAME_4 = "synkro-local-cc-4";
|
|
6646
6546
|
CHANNEL_4_PORT = 8952;
|
|
6647
6547
|
RUN_SCRIPT_SOURCE = `#!/usr/bin/env bash
|
|
@@ -6902,10 +6802,10 @@ log "tmux session ended."
|
|
|
6902
6802
|
cause;
|
|
6903
6803
|
};
|
|
6904
6804
|
CHANNELS = [
|
|
6905
|
-
{ sessionDir:
|
|
6906
|
-
{ sessionDir:
|
|
6907
|
-
{ sessionDir:
|
|
6908
|
-
{ sessionDir:
|
|
6805
|
+
{ sessionDir: SESSION_DIR, pluginPath: PLUGIN_PATH, pluginPkgPath: PLUGIN_PKG_PATH, pluginSettingsDir: PLUGIN_SETTINGS_DIR, pluginSettingsPath: PLUGIN_SETTINGS_PATH, projectMcpPath: PROJECT_MCP_PATH, runScriptPath: RUN_SCRIPT_PATH, runScriptSource: RUN_SCRIPT_SOURCE },
|
|
6806
|
+
{ sessionDir: SESSION_DIR_2, pluginPath: PLUGIN_PATH_2, pluginPkgPath: PLUGIN_PKG_PATH_2, pluginSettingsDir: PLUGIN_SETTINGS_DIR_2, pluginSettingsPath: PLUGIN_SETTINGS_PATH_2, projectMcpPath: PROJECT_MCP_PATH_2, runScriptPath: RUN_SCRIPT_PATH_2, runScriptSource: RUN_SCRIPT_SOURCE_2 },
|
|
6807
|
+
{ sessionDir: SESSION_DIR_3, pluginPath: PLUGIN_PATH_3, pluginPkgPath: PLUGIN_PKG_PATH_3, pluginSettingsDir: PLUGIN_SETTINGS_DIR_3, pluginSettingsPath: PLUGIN_SETTINGS_PATH_3, projectMcpPath: PROJECT_MCP_PATH_3, runScriptPath: RUN_SCRIPT_PATH_3, runScriptSource: RUN_SCRIPT_SOURCE_3 },
|
|
6808
|
+
{ sessionDir: SESSION_DIR_4, pluginPath: PLUGIN_PATH_4, pluginPkgPath: PLUGIN_PKG_PATH_4, pluginSettingsDir: PLUGIN_SETTINGS_DIR_4, pluginSettingsPath: PLUGIN_SETTINGS_PATH_4, projectMcpPath: PROJECT_MCP_PATH_4, runScriptPath: RUN_SCRIPT_PATH_4, runScriptSource: RUN_SCRIPT_SOURCE_4 }
|
|
6909
6809
|
];
|
|
6910
6810
|
}
|
|
6911
6811
|
});
|
|
@@ -6916,26 +6816,24 @@ __export(disconnect_exports, {
|
|
|
6916
6816
|
disconnectCommand: () => disconnectCommand
|
|
6917
6817
|
});
|
|
6918
6818
|
import { existsSync as existsSync11, rmSync } from "fs";
|
|
6919
|
-
import { homedir as
|
|
6920
|
-
import { join as
|
|
6921
|
-
|
|
6819
|
+
import { homedir as homedir10 } from "os";
|
|
6820
|
+
import { join as join10 } from "path";
|
|
6821
|
+
import { spawnSync as spawnSync4 } from "child_process";
|
|
6822
|
+
function tearDownLocalCC(purge) {
|
|
6922
6823
|
const docker = dockerStatus();
|
|
6923
6824
|
if (docker.running) {
|
|
6924
6825
|
dockerStop();
|
|
6925
|
-
console.log("\u2713
|
|
6926
|
-
}
|
|
6927
|
-
|
|
6928
|
-
try {
|
|
6929
|
-
const tasks = [findTask(), findTask(CHANNEL_SECONDARY), findTask(CHANNEL_TERTIARY), findTask(CHANNEL_QUATERNARY)];
|
|
6930
|
-
hadTask = tasks.some((t) => !!t);
|
|
6931
|
-
stopTask();
|
|
6932
|
-
stopTask(CHANNEL_SECONDARY);
|
|
6933
|
-
stopTask(CHANNEL_TERTIARY);
|
|
6934
|
-
stopTask(CHANNEL_QUATERNARY);
|
|
6935
|
-
} catch {
|
|
6826
|
+
console.log("\u2713 stopped synkro-server container");
|
|
6827
|
+
} else {
|
|
6828
|
+
console.log("\xB7 no synkro-server container running");
|
|
6936
6829
|
}
|
|
6937
|
-
if (
|
|
6938
|
-
|
|
6830
|
+
if (purge) {
|
|
6831
|
+
try {
|
|
6832
|
+
const image = imageTag();
|
|
6833
|
+
spawnSync4("docker", ["rmi", image], { encoding: "utf-8", timeout: 3e4 });
|
|
6834
|
+
console.log(`\u2713 removed Docker image ${image}`);
|
|
6835
|
+
} catch {
|
|
6836
|
+
}
|
|
6939
6837
|
}
|
|
6940
6838
|
if (needsKeychainBridge()) {
|
|
6941
6839
|
try {
|
|
@@ -6945,12 +6843,12 @@ function tearDownLocalCC() {
|
|
|
6945
6843
|
}
|
|
6946
6844
|
}
|
|
6947
6845
|
uninstallLocalCC();
|
|
6948
|
-
console.log("\u2713
|
|
6846
|
+
console.log("\u2713 cleaned ~/.claude.json entries");
|
|
6949
6847
|
}
|
|
6950
6848
|
function disconnectCommand(args2 = []) {
|
|
6951
6849
|
const purge = args2.includes("--purge");
|
|
6952
6850
|
console.log("Synkro disconnect starting...\n");
|
|
6953
|
-
tearDownLocalCC();
|
|
6851
|
+
tearDownLocalCC(purge);
|
|
6954
6852
|
const agents = detectAgents();
|
|
6955
6853
|
let sawClaudeCode = false;
|
|
6956
6854
|
for (const agent of agents) {
|
|
@@ -6991,18 +6889,17 @@ var init_disconnect = __esm({
|
|
|
6991
6889
|
init_ccHookConfig();
|
|
6992
6890
|
init_cursorHookConfig();
|
|
6993
6891
|
init_mcpConfig();
|
|
6994
|
-
init_pueue();
|
|
6995
6892
|
init_install2();
|
|
6996
6893
|
init_dockerInstall();
|
|
6997
6894
|
init_macKeychain();
|
|
6998
|
-
SYNKRO_DIR5 =
|
|
6895
|
+
SYNKRO_DIR5 = join10(homedir10(), ".synkro");
|
|
6999
6896
|
}
|
|
7000
6897
|
});
|
|
7001
6898
|
|
|
7002
6899
|
// cli/local-cc/turnLog.ts
|
|
7003
6900
|
import { appendFileSync, existsSync as existsSync12, mkdirSync as mkdirSync10, openSync as openSync2, readFileSync as readFileSync9, readSync, closeSync as closeSync2, statSync as statSync2, watchFile, unwatchFile } from "fs";
|
|
7004
|
-
import { dirname as dirname5, join as
|
|
7005
|
-
import { homedir as
|
|
6901
|
+
import { dirname as dirname5, join as join11 } from "path";
|
|
6902
|
+
import { homedir as homedir11 } from "os";
|
|
7006
6903
|
function truncate(s, max = PREVIEW_MAX) {
|
|
7007
6904
|
if (s.length <= max) return s;
|
|
7008
6905
|
return s.slice(0, max) + "\u2026 [+" + (s.length - max) + " chars]";
|
|
@@ -7041,14 +6938,14 @@ var TURN_LOG_PATH, PREVIEW_MAX;
|
|
|
7041
6938
|
var init_turnLog = __esm({
|
|
7042
6939
|
"cli/local-cc/turnLog.ts"() {
|
|
7043
6940
|
"use strict";
|
|
7044
|
-
TURN_LOG_PATH =
|
|
6941
|
+
TURN_LOG_PATH = join11(homedir11(), ".synkro", "cc_sessions", "turns.log");
|
|
7045
6942
|
PREVIEW_MAX = 400;
|
|
7046
6943
|
}
|
|
7047
6944
|
});
|
|
7048
6945
|
|
|
7049
6946
|
// cli/local-cc/client.ts
|
|
7050
6947
|
import { request as httpRequest } from "http";
|
|
7051
|
-
import { connect
|
|
6948
|
+
import { connect } from "net";
|
|
7052
6949
|
async function submitToChannel(role, payload, opts = {}) {
|
|
7053
6950
|
const body = JSON.stringify({ role, payload, content: payload });
|
|
7054
6951
|
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
@@ -7198,7 +7095,7 @@ var args = process.argv.slice(2);
|
|
|
7198
7095
|
var cmd = args[0] || "";
|
|
7199
7096
|
var subArgs = args.slice(1);
|
|
7200
7097
|
function printVersion() {
|
|
7201
|
-
console.log("1.4.
|
|
7098
|
+
console.log("1.4.91");
|
|
7202
7099
|
}
|
|
7203
7100
|
function printHelp() {
|
|
7204
7101
|
console.log(`Synkro CLI \u2014 runtime safety for AI coding agents
|