@synkro-sh/cli 1.6.6 → 1.6.7
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 +105 -27
- package/dist/bootstrap.js.map +1 -1
- package/package.json +1 -1
package/dist/bootstrap.js
CHANGED
|
@@ -5858,6 +5858,7 @@ __export(dockerInstall_exports, {
|
|
|
5858
5858
|
dockerStop: () => dockerStop,
|
|
5859
5859
|
dockerUpdate: () => dockerUpdate,
|
|
5860
5860
|
imageTag: () => imageTag,
|
|
5861
|
+
readContainerConfig: () => readContainerConfig,
|
|
5861
5862
|
resolveWorkerConfig: () => resolveWorkerConfig,
|
|
5862
5863
|
splitWorkers: () => splitWorkers,
|
|
5863
5864
|
waitForContainerReady: () => waitForContainerReady
|
|
@@ -6091,6 +6092,34 @@ function dockerStatus() {
|
|
|
6091
6092
|
healthz: `http://127.0.0.1:${HOST_MCP_PORT}/`
|
|
6092
6093
|
};
|
|
6093
6094
|
}
|
|
6095
|
+
function readContainerConfig() {
|
|
6096
|
+
const r = spawnSync2("docker", ["inspect", "--format", "{{json .Config.Env}}", CONTAINER_NAME], {
|
|
6097
|
+
encoding: "utf-8",
|
|
6098
|
+
timeout: 5e3
|
|
6099
|
+
});
|
|
6100
|
+
if (r.status !== 0 || !r.stdout) return null;
|
|
6101
|
+
let env;
|
|
6102
|
+
try {
|
|
6103
|
+
env = JSON.parse(r.stdout.trim());
|
|
6104
|
+
} catch {
|
|
6105
|
+
return null;
|
|
6106
|
+
}
|
|
6107
|
+
if (!Array.isArray(env)) return null;
|
|
6108
|
+
const get = (k) => {
|
|
6109
|
+
const hit = env.find((e) => typeof e === "string" && e.startsWith(k + "="));
|
|
6110
|
+
return hit ? hit.slice(k.length + 1) : void 0;
|
|
6111
|
+
};
|
|
6112
|
+
const num = (s) => {
|
|
6113
|
+
if (s === void 0) return void 0;
|
|
6114
|
+
const n = parseInt(s, 10);
|
|
6115
|
+
return Number.isFinite(n) ? n : void 0;
|
|
6116
|
+
};
|
|
6117
|
+
return {
|
|
6118
|
+
claudeWorkers: num(get("CLAUDE_WORKERS")),
|
|
6119
|
+
cursorWorkers: num(get("CURSOR_WORKERS")),
|
|
6120
|
+
connectedRepo: get("SYNKRO_CONNECTED_REPO") || void 0
|
|
6121
|
+
};
|
|
6122
|
+
}
|
|
6094
6123
|
async function dockerSafeStop() {
|
|
6095
6124
|
const status = dockerStatus();
|
|
6096
6125
|
if (!status.running) {
|
|
@@ -6417,7 +6446,7 @@ function writeConfigEnv(opts) {
|
|
|
6417
6446
|
`SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
|
|
6418
6447
|
`SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
|
|
6419
6448
|
`SYNKRO_INFERENCE=${shellQuoteSingle(safeInference)}`,
|
|
6420
|
-
`SYNKRO_VERSION=${shellQuoteSingle("1.6.
|
|
6449
|
+
`SYNKRO_VERSION=${shellQuoteSingle("1.6.7")}`
|
|
6421
6450
|
];
|
|
6422
6451
|
if (safeSynkroBin) lines.push(`SYNKRO_CLI_BIN=${shellQuoteSingle(safeSynkroBin)}`);
|
|
6423
6452
|
if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
|
|
@@ -7540,22 +7569,22 @@ import { existsSync as existsSync11, rmSync, readdirSync as readdirSync3 } from
|
|
|
7540
7569
|
import { homedir as homedir10 } from "os";
|
|
7541
7570
|
import { join as join10 } from "path";
|
|
7542
7571
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
7543
|
-
|
|
7572
|
+
import { createInterface as createInterface4 } from "readline";
|
|
7573
|
+
async function tearDownLocalCC() {
|
|
7544
7574
|
const docker = dockerStatus();
|
|
7545
7575
|
if (docker.running) {
|
|
7546
7576
|
await dockerSafeStop();
|
|
7547
|
-
console.log("\u2713 stopped synkro-server container
|
|
7577
|
+
console.log("\u2713 stopped synkro-server container");
|
|
7548
7578
|
} else {
|
|
7549
7579
|
console.log("\xB7 no synkro-server container running");
|
|
7550
7580
|
}
|
|
7551
7581
|
dockerRemove();
|
|
7552
|
-
|
|
7553
|
-
|
|
7554
|
-
|
|
7555
|
-
|
|
7556
|
-
|
|
7557
|
-
|
|
7558
|
-
}
|
|
7582
|
+
console.log("\u2713 removed synkro-server container");
|
|
7583
|
+
try {
|
|
7584
|
+
const image = imageTag();
|
|
7585
|
+
const r = spawnSync4("docker", ["rmi", "-f", image], { encoding: "utf-8", timeout: 3e4 });
|
|
7586
|
+
console.log(r.status === 0 ? `\u2713 removed Docker image ${image}` : "\xB7 no Docker image to remove");
|
|
7587
|
+
} catch {
|
|
7559
7588
|
}
|
|
7560
7589
|
if (needsKeychainBridge()) {
|
|
7561
7590
|
try {
|
|
@@ -7567,10 +7596,31 @@ async function tearDownLocalCC(purge) {
|
|
|
7567
7596
|
uninstallLocalCC();
|
|
7568
7597
|
console.log("\u2713 cleaned ~/.claude.json entries");
|
|
7569
7598
|
}
|
|
7599
|
+
function confirmPurge() {
|
|
7600
|
+
console.log("\u26A0 WARNING \u2014 synkro uninstall --purge");
|
|
7601
|
+
console.log(" This permanently deletes ALL Synkro data on this machine,");
|
|
7602
|
+
console.log(" including every scan finding, telemetry record, and backup in");
|
|
7603
|
+
console.log(" ~/.synkro/pgdata and ~/.synkro/pgdata-backups. It cannot be undone.\n");
|
|
7604
|
+
if (!process.stdin.isTTY) {
|
|
7605
|
+
console.log(" Non-interactive shell \u2014 re-run in a terminal to confirm.");
|
|
7606
|
+
return Promise.resolve(false);
|
|
7607
|
+
}
|
|
7608
|
+
const rl = createInterface4({ input: process.stdin, output: process.stdout });
|
|
7609
|
+
return new Promise((resolve3) => {
|
|
7610
|
+
rl.question(" Type 'yes' to wipe everything (anything else cancels): ", (answer) => {
|
|
7611
|
+
rl.close();
|
|
7612
|
+
resolve3(answer.trim().toLowerCase() === "yes");
|
|
7613
|
+
});
|
|
7614
|
+
});
|
|
7615
|
+
}
|
|
7570
7616
|
async function disconnectCommand(args2 = []) {
|
|
7571
7617
|
const purge = args2.includes("--purge");
|
|
7572
|
-
|
|
7573
|
-
|
|
7618
|
+
if (purge && !await confirmPurge()) {
|
|
7619
|
+
console.log("\nAborted \u2014 nothing was removed.");
|
|
7620
|
+
return;
|
|
7621
|
+
}
|
|
7622
|
+
console.log("\nSynkro uninstall starting...\n");
|
|
7623
|
+
await tearDownLocalCC();
|
|
7574
7624
|
const agents = detectAgents();
|
|
7575
7625
|
let sawClaudeCode = false;
|
|
7576
7626
|
for (const agent of agents) {
|
|
@@ -7591,31 +7641,32 @@ async function disconnectCommand(args2 = []) {
|
|
|
7591
7641
|
const cursorMcpRemoved = uninstallCursorMcpConfig();
|
|
7592
7642
|
console.log(`${cursorMcpRemoved ? "\u2713" : "\xB7"} MCP guardrails (Cursor): ${cursorMcpRemoved ? "removed from ~/.cursor/mcp.json" : "no entry found"}`);
|
|
7593
7643
|
}
|
|
7594
|
-
if (
|
|
7595
|
-
if (
|
|
7596
|
-
|
|
7597
|
-
|
|
7644
|
+
if (existsSync11(SYNKRO_DIR5)) {
|
|
7645
|
+
if (purge) {
|
|
7646
|
+
rmSync(SYNKRO_DIR5, { recursive: true, force: true });
|
|
7647
|
+
console.log(`\u2713 wiped ${SYNKRO_DIR5} entirely \u2014 including all scan data and backups`);
|
|
7648
|
+
} else {
|
|
7649
|
+
const keep = /* @__PURE__ */ new Set([join10(SYNKRO_DIR5, "pgdata"), join10(SYNKRO_DIR5, "pgdata-backups")]);
|
|
7598
7650
|
const preserved = [];
|
|
7599
7651
|
for (const entry of readdirSync3(SYNKRO_DIR5)) {
|
|
7600
7652
|
const full = join10(SYNKRO_DIR5, entry);
|
|
7601
|
-
if (full
|
|
7653
|
+
if (keep.has(full)) {
|
|
7602
7654
|
preserved.push(entry);
|
|
7603
7655
|
continue;
|
|
7604
7656
|
}
|
|
7605
7657
|
rmSync(full, { recursive: true, force: true });
|
|
7606
7658
|
}
|
|
7607
7659
|
if (preserved.length > 0) {
|
|
7608
|
-
console.log(`\u2713
|
|
7660
|
+
console.log(`\u2713 removed Synkro config from ${SYNKRO_DIR5} (kept your scan data: ${preserved.join(", ")})`);
|
|
7661
|
+
console.log(" run `synkro uninstall --purge` to delete that too");
|
|
7609
7662
|
} else {
|
|
7610
|
-
console.log(`\u2713
|
|
7663
|
+
console.log(`\u2713 removed ${SYNKRO_DIR5}`);
|
|
7611
7664
|
}
|
|
7612
|
-
} else {
|
|
7613
|
-
console.log(`\xB7 ${SYNKRO_DIR5} already gone, nothing to remove`);
|
|
7614
7665
|
}
|
|
7615
|
-
} else
|
|
7616
|
-
console.log(
|
|
7666
|
+
} else {
|
|
7667
|
+
console.log(`\xB7 ${SYNKRO_DIR5} already gone`);
|
|
7617
7668
|
}
|
|
7618
|
-
console.log("\nSynkro
|
|
7669
|
+
console.log(purge ? "\nSynkro fully removed \u2014 this machine is clean, as if it was never installed." : "\nSynkro uninstalled. Your scan data is preserved.");
|
|
7619
7670
|
}
|
|
7620
7671
|
var SYNKRO_DIR5;
|
|
7621
7672
|
var init_disconnect = __esm({
|
|
@@ -7812,7 +7863,8 @@ var lifecycle_exports = {};
|
|
|
7812
7863
|
__export(lifecycle_exports, {
|
|
7813
7864
|
restartCommand: () => restartCommand,
|
|
7814
7865
|
startCommand: () => startCommand,
|
|
7815
|
-
stopCommand: () => stopCommand
|
|
7866
|
+
stopCommand: () => stopCommand,
|
|
7867
|
+
updateCommand: () => updateCommand
|
|
7816
7868
|
});
|
|
7817
7869
|
async function stopCommand() {
|
|
7818
7870
|
assertDockerAvailable();
|
|
@@ -7848,6 +7900,26 @@ Start failed: ${result.error}`);
|
|
|
7848
7900
|
}
|
|
7849
7901
|
console.log("\nServer is running.");
|
|
7850
7902
|
}
|
|
7903
|
+
async function updateCommand() {
|
|
7904
|
+
assertDockerAvailable();
|
|
7905
|
+
const cfg = readContainerConfig();
|
|
7906
|
+
if (!cfg) {
|
|
7907
|
+
console.error("No synkro-server container found. Run `synkro install` first.");
|
|
7908
|
+
process.exit(1);
|
|
7909
|
+
}
|
|
7910
|
+
const claudeWorkers = cfg.claudeWorkers ?? 8;
|
|
7911
|
+
const cursorWorkers = cfg.cursorWorkers ?? 0;
|
|
7912
|
+
console.log("Synkro: updating to the latest container image");
|
|
7913
|
+
console.log(` preserving pool: ${claudeWorkers} claude + ${cursorWorkers} cursor worker(s)
|
|
7914
|
+
`);
|
|
7915
|
+
await dockerUpdate({ claudeWorkers, cursorWorkers, connectedRepo: cfg.connectedRepo });
|
|
7916
|
+
const ready = await waitForContainerReady(9e4);
|
|
7917
|
+
if (!ready) {
|
|
7918
|
+
console.error("\n\u26A0 container did not pass its health check within 90s \u2014 check: docker logs synkro-server");
|
|
7919
|
+
process.exit(1);
|
|
7920
|
+
}
|
|
7921
|
+
console.log("\nSynkro updated \u2014 now running the latest version.");
|
|
7922
|
+
}
|
|
7851
7923
|
async function restartCommand(rest = []) {
|
|
7852
7924
|
assertDockerAvailable();
|
|
7853
7925
|
const cfg = resolveWorkerConfig(rest);
|
|
@@ -7904,7 +7976,7 @@ var args = process.argv.slice(2);
|
|
|
7904
7976
|
var cmd = args[0] || "";
|
|
7905
7977
|
var subArgs = args.slice(1);
|
|
7906
7978
|
function printVersion() {
|
|
7907
|
-
console.log("1.6.
|
|
7979
|
+
console.log("1.6.7");
|
|
7908
7980
|
}
|
|
7909
7981
|
function printHelp() {
|
|
7910
7982
|
console.log(`Synkro CLI \u2014 runtime safety for AI coding agents
|
|
@@ -7914,10 +7986,11 @@ Usage:
|
|
|
7914
7986
|
|
|
7915
7987
|
Commands:
|
|
7916
7988
|
install [--force] Install or update Synkro
|
|
7917
|
-
uninstall [--purge] Remove Synkro
|
|
7989
|
+
uninstall [--purge] Remove Synkro (keeps scan data; --purge wipes that too)
|
|
7918
7990
|
stop Gracefully stop the server (snapshot + checkpoint)
|
|
7919
7991
|
start [opts] Start the server (with pgdata integrity check)
|
|
7920
7992
|
restart [opts] Safe restart (stop \u2192 start, data preserved)
|
|
7993
|
+
update Pull the latest container image and safely restart
|
|
7921
7994
|
version Show version
|
|
7922
7995
|
|
|
7923
7996
|
start/restart opts (recreate the worker pool):
|
|
@@ -7976,6 +8049,11 @@ async function main() {
|
|
|
7976
8049
|
await restartCommand2(args.slice(1));
|
|
7977
8050
|
break;
|
|
7978
8051
|
}
|
|
8052
|
+
case "update": {
|
|
8053
|
+
const { updateCommand: updateCommand2 } = await Promise.resolve().then(() => (init_lifecycle(), lifecycle_exports));
|
|
8054
|
+
await updateCommand2();
|
|
8055
|
+
break;
|
|
8056
|
+
}
|
|
7979
8057
|
default: {
|
|
7980
8058
|
console.error(`Unknown command: ${cmd}`);
|
|
7981
8059
|
printHelp();
|