@synkro-sh/cli 1.4.88 → 1.4.90

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bootstrap.js CHANGED
@@ -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 || "8931";
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 = 8929): Promise<boolean> {
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(8930);
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 || '8931';
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, 8929, timeoutMs);
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, 8930, 45000);
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>/);
1277
+ if (decisionMatch) {
1278
+ const d = decisionMatch[1].trim().toLowerCase();
1279
+ if (d === 'block' || 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 || '8931';
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 8929) \u2500\u2500\u2500
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:8929)' : 'cloud (local-cc channel not reachable)');
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 });
@@ -5353,6 +5360,18 @@ var init_macKeychain = __esm({
5353
5360
  });
5354
5361
 
5355
5362
  // cli/local-cc/dockerInstall.ts
5363
+ var dockerInstall_exports = {};
5364
+ __export(dockerInstall_exports, {
5365
+ DockerInstallError: () => DockerInstallError,
5366
+ SYNKRO_DIR: () => SYNKRO_DIR3,
5367
+ assertDockerAvailable: () => assertDockerAvailable,
5368
+ dockerInstall: () => dockerInstall,
5369
+ dockerStatus: () => dockerStatus,
5370
+ dockerStop: () => dockerStop,
5371
+ dockerUpdate: () => dockerUpdate,
5372
+ imageTag: () => imageTag,
5373
+ waitForContainerReady: () => waitForContainerReady
5374
+ });
5356
5375
  import { existsSync as existsSync8, mkdirSync as mkdirSync7 } from "fs";
5357
5376
  import { homedir as homedir7 } from "os";
5358
5377
  import { join as join7 } from "path";
@@ -5432,6 +5451,10 @@ async function dockerInstall(opts = {}) {
5432
5451
  `${MCP_JWT_PATH}:/data/.mcp-jwt:ro`,
5433
5452
  "-v",
5434
5453
  `${credsDir}:/home/synkro/.claude:rw`,
5454
+ "-v",
5455
+ `${join7(homedir7(), ".claude")}:/data/claude-host:ro`,
5456
+ "-v",
5457
+ `${join7(homedir7(), ".claude.json")}:/home/synkro/.claude.json:rw`,
5435
5458
  "-e",
5436
5459
  `WORKERS_PER_POOL=${workers}`,
5437
5460
  image
@@ -5459,6 +5482,10 @@ function dockerStop() {
5459
5482
  spawnSync2("docker", ["stop", CONTAINER_NAME], { encoding: "utf-8", timeout: 3e4 });
5460
5483
  spawnSync2("docker", ["rm", "-f", CONTAINER_NAME], { encoding: "utf-8", timeout: 3e4 });
5461
5484
  }
5485
+ async function dockerUpdate(workersPerPool) {
5486
+ dockerStop();
5487
+ await dockerInstall({ workersPerPool });
5488
+ }
5462
5489
  function dockerStatus() {
5463
5490
  const r = spawnSync2("docker", ["inspect", "--format", "{{.State.Status}}", CONTAINER_NAME], {
5464
5491
  encoding: "utf-8",
@@ -5642,7 +5669,7 @@ function writeConfigEnv(opts) {
5642
5669
  `SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
5643
5670
  `SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
5644
5671
  `SYNKRO_INFERENCE=${shellQuoteSingle(safeInference)}`,
5645
- `SYNKRO_VERSION=${shellQuoteSingle("1.4.88")}`
5672
+ `SYNKRO_VERSION=${shellQuoteSingle("1.4.90")}`
5646
5673
  ];
5647
5674
  if (safeSynkroBin) lines.push(`SYNKRO_CLI_BIN=${shellQuoteSingle(safeSynkroBin)}`);
5648
5675
  if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
@@ -6080,24 +6107,29 @@ async function installCommand(opts = {}) {
6080
6107
  }
6081
6108
  console.log();
6082
6109
  if (profile.localInference) {
6110
+ const { assertDockerAvailable: assertDockerAvailable2 } = await Promise.resolve().then(() => (init_dockerInstall(), dockerInstall_exports));
6083
6111
  try {
6084
- console.log("Installing Synkro server container...");
6085
- const workersPerPool = parseInt(process.env.SYNKRO_WORKERS_PER_POOL || "4", 10);
6086
- const { image, hostMcpPort, hostGraderPort, hostCwePort } = await dockerInstall({ workersPerPool });
6087
- console.log(` pulled ${image}`);
6088
- console.log(` container started \u2014 MCP=${hostMcpPort} general=${hostGraderPort} CWE=${hostCwePort}`);
6089
- console.log(" waiting for container /healthz...");
6090
- const ready = await waitForContainerReady(6e4);
6091
- if (ready) {
6092
- console.log(" \u2713 container ready");
6093
- } else {
6094
- console.warn(" \u26A0 container did not become healthy within 60s \u2014 check `docker logs synkro-server`");
6095
- }
6096
- console.log();
6112
+ assertDockerAvailable2();
6097
6113
  } catch (err) {
6098
- console.warn(` \u26A0 Docker install failed: ${err.message}
6099
- `);
6114
+ console.error(`
6115
+ \u2717 ${err.message}`);
6116
+ process.exit(1);
6117
+ }
6118
+ console.log("Installing Synkro server container...");
6119
+ const workersPerPool = parseInt(process.env.SYNKRO_WORKERS_PER_POOL || "4", 10);
6120
+ const { image, hostMcpPort, hostGraderPort, hostCwePort } = await dockerInstall({ workersPerPool });
6121
+ console.log(` \u2713 pulled ${image}`);
6122
+ console.log(` container started \u2014 MCP=${hostMcpPort} general=${hostGraderPort} CWE=${hostCwePort}`);
6123
+ console.log(" waiting for container to be ready...");
6124
+ const ready = await waitForContainerReady(6e4);
6125
+ if (ready) {
6126
+ console.log(" \u2713 container ready");
6127
+ } else {
6128
+ console.error(" \u2717 container did not become healthy within 60s");
6129
+ console.error(" Run `docker logs synkro-server` to debug.");
6130
+ process.exit(1);
6100
6131
  }
6132
+ console.log();
6101
6133
  }
6102
6134
  if (transcriptConsent) {
6103
6135
  try {
@@ -6352,7 +6384,7 @@ import { createInterface } from 'node:readline';
6352
6384
 
6353
6385
  const HOME = homedir();
6354
6386
  const TOKEN_PATH = join(HOME, '.synkro', '.mcp-jwt');
6355
- const PORT = parseInt(process.env.SYNKRO_MCP_PORT || '8931', 10);
6387
+ const PORT = parseInt(process.env.SYNKRO_MCP_PORT || '18931', 10);
6356
6388
  const URL = \`http://127.0.0.1:\${PORT}\`;
6357
6389
 
6358
6390
  let token = '';
@@ -6394,105 +6426,6 @@ rl.on('line', async (line) => {
6394
6426
  }
6395
6427
  });
6396
6428
 
6397
- // cli/local-cc/pueue.ts
6398
- import { execFileSync, spawnSync as spawnSync3, spawn } from "child_process";
6399
- import { homedir as homedir9 } from "os";
6400
- import { join as join9 } from "path";
6401
- import { connect } from "net";
6402
- function pueueAvailable() {
6403
- const r = spawnSync3("pueue", ["--version"], { encoding: "utf-8" });
6404
- if (r.status !== 0) {
6405
- throw new PueueError("pueue CLI not found on PATH. Install pueue (https://github.com/Nukesor/pueue) and start `pueued`.");
6406
- }
6407
- }
6408
- function statusJson() {
6409
- pueueAvailable();
6410
- const r = spawnSync3("pueue", ["status", "--json"], { encoding: "utf-8" });
6411
- if (r.status !== 0) {
6412
- throw new PueueError(`pueue status failed: ${r.stderr || r.stdout || "unknown error"} \u2014 is pueued running?`);
6413
- }
6414
- try {
6415
- return JSON.parse(r.stdout);
6416
- } catch (err) {
6417
- throw new PueueError(`pueue status returned non-JSON output: ${r.stdout.slice(0, 200)}`, err);
6418
- }
6419
- }
6420
- function statusName(s) {
6421
- if (typeof s === "string") return s;
6422
- if (s && typeof s === "object") {
6423
- if ("Running" in s) return "Running";
6424
- if ("Done" in s) {
6425
- const result = s.Done?.result;
6426
- if (typeof result === "string") return `Done (${result})`;
6427
- if (result && typeof result === "object") return `Done (${Object.keys(result)[0] ?? "unknown"})`;
6428
- return "Done";
6429
- }
6430
- return Object.keys(s)[0] ?? "unknown";
6431
- }
6432
- return "unknown";
6433
- }
6434
- function findTask(channel = CHANNEL_PRIMARY) {
6435
- const data = statusJson();
6436
- for (const [id, t] of Object.entries(data.tasks)) {
6437
- if (t.label === channel.taskLabel) {
6438
- return {
6439
- id: Number(id),
6440
- label: t.label,
6441
- status: statusName(t.status),
6442
- command: t.command,
6443
- cwd: t.path
6444
- };
6445
- }
6446
- }
6447
- return null;
6448
- }
6449
- function stopTask(channel = CHANNEL_PRIMARY) {
6450
- spawnSync3("tmux", ["kill-session", "-t", `=${channel.tmuxSession}`], { encoding: "utf-8" });
6451
- let t = findTask(channel);
6452
- while (t) {
6453
- if (t.status === "Running" || t.status === "Queued") {
6454
- spawnSync3("pueue", ["kill", String(t.id)], { encoding: "utf-8" });
6455
- for (let i = 0; i < 10; i++) {
6456
- const check = findTask(channel);
6457
- if (!check || check.id !== t.id || check.status !== "Running" && check.status !== "Queued") break;
6458
- spawnSync3("sleep", ["0.5"], { encoding: "utf-8" });
6459
- }
6460
- }
6461
- spawnSync3("pueue", ["remove", String(t.id)], { encoding: "utf-8" });
6462
- t = findTask(channel);
6463
- }
6464
- }
6465
- 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;
6466
- var init_pueue = __esm({
6467
- "cli/local-cc/pueue.ts"() {
6468
- "use strict";
6469
- TASK_LABEL = "synkro-local-cc";
6470
- TMUX_SESSION = "synkro-local-cc";
6471
- SESSION_DIR = join9(homedir9(), ".synkro", "cc_sessions");
6472
- TASK_LABEL_2 = "synkro-local-cc-2";
6473
- TMUX_SESSION_2 = "synkro-local-cc-2";
6474
- SESSION_DIR_2 = join9(homedir9(), ".synkro", "cc_sessions_2");
6475
- TASK_LABEL_3 = "synkro-local-cc-3";
6476
- TMUX_SESSION_3 = "synkro-local-cc-3";
6477
- SESSION_DIR_3 = join9(homedir9(), ".synkro", "cc_sessions_3");
6478
- TASK_LABEL_4 = "synkro-local-cc-4";
6479
- TMUX_SESSION_4 = "synkro-local-cc-4";
6480
- SESSION_DIR_4 = join9(homedir9(), ".synkro", "cc_sessions_4");
6481
- PueueError = class extends Error {
6482
- constructor(message, cause) {
6483
- super(message);
6484
- this.cause = cause;
6485
- this.name = "PueueError";
6486
- }
6487
- cause;
6488
- };
6489
- CHANNEL_PRIMARY = { taskLabel: TASK_LABEL, tmuxSession: TMUX_SESSION, sessionDir: SESSION_DIR };
6490
- CHANNEL_SECONDARY = { taskLabel: TASK_LABEL_2, tmuxSession: TMUX_SESSION_2, sessionDir: SESSION_DIR_2 };
6491
- CHANNEL_TERTIARY = { taskLabel: TASK_LABEL_3, tmuxSession: TMUX_SESSION_3, sessionDir: SESSION_DIR_3 };
6492
- CHANNEL_QUATERNARY = { taskLabel: TASK_LABEL_4, tmuxSession: TMUX_SESSION_4, sessionDir: SESSION_DIR_4 };
6493
- }
6494
- });
6495
-
6496
6429
  // cli/local-cc/channelSource.ts
6497
6430
  var init_channelSource = __esm({
6498
6431
  "cli/local-cc/channelSource.ts"() {
@@ -6502,9 +6435,9 @@ var init_channelSource = __esm({
6502
6435
 
6503
6436
  // cli/local-cc/install.ts
6504
6437
  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";
6505
- import { join as join10 } from "path";
6506
- import { homedir as homedir10 } from "os";
6507
- import { spawnSync as spawnSync4 } from "child_process";
6438
+ import { join as join9 } from "path";
6439
+ import { homedir as homedir9 } from "os";
6440
+ import { spawnSync as spawnSync3 } from "child_process";
6508
6441
  function safelyMutateClaudeJson(mutator) {
6509
6442
  if (!existsSync10(CLAUDE_JSON_PATH)) {
6510
6443
  return;
@@ -6580,47 +6513,47 @@ function uninstallLocalCC() {
6580
6513
  return dirty;
6581
6514
  });
6582
6515
  }
6583
- var CLAUDE_JSON_BACKUP_PATH, SESSION_DIR2, 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_22, 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_32, 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_42, 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;
6516
+ 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;
6584
6517
  var init_install2 = __esm({
6585
6518
  "cli/local-cc/install.ts"() {
6586
6519
  "use strict";
6587
6520
  init_channelSource();
6588
- CLAUDE_JSON_BACKUP_PATH = join10(homedir10(), ".claude.json.synkro-bak");
6589
- SESSION_DIR2 = join10(homedir10(), ".synkro", "cc_sessions");
6590
- PLUGIN_PATH = join10(SESSION_DIR2, "synkro-channel.ts");
6591
- PLUGIN_PKG_PATH = join10(SESSION_DIR2, "package.json");
6592
- PLUGIN_SETTINGS_DIR = join10(SESSION_DIR2, ".claude");
6593
- PLUGIN_SETTINGS_PATH = join10(PLUGIN_SETTINGS_DIR, "settings.json");
6594
- PROJECT_MCP_PATH = join10(SESSION_DIR2, ".mcp.json");
6595
- CLAUDE_JSON_PATH = join10(homedir10(), ".claude.json");
6596
- RUN_SCRIPT_PATH = join10(SESSION_DIR2, "run-claude.sh");
6521
+ CLAUDE_JSON_BACKUP_PATH = join9(homedir9(), ".claude.json.synkro-bak");
6522
+ SESSION_DIR = join9(homedir9(), ".synkro", "cc_sessions");
6523
+ PLUGIN_PATH = join9(SESSION_DIR, "synkro-channel.ts");
6524
+ PLUGIN_PKG_PATH = join9(SESSION_DIR, "package.json");
6525
+ PLUGIN_SETTINGS_DIR = join9(SESSION_DIR, ".claude");
6526
+ PLUGIN_SETTINGS_PATH = join9(PLUGIN_SETTINGS_DIR, "settings.json");
6527
+ PROJECT_MCP_PATH = join9(SESSION_DIR, ".mcp.json");
6528
+ CLAUDE_JSON_PATH = join9(homedir9(), ".claude.json");
6529
+ RUN_SCRIPT_PATH = join9(SESSION_DIR, "run-claude.sh");
6597
6530
  TMUX_SESSION_NAME = "synkro-local-cc";
6598
6531
  CHANNEL_1_PORT = 8941;
6599
- SESSION_DIR_22 = join10(homedir10(), ".synkro", "cc_sessions_2");
6600
- PLUGIN_PATH_2 = join10(SESSION_DIR_22, "synkro-channel.ts");
6601
- PLUGIN_PKG_PATH_2 = join10(SESSION_DIR_22, "package.json");
6602
- PLUGIN_SETTINGS_DIR_2 = join10(SESSION_DIR_22, ".claude");
6603
- PLUGIN_SETTINGS_PATH_2 = join10(PLUGIN_SETTINGS_DIR_2, "settings.json");
6604
- PROJECT_MCP_PATH_2 = join10(SESSION_DIR_22, ".mcp.json");
6605
- RUN_SCRIPT_PATH_2 = join10(SESSION_DIR_22, "run-claude.sh");
6532
+ SESSION_DIR_2 = join9(homedir9(), ".synkro", "cc_sessions_2");
6533
+ PLUGIN_PATH_2 = join9(SESSION_DIR_2, "synkro-channel.ts");
6534
+ PLUGIN_PKG_PATH_2 = join9(SESSION_DIR_2, "package.json");
6535
+ PLUGIN_SETTINGS_DIR_2 = join9(SESSION_DIR_2, ".claude");
6536
+ PLUGIN_SETTINGS_PATH_2 = join9(PLUGIN_SETTINGS_DIR_2, "settings.json");
6537
+ PROJECT_MCP_PATH_2 = join9(SESSION_DIR_2, ".mcp.json");
6538
+ RUN_SCRIPT_PATH_2 = join9(SESSION_DIR_2, "run-claude.sh");
6606
6539
  TMUX_SESSION_NAME_2 = "synkro-local-cc-2";
6607
6540
  CHANNEL_2_PORT = 8951;
6608
- SESSION_DIR_32 = join10(homedir10(), ".synkro", "cc_sessions_3");
6609
- PLUGIN_PATH_3 = join10(SESSION_DIR_32, "synkro-channel.ts");
6610
- PLUGIN_PKG_PATH_3 = join10(SESSION_DIR_32, "package.json");
6611
- PLUGIN_SETTINGS_DIR_3 = join10(SESSION_DIR_32, ".claude");
6612
- PLUGIN_SETTINGS_PATH_3 = join10(PLUGIN_SETTINGS_DIR_3, "settings.json");
6613
- PROJECT_MCP_PATH_3 = join10(SESSION_DIR_32, ".mcp.json");
6614
- RUN_SCRIPT_PATH_3 = join10(SESSION_DIR_32, "run-claude.sh");
6541
+ SESSION_DIR_3 = join9(homedir9(), ".synkro", "cc_sessions_3");
6542
+ PLUGIN_PATH_3 = join9(SESSION_DIR_3, "synkro-channel.ts");
6543
+ PLUGIN_PKG_PATH_3 = join9(SESSION_DIR_3, "package.json");
6544
+ PLUGIN_SETTINGS_DIR_3 = join9(SESSION_DIR_3, ".claude");
6545
+ PLUGIN_SETTINGS_PATH_3 = join9(PLUGIN_SETTINGS_DIR_3, "settings.json");
6546
+ PROJECT_MCP_PATH_3 = join9(SESSION_DIR_3, ".mcp.json");
6547
+ RUN_SCRIPT_PATH_3 = join9(SESSION_DIR_3, "run-claude.sh");
6615
6548
  TMUX_SESSION_NAME_3 = "synkro-local-cc-3";
6616
6549
  CHANNEL_3_PORT = 8942;
6617
- SESSION_DIR_42 = join10(homedir10(), ".synkro", "cc_sessions_4");
6618
- PLUGIN_PATH_4 = join10(SESSION_DIR_42, "synkro-channel.ts");
6619
- PLUGIN_PKG_PATH_4 = join10(SESSION_DIR_42, "package.json");
6620
- PLUGIN_SETTINGS_DIR_4 = join10(SESSION_DIR_42, ".claude");
6621
- PLUGIN_SETTINGS_PATH_4 = join10(PLUGIN_SETTINGS_DIR_4, "settings.json");
6622
- PROJECT_MCP_PATH_4 = join10(SESSION_DIR_42, ".mcp.json");
6623
- RUN_SCRIPT_PATH_4 = join10(SESSION_DIR_42, "run-claude.sh");
6550
+ SESSION_DIR_4 = join9(homedir9(), ".synkro", "cc_sessions_4");
6551
+ PLUGIN_PATH_4 = join9(SESSION_DIR_4, "synkro-channel.ts");
6552
+ PLUGIN_PKG_PATH_4 = join9(SESSION_DIR_4, "package.json");
6553
+ PLUGIN_SETTINGS_DIR_4 = join9(SESSION_DIR_4, ".claude");
6554
+ PLUGIN_SETTINGS_PATH_4 = join9(PLUGIN_SETTINGS_DIR_4, "settings.json");
6555
+ PROJECT_MCP_PATH_4 = join9(SESSION_DIR_4, ".mcp.json");
6556
+ RUN_SCRIPT_PATH_4 = join9(SESSION_DIR_4, "run-claude.sh");
6624
6557
  TMUX_SESSION_NAME_4 = "synkro-local-cc-4";
6625
6558
  CHANNEL_4_PORT = 8952;
6626
6559
  RUN_SCRIPT_SOURCE = `#!/usr/bin/env bash
@@ -6881,10 +6814,10 @@ log "tmux session ended."
6881
6814
  cause;
6882
6815
  };
6883
6816
  CHANNELS = [
6884
- { sessionDir: SESSION_DIR2, 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 },
6885
- { sessionDir: SESSION_DIR_22, 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 },
6886
- { sessionDir: SESSION_DIR_32, 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 },
6887
- { sessionDir: SESSION_DIR_42, 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 }
6817
+ { 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 },
6818
+ { 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 },
6819
+ { 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 },
6820
+ { 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 }
6888
6821
  ];
6889
6822
  }
6890
6823
  });
@@ -6895,26 +6828,24 @@ __export(disconnect_exports, {
6895
6828
  disconnectCommand: () => disconnectCommand
6896
6829
  });
6897
6830
  import { existsSync as existsSync11, rmSync } from "fs";
6898
- import { homedir as homedir11 } from "os";
6899
- import { join as join11 } from "path";
6900
- function tearDownLocalCC() {
6831
+ import { homedir as homedir10 } from "os";
6832
+ import { join as join10 } from "path";
6833
+ import { spawnSync as spawnSync4 } from "child_process";
6834
+ function tearDownLocalCC(purge) {
6901
6835
  const docker = dockerStatus();
6902
6836
  if (docker.running) {
6903
6837
  dockerStop();
6904
- console.log("\u2713 local-cc runtime: stopped synkro-server container");
6905
- }
6906
- let hadTask = false;
6907
- try {
6908
- const tasks = [findTask(), findTask(CHANNEL_SECONDARY), findTask(CHANNEL_TERTIARY), findTask(CHANNEL_QUATERNARY)];
6909
- hadTask = tasks.some((t) => !!t);
6910
- stopTask();
6911
- stopTask(CHANNEL_SECONDARY);
6912
- stopTask(CHANNEL_TERTIARY);
6913
- stopTask(CHANNEL_QUATERNARY);
6914
- } catch {
6838
+ console.log("\u2713 stopped synkro-server container");
6839
+ } else {
6840
+ console.log("\xB7 no synkro-server container running");
6915
6841
  }
6916
- if (!docker.running) {
6917
- console.log(`${hadTask ? "\u2713" : "\xB7"} local-cc runtime: ${hadTask ? "stopped all pueue channels" : "no live tasks"}`);
6842
+ if (purge) {
6843
+ try {
6844
+ const image = imageTag();
6845
+ spawnSync4("docker", ["rmi", image], { encoding: "utf-8", timeout: 3e4 });
6846
+ console.log(`\u2713 removed Docker image ${image}`);
6847
+ } catch {
6848
+ }
6918
6849
  }
6919
6850
  if (needsKeychainBridge()) {
6920
6851
  try {
@@ -6924,12 +6855,12 @@ function tearDownLocalCC() {
6924
6855
  }
6925
6856
  }
6926
6857
  uninstallLocalCC();
6927
- console.log("\u2713 local-cc config: cleaned ~/.claude.json entries");
6858
+ console.log("\u2713 cleaned ~/.claude.json entries");
6928
6859
  }
6929
6860
  function disconnectCommand(args2 = []) {
6930
6861
  const purge = args2.includes("--purge");
6931
6862
  console.log("Synkro disconnect starting...\n");
6932
- tearDownLocalCC();
6863
+ tearDownLocalCC(purge);
6933
6864
  const agents = detectAgents();
6934
6865
  let sawClaudeCode = false;
6935
6866
  for (const agent of agents) {
@@ -6970,18 +6901,17 @@ var init_disconnect = __esm({
6970
6901
  init_ccHookConfig();
6971
6902
  init_cursorHookConfig();
6972
6903
  init_mcpConfig();
6973
- init_pueue();
6974
6904
  init_install2();
6975
6905
  init_dockerInstall();
6976
6906
  init_macKeychain();
6977
- SYNKRO_DIR5 = join11(homedir11(), ".synkro");
6907
+ SYNKRO_DIR5 = join10(homedir10(), ".synkro");
6978
6908
  }
6979
6909
  });
6980
6910
 
6981
6911
  // cli/local-cc/turnLog.ts
6982
6912
  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";
6983
- import { dirname as dirname5, join as join12 } from "path";
6984
- import { homedir as homedir12 } from "os";
6913
+ import { dirname as dirname5, join as join11 } from "path";
6914
+ import { homedir as homedir11 } from "os";
6985
6915
  function truncate(s, max = PREVIEW_MAX) {
6986
6916
  if (s.length <= max) return s;
6987
6917
  return s.slice(0, max) + "\u2026 [+" + (s.length - max) + " chars]";
@@ -7020,14 +6950,14 @@ var TURN_LOG_PATH, PREVIEW_MAX;
7020
6950
  var init_turnLog = __esm({
7021
6951
  "cli/local-cc/turnLog.ts"() {
7022
6952
  "use strict";
7023
- TURN_LOG_PATH = join12(homedir12(), ".synkro", "cc_sessions", "turns.log");
6953
+ TURN_LOG_PATH = join11(homedir11(), ".synkro", "cc_sessions", "turns.log");
7024
6954
  PREVIEW_MAX = 400;
7025
6955
  }
7026
6956
  });
7027
6957
 
7028
6958
  // cli/local-cc/client.ts
7029
6959
  import { request as httpRequest } from "http";
7030
- import { connect as connect2 } from "net";
6960
+ import { connect } from "net";
7031
6961
  async function submitToChannel(role, payload, opts = {}) {
7032
6962
  const body = JSON.stringify({ role, payload, content: payload });
7033
6963
  const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
@@ -7177,7 +7107,7 @@ var args = process.argv.slice(2);
7177
7107
  var cmd = args[0] || "";
7178
7108
  var subArgs = args.slice(1);
7179
7109
  function printVersion() {
7180
- console.log("1.4.88");
7110
+ console.log("1.4.90");
7181
7111
  }
7182
7112
  function printHelp() {
7183
7113
  console.log(`Synkro CLI \u2014 runtime safety for AI coding agents