@synkro-sh/cli 1.5.0 → 1.5.2
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 +35 -69
- package/dist/bootstrap.js.map +1 -1
- package/package.json +1 -1
package/dist/bootstrap.js
CHANGED
|
@@ -51,18 +51,6 @@ function detectAgents() {
|
|
|
51
51
|
version: claudeBinary ? getVersion("claude") : void 0
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
|
-
const codexBinary = which("codex");
|
|
55
|
-
const codexConfigDir = join(home, ".codex");
|
|
56
|
-
if (codexBinary || existsSync(codexConfigDir)) {
|
|
57
|
-
agents.push({
|
|
58
|
-
kind: "codex",
|
|
59
|
-
name: "Codex",
|
|
60
|
-
binaryPath: codexBinary,
|
|
61
|
-
configDir: codexConfigDir,
|
|
62
|
-
settingsPath: join(codexConfigDir, "config.toml"),
|
|
63
|
-
version: codexBinary ? getVersion("codex") : void 0
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
54
|
const cursorBinary = which("cursor");
|
|
67
55
|
const cursorConfigDir = join(home, ".cursor");
|
|
68
56
|
if (cursorBinary || existsSync(cursorConfigDir)) {
|
|
@@ -5645,6 +5633,30 @@ function parseArgs(argv) {
|
|
|
5645
5633
|
}
|
|
5646
5634
|
return opts;
|
|
5647
5635
|
}
|
|
5636
|
+
async function promptAgentSelection(detected) {
|
|
5637
|
+
if (detected.length <= 1) return detected;
|
|
5638
|
+
console.log("Multiple coding agents detected. Which ones do you want Synkro guardrails installed for?");
|
|
5639
|
+
detected.forEach((a, i) => console.log(` ${i + 1}. ${a.name}`));
|
|
5640
|
+
console.log(` ${detected.length + 1}. Both / all (default)`);
|
|
5641
|
+
const rl = createInterface3({ input: process.stdin, output: process.stdout });
|
|
5642
|
+
const ask2 = () => new Promise((resolve3) => {
|
|
5643
|
+
rl.question(`Pick [1-${detected.length + 1}] (default: all): `, (answer) => {
|
|
5644
|
+
const t = answer.trim().toLowerCase();
|
|
5645
|
+
if (t === "" || t === String(detected.length + 1) || t === "both" || t === "all") {
|
|
5646
|
+
rl.close();
|
|
5647
|
+
return resolve3(detected);
|
|
5648
|
+
}
|
|
5649
|
+
const n = parseInt(t, 10);
|
|
5650
|
+
if (Number.isInteger(n) && n >= 1 && n <= detected.length) {
|
|
5651
|
+
rl.close();
|
|
5652
|
+
return resolve3([detected[n - 1]]);
|
|
5653
|
+
}
|
|
5654
|
+
console.log("Invalid choice. Try again.");
|
|
5655
|
+
resolve3(ask2());
|
|
5656
|
+
});
|
|
5657
|
+
});
|
|
5658
|
+
return ask2();
|
|
5659
|
+
}
|
|
5648
5660
|
function ensureSynkroDir() {
|
|
5649
5661
|
mkdirSync8(SYNKRO_DIR4, { recursive: true });
|
|
5650
5662
|
mkdirSync8(HOOKS_DIR, { recursive: true });
|
|
@@ -5746,7 +5758,7 @@ function writeConfigEnv(opts) {
|
|
|
5746
5758
|
`SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
|
|
5747
5759
|
`SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
|
|
5748
5760
|
`SYNKRO_INFERENCE=${shellQuoteSingle(safeInference)}`,
|
|
5749
|
-
`SYNKRO_VERSION=${shellQuoteSingle("1.5.
|
|
5761
|
+
`SYNKRO_VERSION=${shellQuoteSingle("1.5.2")}`
|
|
5750
5762
|
];
|
|
5751
5763
|
if (safeSynkroBin) lines.push(`SYNKRO_CLI_BIN=${shellQuoteSingle(safeSynkroBin)}`);
|
|
5752
5764
|
if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
|
|
@@ -5872,34 +5884,6 @@ function assertGatewayAllowed(gatewayUrl) {
|
|
|
5872
5884
|
throw new Error(`Gateway host not in allowlist (synkro.sh or *.synkro.sh): ${host}`);
|
|
5873
5885
|
}
|
|
5874
5886
|
}
|
|
5875
|
-
function isAlreadyInstalled() {
|
|
5876
|
-
const requiredScripts = [
|
|
5877
|
-
join8(HOOKS_DIR, "cc-bash-judge.ts"),
|
|
5878
|
-
join8(HOOKS_DIR, "cc-bash-followup.ts"),
|
|
5879
|
-
join8(HOOKS_DIR, "cc-edit-precheck.ts"),
|
|
5880
|
-
join8(HOOKS_DIR, "cc-cve-precheck.ts"),
|
|
5881
|
-
join8(HOOKS_DIR, "cc-plan-judge.ts"),
|
|
5882
|
-
join8(HOOKS_DIR, "cc-stop-summary.ts"),
|
|
5883
|
-
join8(HOOKS_DIR, "cc-session-start.ts")
|
|
5884
|
-
];
|
|
5885
|
-
if (!requiredScripts.every((p) => existsSync9(p))) return false;
|
|
5886
|
-
if (!existsSync9(CONFIG_PATH2)) return false;
|
|
5887
|
-
const settingsPath = join8(homedir8(), ".claude", "settings.json");
|
|
5888
|
-
if (!existsSync9(settingsPath)) return false;
|
|
5889
|
-
try {
|
|
5890
|
-
const settings = JSON.parse(readFileSync7(settingsPath, "utf-8"));
|
|
5891
|
-
const hooks = settings?.hooks;
|
|
5892
|
-
if (!hooks || typeof hooks !== "object") return false;
|
|
5893
|
-
const hasManaged = (kind) => Array.isArray(hooks[kind]) && hooks[kind].some((entry) => entry?.__synkro_managed__ === true);
|
|
5894
|
-
if (!hasManaged("PreToolUse")) return false;
|
|
5895
|
-
if (!hasManaged("PostToolUse")) return false;
|
|
5896
|
-
if (!hasManaged("SessionEnd")) return false;
|
|
5897
|
-
if (!hasManaged("SessionStart")) return false;
|
|
5898
|
-
} catch {
|
|
5899
|
-
return false;
|
|
5900
|
-
}
|
|
5901
|
-
return true;
|
|
5902
|
-
}
|
|
5903
5887
|
async function installCommand(opts = {}) {
|
|
5904
5888
|
const gatewayUrl = opts.gatewayUrl || sanitizeGatewayCandidate(process.env.SYNKRO_GATEWAY_URL) || "https://api.synkro.sh";
|
|
5905
5889
|
try {
|
|
@@ -5908,29 +5892,6 @@ async function installCommand(opts = {}) {
|
|
|
5908
5892
|
console.error(err.message);
|
|
5909
5893
|
process.exit(1);
|
|
5910
5894
|
}
|
|
5911
|
-
if (!opts.force && isAuthenticated() && isAlreadyInstalled()) {
|
|
5912
|
-
setApiBaseUrl(`${gatewayUrl}/api`);
|
|
5913
|
-
await ensureValidToken();
|
|
5914
|
-
const currentRepo = detectGitRepo2();
|
|
5915
|
-
if (currentRepo) {
|
|
5916
|
-
try {
|
|
5917
|
-
const projects = await listProjects();
|
|
5918
|
-
const alreadyLinked = projects.some(
|
|
5919
|
-
(p) => p.repos?.some((r) => r.full_name === currentRepo)
|
|
5920
|
-
);
|
|
5921
|
-
if (!alreadyLinked) {
|
|
5922
|
-
console.log(`Synkro is installed. This repo (${currentRepo}) is not linked yet.
|
|
5923
|
-
`);
|
|
5924
|
-
await promptRepoConnection();
|
|
5925
|
-
return;
|
|
5926
|
-
}
|
|
5927
|
-
} catch {
|
|
5928
|
-
}
|
|
5929
|
-
}
|
|
5930
|
-
console.log("\u2713 Synkro is already installed and configured.");
|
|
5931
|
-
console.log(" Run `synkro install --force` to reinstall from scratch.");
|
|
5932
|
-
return;
|
|
5933
|
-
}
|
|
5934
5895
|
console.log("Synkro install starting...\n");
|
|
5935
5896
|
if (!isAuthenticated()) {
|
|
5936
5897
|
console.log("Opening browser for Synkro auth...");
|
|
@@ -5989,16 +5950,21 @@ async function installCommand(opts = {}) {
|
|
|
5989
5950
|
}
|
|
5990
5951
|
setApiBaseUrl(`${gatewayUrl}/api`);
|
|
5991
5952
|
await promptRepoConnection({ linkRepo: opts.linkRepo });
|
|
5992
|
-
const
|
|
5993
|
-
if (
|
|
5994
|
-
console.error("No
|
|
5953
|
+
const detected = detectAgents();
|
|
5954
|
+
if (detected.length === 0) {
|
|
5955
|
+
console.error("No supported coding agents detected. Install Claude Code or Cursor first.");
|
|
5995
5956
|
process.exit(1);
|
|
5996
5957
|
}
|
|
5997
5958
|
console.log("Detected agents:");
|
|
5998
|
-
for (const a of
|
|
5959
|
+
for (const a of detected) {
|
|
5999
5960
|
console.log(` \u2713 ${a.name}${a.version ? ` (${a.version})` : ""}`);
|
|
6000
5961
|
}
|
|
6001
5962
|
console.log();
|
|
5963
|
+
const agents = await promptAgentSelection(detected);
|
|
5964
|
+
if (agents.length < detected.length) {
|
|
5965
|
+
console.log(`Installing hooks for: ${agents.map((a) => a.name).join(", ")}
|
|
5966
|
+
`);
|
|
5967
|
+
}
|
|
6002
5968
|
ensureSynkroDir();
|
|
6003
5969
|
const scripts = writeHookScripts();
|
|
6004
5970
|
console.log("Wrote hook scripts:");
|
|
@@ -7182,7 +7148,7 @@ var args = process.argv.slice(2);
|
|
|
7182
7148
|
var cmd = args[0] || "";
|
|
7183
7149
|
var subArgs = args.slice(1);
|
|
7184
7150
|
function printVersion() {
|
|
7185
|
-
console.log("1.5.
|
|
7151
|
+
console.log("1.5.2");
|
|
7186
7152
|
}
|
|
7187
7153
|
function printHelp() {
|
|
7188
7154
|
console.log(`Synkro CLI \u2014 runtime safety for AI coding agents
|