@synkro-sh/cli 1.3.8 → 1.3.9
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 +93 -43
- package/dist/bootstrap.js.map +1 -1
- package/package.json +1 -1
package/dist/bootstrap.js
CHANGED
|
@@ -2752,8 +2752,30 @@ async function connectGithubAndSelectRepos() {
|
|
|
2752
2752
|
rl.close();
|
|
2753
2753
|
}
|
|
2754
2754
|
}
|
|
2755
|
-
async function promptRepoConnection() {
|
|
2755
|
+
async function promptRepoConnection(opts) {
|
|
2756
2756
|
const localRepo = detectGitRepo();
|
|
2757
|
+
if (opts?.linkRepo !== void 0) {
|
|
2758
|
+
if (opts.linkRepo && localRepo) {
|
|
2759
|
+
try {
|
|
2760
|
+
const existing = await listProjects();
|
|
2761
|
+
const alreadyLinked = existing.some(
|
|
2762
|
+
(p) => p.repos?.some((r) => r.full_name === localRepo.fullName)
|
|
2763
|
+
);
|
|
2764
|
+
if (!alreadyLinked) {
|
|
2765
|
+
await createProject(localRepo.shortName, [{ full_name: localRepo.fullName }]);
|
|
2766
|
+
console.log(` \u2713 Created project "${localRepo.shortName}" linked to ${localRepo.fullName}`);
|
|
2767
|
+
} else {
|
|
2768
|
+
console.log(` \u2713 ${localRepo.fullName} is already linked to a Synkro project.`);
|
|
2769
|
+
}
|
|
2770
|
+
} catch (err) {
|
|
2771
|
+
console.warn(` \u26A0 Could not link repo: ${err.message}`);
|
|
2772
|
+
}
|
|
2773
|
+
} else if (opts.linkRepo) {
|
|
2774
|
+
console.warn(" \u26A0 --link-repo specified but not in a git repo. Skipping.");
|
|
2775
|
+
}
|
|
2776
|
+
console.log();
|
|
2777
|
+
return;
|
|
2778
|
+
}
|
|
2757
2779
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
2758
2780
|
try {
|
|
2759
2781
|
console.log("Connect repos to Synkro:\n");
|
|
@@ -2918,11 +2940,14 @@ async function setupGithubCommand(opts = {}) {
|
|
|
2918
2940
|
process.exit(1);
|
|
2919
2941
|
}
|
|
2920
2942
|
const rl = createInterface2({ input, output });
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2943
|
+
let ghToken = opts.githubToken || "";
|
|
2944
|
+
if (!ghToken) {
|
|
2945
|
+
console.log("Synkro PR scan setup\n");
|
|
2946
|
+
console.log("Requirements:");
|
|
2947
|
+
console.log(" \u2022 A GitHub personal access token with `repo` scope");
|
|
2948
|
+
console.log(" (create at https://github.com/settings/tokens?type=beta)\n");
|
|
2949
|
+
ghToken = (await prompt(rl, "GitHub token (paste): ", { silent: true })).trim();
|
|
2950
|
+
}
|
|
2926
2951
|
if (!ghToken || !ghToken.startsWith("ghp_") && !ghToken.startsWith("github_pat_")) {
|
|
2927
2952
|
console.error("Invalid GitHub token format. Expected ghp_... or github_pat_...");
|
|
2928
2953
|
rl.close();
|
|
@@ -3061,6 +3086,17 @@ function parseArgs(argv) {
|
|
|
3061
3086
|
else if (a === "--skip-auth") opts.skipAuth = true;
|
|
3062
3087
|
else if (a === "--no-mcp") opts.noMcp = true;
|
|
3063
3088
|
else if (a === "--force" || a === "-f") opts.force = true;
|
|
3089
|
+
else if (a === "--non-interactive") opts.nonInteractive = true;
|
|
3090
|
+
else if (a === "--link-repo") opts.linkRepo = true;
|
|
3091
|
+
else if (a === "--sync-transcripts") opts.syncTranscripts = true;
|
|
3092
|
+
else if (a === "--no-sync-transcripts") opts.syncTranscripts = false;
|
|
3093
|
+
else if (a === "--pr-scan=claude-oauth") opts.prScan = "claude-oauth";
|
|
3094
|
+
else if (a === "--pr-scan=byok") opts.prScan = "byok";
|
|
3095
|
+
else if (a === "--pr-scan=skip") opts.prScan = "skip";
|
|
3096
|
+
else if (a.startsWith("--pr-scan=")) opts.prScan = a.slice("--pr-scan=".length);
|
|
3097
|
+
else if (a.startsWith("--inference-key=")) opts.inferenceKey = a.slice("--inference-key=".length);
|
|
3098
|
+
else if (a.startsWith("--inference-model=")) opts.inferenceModel = a.slice("--inference-model=".length);
|
|
3099
|
+
else if (a.startsWith("--github-token=")) opts.githubToken = a.slice("--github-token=".length);
|
|
3064
3100
|
}
|
|
3065
3101
|
if (!opts.gatewayUrl) {
|
|
3066
3102
|
const fromEnv = sanitizeGatewayCandidate(process.env.SYNKRO_GATEWAY_URL);
|
|
@@ -3135,7 +3171,7 @@ function writeConfigEnv(opts) {
|
|
|
3135
3171
|
`SYNKRO_GATEWAY_URL=${shellQuoteSingle(safeGateway)}`,
|
|
3136
3172
|
`SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
|
|
3137
3173
|
`SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
|
|
3138
|
-
`SYNKRO_VERSION=${shellQuoteSingle("1.3.
|
|
3174
|
+
`SYNKRO_VERSION=${shellQuoteSingle("1.3.9")}`
|
|
3139
3175
|
];
|
|
3140
3176
|
if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
|
|
3141
3177
|
if (safeOrgId) lines.push(`SYNKRO_ORG_ID=${shellQuoteSingle(safeOrgId)}`);
|
|
@@ -3238,7 +3274,11 @@ async function installCommand(opts = {}) {
|
|
|
3238
3274
|
console.error("No access token available after auth.");
|
|
3239
3275
|
process.exit(1);
|
|
3240
3276
|
}
|
|
3241
|
-
|
|
3277
|
+
if (opts.nonInteractive) {
|
|
3278
|
+
await promptRepoConnection({ linkRepo: opts.linkRepo ?? true });
|
|
3279
|
+
} else {
|
|
3280
|
+
await promptRepoConnection();
|
|
3281
|
+
}
|
|
3242
3282
|
const agents = detectAgents();
|
|
3243
3283
|
if (agents.length === 0) {
|
|
3244
3284
|
console.error("No AI coding agents detected. Install Claude Code first: https://docs.claude.com/claude-code");
|
|
@@ -3336,7 +3376,7 @@ async function installCommand(opts = {}) {
|
|
|
3336
3376
|
`);
|
|
3337
3377
|
const repo = detectGitRepo2();
|
|
3338
3378
|
if (repo && getClaudeProjectsFolder()) {
|
|
3339
|
-
const syncHistory = await promptYesNo("Sync Claude Code session history for this repo?");
|
|
3379
|
+
const syncHistory = opts.nonInteractive ? opts.syncTranscripts ?? true : await promptYesNo("Sync Claude Code session history for this repo?");
|
|
3340
3380
|
if (syncHistory) {
|
|
3341
3381
|
try {
|
|
3342
3382
|
const ingested = await ingestSessionTranscripts(gatewayUrl, token, repo);
|
|
@@ -3390,51 +3430,52 @@ async function installCommand(opts = {}) {
|
|
|
3390
3430
|
if (ghConnected) {
|
|
3391
3431
|
console.log(`GitHub is connected (${ghLogin || "linked via dashboard"}).`);
|
|
3392
3432
|
}
|
|
3393
|
-
const
|
|
3433
|
+
const prScanChoice = opts.nonInteractive ? opts.prScan ?? "skip" : null;
|
|
3434
|
+
const setupGh = prScanChoice !== null ? prScanChoice !== "skip" : await promptYesNo("Set up GitHub PR scanning?");
|
|
3394
3435
|
if (setupGh) {
|
|
3395
|
-
let
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
});
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3436
|
+
let choice;
|
|
3437
|
+
if (prScanChoice) {
|
|
3438
|
+
choice = prScanChoice === "claude-oauth" ? "1" : prScanChoice === "byok" ? "2" : "3";
|
|
3439
|
+
} else {
|
|
3440
|
+
const rl = createInterface3({ input: stdinStream, output: stdoutStream });
|
|
3441
|
+
console.log("\nHow should PR scans authenticate for AI review?\n");
|
|
3442
|
+
console.log(" 1. Claude Code OAuth \u2014 opens browser, auto-captures token");
|
|
3443
|
+
console.log(" 2. Use your own API key \u2014 paste an Anthropic, OpenAI, or Gemini key");
|
|
3444
|
+
console.log(" 3. Skip for now\n");
|
|
3445
|
+
choice = (await rl.question("Choice [1/2/3]: ")).trim();
|
|
3446
|
+
rl.close();
|
|
3405
3447
|
}
|
|
3406
|
-
const rl = createInterface3({ input: stdinStream, output: stdoutStream });
|
|
3407
|
-
console.log("\nHow should PR scans authenticate for AI review?\n");
|
|
3408
|
-
console.log(" 1. Claude Code OAuth \u2014 opens browser, auto-captures token");
|
|
3409
|
-
console.log(" 2. Use your own API key \u2014 paste an Anthropic, OpenAI, or Gemini key");
|
|
3410
|
-
console.log(" 3. Skip for now\n");
|
|
3411
|
-
const choice = (await rl.question("Choice [1/2/3]: ")).trim();
|
|
3412
|
-
rl.close();
|
|
3413
3448
|
if (choice === "1") {
|
|
3414
3449
|
try {
|
|
3415
|
-
await setupGithubCommand();
|
|
3450
|
+
await setupGithubCommand({ githubToken: opts.githubToken });
|
|
3416
3451
|
} catch (err) {
|
|
3417
3452
|
console.warn(` \u26A0 GitHub setup failed: ${err.message}`);
|
|
3418
3453
|
console.warn(" Run `synkro-cli setup-github` to retry.\n");
|
|
3419
3454
|
}
|
|
3420
3455
|
} else if (choice === "2") {
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3456
|
+
let apiKey = opts.inferenceKey || "";
|
|
3457
|
+
if (!apiKey) {
|
|
3458
|
+
const rl2 = createInterface3({ input: stdinStream, output: stdoutStream });
|
|
3459
|
+
apiKey = (await rl2.question("Paste your API key: ")).trim();
|
|
3460
|
+
rl2.close();
|
|
3461
|
+
}
|
|
3424
3462
|
if (apiKey) {
|
|
3425
3463
|
const provider = detectProviderFromKey(apiKey);
|
|
3426
3464
|
if (provider) {
|
|
3427
|
-
|
|
3428
|
-
|
|
3465
|
+
let selectedModel = opts.inferenceModel || "";
|
|
3466
|
+
if (!selectedModel) {
|
|
3467
|
+
const models = PROVIDER_MODELS[provider];
|
|
3468
|
+
console.log(`
|
|
3429
3469
|
Detected provider: ${provider}`);
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3470
|
+
console.log(" Select a model for classification + grading:\n");
|
|
3471
|
+
models.forEach((m, i) => console.log(` ${i + 1}. ${m}`));
|
|
3472
|
+
console.log();
|
|
3473
|
+
const rl3 = createInterface3({ input: stdinStream, output: stdoutStream });
|
|
3474
|
+
const modelChoice = (await rl3.question(` Model [1-${models.length}]: `)).trim();
|
|
3475
|
+
rl3.close();
|
|
3476
|
+
const modelIdx = parseInt(modelChoice, 10) - 1;
|
|
3477
|
+
selectedModel = modelIdx >= 0 && modelIdx < models.length ? models[modelIdx] : models[0];
|
|
3478
|
+
}
|
|
3438
3479
|
console.log(` Using: ${selectedModel}`);
|
|
3439
3480
|
try {
|
|
3440
3481
|
const resp = await fetch(`${gatewayUrl}/api/v1/settings/inference`, {
|
|
@@ -3468,7 +3509,7 @@ async function installCommand(opts = {}) {
|
|
|
3468
3509
|
}
|
|
3469
3510
|
}
|
|
3470
3511
|
try {
|
|
3471
|
-
await setupGithubCommand({ skipClaudeToken: true });
|
|
3512
|
+
await setupGithubCommand({ skipClaudeToken: true, githubToken: opts.githubToken });
|
|
3472
3513
|
} catch (err) {
|
|
3473
3514
|
console.warn(` \u26A0 GitHub setup failed: ${err.message}`);
|
|
3474
3515
|
console.warn(" Run `synkro-cli setup-github` to retry.\n");
|
|
@@ -4488,7 +4529,16 @@ Usage:
|
|
|
4488
4529
|
synkro <command> [options] (alias)
|
|
4489
4530
|
|
|
4490
4531
|
Commands:
|
|
4491
|
-
install [
|
|
4532
|
+
install [options] Install Synkro hooks for detected agents (Claude Code, etc.)
|
|
4533
|
+
--force Reinstall from scratch
|
|
4534
|
+
--non-interactive Skip all interactive prompts (use flags)
|
|
4535
|
+
--link-repo Auto-link the local git repo
|
|
4536
|
+
--sync-transcripts Sync CC session history (default in non-interactive)
|
|
4537
|
+
--no-sync-transcripts Skip transcript sync
|
|
4538
|
+
--pr-scan=MODE PR scan auth: claude-oauth, byok, or skip
|
|
4539
|
+
--inference-key=KEY BYOK API key (Anthropic, OpenAI, or Gemini)
|
|
4540
|
+
--inference-model=M Model for classification + grading
|
|
4541
|
+
--github-token=TOK GitHub PAT for pushing secrets + workflow
|
|
4492
4542
|
login Authenticate with Synkro (browser OAuth via WorkOS)
|
|
4493
4543
|
logout Clear local credentials
|
|
4494
4544
|
status Show current setup state
|