@keywaysh/cli 0.1.13 → 0.1.14

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.
Files changed (3) hide show
  1. package/README.md +19 -0
  2. package/dist/cli.js +298 -254
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -8,11 +8,11 @@ import {
8
8
 
9
9
  // src/cli.ts
10
10
  import { Command } from "commander";
11
- import pc11 from "picocolors";
11
+ import pc12 from "picocolors";
12
12
 
13
13
  // src/cmds/init.ts
14
- import pc6 from "picocolors";
15
- import prompts5 from "prompts";
14
+ import pc7 from "picocolors";
15
+ import prompts6 from "prompts";
16
16
 
17
17
  // src/utils/git.ts
18
18
  import { execSync } from "child_process";
@@ -140,7 +140,7 @@ var INTERNAL_POSTHOG_HOST = "https://eu.i.posthog.com";
140
140
  // package.json
141
141
  var package_default = {
142
142
  name: "@keywaysh/cli",
143
- version: "0.1.13",
143
+ version: "0.1.14",
144
144
  description: "One link to all your secrets",
145
145
  type: "module",
146
146
  bin: {
@@ -900,10 +900,10 @@ async function addBadgeToReadme(silent = false) {
900
900
  }
901
901
 
902
902
  // src/cmds/push.ts
903
- import pc5 from "picocolors";
904
- import fs4 from "fs";
905
- import path4 from "path";
906
- import prompts4 from "prompts";
903
+ import pc6 from "picocolors";
904
+ import fs5 from "fs";
905
+ import path5 from "path";
906
+ import prompts5 from "prompts";
907
907
 
908
908
  // src/cmds/login.ts
909
909
  import pc4 from "picocolors";
@@ -1112,9 +1112,34 @@ async function logoutCommand() {
1112
1112
  console.log(pc4.gray(`Auth cache cleared: ${getAuthFilePath()}`));
1113
1113
  }
1114
1114
 
1115
+ // src/utils/env.ts
1116
+ import fs4 from "fs";
1117
+ import path4 from "path";
1118
+ import pc5 from "picocolors";
1119
+ import prompts4 from "prompts";
1120
+ async function promptCreateEnvFile() {
1121
+ const { createEnv } = await prompts4({
1122
+ type: "confirm",
1123
+ name: "createEnv",
1124
+ message: "No .env file found. Create one?",
1125
+ initial: true
1126
+ }, {
1127
+ onCancel: () => {
1128
+ throw new Error("Cancelled by user.");
1129
+ }
1130
+ });
1131
+ if (!createEnv) {
1132
+ return false;
1133
+ }
1134
+ const envFilePath = path4.join(process.cwd(), ".env");
1135
+ fs4.writeFileSync(envFilePath, "# Add your environment variables here\n# Example: API_KEY=your-api-key\n");
1136
+ console.log(pc5.green("\u2713 Created .env file"));
1137
+ return true;
1138
+ }
1139
+
1115
1140
  // src/cmds/push.ts
1116
1141
  function deriveEnvFromFile(file) {
1117
- const base = path4.basename(file);
1142
+ const base = path5.basename(file);
1118
1143
  const match = base.match(/\.env(?:\.(.+))?$/);
1119
1144
  if (match) {
1120
1145
  return match[1] || "development";
@@ -1123,15 +1148,15 @@ function deriveEnvFromFile(file) {
1123
1148
  }
1124
1149
  function discoverEnvCandidates(cwd) {
1125
1150
  try {
1126
- const entries = fs4.readdirSync(cwd);
1151
+ const entries = fs5.readdirSync(cwd);
1127
1152
  const hasEnvLocal = entries.includes(".env.local");
1128
1153
  if (hasEnvLocal) {
1129
- console.log(pc5.gray("\u2139\uFE0F Detected .env.local \u2014 not synced by design (machine-specific secrets)"));
1154
+ console.log(pc6.gray("\u2139\uFE0F Detected .env.local \u2014 not synced by design (machine-specific secrets)"));
1130
1155
  }
1131
1156
  const candidates = entries.filter((name) => name.startsWith(".env") && name !== ".env.local").map((name) => {
1132
- const fullPath = path4.join(cwd, name);
1157
+ const fullPath = path5.join(cwd, name);
1133
1158
  try {
1134
- const stat = fs4.statSync(fullPath);
1159
+ const stat = fs5.statSync(fullPath);
1135
1160
  if (!stat.isFile()) return null;
1136
1161
  return { file: name, env: deriveEnvFromFile(name) };
1137
1162
  } catch {
@@ -1152,13 +1177,21 @@ function discoverEnvCandidates(cwd) {
1152
1177
  }
1153
1178
  async function pushCommand(options) {
1154
1179
  try {
1155
- console.log(pc5.blue("\u{1F510} Pushing secrets to Keyway...\n"));
1180
+ console.log(pc6.blue("\u{1F510} Pushing secrets to Keyway...\n"));
1156
1181
  const isInteractive2 = process.stdin.isTTY && process.stdout.isTTY;
1157
1182
  let environment = options.env;
1158
1183
  let envFile = options.file;
1159
1184
  const candidates = discoverEnvCandidates(process.cwd());
1160
1185
  if (candidates.length === 0 && !envFile) {
1161
- throw new Error("No .env file found. Create a .env file first, or use --file <path> to specify one.");
1186
+ if (!isInteractive2) {
1187
+ throw new Error("No .env file found. Create a .env file first, or use --file <path> to specify one.");
1188
+ }
1189
+ const created = await promptCreateEnvFile();
1190
+ if (!created) {
1191
+ throw new Error("No .env file found.");
1192
+ }
1193
+ console.log(pc6.gray(" Add your variables and run keyway push again\n"));
1194
+ return;
1162
1195
  }
1163
1196
  if (environment && !envFile) {
1164
1197
  const match = candidates.find((c) => c.env === environment);
@@ -1167,7 +1200,7 @@ async function pushCommand(options) {
1167
1200
  }
1168
1201
  }
1169
1202
  if (!environment && !envFile && isInteractive2 && candidates.length > 0) {
1170
- const { choice } = await prompts4(
1203
+ const { choice } = await prompts5(
1171
1204
  {
1172
1205
  type: "select",
1173
1206
  name: "choice",
@@ -1190,15 +1223,15 @@ async function pushCommand(options) {
1190
1223
  envFile = choice.file;
1191
1224
  environment = choice.env;
1192
1225
  } else if (choice === "custom") {
1193
- const { fileInput } = await prompts4(
1226
+ const { fileInput } = await prompts5(
1194
1227
  {
1195
1228
  type: "text",
1196
1229
  name: "fileInput",
1197
1230
  message: "Path to env file:",
1198
1231
  validate: (value) => {
1199
1232
  if (!value) return "Path is required";
1200
- const resolved = path4.resolve(process.cwd(), value);
1201
- if (!fs4.existsSync(resolved)) return `File not found: ${value}`;
1233
+ const resolved = path5.resolve(process.cwd(), value);
1234
+ if (!fs5.existsSync(resolved)) return `File not found: ${value}`;
1202
1235
  return true;
1203
1236
  }
1204
1237
  },
@@ -1218,11 +1251,11 @@ async function pushCommand(options) {
1218
1251
  if (!envFile) {
1219
1252
  envFile = ".env";
1220
1253
  }
1221
- const envFilePath = path4.resolve(process.cwd(), envFile);
1222
- if (!fs4.existsSync(envFilePath)) {
1254
+ const envFilePath = path5.resolve(process.cwd(), envFile);
1255
+ if (!fs5.existsSync(envFilePath)) {
1223
1256
  throw new Error(`File not found: ${envFile}`);
1224
1257
  }
1225
- const content = fs4.readFileSync(envFilePath, "utf-8");
1258
+ const content = fs5.readFileSync(envFilePath, "utf-8");
1226
1259
  if (content.trim().length === 0) {
1227
1260
  throw new Error(`File is empty: ${envFile}`);
1228
1261
  }
@@ -1230,17 +1263,17 @@ async function pushCommand(options) {
1230
1263
  const trimmed = line.trim();
1231
1264
  return trimmed.length > 0 && !trimmed.startsWith("#");
1232
1265
  });
1233
- console.log(`File: ${pc5.cyan(envFile)}`);
1234
- console.log(`Environment: ${pc5.cyan(environment)}`);
1235
- console.log(`Variables: ${pc5.cyan(lines.length.toString())}`);
1266
+ console.log(`File: ${pc6.cyan(envFile)}`);
1267
+ console.log(`Environment: ${pc6.cyan(environment)}`);
1268
+ console.log(`Variables: ${pc6.cyan(lines.length.toString())}`);
1236
1269
  const repoFullName = getCurrentRepoFullName();
1237
- console.log(`Repository: ${pc5.cyan(repoFullName)}`);
1270
+ console.log(`Repository: ${pc6.cyan(repoFullName)}`);
1238
1271
  if (!options.yes) {
1239
1272
  const isInteractive3 = process.stdin.isTTY && process.stdout.isTTY;
1240
1273
  if (!isInteractive3) {
1241
1274
  throw new Error("Confirmation required. Re-run with --yes in non-interactive environments.");
1242
1275
  }
1243
- const { confirm } = await prompts4(
1276
+ const { confirm } = await prompts5(
1244
1277
  {
1245
1278
  type: "confirm",
1246
1279
  name: "confirm",
@@ -1254,7 +1287,7 @@ async function pushCommand(options) {
1254
1287
  }
1255
1288
  );
1256
1289
  if (!confirm) {
1257
- console.log(pc5.yellow("Push aborted."));
1290
+ console.log(pc6.yellow("Push aborted."));
1258
1291
  return;
1259
1292
  }
1260
1293
  }
@@ -1266,13 +1299,13 @@ async function pushCommand(options) {
1266
1299
  });
1267
1300
  console.log("\nUploading secrets...");
1268
1301
  const response = await pushSecrets(repoFullName, environment, content, accessToken);
1269
- console.log(pc5.green("\n\u2713 " + response.message));
1302
+ console.log(pc6.green("\n\u2713 " + response.message));
1270
1303
  if (response.stats) {
1271
1304
  const { created, updated, deleted } = response.stats;
1272
1305
  const parts = [];
1273
- if (created > 0) parts.push(pc5.green(`+${created} created`));
1274
- if (updated > 0) parts.push(pc5.yellow(`~${updated} updated`));
1275
- if (deleted > 0) parts.push(pc5.red(`-${deleted} deleted`));
1306
+ if (created > 0) parts.push(pc6.green(`+${created} created`));
1307
+ if (updated > 0) parts.push(pc6.yellow(`~${updated} updated`));
1308
+ if (deleted > 0) parts.push(pc6.red(`-${deleted} deleted`));
1276
1309
  if (parts.length > 0) {
1277
1310
  console.log(`Stats: ${parts.join(", ")}`);
1278
1311
  }
@@ -1281,7 +1314,7 @@ async function pushCommand(options) {
1281
1314
  Your secrets are now encrypted and stored securely.`);
1282
1315
  const dashboardLink = `https://www.keyway.sh/dashboard/vaults/${repoFullName}`;
1283
1316
  console.log(`
1284
- ${pc5.blue("\u2394")} Dashboard: ${pc5.underline(dashboardLink)}`);
1317
+ ${pc6.blue("\u2394")} Dashboard: ${pc6.underline(dashboardLink)}`);
1285
1318
  await shutdownAnalytics();
1286
1319
  } catch (error) {
1287
1320
  let message;
@@ -1294,7 +1327,7 @@ ${pc5.blue("\u2394")} Dashboard: ${pc5.underline(dashboardLink)}`);
1294
1327
  const availableEnvs = envNotFoundMatch[2];
1295
1328
  message = `Environment '${requestedEnv}' does not exist in this vault.`;
1296
1329
  hint = `Available environments: ${availableEnvs}
1297
- Use ${pc5.cyan(`keyway push --env <environment>`)} to specify one, or create '${requestedEnv}' via the dashboard.`;
1330
+ Use ${pc6.cyan(`keyway push --env <environment>`)} to specify one, or create '${requestedEnv}' via the dashboard.`;
1298
1331
  }
1299
1332
  if (error.statusCode === 403 && (error.upgradeUrl || message.toLowerCase().includes("read-only"))) {
1300
1333
  const upgradeMessage = message.toLowerCase().includes("read-only") ? "This vault is read-only on your current plan." : message;
@@ -1317,10 +1350,10 @@ Use ${pc5.cyan(`keyway push --env <environment>`)} to specify one, or create '${
1317
1350
  error: message
1318
1351
  });
1319
1352
  await shutdownAnalytics();
1320
- console.error(pc5.red(`
1353
+ console.error(pc6.red(`
1321
1354
  \u2717 ${message}`));
1322
1355
  if (hint) {
1323
- console.error(pc5.gray(`
1356
+ console.error(pc6.gray(`
1324
1357
  ${hint}`));
1325
1358
  }
1326
1359
  process.exit(1);
@@ -1355,7 +1388,7 @@ async function ensureLoginAndGitHubApp(repoFullName, options = {}) {
1355
1388
  const deviceStart = await startDeviceLogin(repoFullName);
1356
1389
  const installUrl = deviceStart.githubAppInstallUrl || "https://github.com/apps/keyway/installations/new";
1357
1390
  console.log("");
1358
- const { shouldProceed } = await prompts5({
1391
+ const { shouldProceed } = await prompts6({
1359
1392
  type: "confirm",
1360
1393
  name: "shouldProceed",
1361
1394
  message: "Open browser to sign in?",
@@ -1365,8 +1398,8 @@ async function ensureLoginAndGitHubApp(repoFullName, options = {}) {
1365
1398
  throw new Error('Setup required. Run "keyway init" when ready.');
1366
1399
  }
1367
1400
  await openUrl(deviceStart.verificationUriComplete);
1368
- console.log(pc6.blue("\u23F3 Waiting for authorization..."));
1369
- console.log(pc6.gray(" (Press Ctrl+C to cancel)\n"));
1401
+ console.log(pc7.blue("\u23F3 Waiting for authorization..."));
1402
+ console.log(pc7.gray(" (Press Ctrl+C to cancel)\n"));
1370
1403
  const pollIntervalMs = Math.max((deviceStart.interval ?? 5) * 1e3, POLL_INTERVAL_MS);
1371
1404
  const startTime = Date.now();
1372
1405
  let accessToken = null;
@@ -1381,7 +1414,7 @@ async function ensureLoginAndGitHubApp(repoFullName, options = {}) {
1381
1414
  githubLogin: result.githubLogin,
1382
1415
  expiresAt: result.expiresAt
1383
1416
  });
1384
- console.log(pc6.green("\u2713 Signed in!"));
1417
+ console.log(pc7.green("\u2713 Signed in!"));
1385
1418
  if (result.githubLogin) {
1386
1419
  identifyUser(result.githubLogin, {
1387
1420
  github_username: result.githubLogin,
@@ -1391,7 +1424,7 @@ async function ensureLoginAndGitHubApp(repoFullName, options = {}) {
1391
1424
  break;
1392
1425
  }
1393
1426
  consecutiveErrors = 0;
1394
- process.stdout.write(pc6.gray("."));
1427
+ process.stdout.write(pc7.gray("."));
1395
1428
  } catch (error) {
1396
1429
  consecutiveErrors++;
1397
1430
  if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
@@ -1402,35 +1435,35 @@ async function ensureLoginAndGitHubApp(repoFullName, options = {}) {
1402
1435
  }
1403
1436
  if (!accessToken) {
1404
1437
  console.log("");
1405
- console.log(pc6.yellow("\u26A0 Timed out waiting for sign in."));
1438
+ console.log(pc7.yellow("\u26A0 Timed out waiting for sign in."));
1406
1439
  throw new Error("Sign in timed out. Please try again.");
1407
1440
  }
1408
1441
  const installStatus = await checkGitHubAppInstallation(repoOwner, repoName, accessToken);
1409
1442
  if (installStatus.installed) {
1410
- console.log(pc6.green("\u2713 GitHub App installed"));
1443
+ console.log(pc7.green("\u2713 GitHub App installed"));
1411
1444
  console.log("");
1412
1445
  return accessToken;
1413
1446
  }
1414
1447
  console.log("");
1415
- console.log(pc6.yellow("\u26A0 GitHub App not installed on this repository"));
1416
- console.log(pc6.gray(" The Keyway GitHub App is required for secure access."));
1448
+ console.log(pc7.yellow("\u26A0 GitHub App not installed on this repository"));
1449
+ console.log(pc7.gray(" The Keyway GitHub App is required for secure access."));
1417
1450
  console.log("");
1418
- const { shouldInstall } = await prompts5({
1451
+ const { shouldInstall } = await prompts6({
1419
1452
  type: "confirm",
1420
1453
  name: "shouldInstall",
1421
1454
  message: "Open browser to install GitHub App?",
1422
1455
  initial: true
1423
1456
  });
1424
1457
  if (!shouldInstall) {
1425
- console.log(pc6.gray(`
1458
+ console.log(pc7.gray(`
1426
1459
  Install later: ${installUrl}`));
1427
1460
  throw new Error("GitHub App installation required.");
1428
1461
  }
1429
1462
  await openUrl(installUrl);
1430
- console.log(pc6.blue("\u23F3 Waiting for GitHub App installation..."));
1431
- console.log(pc6.gray(' Add this repository and click "Install"'));
1432
- console.log(pc6.gray(" Then return here - the CLI will detect it automatically"));
1433
- console.log(pc6.gray(" (Press Ctrl+C to cancel)\n"));
1463
+ console.log(pc7.blue("\u23F3 Waiting for GitHub App installation..."));
1464
+ console.log(pc7.gray(' Add this repository and click "Install"'));
1465
+ console.log(pc7.gray(" Then return here - the CLI will detect it automatically"));
1466
+ console.log(pc7.gray(" (Press Ctrl+C to cancel)\n"));
1434
1467
  const installStartTime = Date.now();
1435
1468
  consecutiveErrors = 0;
1436
1469
  while (Date.now() - installStartTime < POLL_TIMEOUT_MS) {
@@ -1438,12 +1471,12 @@ async function ensureLoginAndGitHubApp(repoFullName, options = {}) {
1438
1471
  try {
1439
1472
  const pollStatus = await checkGitHubAppInstallation(repoOwner, repoName, accessToken);
1440
1473
  if (pollStatus.installed) {
1441
- console.log(pc6.green("\u2713 GitHub App installed!"));
1474
+ console.log(pc7.green("\u2713 GitHub App installed!"));
1442
1475
  console.log("");
1443
1476
  return accessToken;
1444
1477
  }
1445
1478
  consecutiveErrors = 0;
1446
- process.stdout.write(pc6.gray("."));
1479
+ process.stdout.write(pc7.gray("."));
1447
1480
  } catch (error) {
1448
1481
  consecutiveErrors++;
1449
1482
  if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
@@ -1453,8 +1486,8 @@ async function ensureLoginAndGitHubApp(repoFullName, options = {}) {
1453
1486
  }
1454
1487
  }
1455
1488
  console.log("");
1456
- console.log(pc6.yellow("\u26A0 Timed out waiting for installation."));
1457
- console.log(pc6.gray(` Install the GitHub App: ${installUrl}`));
1489
+ console.log(pc7.yellow("\u26A0 Timed out waiting for installation."));
1490
+ console.log(pc7.gray(` Install the GitHub App: ${installUrl}`));
1458
1491
  throw new Error("GitHub App installation timed out.");
1459
1492
  }
1460
1493
  async function ensureGitHubAppInstalledOnly(repoFullName, accessToken) {
@@ -1464,7 +1497,7 @@ async function ensureGitHubAppInstalledOnly(repoFullName, accessToken) {
1464
1497
  status = await checkGitHubAppInstallation(repoOwner, repoName, accessToken);
1465
1498
  } catch (error) {
1466
1499
  if (error instanceof APIError && error.statusCode === 401) {
1467
- console.log(pc6.yellow("\n\u26A0 Session expired or invalid. Clearing credentials..."));
1500
+ console.log(pc7.yellow("\n\u26A0 Session expired or invalid. Clearing credentials..."));
1468
1501
  const { clearAuth: clearAuth2 } = await import("./auth-QLPQ24HZ.js");
1469
1502
  clearAuth2();
1470
1503
  return null;
@@ -1475,29 +1508,29 @@ async function ensureGitHubAppInstalledOnly(repoFullName, accessToken) {
1475
1508
  return accessToken;
1476
1509
  }
1477
1510
  console.log("");
1478
- console.log(pc6.yellow("\u26A0 GitHub App not installed for this repository"));
1511
+ console.log(pc7.yellow("\u26A0 GitHub App not installed for this repository"));
1479
1512
  console.log("");
1480
- console.log(pc6.gray(" The Keyway GitHub App is required to securely manage secrets."));
1481
- console.log(pc6.gray(" It only requests minimal permissions (repository metadata)."));
1513
+ console.log(pc7.gray(" The Keyway GitHub App is required to securely manage secrets."));
1514
+ console.log(pc7.gray(" It only requests minimal permissions (repository metadata)."));
1482
1515
  console.log("");
1483
1516
  if (!isInteractive()) {
1484
- console.log(pc6.gray(` Install the Keyway GitHub App: ${status.installUrl}`));
1517
+ console.log(pc7.gray(` Install the Keyway GitHub App: ${status.installUrl}`));
1485
1518
  throw new Error("GitHub App installation required.");
1486
1519
  }
1487
- const { shouldInstall } = await prompts5({
1520
+ const { shouldInstall } = await prompts6({
1488
1521
  type: "confirm",
1489
1522
  name: "shouldInstall",
1490
1523
  message: "Open browser to install Keyway GitHub App?",
1491
1524
  initial: true
1492
1525
  });
1493
1526
  if (!shouldInstall) {
1494
- console.log(pc6.gray(`
1527
+ console.log(pc7.gray(`
1495
1528
  You can install later: ${status.installUrl}`));
1496
1529
  throw new Error("GitHub App installation required.");
1497
1530
  }
1498
1531
  await openUrl(status.installUrl);
1499
- console.log(pc6.blue("\u23F3 Waiting for GitHub App installation..."));
1500
- console.log(pc6.gray(" (Press Ctrl+C to cancel)\n"));
1532
+ console.log(pc7.blue("\u23F3 Waiting for GitHub App installation..."));
1533
+ console.log(pc7.gray(" (Press Ctrl+C to cancel)\n"));
1501
1534
  const startTime = Date.now();
1502
1535
  let consecutiveErrors = 0;
1503
1536
  while (Date.now() - startTime < POLL_TIMEOUT_MS) {
@@ -1505,12 +1538,12 @@ async function ensureGitHubAppInstalledOnly(repoFullName, accessToken) {
1505
1538
  try {
1506
1539
  const pollStatus = await checkGitHubAppInstallation(repoOwner, repoName, accessToken);
1507
1540
  if (pollStatus.installed) {
1508
- console.log(pc6.green("\u2713 GitHub App installed!"));
1541
+ console.log(pc7.green("\u2713 GitHub App installed!"));
1509
1542
  console.log("");
1510
1543
  return accessToken;
1511
1544
  }
1512
1545
  consecutiveErrors = 0;
1513
- process.stdout.write(pc6.gray("."));
1546
+ process.stdout.write(pc7.gray("."));
1514
1547
  } catch (error) {
1515
1548
  consecutiveErrors++;
1516
1549
  if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
@@ -1520,35 +1553,35 @@ async function ensureGitHubAppInstalledOnly(repoFullName, accessToken) {
1520
1553
  }
1521
1554
  }
1522
1555
  console.log("");
1523
- console.log(pc6.yellow("\u26A0 Timed out waiting for installation."));
1524
- console.log(pc6.gray(` You can install the GitHub App later: ${status.installUrl}`));
1556
+ console.log(pc7.yellow("\u26A0 Timed out waiting for installation."));
1557
+ console.log(pc7.gray(` You can install the GitHub App later: ${status.installUrl}`));
1525
1558
  throw new Error("GitHub App installation timed out.");
1526
1559
  }
1527
1560
  async function initCommand(options = {}) {
1528
1561
  try {
1529
1562
  const repoFullName = getCurrentRepoFullName();
1530
1563
  const dashboardLink = `${DASHBOARD_URL}/${repoFullName}`;
1531
- console.log(pc6.blue("\u{1F510} Initializing Keyway vault...\n"));
1532
- console.log(` ${pc6.gray("Repository:")} ${pc6.white(repoFullName)}`);
1564
+ console.log(pc7.blue("\u{1F510} Initializing Keyway vault...\n"));
1565
+ console.log(` ${pc7.gray("Repository:")} ${pc7.white(repoFullName)}`);
1533
1566
  const accessToken = await ensureLoginAndGitHubApp(repoFullName, {
1534
1567
  allowPrompt: options.loginPrompt !== false
1535
1568
  });
1536
1569
  trackEvent(AnalyticsEvents.CLI_INIT, { repoFullName, githubAppInstalled: true });
1537
1570
  const vaultExists = await checkVaultExists(accessToken, repoFullName);
1538
1571
  if (vaultExists) {
1539
- console.log(pc6.green("\n\u2713 Already initialized!\n"));
1540
- console.log(` ${pc6.yellow("\u2192")} Run ${pc6.cyan("keyway push")} to sync your secrets`);
1541
- console.log(` ${pc6.blue("\u2394")} Dashboard: ${pc6.underline(dashboardLink)}`);
1572
+ console.log(pc7.green("\n\u2713 Already initialized!\n"));
1573
+ console.log(` ${pc7.yellow("\u2192")} Run ${pc7.cyan("keyway push")} to sync your secrets`);
1574
+ console.log(` ${pc7.blue("\u2394")} Dashboard: ${pc7.underline(dashboardLink)}`);
1542
1575
  console.log("");
1543
1576
  await shutdownAnalytics();
1544
1577
  return;
1545
1578
  }
1546
1579
  await initVault(repoFullName, accessToken);
1547
- console.log(pc6.green("\u2713 Vault created!"));
1580
+ console.log(pc7.green("\u2713 Vault created!"));
1548
1581
  try {
1549
1582
  const badgeAdded = await addBadgeToReadme(true);
1550
1583
  if (badgeAdded) {
1551
- console.log(pc6.green("\u2713 Badge added to README.md"));
1584
+ console.log(pc7.green("\u2713 Badge added to README.md"));
1552
1585
  }
1553
1586
  } catch {
1554
1587
  }
@@ -1556,9 +1589,9 @@ async function initCommand(options = {}) {
1556
1589
  const envCandidates = discoverEnvCandidates(process.cwd());
1557
1590
  const isInteractive2 = process.stdin.isTTY && process.stdout.isTTY;
1558
1591
  if (envCandidates.length > 0 && isInteractive2) {
1559
- console.log(pc6.gray(` Found ${envCandidates.length} env file(s): ${envCandidates.map((c) => c.file).join(", ")}
1592
+ console.log(pc7.gray(` Found ${envCandidates.length} env file(s): ${envCandidates.map((c) => c.file).join(", ")}
1560
1593
  `));
1561
- const { shouldPush } = await prompts5({
1594
+ const { shouldPush } = await prompts6({
1562
1595
  type: "confirm",
1563
1596
  name: "shouldPush",
1564
1597
  message: "Push secrets now?",
@@ -1570,25 +1603,36 @@ async function initCommand(options = {}) {
1570
1603
  return;
1571
1604
  }
1572
1605
  }
1573
- console.log(pc6.dim("\u2500".repeat(50)));
1606
+ console.log(pc7.dim("\u2500".repeat(50)));
1574
1607
  console.log("");
1575
1608
  if (envCandidates.length === 0) {
1576
- console.log(`${pc6.yellow("\u26A0")} No .env file found - your vault is empty`);
1577
- console.log(` Next: Create ${pc6.cyan(".env")} and run ${pc6.cyan("keyway push")}
1609
+ if (isInteractive2) {
1610
+ const created = await promptCreateEnvFile();
1611
+ if (created) {
1612
+ console.log(` Add your variables and run ${pc7.cyan("keyway push")}
1578
1613
  `);
1614
+ } else {
1615
+ console.log(` Next: Create ${pc7.cyan(".env")} and run ${pc7.cyan("keyway push")}
1616
+ `);
1617
+ }
1618
+ } else {
1619
+ console.log(`${pc7.yellow("\u26A0")} No .env file found - your vault is empty`);
1620
+ console.log(` Next: Create ${pc7.cyan(".env")} and run ${pc7.cyan("keyway push")}
1621
+ `);
1622
+ }
1579
1623
  } else {
1580
- console.log(` ${pc6.yellow("\u2192")} Run ${pc6.cyan("keyway push")} to sync your secrets
1624
+ console.log(` ${pc7.yellow("\u2192")} Run ${pc7.cyan("keyway push")} to sync your secrets
1581
1625
  `);
1582
1626
  }
1583
- console.log(` ${pc6.blue("\u2394")} Dashboard: ${pc6.underline(dashboardLink)}`);
1627
+ console.log(` ${pc7.blue("\u2394")} Dashboard: ${pc7.underline(dashboardLink)}`);
1584
1628
  console.log("");
1585
1629
  await shutdownAnalytics();
1586
1630
  } catch (error) {
1587
1631
  if (error instanceof APIError) {
1588
1632
  if (error.statusCode === 409) {
1589
- console.log(pc6.green("\n\u2713 Already initialized!\n"));
1590
- console.log(` ${pc6.yellow("\u2192")} Run ${pc6.cyan("keyway push")} to sync your secrets`);
1591
- console.log(` ${pc6.blue("\u2394")} Dashboard: ${pc6.underline(`${DASHBOARD_URL}/${getCurrentRepoFullName()}`)}`);
1633
+ console.log(pc7.green("\n\u2713 Already initialized!\n"));
1634
+ console.log(` ${pc7.yellow("\u2192")} Run ${pc7.cyan("keyway push")} to sync your secrets`);
1635
+ console.log(` ${pc7.blue("\u2394")} Dashboard: ${pc7.underline(`${DASHBOARD_URL}/${getCurrentRepoFullName()}`)}`);
1592
1636
  console.log("");
1593
1637
  await shutdownAnalytics();
1594
1638
  return;
@@ -1606,25 +1650,25 @@ async function initCommand(options = {}) {
1606
1650
  error: message
1607
1651
  });
1608
1652
  await shutdownAnalytics();
1609
- console.error(pc6.red(`
1653
+ console.error(pc7.red(`
1610
1654
  \u2717 ${message}`));
1611
1655
  process.exit(1);
1612
1656
  }
1613
1657
  }
1614
1658
 
1615
1659
  // src/cmds/pull.ts
1616
- import pc7 from "picocolors";
1617
- import fs5 from "fs";
1618
- import path5 from "path";
1619
- import prompts6 from "prompts";
1660
+ import pc8 from "picocolors";
1661
+ import fs6 from "fs";
1662
+ import path6 from "path";
1663
+ import prompts7 from "prompts";
1620
1664
  async function pullCommand(options) {
1621
1665
  try {
1622
1666
  const environment = options.env || "development";
1623
1667
  const envFile = options.file || ".env";
1624
- console.log(pc7.blue("\u{1F510} Pulling secrets from Keyway...\n"));
1625
- console.log(`Environment: ${pc7.cyan(environment)}`);
1668
+ console.log(pc8.blue("\u{1F510} Pulling secrets from Keyway...\n"));
1669
+ console.log(`Environment: ${pc8.cyan(environment)}`);
1626
1670
  const repoFullName = getCurrentRepoFullName();
1627
- console.log(`Repository: ${pc7.cyan(repoFullName)}`);
1671
+ console.log(`Repository: ${pc8.cyan(repoFullName)}`);
1628
1672
  const accessToken = await ensureLogin({ allowPrompt: options.loginPrompt !== false });
1629
1673
  trackEvent(AnalyticsEvents.CLI_PULL, {
1630
1674
  repoFullName,
@@ -1632,16 +1676,16 @@ async function pullCommand(options) {
1632
1676
  });
1633
1677
  console.log("\nDownloading secrets...");
1634
1678
  const response = await pullSecrets(repoFullName, environment, accessToken);
1635
- const envFilePath = path5.resolve(process.cwd(), envFile);
1636
- if (fs5.existsSync(envFilePath)) {
1679
+ const envFilePath = path6.resolve(process.cwd(), envFile);
1680
+ if (fs6.existsSync(envFilePath)) {
1637
1681
  const isInteractive2 = process.stdin.isTTY && process.stdout.isTTY;
1638
1682
  if (options.yes) {
1639
- console.log(pc7.yellow(`
1683
+ console.log(pc8.yellow(`
1640
1684
  \u26A0 Overwriting existing file: ${envFile}`));
1641
1685
  } else if (!isInteractive2) {
1642
1686
  throw new Error(`File ${envFile} exists. Re-run with --yes to overwrite or choose a different --file.`);
1643
1687
  } else {
1644
- const { confirm } = await prompts6(
1688
+ const { confirm } = await prompts7(
1645
1689
  {
1646
1690
  type: "confirm",
1647
1691
  name: "confirm",
@@ -1655,21 +1699,21 @@ async function pullCommand(options) {
1655
1699
  }
1656
1700
  );
1657
1701
  if (!confirm) {
1658
- console.log(pc7.yellow("Pull aborted."));
1702
+ console.log(pc8.yellow("Pull aborted."));
1659
1703
  return;
1660
1704
  }
1661
1705
  }
1662
1706
  }
1663
- fs5.writeFileSync(envFilePath, response.content, "utf-8");
1707
+ fs6.writeFileSync(envFilePath, response.content, "utf-8");
1664
1708
  const lines = response.content.split("\n").filter((line) => {
1665
1709
  const trimmed = line.trim();
1666
1710
  return trimmed.length > 0 && !trimmed.startsWith("#");
1667
1711
  });
1668
- console.log(pc7.green(`
1712
+ console.log(pc8.green(`
1669
1713
  \u2713 Secrets downloaded successfully`));
1670
1714
  console.log(`
1671
- File: ${pc7.cyan(envFile)}`);
1672
- console.log(`Variables: ${pc7.cyan(lines.length.toString())}`);
1715
+ File: ${pc8.cyan(envFile)}`);
1716
+ console.log(`Variables: ${pc8.cyan(lines.length.toString())}`);
1673
1717
  await shutdownAnalytics();
1674
1718
  } catch (error) {
1675
1719
  const message = error instanceof APIError ? `API ${error.statusCode}: ${error.message}` : error instanceof Error ? truncateMessage(error.message) : "Unknown error";
@@ -1678,14 +1722,14 @@ File: ${pc7.cyan(envFile)}`);
1678
1722
  error: message
1679
1723
  });
1680
1724
  await shutdownAnalytics();
1681
- console.error(pc7.red(`
1725
+ console.error(pc8.red(`
1682
1726
  \u2717 ${message}`));
1683
1727
  process.exit(1);
1684
1728
  }
1685
1729
  }
1686
1730
 
1687
1731
  // src/cmds/doctor.ts
1688
- import pc8 from "picocolors";
1732
+ import pc9 from "picocolors";
1689
1733
 
1690
1734
  // src/core/doctor.ts
1691
1735
  import { execSync as execSync2 } from "child_process";
@@ -1939,9 +1983,9 @@ async function runAllChecks(options = {}) {
1939
1983
  // src/cmds/doctor.ts
1940
1984
  function formatSummary(results) {
1941
1985
  const parts = [
1942
- pc8.green(`${results.summary.pass} passed`),
1943
- results.summary.warn > 0 ? pc8.yellow(`${results.summary.warn} warnings`) : null,
1944
- results.summary.fail > 0 ? pc8.red(`${results.summary.fail} failed`) : null
1986
+ pc9.green(`${results.summary.pass} passed`),
1987
+ results.summary.warn > 0 ? pc9.yellow(`${results.summary.warn} warnings`) : null,
1988
+ results.summary.fail > 0 ? pc9.red(`${results.summary.fail} failed`) : null
1945
1989
  ].filter(Boolean);
1946
1990
  return parts.join(", ");
1947
1991
  }
@@ -1958,20 +2002,20 @@ async function doctorCommand(options = {}) {
1958
2002
  process.stdout.write(JSON.stringify(results, null, 0) + "\n");
1959
2003
  process.exit(results.exitCode);
1960
2004
  }
1961
- console.log(pc8.cyan("\n\u{1F50D} Keyway Doctor - Environment Check\n"));
2005
+ console.log(pc9.cyan("\n\u{1F50D} Keyway Doctor - Environment Check\n"));
1962
2006
  results.checks.forEach((check) => {
1963
- const icon = check.status === "pass" ? pc8.green("\u2713") : check.status === "warn" ? pc8.yellow("!") : pc8.red("\u2717");
1964
- const detail = check.detail ? pc8.dim(` \u2014 ${check.detail}`) : "";
2007
+ const icon = check.status === "pass" ? pc9.green("\u2713") : check.status === "warn" ? pc9.yellow("!") : pc9.red("\u2717");
2008
+ const detail = check.detail ? pc9.dim(` \u2014 ${check.detail}`) : "";
1965
2009
  console.log(` ${icon} ${check.name}${detail}`);
1966
2010
  });
1967
2011
  console.log(`
1968
2012
  Summary: ${formatSummary(results)}`);
1969
2013
  if (results.summary.fail > 0) {
1970
- console.log(pc8.red("\u26A0 Some checks failed. Please resolve the issues above before using Keyway."));
2014
+ console.log(pc9.red("\u26A0 Some checks failed. Please resolve the issues above before using Keyway."));
1971
2015
  } else if (results.summary.warn > 0) {
1972
- console.log(pc8.yellow("\u26A0 Some warnings detected. Keyway should work but consider addressing them."));
2016
+ console.log(pc9.yellow("\u26A0 Some warnings detected. Keyway should work but consider addressing them."));
1973
2017
  } else {
1974
- console.log(pc8.green("\u2728 All checks passed! Your environment is ready for Keyway."));
2018
+ console.log(pc9.green("\u2728 All checks passed! Your environment is ready for Keyway."));
1975
2019
  }
1976
2020
  process.exit(results.exitCode);
1977
2021
  } catch (error) {
@@ -1992,7 +2036,7 @@ Summary: ${formatSummary(results)}`);
1992
2036
  };
1993
2037
  process.stdout.write(JSON.stringify(errorResult, null, 0) + "\n");
1994
2038
  } else {
1995
- console.error(pc8.red(`
2039
+ console.error(pc9.red(`
1996
2040
  \u2717 ${message}`));
1997
2041
  }
1998
2042
  process.exit(1);
@@ -2000,8 +2044,8 @@ Summary: ${formatSummary(results)}`);
2000
2044
  }
2001
2045
 
2002
2046
  // src/cmds/connect.ts
2003
- import pc9 from "picocolors";
2004
- import prompts7 from "prompts";
2047
+ import pc10 from "picocolors";
2048
+ import prompts8 from "prompts";
2005
2049
  var TOKEN_AUTH_PROVIDERS = ["railway"];
2006
2050
  function getTokenCreationUrl(provider) {
2007
2051
  switch (provider) {
@@ -2014,37 +2058,37 @@ function getTokenCreationUrl(provider) {
2014
2058
  async function connectWithTokenFlow(accessToken, provider, displayName) {
2015
2059
  const tokenUrl = getTokenCreationUrl(provider);
2016
2060
  if (provider === "railway") {
2017
- console.log(pc9.yellow("\nTip: Select the workspace containing your projects."));
2018
- console.log(pc9.yellow(` Do NOT use "No workspace" - it won't have access to your projects.`));
2061
+ console.log(pc10.yellow("\nTip: Select the workspace containing your projects."));
2062
+ console.log(pc10.yellow(` Do NOT use "No workspace" - it won't have access to your projects.`));
2019
2063
  }
2020
2064
  await openUrl(tokenUrl);
2021
- const { token } = await prompts7({
2065
+ const { token } = await prompts8({
2022
2066
  type: "password",
2023
2067
  name: "token",
2024
2068
  message: `${displayName} API Token:`
2025
2069
  });
2026
2070
  if (!token) {
2027
- console.log(pc9.gray("Cancelled."));
2071
+ console.log(pc10.gray("Cancelled."));
2028
2072
  return false;
2029
2073
  }
2030
- console.log(pc9.gray("\nValidating token..."));
2074
+ console.log(pc10.gray("\nValidating token..."));
2031
2075
  try {
2032
2076
  const result = await connectWithToken(accessToken, provider, token);
2033
2077
  if (result.success) {
2034
- console.log(pc9.green(`
2078
+ console.log(pc10.green(`
2035
2079
  \u2713 Connected to ${displayName}!`));
2036
- console.log(pc9.gray(` Account: ${result.user.username}`));
2080
+ console.log(pc10.gray(` Account: ${result.user.username}`));
2037
2081
  if (result.user.teamName) {
2038
- console.log(pc9.gray(` Team: ${result.user.teamName}`));
2082
+ console.log(pc10.gray(` Team: ${result.user.teamName}`));
2039
2083
  }
2040
2084
  return true;
2041
2085
  } else {
2042
- console.log(pc9.red("\n\u2717 Connection failed."));
2086
+ console.log(pc10.red("\n\u2717 Connection failed."));
2043
2087
  return false;
2044
2088
  }
2045
2089
  } catch (error) {
2046
2090
  const message = error instanceof Error ? error.message : "Token validation failed";
2047
- console.log(pc9.red(`
2091
+ console.log(pc10.red(`
2048
2092
  \u2717 ${message}`));
2049
2093
  return false;
2050
2094
  }
@@ -2053,7 +2097,7 @@ async function connectWithOAuthFlow(accessToken, provider, displayName) {
2053
2097
  const authUrl = getProviderAuthUrl(provider, accessToken);
2054
2098
  const startTime = /* @__PURE__ */ new Date();
2055
2099
  await openUrl(authUrl);
2056
- console.log(pc9.gray("Waiting for authorization..."));
2100
+ console.log(pc10.gray("Waiting for authorization..."));
2057
2101
  const maxAttempts = 60;
2058
2102
  let attempts = 0;
2059
2103
  while (attempts < maxAttempts) {
@@ -2065,15 +2109,15 @@ async function connectWithOAuthFlow(accessToken, provider, displayName) {
2065
2109
  (c) => c.provider === provider && new Date(c.createdAt) > startTime
2066
2110
  );
2067
2111
  if (newConn) {
2068
- console.log(pc9.green(`
2112
+ console.log(pc10.green(`
2069
2113
  \u2713 Connected to ${displayName}!`));
2070
2114
  return true;
2071
2115
  }
2072
2116
  } catch {
2073
2117
  }
2074
2118
  }
2075
- console.log(pc9.red("\n\u2717 Authorization timeout."));
2076
- console.log(pc9.gray("Run `keyway connections` to check if the connection was established."));
2119
+ console.log(pc10.red("\n\u2717 Authorization timeout."));
2120
+ console.log(pc10.gray("Run `keyway connections` to check if the connection was established."));
2077
2121
  return false;
2078
2122
  }
2079
2123
  async function connectCommand(provider, options = {}) {
@@ -2083,30 +2127,30 @@ async function connectCommand(provider, options = {}) {
2083
2127
  const providerInfo = providers.find((p) => p.name === provider.toLowerCase());
2084
2128
  if (!providerInfo) {
2085
2129
  const available = providers.map((p) => p.name).join(", ");
2086
- console.error(pc9.red(`Unknown provider: ${provider}`));
2087
- console.log(pc9.gray(`Available providers: ${available || "none"}`));
2130
+ console.error(pc10.red(`Unknown provider: ${provider}`));
2131
+ console.log(pc10.gray(`Available providers: ${available || "none"}`));
2088
2132
  process.exit(1);
2089
2133
  }
2090
2134
  if (!providerInfo.configured) {
2091
- console.error(pc9.red(`Provider ${providerInfo.displayName} is not configured on the server.`));
2092
- console.log(pc9.gray("Contact your administrator to enable this integration."));
2135
+ console.error(pc10.red(`Provider ${providerInfo.displayName} is not configured on the server.`));
2136
+ console.log(pc10.gray("Contact your administrator to enable this integration."));
2093
2137
  process.exit(1);
2094
2138
  }
2095
2139
  const { connections } = await getConnections(accessToken);
2096
2140
  const existingConnection = connections.find((c) => c.provider === provider.toLowerCase());
2097
2141
  if (existingConnection) {
2098
- const { reconnect } = await prompts7({
2142
+ const { reconnect } = await prompts8({
2099
2143
  type: "confirm",
2100
2144
  name: "reconnect",
2101
2145
  message: `You're already connected to ${providerInfo.displayName}. Reconnect?`,
2102
2146
  initial: false
2103
2147
  });
2104
2148
  if (!reconnect) {
2105
- console.log(pc9.gray("Keeping existing connection."));
2149
+ console.log(pc10.gray("Keeping existing connection."));
2106
2150
  return;
2107
2151
  }
2108
2152
  }
2109
- console.log(pc9.blue(`
2153
+ console.log(pc10.blue(`
2110
2154
  Connecting to ${providerInfo.displayName}...
2111
2155
  `));
2112
2156
  let connected = false;
@@ -2125,7 +2169,7 @@ Connecting to ${providerInfo.displayName}...
2125
2169
  command: "connect",
2126
2170
  error: truncateMessage(message)
2127
2171
  });
2128
- console.error(pc9.red(`
2172
+ console.error(pc10.red(`
2129
2173
  \u2717 ${message}`));
2130
2174
  process.exit(1);
2131
2175
  }
@@ -2135,24 +2179,24 @@ async function connectionsCommand(options = {}) {
2135
2179
  const accessToken = await ensureLogin({ allowPrompt: options.loginPrompt !== false });
2136
2180
  const { connections } = await getConnections(accessToken);
2137
2181
  if (connections.length === 0) {
2138
- console.log(pc9.gray("No provider connections found."));
2139
- console.log(pc9.gray("\nConnect to a provider with: keyway connect <provider>"));
2140
- console.log(pc9.gray("Available providers: vercel, railway"));
2182
+ console.log(pc10.gray("No provider connections found."));
2183
+ console.log(pc10.gray("\nConnect to a provider with: keyway connect <provider>"));
2184
+ console.log(pc10.gray("Available providers: vercel, railway"));
2141
2185
  return;
2142
2186
  }
2143
- console.log(pc9.blue("\n\u{1F4E1} Provider Connections\n"));
2187
+ console.log(pc10.blue("\n\u{1F4E1} Provider Connections\n"));
2144
2188
  for (const conn of connections) {
2145
2189
  const providerName = conn.provider.charAt(0).toUpperCase() + conn.provider.slice(1);
2146
- const teamInfo = conn.providerTeamId ? pc9.gray(` (Team: ${conn.providerTeamId})`) : "";
2190
+ const teamInfo = conn.providerTeamId ? pc10.gray(` (Team: ${conn.providerTeamId})`) : "";
2147
2191
  const date = new Date(conn.createdAt).toLocaleDateString();
2148
- console.log(` ${pc9.green("\u25CF")} ${pc9.bold(providerName)}${teamInfo}`);
2149
- console.log(pc9.gray(` Connected: ${date}`));
2150
- console.log(pc9.gray(` ID: ${conn.id}`));
2192
+ console.log(` ${pc10.green("\u25CF")} ${pc10.bold(providerName)}${teamInfo}`);
2193
+ console.log(pc10.gray(` Connected: ${date}`));
2194
+ console.log(pc10.gray(` ID: ${conn.id}`));
2151
2195
  console.log("");
2152
2196
  }
2153
2197
  } catch (error) {
2154
2198
  const message = error instanceof Error ? error.message : "Failed to list connections";
2155
- console.error(pc9.red(`
2199
+ console.error(pc10.red(`
2156
2200
  \u2717 ${message}`));
2157
2201
  process.exit(1);
2158
2202
  }
@@ -2163,22 +2207,22 @@ async function disconnectCommand(provider, options = {}) {
2163
2207
  const { connections } = await getConnections(accessToken);
2164
2208
  const connection = connections.find((c) => c.provider === provider.toLowerCase());
2165
2209
  if (!connection) {
2166
- console.log(pc9.gray(`No connection found for provider: ${provider}`));
2210
+ console.log(pc10.gray(`No connection found for provider: ${provider}`));
2167
2211
  return;
2168
2212
  }
2169
2213
  const providerName = provider.charAt(0).toUpperCase() + provider.slice(1);
2170
- const { confirm } = await prompts7({
2214
+ const { confirm } = await prompts8({
2171
2215
  type: "confirm",
2172
2216
  name: "confirm",
2173
2217
  message: `Disconnect from ${providerName}?`,
2174
2218
  initial: false
2175
2219
  });
2176
2220
  if (!confirm) {
2177
- console.log(pc9.gray("Cancelled."));
2221
+ console.log(pc10.gray("Cancelled."));
2178
2222
  return;
2179
2223
  }
2180
2224
  await deleteConnection(accessToken, connection.id);
2181
- console.log(pc9.green(`
2225
+ console.log(pc10.green(`
2182
2226
  \u2713 Disconnected from ${providerName}`));
2183
2227
  trackEvent(AnalyticsEvents.CLI_DISCONNECT, {
2184
2228
  provider: provider.toLowerCase()
@@ -2189,15 +2233,15 @@ async function disconnectCommand(provider, options = {}) {
2189
2233
  command: "disconnect",
2190
2234
  error: truncateMessage(message)
2191
2235
  });
2192
- console.error(pc9.red(`
2236
+ console.error(pc10.red(`
2193
2237
  \u2717 ${message}`));
2194
2238
  process.exit(1);
2195
2239
  }
2196
2240
  }
2197
2241
 
2198
2242
  // src/cmds/sync.ts
2199
- import pc10 from "picocolors";
2200
- import prompts8 from "prompts";
2243
+ import pc11 from "picocolors";
2244
+ import prompts9 from "prompts";
2201
2245
  function mapToVercelEnvironment(keywayEnv) {
2202
2246
  const mapping = {
2203
2247
  production: "production",
@@ -2241,36 +2285,36 @@ function mapToProviderEnvironment(provider, keywayEnv) {
2241
2285
  function displayDiffSummary(diff, providerName) {
2242
2286
  const totalDiff = diff.onlyInKeyway.length + diff.onlyInProvider.length + diff.different.length;
2243
2287
  if (totalDiff === 0 && diff.same.length > 0) {
2244
- console.log(pc10.green(`
2288
+ console.log(pc11.green(`
2245
2289
  \u2713 Already in sync (${diff.same.length} secrets)`));
2246
2290
  return;
2247
2291
  }
2248
- console.log(pc10.blue("\n\u{1F4CA} Comparison Summary\n"));
2249
- console.log(pc10.gray(` Keyway: ${diff.keywayCount} secrets | ${providerName}: ${diff.providerCount} secrets
2292
+ console.log(pc11.blue("\n\u{1F4CA} Comparison Summary\n"));
2293
+ console.log(pc11.gray(` Keyway: ${diff.keywayCount} secrets | ${providerName}: ${diff.providerCount} secrets
2250
2294
  `));
2251
2295
  if (diff.onlyInKeyway.length > 0) {
2252
- console.log(pc10.cyan(` \u2192 ${diff.onlyInKeyway.length} only in Keyway`));
2253
- diff.onlyInKeyway.slice(0, 3).forEach((key) => console.log(pc10.gray(` ${key}`)));
2296
+ console.log(pc11.cyan(` \u2192 ${diff.onlyInKeyway.length} only in Keyway`));
2297
+ diff.onlyInKeyway.slice(0, 3).forEach((key) => console.log(pc11.gray(` ${key}`)));
2254
2298
  if (diff.onlyInKeyway.length > 3) {
2255
- console.log(pc10.gray(` ... and ${diff.onlyInKeyway.length - 3} more`));
2299
+ console.log(pc11.gray(` ... and ${diff.onlyInKeyway.length - 3} more`));
2256
2300
  }
2257
2301
  }
2258
2302
  if (diff.onlyInProvider.length > 0) {
2259
- console.log(pc10.magenta(` \u2190 ${diff.onlyInProvider.length} only in ${providerName}`));
2260
- diff.onlyInProvider.slice(0, 3).forEach((key) => console.log(pc10.gray(` ${key}`)));
2303
+ console.log(pc11.magenta(` \u2190 ${diff.onlyInProvider.length} only in ${providerName}`));
2304
+ diff.onlyInProvider.slice(0, 3).forEach((key) => console.log(pc11.gray(` ${key}`)));
2261
2305
  if (diff.onlyInProvider.length > 3) {
2262
- console.log(pc10.gray(` ... and ${diff.onlyInProvider.length - 3} more`));
2306
+ console.log(pc11.gray(` ... and ${diff.onlyInProvider.length - 3} more`));
2263
2307
  }
2264
2308
  }
2265
2309
  if (diff.different.length > 0) {
2266
- console.log(pc10.yellow(` \u2260 ${diff.different.length} with different values`));
2267
- diff.different.slice(0, 3).forEach((key) => console.log(pc10.gray(` ${key}`)));
2310
+ console.log(pc11.yellow(` \u2260 ${diff.different.length} with different values`));
2311
+ diff.different.slice(0, 3).forEach((key) => console.log(pc11.gray(` ${key}`)));
2268
2312
  if (diff.different.length > 3) {
2269
- console.log(pc10.gray(` ... and ${diff.different.length - 3} more`));
2313
+ console.log(pc11.gray(` ... and ${diff.different.length - 3} more`));
2270
2314
  }
2271
2315
  }
2272
2316
  if (diff.same.length > 0) {
2273
- console.log(pc10.gray(` = ${diff.same.length} identical`));
2317
+ console.log(pc11.gray(` = ${diff.same.length} identical`));
2274
2318
  }
2275
2319
  console.log("");
2276
2320
  }
@@ -2317,25 +2361,25 @@ async function promptProjectSelection(projects, repoFullName) {
2317
2361
  let title = displayName;
2318
2362
  const badges = [];
2319
2363
  if (p.linkedRepo?.toLowerCase() === repoFullName.toLowerCase()) {
2320
- badges.push(pc10.green("\u2190 linked"));
2364
+ badges.push(pc11.green("\u2190 linked"));
2321
2365
  } else if (p.name.toLowerCase() === repoName || p.serviceName?.toLowerCase() === repoName) {
2322
- badges.push(pc10.green("\u2190 same name"));
2366
+ badges.push(pc11.green("\u2190 same name"));
2323
2367
  } else if (p.linkedRepo) {
2324
- badges.push(pc10.gray(`\u2192 ${p.linkedRepo}`));
2368
+ badges.push(pc11.gray(`\u2192 ${p.linkedRepo}`));
2325
2369
  }
2326
2370
  if (badges.length > 0) {
2327
2371
  title = `${displayName} ${badges.join(" ")}`;
2328
2372
  }
2329
2373
  return { title, value: p.id };
2330
2374
  });
2331
- const { projectChoice } = await prompts8({
2375
+ const { projectChoice } = await prompts9({
2332
2376
  type: "select",
2333
2377
  name: "projectChoice",
2334
2378
  message: "Select a project:",
2335
2379
  choices
2336
2380
  });
2337
2381
  if (!projectChoice) {
2338
- console.log(pc10.gray("Cancelled."));
2382
+ console.log(pc11.gray("Cancelled."));
2339
2383
  process.exit(0);
2340
2384
  }
2341
2385
  return projects.find((p) => p.id === projectChoice);
@@ -2343,40 +2387,40 @@ async function promptProjectSelection(projects, repoFullName) {
2343
2387
  async function syncCommand(provider, options = {}) {
2344
2388
  try {
2345
2389
  if (options.pull && options.allowDelete) {
2346
- console.error(pc10.red("Error: --allow-delete cannot be used with --pull"));
2347
- console.log(pc10.gray("The --allow-delete flag is only for push operations."));
2390
+ console.error(pc11.red("Error: --allow-delete cannot be used with --pull"));
2391
+ console.log(pc11.gray("The --allow-delete flag is only for push operations."));
2348
2392
  process.exit(1);
2349
2393
  }
2350
2394
  const accessToken = await ensureLogin({ allowPrompt: options.loginPrompt !== false });
2351
2395
  const repoFullName = detectGitRepo();
2352
2396
  if (!repoFullName) {
2353
- console.error(pc10.red("Could not detect Git repository."));
2354
- console.log(pc10.gray("Run this command from a Git repository directory."));
2397
+ console.error(pc11.red("Could not detect Git repository."));
2398
+ console.log(pc11.gray("Run this command from a Git repository directory."));
2355
2399
  process.exit(1);
2356
2400
  }
2357
- console.log(pc10.gray(`Repository: ${repoFullName}`));
2401
+ console.log(pc11.gray(`Repository: ${repoFullName}`));
2358
2402
  const vaultExists = await checkVaultExists(accessToken, repoFullName);
2359
2403
  if (!vaultExists) {
2360
- console.log(pc10.yellow(`
2404
+ console.log(pc11.yellow(`
2361
2405
  No vault found for ${repoFullName}.`));
2362
- const { shouldCreate } = await prompts8({
2406
+ const { shouldCreate } = await prompts9({
2363
2407
  type: "confirm",
2364
2408
  name: "shouldCreate",
2365
2409
  message: "Create vault now?",
2366
2410
  initial: true
2367
2411
  });
2368
2412
  if (!shouldCreate) {
2369
- console.log(pc10.gray("Cancelled. Run `keyway init` to create a vault first."));
2413
+ console.log(pc11.gray("Cancelled. Run `keyway init` to create a vault first."));
2370
2414
  process.exit(0);
2371
2415
  }
2372
- console.log(pc10.gray("\nCreating vault..."));
2416
+ console.log(pc11.gray("\nCreating vault..."));
2373
2417
  try {
2374
2418
  await initVault(repoFullName, accessToken);
2375
- console.log(pc10.green(`\u2713 Vault created for ${repoFullName}
2419
+ console.log(pc11.green(`\u2713 Vault created for ${repoFullName}
2376
2420
  `));
2377
2421
  } catch (error) {
2378
2422
  const message = error instanceof Error ? error.message : "Failed to create vault";
2379
- console.error(pc10.red(`
2423
+ console.error(pc11.red(`
2380
2424
  \u2717 ${message}`));
2381
2425
  process.exit(1);
2382
2426
  }
@@ -2385,16 +2429,16 @@ No vault found for ${repoFullName}.`));
2385
2429
  let connection = connections.find((c) => c.provider === provider.toLowerCase());
2386
2430
  if (!connection) {
2387
2431
  const providerDisplayName = provider.charAt(0).toUpperCase() + provider.slice(1);
2388
- console.log(pc10.yellow(`
2432
+ console.log(pc11.yellow(`
2389
2433
  Not connected to ${providerDisplayName}.`));
2390
- const { shouldConnect } = await prompts8({
2434
+ const { shouldConnect } = await prompts9({
2391
2435
  type: "confirm",
2392
2436
  name: "shouldConnect",
2393
2437
  message: `Connect to ${providerDisplayName} now?`,
2394
2438
  initial: true
2395
2439
  });
2396
2440
  if (!shouldConnect) {
2397
- console.log(pc10.gray("Cancelled."));
2441
+ console.log(pc11.gray("Cancelled."));
2398
2442
  process.exit(0);
2399
2443
  }
2400
2444
  await connectCommand(provider, { loginPrompt: false });
@@ -2402,7 +2446,7 @@ Not connected to ${providerDisplayName}.`));
2402
2446
  connections = refreshed.connections;
2403
2447
  connection = connections.find((c) => c.provider === provider.toLowerCase());
2404
2448
  if (!connection) {
2405
- console.error(pc10.red(`
2449
+ console.error(pc11.red(`
2406
2450
  Connection to ${providerDisplayName} failed.`));
2407
2451
  process.exit(1);
2408
2452
  }
@@ -2410,7 +2454,7 @@ Connection to ${providerDisplayName} failed.`));
2410
2454
  }
2411
2455
  const { projects } = await getConnectionProjects(accessToken, connection.id);
2412
2456
  if (projects.length === 0) {
2413
- console.error(pc10.red(`No projects found in your ${provider} account.`));
2457
+ console.error(pc11.red(`No projects found in your ${provider} account.`));
2414
2458
  process.exit(1);
2415
2459
  }
2416
2460
  let selectedProject;
@@ -2419,21 +2463,21 @@ Connection to ${providerDisplayName} failed.`));
2419
2463
  (p) => p.id === options.project || p.name.toLowerCase() === options.project?.toLowerCase() || p.serviceName?.toLowerCase() === options.project?.toLowerCase()
2420
2464
  );
2421
2465
  if (!found) {
2422
- console.error(pc10.red(`Project not found: ${options.project}`));
2423
- console.log(pc10.gray("Available projects:"));
2424
- projects.forEach((p) => console.log(pc10.gray(` - ${getProjectDisplayName(p)}`)));
2466
+ console.error(pc11.red(`Project not found: ${options.project}`));
2467
+ console.log(pc11.gray("Available projects:"));
2468
+ projects.forEach((p) => console.log(pc11.gray(` - ${getProjectDisplayName(p)}`)));
2425
2469
  process.exit(1);
2426
2470
  }
2427
2471
  selectedProject = found;
2428
2472
  if (!projectMatchesRepo(selectedProject, repoFullName)) {
2429
2473
  console.log("");
2430
- console.log(pc10.yellow("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
2431
- console.log(pc10.yellow("\u2502 \u26A0\uFE0F WARNING: Project does not match current repository \u2502"));
2432
- console.log(pc10.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"));
2433
- console.log(pc10.yellow(` Current repo: ${repoFullName}`));
2434
- console.log(pc10.yellow(` Selected project: ${getProjectDisplayName(selectedProject)}`));
2474
+ console.log(pc11.yellow("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
2475
+ console.log(pc11.yellow("\u2502 \u26A0\uFE0F WARNING: Project does not match current repository \u2502"));
2476
+ console.log(pc11.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"));
2477
+ console.log(pc11.yellow(` Current repo: ${repoFullName}`));
2478
+ console.log(pc11.yellow(` Selected project: ${getProjectDisplayName(selectedProject)}`));
2435
2479
  if (selectedProject.linkedRepo) {
2436
- console.log(pc10.yellow(` Project linked to: ${selectedProject.linkedRepo}`));
2480
+ console.log(pc11.yellow(` Project linked to: ${selectedProject.linkedRepo}`));
2437
2481
  }
2438
2482
  console.log("");
2439
2483
  }
@@ -2442,11 +2486,11 @@ Connection to ${providerDisplayName} failed.`));
2442
2486
  if (autoMatch && (autoMatch.matchType === "linked_repo" || autoMatch.matchType === "exact_name")) {
2443
2487
  selectedProject = autoMatch.project;
2444
2488
  const matchReason = autoMatch.matchType === "linked_repo" ? `linked to ${repoFullName}` : "exact name match";
2445
- console.log(pc10.green(`\u2713 Auto-selected project: ${getProjectDisplayName(selectedProject)} (${matchReason})`));
2489
+ console.log(pc11.green(`\u2713 Auto-selected project: ${getProjectDisplayName(selectedProject)} (${matchReason})`));
2446
2490
  } else if (autoMatch && autoMatch.matchType === "partial_name") {
2447
2491
  const partialDisplayName = getProjectDisplayName(autoMatch.project);
2448
- console.log(pc10.yellow(`Detected project: ${partialDisplayName} (partial match)`));
2449
- const { useDetected } = await prompts8({
2492
+ console.log(pc11.yellow(`Detected project: ${partialDisplayName} (partial match)`));
2493
+ const { useDetected } = await prompts9({
2450
2494
  type: "confirm",
2451
2495
  name: "useDetected",
2452
2496
  message: `Use ${partialDisplayName}?`,
@@ -2461,30 +2505,30 @@ Connection to ${providerDisplayName} failed.`));
2461
2505
  selectedProject = projects[0];
2462
2506
  if (!projectMatchesRepo(selectedProject, repoFullName)) {
2463
2507
  console.log("");
2464
- console.log(pc10.yellow("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
2465
- console.log(pc10.yellow("\u2502 \u26A0\uFE0F WARNING: Project does not match current repository \u2502"));
2466
- console.log(pc10.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"));
2467
- console.log(pc10.yellow(` Current repo: ${repoFullName}`));
2468
- console.log(pc10.yellow(` Only project: ${getProjectDisplayName(selectedProject)}`));
2508
+ console.log(pc11.yellow("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
2509
+ console.log(pc11.yellow("\u2502 \u26A0\uFE0F WARNING: Project does not match current repository \u2502"));
2510
+ console.log(pc11.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"));
2511
+ console.log(pc11.yellow(` Current repo: ${repoFullName}`));
2512
+ console.log(pc11.yellow(` Only project: ${getProjectDisplayName(selectedProject)}`));
2469
2513
  if (selectedProject.linkedRepo) {
2470
- console.log(pc10.yellow(` Project linked to: ${selectedProject.linkedRepo}`));
2514
+ console.log(pc11.yellow(` Project linked to: ${selectedProject.linkedRepo}`));
2471
2515
  }
2472
2516
  console.log("");
2473
- const { continueAnyway } = await prompts8({
2517
+ const { continueAnyway } = await prompts9({
2474
2518
  type: "confirm",
2475
2519
  name: "continueAnyway",
2476
2520
  message: "Continue anyway?",
2477
2521
  initial: false
2478
2522
  });
2479
2523
  if (!continueAnyway) {
2480
- console.log(pc10.gray("Cancelled."));
2524
+ console.log(pc11.gray("Cancelled."));
2481
2525
  process.exit(0);
2482
2526
  }
2483
2527
  }
2484
2528
  } else {
2485
- console.log(pc10.yellow(`
2529
+ console.log(pc11.yellow(`
2486
2530
  \u26A0\uFE0F No matching project found for ${repoFullName}`));
2487
- console.log(pc10.gray("Select a project manually:\n"));
2531
+ console.log(pc11.gray("Select a project manually:\n"));
2488
2532
  selectedProject = await promptProjectSelection(projects, repoFullName);
2489
2533
  }
2490
2534
  }
@@ -2492,23 +2536,23 @@ Connection to ${providerDisplayName} failed.`));
2492
2536
  const autoMatch = findMatchingProject(projects, repoFullName);
2493
2537
  if (autoMatch && autoMatch.project.id !== selectedProject.id) {
2494
2538
  console.log("");
2495
- console.log(pc10.yellow("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
2496
- console.log(pc10.yellow("\u2502 \u26A0\uFE0F WARNING: You selected a different project \u2502"));
2497
- console.log(pc10.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"));
2498
- console.log(pc10.yellow(` Current repo: ${repoFullName}`));
2499
- console.log(pc10.yellow(` Selected project: ${getProjectDisplayName(selectedProject)}`));
2539
+ console.log(pc11.yellow("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
2540
+ console.log(pc11.yellow("\u2502 \u26A0\uFE0F WARNING: You selected a different project \u2502"));
2541
+ console.log(pc11.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"));
2542
+ console.log(pc11.yellow(` Current repo: ${repoFullName}`));
2543
+ console.log(pc11.yellow(` Selected project: ${getProjectDisplayName(selectedProject)}`));
2500
2544
  if (selectedProject.linkedRepo) {
2501
- console.log(pc10.yellow(` Project linked to: ${selectedProject.linkedRepo}`));
2545
+ console.log(pc11.yellow(` Project linked to: ${selectedProject.linkedRepo}`));
2502
2546
  }
2503
2547
  console.log("");
2504
- const { continueAnyway } = await prompts8({
2548
+ const { continueAnyway } = await prompts9({
2505
2549
  type: "confirm",
2506
2550
  name: "continueAnyway",
2507
2551
  message: "Are you sure you want to sync with this project?",
2508
2552
  initial: false
2509
2553
  });
2510
2554
  if (!continueAnyway) {
2511
- console.log(pc10.gray("Cancelled."));
2555
+ console.log(pc11.gray("Cancelled."));
2512
2556
  process.exit(0);
2513
2557
  }
2514
2558
  }
@@ -2522,7 +2566,7 @@ Connection to ${providerDisplayName} failed.`));
2522
2566
  if (needsEnvPrompt || needsDirectionPrompt) {
2523
2567
  if (needsEnvPrompt) {
2524
2568
  const vaultEnvs = await getVaultEnvironments(accessToken, repoFullName);
2525
- const { selectedEnv } = await prompts8({
2569
+ const { selectedEnv } = await prompts9({
2526
2570
  type: "select",
2527
2571
  name: "selectedEnv",
2528
2572
  message: "Keyway environment:",
@@ -2530,7 +2574,7 @@ Connection to ${providerDisplayName} failed.`));
2530
2574
  initial: Math.max(0, vaultEnvs.indexOf("production"))
2531
2575
  });
2532
2576
  if (!selectedEnv) {
2533
- console.log(pc10.gray("Cancelled."));
2577
+ console.log(pc11.gray("Cancelled."));
2534
2578
  process.exit(0);
2535
2579
  }
2536
2580
  keywayEnv = selectedEnv;
@@ -2544,9 +2588,9 @@ Connection to ${providerDisplayName} failed.`));
2544
2588
  providerEnv = mappedEnv;
2545
2589
  } else if (selectedProject.environments.length === 1) {
2546
2590
  providerEnv = selectedProject.environments[0];
2547
- console.log(pc10.gray(`Using ${providerName} environment: ${providerEnv}`));
2591
+ console.log(pc11.gray(`Using ${providerName} environment: ${providerEnv}`));
2548
2592
  } else {
2549
- const { selectedProviderEnv } = await prompts8({
2593
+ const { selectedProviderEnv } = await prompts9({
2550
2594
  type: "select",
2551
2595
  name: "selectedProviderEnv",
2552
2596
  message: `${providerName} environment:`,
@@ -2556,7 +2600,7 @@ Connection to ${providerDisplayName} failed.`));
2556
2600
  ))
2557
2601
  });
2558
2602
  if (!selectedProviderEnv) {
2559
- console.log(pc10.gray("Cancelled."));
2603
+ console.log(pc11.gray("Cancelled."));
2560
2604
  process.exit(0);
2561
2605
  }
2562
2606
  providerEnv = selectedProviderEnv;
@@ -2570,7 +2614,7 @@ Connection to ${providerDisplayName} failed.`));
2570
2614
  if (needsDirectionPrompt) {
2571
2615
  const effectiveKeywayEnv = keywayEnv || "production";
2572
2616
  const effectiveProviderEnv = providerEnv || mapToProviderEnvironment(provider, effectiveKeywayEnv);
2573
- console.log(pc10.gray("\nComparing secrets..."));
2617
+ console.log(pc11.gray("\nComparing secrets..."));
2574
2618
  diff = await getSyncDiff(accessToken, repoFullName, {
2575
2619
  connectionId: connection.id,
2576
2620
  projectId: selectedProject.id,
@@ -2592,7 +2636,7 @@ Connection to ${providerDisplayName} failed.`));
2592
2636
  } else if (diff.providerCount === 0 && diff.keywayCount > 0) {
2593
2637
  defaultDirection = 0;
2594
2638
  }
2595
- const { selectedDirection } = await prompts8({
2639
+ const { selectedDirection } = await prompts9({
2596
2640
  type: "select",
2597
2641
  name: "selectedDirection",
2598
2642
  message: "Sync direction:",
@@ -2603,7 +2647,7 @@ Connection to ${providerDisplayName} failed.`));
2603
2647
  initial: defaultDirection
2604
2648
  });
2605
2649
  if (!selectedDirection) {
2606
- console.log(pc10.gray("Cancelled."));
2650
+ console.log(pc11.gray("Cancelled."));
2607
2651
  process.exit(0);
2608
2652
  }
2609
2653
  direction = selectedDirection;
@@ -2620,10 +2664,10 @@ Connection to ${providerDisplayName} failed.`));
2620
2664
  keywayEnv
2621
2665
  );
2622
2666
  if (status.isFirstSync && direction === "push" && status.vaultIsEmpty && status.providerHasSecrets) {
2623
- console.log(pc10.yellow(`
2667
+ console.log(pc11.yellow(`
2624
2668
  \u26A0\uFE0F Your Keyway vault is empty for "${keywayEnv}", but ${providerName} has ${status.providerSecretCount} secrets.`));
2625
- console.log(pc10.gray(` (Use --environment to sync a different environment)`));
2626
- const { importFirst } = await prompts8({
2669
+ console.log(pc11.gray(` (Use --environment to sync a different environment)`));
2670
+ const { importFirst } = await prompts9({
2627
2671
  type: "confirm",
2628
2672
  name: "importFirst",
2629
2673
  message: `Import secrets from ${providerName} first?`,
@@ -2664,7 +2708,7 @@ Connection to ${providerDisplayName} failed.`));
2664
2708
  command: "sync",
2665
2709
  error: truncateMessage(message)
2666
2710
  });
2667
- console.error(pc10.red(`
2711
+ console.error(pc11.red(`
2668
2712
  \u2717 ${message}`));
2669
2713
  process.exit(1);
2670
2714
  }
@@ -2683,49 +2727,49 @@ async function executeSyncOperation(accessToken, repoFullName, connectionId, pro
2683
2727
  });
2684
2728
  const totalChanges = preview.toCreate.length + preview.toUpdate.length + preview.toDelete.length;
2685
2729
  if (totalChanges === 0) {
2686
- console.log(pc10.green("\n\u2713 Already in sync. No changes needed."));
2730
+ console.log(pc11.green("\n\u2713 Already in sync. No changes needed."));
2687
2731
  return;
2688
2732
  }
2689
- console.log(pc10.blue("\n\u{1F4CB} Sync Preview\n"));
2733
+ console.log(pc11.blue("\n\u{1F4CB} Sync Preview\n"));
2690
2734
  if (preview.toCreate.length > 0) {
2691
- console.log(pc10.green(` + ${preview.toCreate.length} to create`));
2692
- preview.toCreate.slice(0, 5).forEach((key) => console.log(pc10.gray(` ${key}`)));
2735
+ console.log(pc11.green(` + ${preview.toCreate.length} to create`));
2736
+ preview.toCreate.slice(0, 5).forEach((key) => console.log(pc11.gray(` ${key}`)));
2693
2737
  if (preview.toCreate.length > 5) {
2694
- console.log(pc10.gray(` ... and ${preview.toCreate.length - 5} more`));
2738
+ console.log(pc11.gray(` ... and ${preview.toCreate.length - 5} more`));
2695
2739
  }
2696
2740
  }
2697
2741
  if (preview.toUpdate.length > 0) {
2698
- console.log(pc10.yellow(` ~ ${preview.toUpdate.length} to update`));
2699
- preview.toUpdate.slice(0, 5).forEach((key) => console.log(pc10.gray(` ${key}`)));
2742
+ console.log(pc11.yellow(` ~ ${preview.toUpdate.length} to update`));
2743
+ preview.toUpdate.slice(0, 5).forEach((key) => console.log(pc11.gray(` ${key}`)));
2700
2744
  if (preview.toUpdate.length > 5) {
2701
- console.log(pc10.gray(` ... and ${preview.toUpdate.length - 5} more`));
2745
+ console.log(pc11.gray(` ... and ${preview.toUpdate.length - 5} more`));
2702
2746
  }
2703
2747
  }
2704
2748
  if (preview.toDelete.length > 0) {
2705
- console.log(pc10.red(` - ${preview.toDelete.length} to delete`));
2706
- preview.toDelete.slice(0, 5).forEach((key) => console.log(pc10.gray(` ${key}`)));
2749
+ console.log(pc11.red(` - ${preview.toDelete.length} to delete`));
2750
+ preview.toDelete.slice(0, 5).forEach((key) => console.log(pc11.gray(` ${key}`)));
2707
2751
  if (preview.toDelete.length > 5) {
2708
- console.log(pc10.gray(` ... and ${preview.toDelete.length - 5} more`));
2752
+ console.log(pc11.gray(` ... and ${preview.toDelete.length - 5} more`));
2709
2753
  }
2710
2754
  }
2711
2755
  if (preview.toSkip.length > 0) {
2712
- console.log(pc10.gray(` \u25CB ${preview.toSkip.length} unchanged`));
2756
+ console.log(pc11.gray(` \u25CB ${preview.toSkip.length} unchanged`));
2713
2757
  }
2714
2758
  console.log("");
2715
2759
  if (!skipConfirm) {
2716
2760
  const target = direction === "push" ? providerName : "Keyway";
2717
- const { confirm } = await prompts8({
2761
+ const { confirm } = await prompts9({
2718
2762
  type: "confirm",
2719
2763
  name: "confirm",
2720
2764
  message: `Apply ${totalChanges} changes to ${target}?`,
2721
2765
  initial: true
2722
2766
  });
2723
2767
  if (!confirm) {
2724
- console.log(pc10.gray("Cancelled."));
2768
+ console.log(pc11.gray("Cancelled."));
2725
2769
  return;
2726
2770
  }
2727
2771
  }
2728
- console.log(pc10.blue("\n\u23F3 Syncing...\n"));
2772
+ console.log(pc11.blue("\n\u23F3 Syncing...\n"));
2729
2773
  const result = await executeSync(accessToken, repoFullName, {
2730
2774
  connectionId,
2731
2775
  projectId: project.id,
@@ -2737,11 +2781,11 @@ async function executeSyncOperation(accessToken, repoFullName, connectionId, pro
2737
2781
  allowDelete
2738
2782
  });
2739
2783
  if (result.success) {
2740
- console.log(pc10.green("\u2713 Sync complete"));
2741
- console.log(pc10.gray(` Created: ${result.stats.created}`));
2742
- console.log(pc10.gray(` Updated: ${result.stats.updated}`));
2784
+ console.log(pc11.green("\u2713 Sync complete"));
2785
+ console.log(pc11.gray(` Created: ${result.stats.created}`));
2786
+ console.log(pc11.gray(` Updated: ${result.stats.updated}`));
2743
2787
  if (result.stats.deleted > 0) {
2744
- console.log(pc10.gray(` Deleted: ${result.stats.deleted}`));
2788
+ console.log(pc11.gray(` Deleted: ${result.stats.deleted}`));
2745
2789
  }
2746
2790
  trackEvent(AnalyticsEvents.CLI_SYNC, {
2747
2791
  provider,
@@ -2751,7 +2795,7 @@ async function executeSyncOperation(accessToken, repoFullName, connectionId, pro
2751
2795
  deleted: result.stats.deleted
2752
2796
  });
2753
2797
  } else {
2754
- console.error(pc10.red(`
2798
+ console.error(pc11.red(`
2755
2799
  \u2717 ${result.error}`));
2756
2800
  process.exit(1);
2757
2801
  }
@@ -2759,16 +2803,16 @@ async function executeSyncOperation(accessToken, repoFullName, connectionId, pro
2759
2803
 
2760
2804
  // src/cli.ts
2761
2805
  process.on("unhandledRejection", (reason) => {
2762
- console.error(pc11.red("Unhandled error:"), reason);
2806
+ console.error(pc12.red("Unhandled error:"), reason);
2763
2807
  process.exit(1);
2764
2808
  });
2765
2809
  var program = new Command();
2766
2810
  var TAGLINE = "Sync secrets with your team and infra";
2767
2811
  var showBanner = () => {
2768
- const text = pc11.bold(pc11.cyan("Keyway CLI"));
2812
+ const text = pc12.bold(pc12.cyan("Keyway CLI"));
2769
2813
  console.log(`
2770
2814
  ${text}
2771
- ${pc11.gray(TAGLINE)}
2815
+ ${pc12.gray(TAGLINE)}
2772
2816
  `);
2773
2817
  };
2774
2818
  showBanner();
@@ -2807,6 +2851,6 @@ program.command("sync <provider>").description("Sync secrets with a provider (e.
2807
2851
  await warnIfEnvNotGitignored();
2808
2852
  await program.parseAsync();
2809
2853
  })().catch((error) => {
2810
- console.error(pc11.red("Error:"), error.message || error);
2854
+ console.error(pc12.red("Error:"), error.message || error);
2811
2855
  process.exit(1);
2812
2856
  });