@synkro-sh/cli 1.6.32 → 1.6.33

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
@@ -1144,6 +1144,7 @@ export function findGitRoot(cwd: string): string {
1144
1144
 
1145
1145
  export interface SynkroFileConfig {
1146
1146
  version: number;
1147
+ harness: ('claude-code' | 'cursor')[];
1147
1148
  grader: { pool: 'auto' | 'claude' | 'cursor'; mode?: string };
1148
1149
  ruleset: string;
1149
1150
  scanning: { cwe: boolean; cve: boolean };
@@ -1151,6 +1152,7 @@ export interface SynkroFileConfig {
1151
1152
 
1152
1153
  const SYNKRO_FILE_DEFAULTS: SynkroFileConfig = {
1153
1154
  version: 1,
1155
+ harness: ['claude-code', 'cursor'],
1154
1156
  grader: { pool: 'auto' },
1155
1157
  ruleset: 'default',
1156
1158
  scanning: { cwe: true, cve: true },
@@ -1166,8 +1168,13 @@ export function loadSynkroFile(cwd?: string): SynkroFileConfig {
1166
1168
  try {
1167
1169
  if (!existsSync(fp)) { _synkroFileCache = SYNKRO_FILE_DEFAULTS; return _synkroFileCache; }
1168
1170
  const parsed = JSON.parse(readFileSync(fp, 'utf-8'));
1171
+ const validHarness = ['claude-code', 'cursor'] as const;
1172
+ const harness = Array.isArray(parsed.harness)
1173
+ ? parsed.harness.filter((h: string) => validHarness.includes(h as any))
1174
+ : ['claude-code', 'cursor'];
1169
1175
  _synkroFileCache = {
1170
1176
  version: parsed.version || 1,
1177
+ harness: harness.length > 0 ? harness : ['claude-code', 'cursor'],
1171
1178
  grader: {
1172
1179
  pool: ['auto', 'claude', 'cursor'].includes(parsed.grader?.pool) ? parsed.grader.pool : 'auto',
1173
1180
  mode: ['local', 'byok'].includes(parsed.grader?.mode) ? parsed.grader.mode : undefined,
@@ -7865,7 +7872,9 @@ var install_exports = {};
7865
7872
  __export(install_exports, {
7866
7873
  detectGitRepo: () => detectGitRepo2,
7867
7874
  installCommand: () => installCommand,
7868
- parseArgs: () => parseArgs
7875
+ parseArgs: () => parseArgs,
7876
+ reconcileHarness: () => reconcileHarness,
7877
+ writeHookScripts: () => writeHookScripts
7869
7878
  });
7870
7879
  import { existsSync as existsSync9, mkdirSync as mkdirSync8, writeFileSync as writeFileSync7, chmodSync as chmodSync2, readFileSync as readFileSync8, readdirSync as readdirSync3 } from "fs";
7871
7880
  import { homedir as homedir8 } from "os";
@@ -8113,7 +8122,7 @@ function writeConfigEnv(opts) {
8113
8122
  `SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
8114
8123
  `SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
8115
8124
  `SYNKRO_INFERENCE=${shellQuoteSingle(safeInference)}`,
8116
- `SYNKRO_VERSION=${shellQuoteSingle("1.6.32")}`
8125
+ `SYNKRO_VERSION=${shellQuoteSingle("1.6.33")}`
8117
8126
  ];
8118
8127
  if (safeSynkroBin) lines.push(`SYNKRO_CLI_BIN=${shellQuoteSingle(safeSynkroBin)}`);
8119
8128
  if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
@@ -8648,10 +8657,18 @@ function writeSynkroFileIfMissing(opts) {
8648
8657
  return;
8649
8658
  }
8650
8659
  let pool = "auto";
8651
- if (opts.hasClaudeCode && !opts.hasCursor) pool = "claude";
8652
- else if (opts.hasCursor && !opts.hasClaudeCode) pool = "cursor";
8660
+ const harness = [];
8661
+ if (opts.hasClaudeCode) {
8662
+ harness.push("claude-code");
8663
+ if (!opts.hasCursor) pool = "claude";
8664
+ }
8665
+ if (opts.hasCursor) {
8666
+ harness.push("cursor");
8667
+ if (!opts.hasClaudeCode) pool = "cursor";
8668
+ }
8653
8669
  const config = {
8654
8670
  version: 1,
8671
+ harness,
8655
8672
  grader: {
8656
8673
  pool,
8657
8674
  mode: opts.gradingMode === "byok" ? "byok" : "local"
@@ -8677,6 +8694,109 @@ function readSynkroFilePool2() {
8677
8694
  }
8678
8695
  return "auto";
8679
8696
  }
8697
+ function readFullSynkroFile() {
8698
+ try {
8699
+ const root = execSync6("git rev-parse --show-toplevel", { encoding: "utf-8", timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
8700
+ if (!root) return null;
8701
+ const fp = join8(root, ".synkro");
8702
+ if (!existsSync9(fp)) return null;
8703
+ const parsed = JSON.parse(readFileSync8(fp, "utf-8"));
8704
+ const valid = ["claude-code", "cursor"];
8705
+ const harness = Array.isArray(parsed.harness) ? parsed.harness.filter((h) => valid.includes(h)) : ["claude-code", "cursor"];
8706
+ return {
8707
+ harness: harness.length > 0 ? harness : ["claude-code", "cursor"],
8708
+ grader: {
8709
+ pool: ["auto", "claude", "cursor"].includes(parsed.grader?.pool) ? parsed.grader.pool : "auto",
8710
+ mode: ["local", "byok"].includes(parsed.grader?.mode) ? parsed.grader.mode : "local"
8711
+ },
8712
+ ruleset: parsed.ruleset || "default",
8713
+ scanning: { cwe: parsed.scanning?.cwe !== false, cve: parsed.scanning?.cve !== false }
8714
+ };
8715
+ } catch {
8716
+ return null;
8717
+ }
8718
+ }
8719
+ function reconcileHarness() {
8720
+ const sf = readFullSynkroFile();
8721
+ if (!sf) {
8722
+ console.log("No .synkro file found in repo root \u2014 skipping harness reconciliation.");
8723
+ return null;
8724
+ }
8725
+ const wantCC = sf.harness.includes("claude-code");
8726
+ const wantCursor = sf.harness.includes("cursor");
8727
+ console.log(`.synkro: harness=[${sf.harness.join(", ")}] pool=${sf.grader.pool} mode=${sf.grader.mode}`);
8728
+ const scripts = writeHookScripts();
8729
+ console.log("Wrote hook scripts to ~/.synkro/hooks/");
8730
+ const ccSettings = join8(homedir8(), ".claude", "settings.json");
8731
+ if (wantCC) {
8732
+ installCCHooks(ccSettings, {
8733
+ bashJudgeScriptPath: scripts.bashScript,
8734
+ bashFollowupScriptPath: scripts.bashFollowupScript,
8735
+ editPrecheckScriptPath: scripts.editPrecheckScript,
8736
+ cwePrecheckScriptPath: scripts.cwePrecheckScript,
8737
+ cvePrecheckScriptPath: scripts.cvePrecheckScript,
8738
+ planJudgeScriptPath: scripts.planJudgeScript,
8739
+ agentJudgeScriptPath: scripts.agentJudgeScript,
8740
+ stopSummaryScriptPath: scripts.stopSummaryScript,
8741
+ sessionStartScriptPath: scripts.sessionStartScript,
8742
+ transcriptSyncScriptPath: scripts.transcriptSyncScript,
8743
+ userPromptSubmitScriptPath: scripts.userPromptSubmitScript,
8744
+ installScanScriptPath: scripts.installScanScript
8745
+ });
8746
+ console.log(" \u2713 Claude Code hooks registered");
8747
+ try {
8748
+ const mcpJwt = readFileSync8(join8(SYNKRO_DIR4, ".mcp-jwt"), "utf-8").trim();
8749
+ if (mcpJwt) {
8750
+ installMcpConfig({ gatewayUrl: "", bearerToken: mcpJwt, local: true });
8751
+ console.log(" \u2713 Claude Code MCP registered");
8752
+ }
8753
+ } catch {
8754
+ }
8755
+ } else {
8756
+ if (uninstallCCHooks(ccSettings)) console.log(" \u2717 Claude Code hooks removed");
8757
+ if (uninstallMcpConfig()) console.log(" \u2717 Claude Code MCP removed");
8758
+ }
8759
+ const cursorHooks = join8(homedir8(), ".cursor", "hooks.json");
8760
+ if (wantCursor) {
8761
+ installCursorHooks(cursorHooks, {
8762
+ bashJudgeScriptPath: scripts.cursorBashJudgeScript,
8763
+ editCaptureScriptPath: scripts.cursorEditCaptureScript,
8764
+ agentCaptureScriptPath: scripts.cursorAgentCaptureScript,
8765
+ bashFollowupScriptPath: scripts.bashFollowupScript,
8766
+ editPrecheckScriptPath: scripts.editPrecheckScript,
8767
+ cwePrecheckScriptPath: scripts.cwePrecheckScript,
8768
+ cvePrecheckScriptPath: scripts.cvePrecheckScript,
8769
+ planJudgeScriptPath: scripts.planJudgeScript,
8770
+ agentJudgeScriptPath: scripts.agentJudgeScript,
8771
+ stopSummaryScriptPath: scripts.stopSummaryScript,
8772
+ sessionStartScriptPath: scripts.sessionStartScript,
8773
+ userPromptSubmitScriptPath: scripts.userPromptSubmitScript,
8774
+ transcriptSyncScriptPath: scripts.transcriptSyncScript,
8775
+ installScanScriptPath: scripts.installScanScript
8776
+ });
8777
+ console.log(" \u2713 Cursor hooks registered");
8778
+ try {
8779
+ installCursorMcpConfig({ gatewayUrl: "", bearerToken: "", local: true });
8780
+ console.log(" \u2713 Cursor MCP registered");
8781
+ } catch {
8782
+ }
8783
+ } else {
8784
+ if (uninstallCursorHooks(cursorHooks)) console.log(" \u2717 Cursor hooks removed");
8785
+ if (uninstallCursorMcpConfig()) console.log(" \u2717 Cursor MCP removed");
8786
+ }
8787
+ const total = parseInt(process.env.SYNKRO_WORKERS_PER_POOL || "8", 10);
8788
+ const providers = [];
8789
+ if (sf.grader.pool === "cursor") {
8790
+ providers.push("cursor");
8791
+ } else if (sf.grader.pool === "claude") {
8792
+ providers.push("claude_code");
8793
+ } else {
8794
+ if (wantCC) providers.push("claude_code");
8795
+ if (wantCursor) providers.push("cursor");
8796
+ }
8797
+ if (providers.length === 0) providers.push("claude_code");
8798
+ return splitWorkers(total, providers);
8799
+ }
8680
8800
  function detectGitRepo2() {
8681
8801
  const run = (cmd2) => {
8682
8802
  try {
@@ -10400,7 +10520,19 @@ function cmdStop() {
10400
10520
  }
10401
10521
  async function cmdRestart(rest = []) {
10402
10522
  if (inDockerMode()) {
10403
- const { claudeWorkers, cursorWorkers } = resolveWorkerConfig(rest);
10523
+ const { explicit } = resolveWorkerConfig(rest);
10524
+ let claudeWorkers;
10525
+ let cursorWorkers;
10526
+ if (explicit) {
10527
+ ({ claudeWorkers, cursorWorkers } = resolveWorkerConfig(rest));
10528
+ } else {
10529
+ const reconciled = reconcileHarness();
10530
+ if (reconciled) {
10531
+ ({ claudeWorkers, cursorWorkers } = reconciled);
10532
+ } else {
10533
+ ({ claudeWorkers, cursorWorkers } = resolveWorkerConfig(rest));
10534
+ }
10535
+ }
10404
10536
  console.log(`Restarting synkro-server container (${claudeWorkers} claude + ${cursorWorkers} cursor, pulling latest image)...`);
10405
10537
  await dockerUpdate({ claudeWorkers, cursorWorkers });
10406
10538
  const ready = await waitForContainerReady(6e4);
@@ -10644,6 +10776,7 @@ var init_localCc = __esm({
10644
10776
  init_settings();
10645
10777
  init_macKeychain();
10646
10778
  init_dockerInstall();
10779
+ init_install();
10647
10780
  init_client();
10648
10781
  init_stub();
10649
10782
  SYNKRO_CONFIG_PATH = join14(homedir14(), ".synkro", "config.env");
@@ -10922,7 +11055,7 @@ var args = process.argv.slice(2);
10922
11055
  var cmd = args[0] || "";
10923
11056
  var subArgs = args.slice(1);
10924
11057
  function printVersion() {
10925
- console.log("1.6.32");
11058
+ console.log("1.6.33");
10926
11059
  }
10927
11060
  function printHelp2() {
10928
11061
  console.log(`Synkro CLI \u2014 runtime safety for AI coding agents