@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 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>/) || 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 || '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 });
@@ -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>${synkroBinPath}</string>
5287
- <string>local-cc</string>
5288
- <string>refresh-creds</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 = 6 * 60 * 60;
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.89")}`
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
- try {
5880
- ghToken = await connectGitHub(gatewayUrl, token);
5881
- } catch {
5882
- }
5883
- if (ghToken) {
5884
- console.log();
5885
- } else {
5886
- console.log(" Skipped. Run `synkro install` again to enable PR scanning.\n");
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
- let transcriptConsent = true;
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 || '8931', 10);
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 join10 } from "path";
6527
- import { homedir as homedir10 } from "os";
6528
- import { spawnSync as spawnSync4 } from "child_process";
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, 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;
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
- init_channelSource();
6609
- CLAUDE_JSON_BACKUP_PATH = join10(homedir10(), ".claude.json.synkro-bak");
6610
- SESSION_DIR2 = join10(homedir10(), ".synkro", "cc_sessions");
6611
- PLUGIN_PATH = join10(SESSION_DIR2, "synkro-channel.ts");
6612
- PLUGIN_PKG_PATH = join10(SESSION_DIR2, "package.json");
6613
- PLUGIN_SETTINGS_DIR = join10(SESSION_DIR2, ".claude");
6614
- PLUGIN_SETTINGS_PATH = join10(PLUGIN_SETTINGS_DIR, "settings.json");
6615
- PROJECT_MCP_PATH = join10(SESSION_DIR2, ".mcp.json");
6616
- CLAUDE_JSON_PATH = join10(homedir10(), ".claude.json");
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
- SESSION_DIR_22 = join10(homedir10(), ".synkro", "cc_sessions_2");
6621
- PLUGIN_PATH_2 = join10(SESSION_DIR_22, "synkro-channel.ts");
6622
- PLUGIN_PKG_PATH_2 = join10(SESSION_DIR_22, "package.json");
6623
- PLUGIN_SETTINGS_DIR_2 = join10(SESSION_DIR_22, ".claude");
6624
- PLUGIN_SETTINGS_PATH_2 = join10(PLUGIN_SETTINGS_DIR_2, "settings.json");
6625
- PROJECT_MCP_PATH_2 = join10(SESSION_DIR_22, ".mcp.json");
6626
- RUN_SCRIPT_PATH_2 = join10(SESSION_DIR_22, "run-claude.sh");
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
- SESSION_DIR_32 = join10(homedir10(), ".synkro", "cc_sessions_3");
6630
- PLUGIN_PATH_3 = join10(SESSION_DIR_32, "synkro-channel.ts");
6631
- PLUGIN_PKG_PATH_3 = join10(SESSION_DIR_32, "package.json");
6632
- PLUGIN_SETTINGS_DIR_3 = join10(SESSION_DIR_32, ".claude");
6633
- PLUGIN_SETTINGS_PATH_3 = join10(PLUGIN_SETTINGS_DIR_3, "settings.json");
6634
- PROJECT_MCP_PATH_3 = join10(SESSION_DIR_32, ".mcp.json");
6635
- RUN_SCRIPT_PATH_3 = join10(SESSION_DIR_32, "run-claude.sh");
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
- SESSION_DIR_42 = join10(homedir10(), ".synkro", "cc_sessions_4");
6639
- PLUGIN_PATH_4 = join10(SESSION_DIR_42, "synkro-channel.ts");
6640
- PLUGIN_PKG_PATH_4 = join10(SESSION_DIR_42, "package.json");
6641
- PLUGIN_SETTINGS_DIR_4 = join10(SESSION_DIR_42, ".claude");
6642
- PLUGIN_SETTINGS_PATH_4 = join10(PLUGIN_SETTINGS_DIR_4, "settings.json");
6643
- PROJECT_MCP_PATH_4 = join10(SESSION_DIR_42, ".mcp.json");
6644
- RUN_SCRIPT_PATH_4 = join10(SESSION_DIR_42, "run-claude.sh");
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: 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 },
6906
- { 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 },
6907
- { 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 },
6908
- { 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 }
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 homedir11 } from "os";
6920
- import { join as join11 } from "path";
6921
- function tearDownLocalCC() {
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 local-cc runtime: stopped synkro-server container");
6926
- }
6927
- let hadTask = false;
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 (!docker.running) {
6938
- console.log(`${hadTask ? "\u2713" : "\xB7"} local-cc runtime: ${hadTask ? "stopped all pueue channels" : "no live tasks"}`);
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 local-cc config: cleaned ~/.claude.json entries");
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 = join11(homedir11(), ".synkro");
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 join12 } from "path";
7005
- import { homedir as homedir12 } from "os";
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 = join12(homedir12(), ".synkro", "cc_sessions", "turns.log");
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 as connect2 } from "net";
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.89");
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