@specific.dev/cli 0.1.74 → 0.1.76

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 (68) hide show
  1. package/dist/admin/404/index.html +1 -1
  2. package/dist/admin/404.html +1 -1
  3. package/dist/admin/__next.!KGRlZmF1bHQp.__PAGE__.txt +1 -1
  4. package/dist/admin/__next.!KGRlZmF1bHQp.txt +1 -1
  5. package/dist/admin/__next._full.txt +1 -1
  6. package/dist/admin/__next._head.txt +1 -1
  7. package/dist/admin/__next._index.txt +1 -1
  8. package/dist/admin/__next._tree.txt +1 -1
  9. package/dist/admin/_not-found/__next._full.txt +1 -1
  10. package/dist/admin/_not-found/__next._head.txt +1 -1
  11. package/dist/admin/_not-found/__next._index.txt +1 -1
  12. package/dist/admin/_not-found/__next._not-found.__PAGE__.txt +1 -1
  13. package/dist/admin/_not-found/__next._not-found.txt +1 -1
  14. package/dist/admin/_not-found/__next._tree.txt +1 -1
  15. package/dist/admin/_not-found/index.html +1 -1
  16. package/dist/admin/_not-found/index.txt +1 -1
  17. package/dist/admin/databases/__next.!KGRlZmF1bHQp.databases.__PAGE__.txt +1 -1
  18. package/dist/admin/databases/__next.!KGRlZmF1bHQp.databases.txt +1 -1
  19. package/dist/admin/databases/__next.!KGRlZmF1bHQp.txt +1 -1
  20. package/dist/admin/databases/__next._full.txt +1 -1
  21. package/dist/admin/databases/__next._head.txt +1 -1
  22. package/dist/admin/databases/__next._index.txt +1 -1
  23. package/dist/admin/databases/__next._tree.txt +1 -1
  24. package/dist/admin/databases/index.html +1 -1
  25. package/dist/admin/databases/index.txt +1 -1
  26. package/dist/admin/fullscreen/__next._full.txt +1 -1
  27. package/dist/admin/fullscreen/__next._head.txt +1 -1
  28. package/dist/admin/fullscreen/__next._index.txt +1 -1
  29. package/dist/admin/fullscreen/__next._tree.txt +1 -1
  30. package/dist/admin/fullscreen/__next.fullscreen.__PAGE__.txt +1 -1
  31. package/dist/admin/fullscreen/__next.fullscreen.txt +1 -1
  32. package/dist/admin/fullscreen/databases/__next._full.txt +1 -1
  33. package/dist/admin/fullscreen/databases/__next._head.txt +1 -1
  34. package/dist/admin/fullscreen/databases/__next._index.txt +1 -1
  35. package/dist/admin/fullscreen/databases/__next._tree.txt +1 -1
  36. package/dist/admin/fullscreen/databases/__next.fullscreen.databases.__PAGE__.txt +1 -1
  37. package/dist/admin/fullscreen/databases/__next.fullscreen.databases.txt +1 -1
  38. package/dist/admin/fullscreen/databases/__next.fullscreen.txt +1 -1
  39. package/dist/admin/fullscreen/databases/index.html +1 -1
  40. package/dist/admin/fullscreen/databases/index.txt +1 -1
  41. package/dist/admin/fullscreen/index.html +1 -1
  42. package/dist/admin/fullscreen/index.txt +1 -1
  43. package/dist/admin/index.html +1 -1
  44. package/dist/admin/index.txt +1 -1
  45. package/dist/admin/mail/__next.!KGRlZmF1bHQp.mail.__PAGE__.txt +1 -1
  46. package/dist/admin/mail/__next.!KGRlZmF1bHQp.mail.txt +1 -1
  47. package/dist/admin/mail/__next.!KGRlZmF1bHQp.txt +1 -1
  48. package/dist/admin/mail/__next._full.txt +1 -1
  49. package/dist/admin/mail/__next._head.txt +1 -1
  50. package/dist/admin/mail/__next._index.txt +1 -1
  51. package/dist/admin/mail/__next._tree.txt +1 -1
  52. package/dist/admin/mail/index.html +1 -1
  53. package/dist/admin/mail/index.txt +1 -1
  54. package/dist/admin/workflows/__next.!KGRlZmF1bHQp.txt +1 -1
  55. package/dist/admin/workflows/__next.!KGRlZmF1bHQp.workflows.__PAGE__.txt +1 -1
  56. package/dist/admin/workflows/__next.!KGRlZmF1bHQp.workflows.txt +1 -1
  57. package/dist/admin/workflows/__next._full.txt +1 -1
  58. package/dist/admin/workflows/__next._head.txt +1 -1
  59. package/dist/admin/workflows/__next._index.txt +1 -1
  60. package/dist/admin/workflows/__next._tree.txt +1 -1
  61. package/dist/admin/workflows/index.html +1 -1
  62. package/dist/admin/workflows/index.txt +1 -1
  63. package/dist/cli.js +357 -322
  64. package/dist/postinstall.js +1 -1
  65. package/package.json +1 -1
  66. /package/dist/admin/_next/static/{rlz8iRhM93pN2MuVf1ScD → j9zz6vmZhKrtrUzT5h_gg}/_buildManifest.js +0 -0
  67. /package/dist/admin/_next/static/{rlz8iRhM93pN2MuVf1ScD → j9zz6vmZhKrtrUzT5h_gg}/_clientMiddlewareManifest.json +0 -0
  68. /package/dist/admin/_next/static/{rlz8iRhM93pN2MuVf1ScD → j9zz6vmZhKrtrUzT5h_gg}/_ssgManifest.js +0 -0
package/dist/cli.js CHANGED
@@ -39,10 +39,10 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
39
39
  ));
40
40
 
41
41
  // node_modules/.pnpm/is-docker@3.0.0/node_modules/is-docker/index.js
42
- import fs6 from "node:fs";
42
+ import fs5 from "node:fs";
43
43
  function hasDockerEnv() {
44
44
  try {
45
- fs6.statSync("/.dockerenv");
45
+ fs5.statSync("/.dockerenv");
46
46
  return true;
47
47
  } catch {
48
48
  return false;
@@ -50,7 +50,7 @@ function hasDockerEnv() {
50
50
  }
51
51
  function hasDockerCGroup() {
52
52
  try {
53
- return fs6.readFileSync("/proc/self/cgroup", "utf8").includes("docker");
53
+ return fs5.readFileSync("/proc/self/cgroup", "utf8").includes("docker");
54
54
  } catch {
55
55
  return false;
56
56
  }
@@ -68,7 +68,7 @@ var init_is_docker = __esm({
68
68
  });
69
69
 
70
70
  // node_modules/.pnpm/is-inside-container@1.0.0/node_modules/is-inside-container/index.js
71
- import fs7 from "node:fs";
71
+ import fs6 from "node:fs";
72
72
  function isInsideContainer() {
73
73
  if (cachedResult === void 0) {
74
74
  cachedResult = hasContainerEnv() || isDocker();
@@ -81,7 +81,7 @@ var init_is_inside_container = __esm({
81
81
  init_is_docker();
82
82
  hasContainerEnv = () => {
83
83
  try {
84
- fs7.statSync("/run/.containerenv");
84
+ fs6.statSync("/run/.containerenv");
85
85
  return true;
86
86
  } catch {
87
87
  return false;
@@ -92,8 +92,8 @@ var init_is_inside_container = __esm({
92
92
 
93
93
  // node_modules/.pnpm/is-wsl@3.1.0/node_modules/is-wsl/index.js
94
94
  import process2 from "node:process";
95
- import os5 from "node:os";
96
- import fs8 from "node:fs";
95
+ import os4 from "node:os";
96
+ import fs7 from "node:fs";
97
97
  var isWsl, is_wsl_default;
98
98
  var init_is_wsl = __esm({
99
99
  "node_modules/.pnpm/is-wsl@3.1.0/node_modules/is-wsl/index.js"() {
@@ -102,14 +102,14 @@ var init_is_wsl = __esm({
102
102
  if (process2.platform !== "linux") {
103
103
  return false;
104
104
  }
105
- if (os5.release().toLowerCase().includes("microsoft")) {
105
+ if (os4.release().toLowerCase().includes("microsoft")) {
106
106
  if (isInsideContainer()) {
107
107
  return false;
108
108
  }
109
109
  return true;
110
110
  }
111
111
  try {
112
- return fs8.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft") ? !isInsideContainer() : false;
112
+ return fs7.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft") ? !isInsideContainer() : false;
113
113
  } catch {
114
114
  return false;
115
115
  }
@@ -179,7 +179,7 @@ var init_utilities = __esm({
179
179
  // node_modules/.pnpm/wsl-utils@0.3.1/node_modules/wsl-utils/index.js
180
180
  import { promisify as promisify2 } from "node:util";
181
181
  import childProcess2 from "node:child_process";
182
- import fs9, { constants as fsConstants } from "node:fs/promises";
182
+ import fs8, { constants as fsConstants } from "node:fs/promises";
183
183
  var execFile2, wslDrivesMountPoint, powerShellPathFromWsl, powerShellPath2, canAccessPowerShellPromise, canAccessPowerShell, wslDefaultBrowser, convertWslPathToWindows;
184
184
  var init_wsl_utils = __esm({
185
185
  "node_modules/.pnpm/wsl-utils@0.3.1/node_modules/wsl-utils/index.js"() {
@@ -198,14 +198,14 @@ var init_wsl_utils = __esm({
198
198
  const configFilePath = "/etc/wsl.conf";
199
199
  let isConfigFileExists = false;
200
200
  try {
201
- await fs9.access(configFilePath, fsConstants.F_OK);
201
+ await fs8.access(configFilePath, fsConstants.F_OK);
202
202
  isConfigFileExists = true;
203
203
  } catch {
204
204
  }
205
205
  if (!isConfigFileExists) {
206
206
  return defaultMountPoint;
207
207
  }
208
- const configContent = await fs9.readFile(configFilePath, { encoding: "utf8" });
208
+ const configContent = await fs8.readFile(configFilePath, { encoding: "utf8" });
209
209
  const parsedMountPoint = parseMountPointFromConfig(configContent);
210
210
  if (parsedMountPoint === void 0) {
211
211
  return defaultMountPoint;
@@ -224,7 +224,7 @@ var init_wsl_utils = __esm({
224
224
  canAccessPowerShellPromise ??= (async () => {
225
225
  try {
226
226
  const psPath = await powerShellPath2();
227
- await fs9.access(psPath, fsConstants.X_OK);
227
+ await fs8.access(psPath, fsConstants.X_OK);
228
228
  return true;
229
229
  } catch {
230
230
  return false;
@@ -435,7 +435,7 @@ import process8 from "node:process";
435
435
  import path5 from "node:path";
436
436
  import { fileURLToPath } from "node:url";
437
437
  import childProcess3 from "node:child_process";
438
- import fs10, { constants as fsConstants2 } from "node:fs/promises";
438
+ import fs9, { constants as fsConstants2 } from "node:fs/promises";
439
439
  function detectArchBinary(binary) {
440
440
  if (typeof binary === "string" || Array.isArray(binary)) {
441
441
  return binary;
@@ -446,16 +446,16 @@ function detectArchBinary(binary) {
446
446
  }
447
447
  return archBinary;
448
448
  }
449
- function detectPlatformBinary({ [platform4]: platformBinary }, { wsl } = {}) {
449
+ function detectPlatformBinary({ [platform3]: platformBinary }, { wsl } = {}) {
450
450
  if (wsl && is_wsl_default) {
451
451
  return detectArchBinary(wsl);
452
452
  }
453
453
  if (!platformBinary) {
454
- throw new Error(`${platform4} is not supported`);
454
+ throw new Error(`${platform3} is not supported`);
455
455
  }
456
456
  return detectArchBinary(platformBinary);
457
457
  }
458
- var fallbackAttemptSymbol, __dirname, localXdgOpenPath, platform4, arch, tryEachApp, baseOpen, open, openApp, apps, open_default;
458
+ var fallbackAttemptSymbol, __dirname, localXdgOpenPath, platform3, arch, tryEachApp, baseOpen, open, openApp, apps, open_default;
459
459
  var init_open = __esm({
460
460
  "node_modules/.pnpm/open@11.0.0/node_modules/open/index.js"() {
461
461
  init_wsl_utils();
@@ -467,7 +467,7 @@ var init_open = __esm({
467
467
  fallbackAttemptSymbol = Symbol("fallbackAttempt");
468
468
  __dirname = import.meta.url ? path5.dirname(fileURLToPath(import.meta.url)) : "";
469
469
  localXdgOpenPath = path5.join(__dirname, "xdg-open");
470
- ({ platform: platform4, arch } = process8);
470
+ ({ platform: platform3, arch } = process8);
471
471
  tryEachApp = async (apps2, opener) => {
472
472
  if (apps2.length === 0) {
473
473
  return;
@@ -564,7 +564,7 @@ var init_open = __esm({
564
564
  if (is_wsl_default && !isInsideContainer() && !is_in_ssh_default && !app) {
565
565
  shouldUseWindowsInWsl = await canAccessPowerShell();
566
566
  }
567
- if (platform4 === "darwin") {
567
+ if (platform3 === "darwin") {
568
568
  command = "open";
569
569
  if (options2.wait) {
570
570
  cliArguments.push("--wait-apps");
@@ -578,7 +578,7 @@ var init_open = __esm({
578
578
  if (app) {
579
579
  cliArguments.push("-a", app);
580
580
  }
581
- } else if (platform4 === "win32" || shouldUseWindowsInWsl) {
581
+ } else if (platform3 === "win32" || shouldUseWindowsInWsl) {
582
582
  command = await powerShellPath2();
583
583
  cliArguments.push(...executePowerShell.argumentsPrefix);
584
584
  if (!is_wsl_default) {
@@ -614,11 +614,11 @@ var init_open = __esm({
614
614
  const isBundled = !__dirname || __dirname === "/";
615
615
  let exeLocalXdgOpen = false;
616
616
  try {
617
- await fs10.access(localXdgOpenPath, fsConstants2.X_OK);
617
+ await fs9.access(localXdgOpenPath, fsConstants2.X_OK);
618
618
  exeLocalXdgOpen = true;
619
619
  } catch {
620
620
  }
621
- const useSystemXdgOpen = process8.versions.electron ?? (platform4 === "android" || isBundled || !exeLocalXdgOpen);
621
+ const useSystemXdgOpen = process8.versions.electron ?? (platform3 === "android" || isBundled || !exeLocalXdgOpen);
622
622
  command = useSystemXdgOpen ? "xdg-open" : localXdgOpenPath;
623
623
  }
624
624
  if (appArguments.length > 0) {
@@ -629,7 +629,7 @@ var init_open = __esm({
629
629
  childProcessOptions.detached = true;
630
630
  }
631
631
  }
632
- if (platform4 === "darwin" && appArguments.length > 0) {
632
+ if (platform3 === "darwin" && appArguments.length > 0) {
633
633
  cliArguments.push("--args", ...appArguments);
634
634
  }
635
635
  if (options2.target) {
@@ -754,8 +754,8 @@ var require_dist = __commonJS({
754
754
  var $global, $module, $NaN = NaN;
755
755
  if ("undefined" != typeof window ? $global = window : "undefined" != typeof self ? $global = self : "undefined" != typeof global ? ($global = global).require = __require : $global = this, void 0 === $global || void 0 === $global.Array) throw new Error("no global object found");
756
756
  if ("undefined" != typeof module && ($module = module), !$global.fs && $global.require) try {
757
- var fs33 = $global.require("fs");
758
- "object" == typeof fs33 && null !== fs33 && 0 !== Object.keys(fs33).length && ($global.fs = fs33);
757
+ var fs32 = $global.require("fs");
758
+ "object" == typeof fs32 && null !== fs32 && 0 !== Object.keys(fs32).length && ($global.fs = fs32);
759
759
  } catch (e) {
760
760
  }
761
761
  if (!$global.fs) {
@@ -183430,13 +183430,11 @@ import { Command } from "commander";
183430
183430
  import React2, { useState, useEffect } from "react";
183431
183431
  import { render as render2, Text as Text2, Box as Box2, useInput, useApp } from "ink";
183432
183432
  import "ink-spinner";
183433
- import * as fs12 from "fs";
183433
+ import * as fs11 from "fs";
183434
183434
  import * as path7 from "path";
183435
183435
 
183436
183436
  // src/lib/dev/system-setup.ts
183437
183437
  import { execSync as execSync2 } from "child_process";
183438
- import * as fs4 from "fs";
183439
- import * as os4 from "os";
183440
183438
  import * as path3 from "path";
183441
183439
 
183442
183440
  // src/lib/dev/local-ca.ts
@@ -183472,20 +183470,24 @@ function caInstalledInTrustStore() {
183472
183470
  if (!caFilesExist()) {
183473
183471
  return false;
183474
183472
  }
183475
- const platform6 = os.platform();
183473
+ const platform5 = os.platform();
183476
183474
  const certPath = path.join(getCADir(), "ca.crt");
183477
183475
  const diskCert = fs.readFileSync(certPath, "utf-8").replace(/\r\n/g, "\n").trim();
183478
183476
  try {
183479
- if (platform6 === "darwin") {
183477
+ if (platform5 === "darwin") {
183480
183478
  const keychainCert = execSync(
183481
183479
  'security find-certificate -c "Specific Local Development CA" -p /Library/Keychains/System.keychain',
183482
183480
  { encoding: "utf-8" }
183483
183481
  ).replace(/\r\n/g, "\n").trim();
183484
183482
  return keychainCert === diskCert;
183485
- } else if (platform6 === "linux") {
183483
+ } else if (platform5 === "linux") {
183486
183484
  const trustPaths = [
183487
183485
  "/usr/local/share/ca-certificates/specific-local-ca.crt",
183488
- "/etc/pki/ca-trust/source/anchors/specific-local-ca.crt"
183486
+ // Debian/Ubuntu
183487
+ "/etc/pki/ca-trust/source/anchors/specific-local-ca.crt",
183488
+ // RHEL/Fedora
183489
+ "/etc/ca-certificates/trust-source/anchors/specific-local-ca.crt"
183490
+ // Arch
183489
183491
  ];
183490
183492
  for (const trustPath of trustPaths) {
183491
183493
  if (fs.existsSync(trustPath)) {
@@ -183590,15 +183592,15 @@ function removeCA() {
183590
183592
  }
183591
183593
  }
183592
183594
  function getCAInstallCommands(certPath) {
183593
- const platform6 = os.platform();
183594
- if (platform6 === "darwin") {
183595
+ const platform5 = os.platform();
183596
+ if (platform5 === "darwin") {
183595
183597
  return [
183596
183598
  // Remove any existing cert with the same CN first — add-trusted-cert
183597
183599
  // silently does nothing if a cert with the same subject already exists.
183598
183600
  'security delete-certificate -c "Specific Local Development CA" /Library/Keychains/System.keychain 2>/dev/null || true',
183599
183601
  `security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain "${certPath}"`
183600
183602
  ];
183601
- } else if (platform6 === "linux") {
183603
+ } else if (platform5 === "linux") {
183602
183604
  if (fs.existsSync("/usr/local/share/ca-certificates")) {
183603
183605
  return [
183604
183606
  `cp "${certPath}" /usr/local/share/ca-certificates/specific-local-ca.crt`,
@@ -183609,10 +183611,15 @@ function getCAInstallCommands(certPath) {
183609
183611
  `cp "${certPath}" /etc/pki/ca-trust/source/anchors/specific-local-ca.crt`,
183610
183612
  "update-ca-trust extract"
183611
183613
  ];
183614
+ } else if (fs.existsSync("/etc/ca-certificates/trust-source/anchors")) {
183615
+ return [
183616
+ `cp "${certPath}" /etc/ca-certificates/trust-source/anchors/specific-local-ca.crt`,
183617
+ "trust extract-compat"
183618
+ ];
183612
183619
  }
183613
183620
  throw new Error("Could not detect Linux certificate trust mechanism");
183614
183621
  }
183615
- throw new Error(`Unsupported platform: ${platform6}`);
183622
+ throw new Error(`Unsupported platform: ${platform5}`);
183616
183623
  }
183617
183624
  function generateCertificate(domain, keys = []) {
183618
183625
  const caDir = getCADir();
@@ -183658,23 +183665,23 @@ var RESOLVER_FILE_MACOS = "/etc/resolver/spcf.localhost";
183658
183665
  var OLD_RESOLVER_FILE_MACOS = "/etc/resolver/local.spcf.app";
183659
183666
  var RESOLVER_FILE_LINUX = "/etc/systemd/resolved.conf.d/specific-local.conf";
183660
183667
  function resolverConfigExists() {
183661
- const platform6 = os2.platform();
183662
- if (platform6 === "darwin") {
183668
+ const platform5 = os2.platform();
183669
+ if (platform5 === "darwin") {
183663
183670
  return fs2.existsSync(RESOLVER_FILE_MACOS);
183664
- } else if (platform6 === "linux") {
183671
+ } else if (platform5 === "linux") {
183665
183672
  return fs2.existsSync(RESOLVER_FILE_LINUX);
183666
183673
  }
183667
183674
  return false;
183668
183675
  }
183669
183676
  function getResolverInstallCommands(port) {
183670
- const platform6 = os2.platform();
183671
- if (platform6 === "darwin") {
183677
+ const platform5 = os2.platform();
183678
+ if (platform5 === "darwin") {
183672
183679
  return [
183673
183680
  "mkdir -p /etc/resolver",
183674
183681
  `rm -f ${OLD_RESOLVER_FILE_MACOS}`,
183675
183682
  `printf "nameserver 127.0.0.1\\nport ${port}\\n" > ${RESOLVER_FILE_MACOS}`
183676
183683
  ];
183677
- } else if (platform6 === "linux") {
183684
+ } else if (platform5 === "linux") {
183678
183685
  if (fs2.existsSync("/etc/systemd/resolved.conf.d") || fs2.existsSync("/etc/systemd")) {
183679
183686
  return [
183680
183687
  "mkdir -p /etc/systemd/resolved.conf.d",
@@ -183793,7 +183800,7 @@ function performSystemSetup() {
183793
183800
  return;
183794
183801
  }
183795
183802
  try {
183796
- execPrivileged(commands);
183803
+ execSync2(`sudo sh -c '${commands.join(" && ")}'`, { stdio: "inherit" });
183797
183804
  } catch (err) {
183798
183805
  if (needsGenerate) {
183799
183806
  removeCA();
@@ -183801,43 +183808,14 @@ function performSystemSetup() {
183801
183808
  throw err;
183802
183809
  }
183803
183810
  }
183804
- function execPrivileged(commands) {
183805
- if (commands.length === 0) return;
183806
- if (os4.platform() === "darwin") {
183807
- const scriptPath = path3.join(os4.tmpdir(), "specific-setup.sh");
183808
- const appPath = path3.join(os4.tmpdir(), "Specific.app");
183809
- try {
183810
- fs4.writeFileSync(
183811
- scriptPath,
183812
- "#!/bin/sh\nset -e\n" + commands.join("\n") + "\n",
183813
- { mode: 448 }
183814
- );
183815
- execSync2(
183816
- `osacompile -o '${appPath}' -e 'do shell script "sh ${scriptPath}" with administrator privileges'`
183817
- );
183818
- execSync2(`'${appPath}/Contents/MacOS/applet'`, { stdio: "pipe" });
183819
- } finally {
183820
- try {
183821
- fs4.unlinkSync(scriptPath);
183822
- } catch {
183823
- }
183824
- try {
183825
- fs4.rmSync(appPath, { recursive: true });
183826
- } catch {
183827
- }
183828
- }
183829
- } else {
183830
- execSync2(`sudo sh -c '${commands.join(" && ")}'`, { stdio: "inherit" });
183831
- }
183832
- }
183833
183811
 
183834
183812
  // src/lib/analytics/index.ts
183835
183813
  import { PostHog } from "posthog-node";
183836
- import * as os7 from "os";
183814
+ import * as os6 from "os";
183837
183815
  import * as crypto from "crypto";
183838
183816
 
183839
183817
  // src/lib/project/config.ts
183840
- import * as fs5 from "fs";
183818
+ import * as fs4 from "fs";
183841
183819
  import * as path4 from "path";
183842
183820
  var PROJECT_ID_FILE = ".specific/project_id";
183843
183821
  var ProjectNotLinkedError = class extends Error {
@@ -183854,10 +183832,10 @@ Run: specific deploy`
183854
183832
  };
183855
183833
  function readProjectId(projectDir = process.cwd()) {
183856
183834
  const projectIdPath = path4.join(projectDir, PROJECT_ID_FILE);
183857
- if (!fs5.existsSync(projectIdPath)) {
183835
+ if (!fs4.existsSync(projectIdPath)) {
183858
183836
  throw new ProjectNotLinkedError();
183859
183837
  }
183860
- const projectId = fs5.readFileSync(projectIdPath, "utf-8").trim();
183838
+ const projectId = fs4.readFileSync(projectIdPath, "utf-8").trim();
183861
183839
  if (!projectId) {
183862
183840
  throw new Error(`${PROJECT_ID_FILE} is empty`);
183863
183841
  }
@@ -183865,20 +183843,20 @@ function readProjectId(projectDir = process.cwd()) {
183865
183843
  }
183866
183844
  function hasProjectId(projectDir = process.cwd()) {
183867
183845
  const projectIdPath = path4.join(projectDir, PROJECT_ID_FILE);
183868
- return fs5.existsSync(projectIdPath);
183846
+ return fs4.existsSync(projectIdPath);
183869
183847
  }
183870
183848
  function writeProjectId(projectId, projectDir = process.cwd()) {
183871
183849
  const specificDir = path4.join(projectDir, ".specific");
183872
- if (!fs5.existsSync(specificDir)) {
183873
- fs5.mkdirSync(specificDir, { recursive: true });
183850
+ if (!fs4.existsSync(specificDir)) {
183851
+ fs4.mkdirSync(specificDir, { recursive: true });
183874
183852
  }
183875
- fs5.writeFileSync(path4.join(specificDir, "project_id"), projectId + "\n");
183853
+ fs4.writeFileSync(path4.join(specificDir, "project_id"), projectId + "\n");
183876
183854
  }
183877
183855
 
183878
183856
  // src/lib/auth/credentials.ts
183879
- import * as fs11 from "fs";
183857
+ import * as fs10 from "fs";
183880
183858
  import * as path6 from "path";
183881
- import * as os6 from "os";
183859
+ import * as os5 from "os";
183882
183860
 
183883
183861
  // src/lib/auth/errors.ts
183884
183862
  var RefreshTokenExpiredError = class extends Error {
@@ -184362,9 +184340,12 @@ var ApiClient = class {
184362
184340
  }
184363
184341
  return response.json();
184364
184342
  }
184365
- async createProject(name) {
184343
+ async createProject(name, organizationId) {
184366
184344
  const url = `${this.baseUrl}/projects`;
184367
184345
  const requestBody = { name };
184346
+ if (organizationId) {
184347
+ requestBody.organizationId = organizationId;
184348
+ }
184368
184349
  writeLog("api", `POST ${url}`);
184369
184350
  writeLog("api", `Request body: ${JSON.stringify(requestBody)}`);
184370
184351
  const response = await fetch(url, {
@@ -184399,6 +184380,31 @@ var ApiClient = class {
184399
184380
  }
184400
184381
  return response.json();
184401
184382
  }
184383
+ async listOrganizations() {
184384
+ const url = `${this.baseUrl}/user/organizations`;
184385
+ writeLog("api", `GET ${url}`);
184386
+ const response = await fetch(url, {
184387
+ headers: await this.authHeaders()
184388
+ });
184389
+ writeLog("api", `Response: ${response.status} ${response.statusText}`);
184390
+ if (!response.ok) {
184391
+ let errorBody;
184392
+ try {
184393
+ const error = await response.json();
184394
+ errorBody = JSON.stringify(error);
184395
+ writeLog("api:error", `API error: ${error.error} (${error.code})`);
184396
+ throw new Error(`Failed to list organizations: ${error.error} (${error.code})`);
184397
+ } catch (e) {
184398
+ if (e instanceof Error && e.message.startsWith("Failed to list organizations")) {
184399
+ throw e;
184400
+ }
184401
+ errorBody = await response.text();
184402
+ writeLog("api:error", `Failed to parse error response: ${errorBody}`);
184403
+ throw new Error(`Failed to list organizations: ${response.statusText}`);
184404
+ }
184405
+ }
184406
+ return response.json();
184407
+ }
184402
184408
  async getMe(signal) {
184403
184409
  const url = `${this.baseUrl}/users/me`;
184404
184410
  writeLog("api", `GET ${url}`);
@@ -184431,18 +184437,18 @@ var ApiClient = class {
184431
184437
 
184432
184438
  // src/lib/auth/credentials.ts
184433
184439
  function getUserCredentialsDir() {
184434
- return path6.join(os6.homedir(), ".specific");
184440
+ return path6.join(os5.homedir(), ".specific");
184435
184441
  }
184436
184442
  function getCredentialsPath() {
184437
184443
  return path6.join(getUserCredentialsDir(), "credentials.json");
184438
184444
  }
184439
184445
  function readUserCredentials() {
184440
184446
  const credentialsPath = getCredentialsPath();
184441
- if (!fs11.existsSync(credentialsPath)) {
184447
+ if (!fs10.existsSync(credentialsPath)) {
184442
184448
  return null;
184443
184449
  }
184444
184450
  try {
184445
- const content = fs11.readFileSync(credentialsPath, "utf-8");
184451
+ const content = fs10.readFileSync(credentialsPath, "utf-8");
184446
184452
  return JSON.parse(content);
184447
184453
  } catch {
184448
184454
  return null;
@@ -184450,18 +184456,18 @@ function readUserCredentials() {
184450
184456
  }
184451
184457
  function writeUserCredentials(credentials) {
184452
184458
  const dir = getUserCredentialsDir();
184453
- if (!fs11.existsSync(dir)) {
184454
- fs11.mkdirSync(dir, { recursive: true, mode: 448 });
184459
+ if (!fs10.existsSync(dir)) {
184460
+ fs10.mkdirSync(dir, { recursive: true, mode: 448 });
184455
184461
  }
184456
184462
  const credentialsPath = getCredentialsPath();
184457
- fs11.writeFileSync(credentialsPath, JSON.stringify(credentials, null, 2), {
184463
+ fs10.writeFileSync(credentialsPath, JSON.stringify(credentials, null, 2), {
184458
184464
  mode: 384
184459
184465
  });
184460
184466
  }
184461
184467
  function clearUserCredentials() {
184462
184468
  const credentialsPath = getCredentialsPath();
184463
- if (fs11.existsSync(credentialsPath)) {
184464
- fs11.unlinkSync(credentialsPath);
184469
+ if (fs10.existsSync(credentialsPath)) {
184470
+ fs10.unlinkSync(credentialsPath);
184465
184471
  }
184466
184472
  }
184467
184473
  function isLoggedIn() {
@@ -184540,7 +184546,7 @@ function isEnabled() {
184540
184546
  }
184541
184547
  function getAnonymousId() {
184542
184548
  if (anonymousId) return anonymousId;
184543
- const machineId = `${os7.hostname()}-${os7.userInfo().username}`;
184549
+ const machineId = `${os6.hostname()}-${os6.userInfo().username}`;
184544
184550
  anonymousId = crypto.createHash("sha256").update(machineId).digest("hex").slice(0, 16);
184545
184551
  return anonymousId;
184546
184552
  }
@@ -184587,7 +184593,7 @@ function trackEvent(event, properties) {
184587
184593
  event,
184588
184594
  properties: {
184589
184595
  ...properties,
184590
- cli_version: "0.1.74",
184596
+ cli_version: "0.1.76",
184591
184597
  platform: process.platform,
184592
184598
  node_version: process.version,
184593
184599
  project_id: getProjectId()
@@ -184624,57 +184630,57 @@ var options = [
184624
184630
  ];
184625
184631
  function isGitProject() {
184626
184632
  const gitPath = path7.join(process.cwd(), ".git");
184627
- return fs12.existsSync(gitPath);
184633
+ return fs11.existsSync(gitPath);
184628
184634
  }
184629
184635
  function detectExistingAgents() {
184630
184636
  const detected = {};
184631
184637
  const cursorDir = path7.join(process.cwd(), ".cursor");
184632
- if (fs12.existsSync(cursorDir)) {
184638
+ if (fs11.existsSync(cursorDir)) {
184633
184639
  detected["cursor"] = true;
184634
184640
  }
184635
184641
  const claudeDir = path7.join(process.cwd(), ".claude");
184636
184642
  const claudeMd = path7.join(process.cwd(), "CLAUDE.md");
184637
- if (fs12.existsSync(claudeDir) || fs12.existsSync(claudeMd)) {
184643
+ if (fs11.existsSync(claudeDir) || fs11.existsSync(claudeMd)) {
184638
184644
  detected["claude"] = true;
184639
184645
  }
184640
184646
  const agentsMd = path7.join(process.cwd(), "AGENTS.md");
184641
- if (fs12.existsSync(agentsMd)) {
184647
+ if (fs11.existsSync(agentsMd)) {
184642
184648
  detected["codex"] = true;
184643
184649
  }
184644
184650
  return detected;
184645
184651
  }
184646
184652
  function appendOrCreateFile(filePath, content) {
184647
- if (fs12.existsSync(filePath)) {
184648
- const existing = fs12.readFileSync(filePath, "utf-8");
184653
+ if (fs11.existsSync(filePath)) {
184654
+ const existing = fs11.readFileSync(filePath, "utf-8");
184649
184655
  if (existing.includes("specific docs") || existing.includes("specific check")) {
184650
184656
  return "unchanged";
184651
184657
  }
184652
184658
  const separator = existing.endsWith("\n") ? "\n" : "\n\n";
184653
- fs12.writeFileSync(filePath, existing + separator + content + "\n");
184659
+ fs11.writeFileSync(filePath, existing + separator + content + "\n");
184654
184660
  return "modified";
184655
184661
  } else {
184656
- fs12.writeFileSync(filePath, content + "\n");
184662
+ fs11.writeFileSync(filePath, content + "\n");
184657
184663
  return "created";
184658
184664
  }
184659
184665
  }
184660
184666
  function addToGitignore() {
184661
184667
  const gitignorePath = path7.join(process.cwd(), ".gitignore");
184662
184668
  const entries = [".specific", "specific.local"];
184663
- if (fs12.existsSync(gitignorePath)) {
184664
- const existing = fs12.readFileSync(gitignorePath, "utf-8");
184669
+ if (fs11.existsSync(gitignorePath)) {
184670
+ const existing = fs11.readFileSync(gitignorePath, "utf-8");
184665
184671
  const lines = existing.split("\n").map((l) => l.trim());
184666
184672
  const missingEntries = entries.filter((entry) => !lines.includes(entry));
184667
184673
  if (missingEntries.length === 0) {
184668
184674
  return "unchanged";
184669
184675
  }
184670
184676
  const separator = existing.endsWith("\n") ? "" : "\n";
184671
- fs12.writeFileSync(
184677
+ fs11.writeFileSync(
184672
184678
  gitignorePath,
184673
184679
  existing + separator + missingEntries.join("\n") + "\n"
184674
184680
  );
184675
184681
  return "modified";
184676
184682
  } else {
184677
- fs12.writeFileSync(gitignorePath, entries.join("\n") + "\n");
184683
+ fs11.writeFileSync(gitignorePath, entries.join("\n") + "\n");
184678
184684
  return "created";
184679
184685
  }
184680
184686
  }
@@ -184682,8 +184688,8 @@ function configureClaudeCodePermissions() {
184682
184688
  const claudeDir = path7.join(process.cwd(), ".claude");
184683
184689
  const settingsPath = path7.join(claudeDir, "settings.local.json");
184684
184690
  const permissions = ["Bash(specific docs:*)", "Bash(specific check:*)"];
184685
- if (fs12.existsSync(settingsPath)) {
184686
- const existing = JSON.parse(fs12.readFileSync(settingsPath, "utf-8"));
184691
+ if (fs11.existsSync(settingsPath)) {
184692
+ const existing = JSON.parse(fs11.readFileSync(settingsPath, "utf-8"));
184687
184693
  const allowList = existing?.permissions?.allow || [];
184688
184694
  const missingPermissions = permissions.filter(
184689
184695
  (p) => !allowList.includes(p)
@@ -184698,39 +184704,39 @@ function configureClaudeCodePermissions() {
184698
184704
  existing.permissions.allow = [];
184699
184705
  }
184700
184706
  existing.permissions.allow.push(...missingPermissions);
184701
- fs12.writeFileSync(settingsPath, JSON.stringify(existing, null, 2) + "\n");
184707
+ fs11.writeFileSync(settingsPath, JSON.stringify(existing, null, 2) + "\n");
184702
184708
  return "modified";
184703
184709
  }
184704
- if (!fs12.existsSync(claudeDir)) {
184705
- fs12.mkdirSync(claudeDir);
184710
+ if (!fs11.existsSync(claudeDir)) {
184711
+ fs11.mkdirSync(claudeDir);
184706
184712
  }
184707
184713
  const settings = {
184708
184714
  permissions: {
184709
184715
  allow: permissions
184710
184716
  }
184711
184717
  };
184712
- fs12.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
184718
+ fs11.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
184713
184719
  return "created";
184714
184720
  }
184715
184721
  function createCursorRule() {
184716
184722
  const cursorDir = path7.join(process.cwd(), ".cursor");
184717
184723
  const rulesDir = path7.join(cursorDir, "rules");
184718
184724
  const mdcPath = path7.join(rulesDir, "specific.mdc");
184719
- if (fs12.existsSync(mdcPath)) {
184720
- const existing = fs12.readFileSync(mdcPath, "utf-8");
184725
+ if (fs11.existsSync(mdcPath)) {
184726
+ const existing = fs11.readFileSync(mdcPath, "utf-8");
184721
184727
  if (existing.includes("specific docs") || existing.includes("specific check")) {
184722
184728
  return "unchanged";
184723
184729
  }
184724
- fs12.writeFileSync(mdcPath, CURSOR_MDC_CONTENT);
184730
+ fs11.writeFileSync(mdcPath, CURSOR_MDC_CONTENT);
184725
184731
  return "modified";
184726
184732
  }
184727
- if (!fs12.existsSync(cursorDir)) {
184728
- fs12.mkdirSync(cursorDir);
184733
+ if (!fs11.existsSync(cursorDir)) {
184734
+ fs11.mkdirSync(cursorDir);
184729
184735
  }
184730
- if (!fs12.existsSync(rulesDir)) {
184731
- fs12.mkdirSync(rulesDir);
184736
+ if (!fs11.existsSync(rulesDir)) {
184737
+ fs11.mkdirSync(rulesDir);
184732
184738
  }
184733
- fs12.writeFileSync(mdcPath, CURSOR_MDC_CONTENT);
184739
+ fs11.writeFileSync(mdcPath, CURSOR_MDC_CONTENT);
184734
184740
  return "created";
184735
184741
  }
184736
184742
  function configureAgents(checked) {
@@ -184973,7 +184979,7 @@ var BETA_REGISTRY = [
184973
184979
  ];
184974
184980
 
184975
184981
  // src/lib/beta/storage.ts
184976
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync6, existsSync as existsSync6, mkdirSync as mkdirSync6 } from "fs";
184982
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync5, existsSync as existsSync6, mkdirSync as mkdirSync6 } from "fs";
184977
184983
  import { join as join7 } from "path";
184978
184984
  var BETAS_FILE = ".specific/betas.json";
184979
184985
  function loadEnabledBetas(projectDir = process.cwd()) {
@@ -185006,7 +185012,7 @@ function saveBetas(enabled, projectDir) {
185006
185012
  mkdirSync6(specificDir, { recursive: true });
185007
185013
  }
185008
185014
  const data = { enabled };
185009
- writeFileSync6(
185015
+ writeFileSync5(
185010
185016
  join7(projectDir, BETAS_FILE),
185011
185017
  JSON.stringify(data, null, 2) + "\n"
185012
185018
  );
@@ -185073,7 +185079,7 @@ function resolveFilesystemDoc(path30) {
185073
185079
  import React3, { useState as useState2, useEffect as useEffect2 } from "react";
185074
185080
  import { render as render3, Text as Text3, Box as Box3 } from "ink";
185075
185081
  import Spinner3 from "ink-spinner";
185076
- import * as fs14 from "fs";
185082
+ import * as fs13 from "fs";
185077
185083
  import * as path9 from "path";
185078
185084
  import { execFile as execFile7 } from "child_process";
185079
185085
 
@@ -185945,32 +185951,32 @@ var ExtractionError = class extends Error {
185945
185951
  };
185946
185952
 
185947
185953
  // src/lib/bin/manager.ts
185948
- import * as fs13 from "fs";
185954
+ import * as fs12 from "fs";
185949
185955
  import * as path8 from "path";
185950
- import * as os8 from "os";
185956
+ import * as os7 from "os";
185951
185957
  import { createReadStream } from "fs";
185952
185958
  import { createTarExtractor, extractTo } from "tar-vern";
185953
185959
  function getLibraryEnv(binary) {
185954
185960
  if (!binary.libraryPath) {
185955
185961
  return {};
185956
185962
  }
185957
- const platform6 = os8.platform();
185958
- if (platform6 === "darwin") {
185963
+ const platform5 = os7.platform();
185964
+ if (platform5 === "darwin") {
185959
185965
  return { DYLD_LIBRARY_PATH: binary.libraryPath };
185960
- } else if (platform6 === "linux") {
185966
+ } else if (platform5 === "linux") {
185961
185967
  return { LD_LIBRARY_PATH: binary.libraryPath };
185962
185968
  }
185963
185969
  return {};
185964
185970
  }
185965
185971
  function getBinBaseDir() {
185966
- return path8.join(os8.homedir(), ".specific", "bin");
185972
+ return path8.join(os7.homedir(), ".specific", "bin");
185967
185973
  }
185968
185974
  function getPlatformInfo() {
185969
- const platform6 = os8.platform();
185970
- const arch3 = os8.arch();
185971
- if (platform6 !== "darwin" && platform6 !== "linux") {
185975
+ const platform5 = os7.platform();
185976
+ const arch3 = os7.arch();
185977
+ if (platform5 !== "darwin" && platform5 !== "linux") {
185972
185978
  throw new Error(
185973
- `Unsupported platform: ${platform6}. Only macOS and Linux are supported.`
185979
+ `Unsupported platform: ${platform5}. Only macOS and Linux are supported.`
185974
185980
  );
185975
185981
  }
185976
185982
  const archStr = arch3;
@@ -185984,7 +185990,7 @@ function getPlatformInfo() {
185984
185990
  `Unsupported architecture: ${arch3}. Only x64 and arm64 are supported.`
185985
185991
  );
185986
185992
  }
185987
- return { platform: platform6, arch: mappedArch };
185993
+ return { platform: platform5, arch: mappedArch };
185988
185994
  }
185989
185995
  function getBinaryDir(definition, version, platformInfo) {
185990
185996
  return path8.join(
@@ -185998,7 +186004,7 @@ function isBinaryInstalled(definition, version, platformInfo) {
185998
186004
  const binDir = getBinaryDir(definition, version, platformInfo);
185999
186005
  for (const execPath of definition.executables) {
186000
186006
  const fullPath = path8.join(binDir, execPath);
186001
- if (!fs13.existsSync(fullPath)) {
186007
+ if (!fs12.existsSync(fullPath)) {
186002
186008
  return false;
186003
186009
  }
186004
186010
  }
@@ -186027,11 +186033,11 @@ async function downloadFile(url, destPath, onProgress) {
186027
186033
  );
186028
186034
  let bytesDownloaded = 0;
186029
186035
  const parentDir = path8.dirname(destPath);
186030
- if (!fs13.existsSync(parentDir)) {
186031
- fs13.mkdirSync(parentDir, { recursive: true });
186036
+ if (!fs12.existsSync(parentDir)) {
186037
+ fs12.mkdirSync(parentDir, { recursive: true });
186032
186038
  }
186033
186039
  const partPath = destPath + ".part";
186034
- const fileStream = fs13.createWriteStream(partPath);
186040
+ const fileStream = fs12.createWriteStream(partPath);
186035
186041
  try {
186036
186042
  const reader = response.body.getReader();
186037
186043
  while (true) {
@@ -186054,12 +186060,12 @@ async function downloadFile(url, destPath, onProgress) {
186054
186060
  else resolve9();
186055
186061
  });
186056
186062
  });
186057
- fs13.renameSync(partPath, destPath);
186063
+ fs12.renameSync(partPath, destPath);
186058
186064
  } catch (error) {
186059
186065
  try {
186060
186066
  fileStream.close();
186061
- if (fs13.existsSync(partPath)) {
186062
- fs13.unlinkSync(partPath);
186067
+ if (fs12.existsSync(partPath)) {
186068
+ fs12.unlinkSync(partPath);
186063
186069
  }
186064
186070
  } catch {
186065
186071
  }
@@ -186068,8 +186074,8 @@ async function downloadFile(url, destPath, onProgress) {
186068
186074
  }
186069
186075
  async function extractTarball(archivePath, destDir, definition, onProgress) {
186070
186076
  onProgress?.({ phase: "extracting" });
186071
- if (!fs13.existsSync(destDir)) {
186072
- fs13.mkdirSync(destDir, { recursive: true });
186077
+ if (!fs12.existsSync(destDir)) {
186078
+ fs12.mkdirSync(destDir, { recursive: true });
186073
186079
  }
186074
186080
  try {
186075
186081
  const fileStream = createReadStream(archivePath);
@@ -186078,8 +186084,8 @@ async function extractTarball(archivePath, destDir, definition, onProgress) {
186078
186084
  onProgress?.({ phase: "finalizing" });
186079
186085
  for (const execPath of definition.executables) {
186080
186086
  const fullPath = path8.join(destDir, execPath);
186081
- if (fs13.existsSync(fullPath)) {
186082
- fs13.chmodSync(fullPath, 493);
186087
+ if (fs12.existsSync(fullPath)) {
186088
+ fs12.chmodSync(fullPath, 493);
186083
186089
  }
186084
186090
  }
186085
186091
  } catch (error) {
@@ -186103,12 +186109,12 @@ async function ensureBinary(definition, version, onProgress) {
186103
186109
  `Binary type definitions must have exactly one executable, got ${definition.executables.length}`
186104
186110
  );
186105
186111
  }
186106
- if (!fs13.existsSync(binDir)) {
186107
- fs13.mkdirSync(binDir, { recursive: true });
186112
+ if (!fs12.existsSync(binDir)) {
186113
+ fs12.mkdirSync(binDir, { recursive: true });
186108
186114
  }
186109
186115
  const execPath = path8.join(binDir, definition.executables[0]);
186110
186116
  await downloadFile(url, execPath, onProgress);
186111
- fs13.chmodSync(execPath, 493);
186117
+ fs12.chmodSync(execPath, 493);
186112
186118
  onProgress?.({ phase: "finalizing" });
186113
186119
  } else {
186114
186120
  const downloadDir = path8.join(getBinBaseDir(), "downloads");
@@ -186119,8 +186125,8 @@ async function ensureBinary(definition, version, onProgress) {
186119
186125
  await extractTarball(archivePath, binDir, definition, onProgress);
186120
186126
  } finally {
186121
186127
  try {
186122
- if (fs13.existsSync(archivePath)) {
186123
- fs13.unlinkSync(archivePath);
186128
+ if (fs12.existsSync(archivePath)) {
186129
+ fs12.unlinkSync(archivePath);
186124
186130
  }
186125
186131
  } catch {
186126
186132
  }
@@ -186296,20 +186302,20 @@ function CheckUI() {
186296
186302
  useEffect2(() => {
186297
186303
  async function load() {
186298
186304
  const configPath = path9.join(process.cwd(), "specific.hcl");
186299
- if (!fs14.existsSync(configPath)) {
186305
+ if (!fs13.existsSync(configPath)) {
186300
186306
  setState({
186301
186307
  status: "error",
186302
186308
  error: "No specific.hcl found in current directory"
186303
186309
  });
186304
186310
  return;
186305
186311
  }
186306
- const hcl = fs14.readFileSync(configPath, "utf-8");
186312
+ const hcl = fs13.readFileSync(configPath, "utf-8");
186307
186313
  try {
186308
186314
  const config2 = await parseConfig(hcl);
186309
186315
  for (const build of config2.builds) {
186310
186316
  if (build.dockerfile) {
186311
186317
  const dockerfilePath = path9.resolve(process.cwd(), build.dockerfile);
186312
- if (!fs14.existsSync(dockerfilePath)) {
186318
+ if (!fs13.existsSync(dockerfilePath)) {
186313
186319
  setState({
186314
186320
  status: "error",
186315
186321
  error: `Build "${build.name}": Dockerfile not found at "${build.dockerfile}" (resolved to ${dockerfilePath})`
@@ -186325,7 +186331,7 @@ function CheckUI() {
186325
186331
  process.cwd(),
186326
186332
  pg.reshape.migrations_dir ?? "migrations"
186327
186333
  );
186328
- if (!fs14.existsSync(migrationsDir)) {
186334
+ if (!fs13.existsSync(migrationsDir)) {
186329
186335
  reshapeChecks2.push({
186330
186336
  databaseName: pg.name,
186331
186337
  migrationsDir: pg.reshape.migrations_dir ?? "migrations",
@@ -186378,7 +186384,7 @@ function checkCommand() {
186378
186384
  import React6, { useState as useState5, useEffect as useEffect3, useRef } from "react";
186379
186385
  import { render as render4, Text as Text6, Box as Box6, useApp as useApp2, Static, useInput as useInput4 } from "ink";
186380
186386
  import Spinner4 from "ink-spinner";
186381
- import * as fs24 from "fs";
186387
+ import * as fs23 from "fs";
186382
186388
  import * as path20 from "path";
186383
186389
 
186384
186390
  // node_modules/.pnpm/chokidar@5.0.0/node_modules/chokidar/index.js
@@ -188133,7 +188139,7 @@ var PortAllocator = class {
188133
188139
  };
188134
188140
 
188135
188141
  // src/lib/dev/stable-port-allocator.ts
188136
- import * as fs15 from "fs";
188142
+ import * as fs14 from "fs";
188137
188143
  import * as path10 from "path";
188138
188144
  var PORT_RANGE_START2 = 4e4;
188139
188145
  var PORT_RANGE_END2 = 49999;
@@ -188148,11 +188154,11 @@ var StablePortAllocator = class {
188148
188154
  this.loadPorts();
188149
188155
  }
188150
188156
  loadPorts() {
188151
- if (!fs15.existsSync(this.portsFilePath)) {
188157
+ if (!fs14.existsSync(this.portsFilePath)) {
188152
188158
  return;
188153
188159
  }
188154
188160
  try {
188155
- const content = fs15.readFileSync(this.portsFilePath, "utf-8");
188161
+ const content = fs14.readFileSync(this.portsFilePath, "utf-8");
188156
188162
  const data = JSON.parse(content);
188157
188163
  if (data.version === 1 && data.ports) {
188158
188164
  this.savedPorts = data.ports;
@@ -188165,14 +188171,14 @@ var StablePortAllocator = class {
188165
188171
  }
188166
188172
  }
188167
188173
  savePorts() {
188168
- if (!fs15.existsSync(this.portsDir)) {
188169
- fs15.mkdirSync(this.portsDir, { recursive: true });
188174
+ if (!fs14.existsSync(this.portsDir)) {
188175
+ fs14.mkdirSync(this.portsDir, { recursive: true });
188170
188176
  }
188171
188177
  const data = {
188172
188178
  version: 1,
188173
188179
  ports: this.savedPorts
188174
188180
  };
188175
- fs15.writeFileSync(this.portsFilePath, JSON.stringify(data, null, 2));
188181
+ fs14.writeFileSync(this.portsFilePath, JSON.stringify(data, null, 2));
188176
188182
  }
188177
188183
  allocateRandom() {
188178
188184
  const rangeSize = PORT_RANGE_END2 - PORT_RANGE_START2 + 1;
@@ -188199,7 +188205,7 @@ var StablePortAllocator = class {
188199
188205
  };
188200
188206
 
188201
188207
  // src/lib/dev/database-manager.ts
188202
- import * as fs16 from "fs";
188208
+ import * as fs15 from "fs";
188203
188209
  import * as path11 from "path";
188204
188210
  import * as net from "net";
188205
188211
  import { spawn } from "child_process";
@@ -188211,9 +188217,9 @@ async function startPostgres(pg, port, dataDir, onProgress) {
188211
188217
  const password = "postgres";
188212
188218
  const libraryEnv = getLibraryEnv(binary);
188213
188219
  const env2 = { ...process.env, ...libraryEnv };
188214
- const dataExists = fs16.existsSync(dbDataPath);
188220
+ const dataExists = fs15.existsSync(dbDataPath);
188215
188221
  if (!dataExists) {
188216
- fs16.mkdirSync(dbDataPath, { recursive: true });
188222
+ fs15.mkdirSync(dbDataPath, { recursive: true });
188217
188223
  await runCommand(
188218
188224
  binary.executables["initdb"],
188219
188225
  ["-D", dbDataPath, "-U", user, "--auth=trust", "--no-locale", "-E", "UTF8"],
@@ -188290,8 +188296,8 @@ async function startRedis(redis, port, onProgress) {
188290
188296
  async function startStorage(storage, port, dataDir) {
188291
188297
  const S3rver = (await import("s3rver")).default;
188292
188298
  const storageDataPath = path11.join(process.cwd(), dataDir, storage.name);
188293
- if (!fs16.existsSync(storageDataPath)) {
188294
- fs16.mkdirSync(storageDataPath, { recursive: true });
188299
+ if (!fs15.existsSync(storageDataPath)) {
188300
+ fs15.mkdirSync(storageDataPath, { recursive: true });
188295
188301
  }
188296
188302
  const host = "127.0.0.1";
188297
188303
  const accessKey = "S3RVER";
@@ -188934,7 +188940,7 @@ function startService(service, resources, secrets, configs, endpointPorts, servi
188934
188940
  }
188935
188941
 
188936
188942
  // src/lib/dev/instance-state.ts
188937
- import * as fs17 from "fs";
188943
+ import * as fs16 from "fs";
188938
188944
  import * as path12 from "path";
188939
188945
  var InstanceStateManager = class {
188940
188946
  stateDir;
@@ -188952,8 +188958,8 @@ var InstanceStateManager = class {
188952
188958
  return this.key;
188953
188959
  }
188954
188960
  ensureStateDir() {
188955
- if (!fs17.existsSync(this.stateDir)) {
188956
- fs17.mkdirSync(this.stateDir, { recursive: true });
188961
+ if (!fs16.existsSync(this.stateDir)) {
188962
+ fs16.mkdirSync(this.stateDir, { recursive: true });
188957
188963
  }
188958
188964
  }
188959
188965
  isProcessRunning(pid) {
@@ -188970,15 +188976,15 @@ var InstanceStateManager = class {
188970
188976
  const startTime = Date.now();
188971
188977
  while (Date.now() - startTime < timeoutMs) {
188972
188978
  try {
188973
- const fd = fs17.openSync(
188979
+ const fd = fs16.openSync(
188974
188980
  this.lockPath,
188975
- fs17.constants.O_CREAT | fs17.constants.O_EXCL | fs17.constants.O_WRONLY
188981
+ fs16.constants.O_CREAT | fs16.constants.O_EXCL | fs16.constants.O_WRONLY
188976
188982
  );
188977
- fs17.writeSync(fd, String(process.pid));
188978
- fs17.closeSync(fd);
188983
+ fs16.writeSync(fd, String(process.pid));
188984
+ fs16.closeSync(fd);
188979
188985
  return () => {
188980
188986
  try {
188981
- fs17.unlinkSync(this.lockPath);
188987
+ fs16.unlinkSync(this.lockPath);
188982
188988
  } catch {
188983
188989
  }
188984
188990
  };
@@ -188987,16 +188993,16 @@ var InstanceStateManager = class {
188987
188993
  if (err.code === "EEXIST") {
188988
188994
  try {
188989
188995
  const lockPid = parseInt(
188990
- fs17.readFileSync(this.lockPath, "utf-8").trim(),
188996
+ fs16.readFileSync(this.lockPath, "utf-8").trim(),
188991
188997
  10
188992
188998
  );
188993
188999
  if (!this.isProcessRunning(lockPid)) {
188994
- fs17.unlinkSync(this.lockPath);
189000
+ fs16.unlinkSync(this.lockPath);
188995
189001
  continue;
188996
189002
  }
188997
189003
  } catch {
188998
189004
  try {
188999
- fs17.unlinkSync(this.lockPath);
189005
+ fs16.unlinkSync(this.lockPath);
189000
189006
  } catch {
189001
189007
  }
189002
189008
  continue;
@@ -189010,12 +189016,12 @@ var InstanceStateManager = class {
189010
189016
  throw new Error("Failed to acquire state lock (timeout)");
189011
189017
  }
189012
189018
  async getExistingInstances() {
189013
- if (!fs17.existsSync(this.statePath)) {
189019
+ if (!fs16.existsSync(this.statePath)) {
189014
189020
  return null;
189015
189021
  }
189016
189022
  const releaseLock = await this.acquireLock();
189017
189023
  try {
189018
- const content = fs17.readFileSync(this.statePath, "utf-8");
189024
+ const content = fs16.readFileSync(this.statePath, "utf-8");
189019
189025
  const state = JSON.parse(content);
189020
189026
  if (!this.isProcessRunning(state.owner.pid)) {
189021
189027
  return null;
@@ -189028,21 +189034,21 @@ var InstanceStateManager = class {
189028
189034
  }
189029
189035
  }
189030
189036
  async cleanStaleState() {
189031
- if (!fs17.existsSync(this.statePath)) {
189037
+ if (!fs16.existsSync(this.statePath)) {
189032
189038
  return false;
189033
189039
  }
189034
189040
  const releaseLock = await this.acquireLock();
189035
189041
  try {
189036
- const content = fs17.readFileSync(this.statePath, "utf-8");
189042
+ const content = fs16.readFileSync(this.statePath, "utf-8");
189037
189043
  const state = JSON.parse(content);
189038
189044
  if (!this.isProcessRunning(state.owner.pid)) {
189039
- fs17.unlinkSync(this.statePath);
189045
+ fs16.unlinkSync(this.statePath);
189040
189046
  return true;
189041
189047
  }
189042
189048
  return false;
189043
189049
  } catch {
189044
189050
  try {
189045
- fs17.unlinkSync(this.statePath);
189051
+ fs16.unlinkSync(this.statePath);
189046
189052
  return true;
189047
189053
  } catch {
189048
189054
  }
@@ -189054,8 +189060,8 @@ var InstanceStateManager = class {
189054
189060
  async claimOwnership(command) {
189055
189061
  const releaseLock = await this.acquireLock();
189056
189062
  try {
189057
- if (fs17.existsSync(this.statePath)) {
189058
- const content = fs17.readFileSync(this.statePath, "utf-8");
189063
+ if (fs16.existsSync(this.statePath)) {
189064
+ const content = fs16.readFileSync(this.statePath, "utf-8");
189059
189065
  const state2 = JSON.parse(content);
189060
189066
  if (this.isProcessRunning(state2.owner.pid)) {
189061
189067
  throw new Error(`Instances already owned by PID ${state2.owner.pid}`);
@@ -189124,8 +189130,8 @@ var InstanceStateManager = class {
189124
189130
  }
189125
189131
  const releaseLock = await this.acquireLock();
189126
189132
  try {
189127
- if (fs17.existsSync(this.statePath)) {
189128
- fs17.unlinkSync(this.statePath);
189133
+ if (fs16.existsSync(this.statePath)) {
189134
+ fs16.unlinkSync(this.statePath);
189129
189135
  }
189130
189136
  this.ownsInstances = false;
189131
189137
  } finally {
@@ -189133,21 +189139,21 @@ var InstanceStateManager = class {
189133
189139
  }
189134
189140
  }
189135
189141
  readState() {
189136
- const content = fs17.readFileSync(this.statePath, "utf-8");
189142
+ const content = fs16.readFileSync(this.statePath, "utf-8");
189137
189143
  return JSON.parse(content);
189138
189144
  }
189139
189145
  writeStateAtomic(state) {
189140
189146
  this.ensureStateDir();
189141
189147
  const tmpPath = this.statePath + ".tmp";
189142
- fs17.writeFileSync(tmpPath, JSON.stringify(state, null, 2));
189143
- fs17.renameSync(tmpPath, this.statePath);
189148
+ fs16.writeFileSync(tmpPath, JSON.stringify(state, null, 2));
189149
+ fs16.renameSync(tmpPath, this.statePath);
189144
189150
  }
189145
189151
  };
189146
189152
 
189147
189153
  // src/lib/dev/http-proxy.ts
189148
189154
  import * as http from "http";
189149
189155
  import * as https from "https";
189150
- import * as fs18 from "fs";
189156
+ import * as fs17 from "fs";
189151
189157
  import * as path13 from "path";
189152
189158
  import { fileURLToPath as fileURLToPath3 } from "url";
189153
189159
  import httpProxy from "http-proxy";
@@ -189555,10 +189561,10 @@ function serveFilesystemFile(res, pathname) {
189555
189561
  res.end("<h1>Forbidden</h1>");
189556
189562
  return;
189557
189563
  }
189558
- if (fs18.existsSync(resolvedPath)) {
189559
- if (fs18.statSync(resolvedPath).isDirectory()) {
189564
+ if (fs17.existsSync(resolvedPath)) {
189565
+ if (fs17.statSync(resolvedPath).isDirectory()) {
189560
189566
  const indexPath2 = path13.join(resolvedPath, "index.html");
189561
- if (fs18.existsSync(indexPath2)) {
189567
+ if (fs17.existsSync(indexPath2)) {
189562
189568
  return serveFile(res, indexPath2);
189563
189569
  }
189564
189570
  } else {
@@ -189566,15 +189572,15 @@ function serveFilesystemFile(res, pathname) {
189566
189572
  }
189567
189573
  }
189568
189574
  const htmlPath = resolvedPath + ".html";
189569
- if (fs18.existsSync(htmlPath)) {
189575
+ if (fs17.existsSync(htmlPath)) {
189570
189576
  return serveFile(res, htmlPath);
189571
189577
  }
189572
189578
  const indexPath = path13.join(resolvedPath, "index.html");
189573
- if (fs18.existsSync(indexPath)) {
189579
+ if (fs17.existsSync(indexPath)) {
189574
189580
  return serveFile(res, indexPath);
189575
189581
  }
189576
189582
  const notFoundPath = path13.join(adminDir, "404.html");
189577
- if (fs18.existsSync(notFoundPath)) {
189583
+ if (fs17.existsSync(notFoundPath)) {
189578
189584
  return serveFileContent(res, notFoundPath, "text/html", 404);
189579
189585
  }
189580
189586
  res.writeHead(404, { "Content-Type": "text/html" });
@@ -189587,7 +189593,7 @@ function serveFile(res, filePath) {
189587
189593
  }
189588
189594
  function serveFileContent(res, filePath, contentType, statusCode = 200) {
189589
189595
  try {
189590
- const content = fs18.readFileSync(filePath);
189596
+ const content = fs17.readFileSync(filePath);
189591
189597
  res.writeHead(statusCode, { "Content-Type": contentType });
189592
189598
  res.end(content);
189593
189599
  } catch (err) {
@@ -189962,7 +189968,7 @@ async function startMailServer(mail, smtpPort, apiPort) {
189962
189968
 
189963
189969
  // src/lib/dev/drizzle-gateway-manager.ts
189964
189970
  import * as net3 from "net";
189965
- import * as fs19 from "fs";
189971
+ import * as fs18 from "fs";
189966
189972
  import * as path15 from "path";
189967
189973
  import { spawn as spawn4 } from "child_process";
189968
189974
  import { randomUUID as randomUUID2 } from "crypto";
@@ -189996,12 +190002,12 @@ async function startDrizzleGateway(postgresInstances, port, configDir, options2)
189996
190002
  );
189997
190003
  const host = "127.0.0.1";
189998
190004
  const drizzleConfigDir = path15.join(configDir, "drizzle-gateway");
189999
- if (!fs19.existsSync(drizzleConfigDir)) {
190000
- fs19.mkdirSync(drizzleConfigDir, { recursive: true });
190005
+ if (!fs18.existsSync(drizzleConfigDir)) {
190006
+ fs18.mkdirSync(drizzleConfigDir, { recursive: true });
190001
190007
  }
190002
190008
  const storeJson = generateStoreJson(postgresInstances);
190003
190009
  const storeJsonPath = path15.join(drizzleConfigDir, "store.json");
190004
- fs19.writeFileSync(storeJsonPath, JSON.stringify(storeJson, null, 2));
190010
+ fs18.writeFileSync(storeJsonPath, JSON.stringify(storeJson, null, 2));
190005
190011
  writeLog("drizzle-gateway", `Starting Drizzle Gateway`);
190006
190012
  writeLog("drizzle-gateway", `STORE_PATH: ${drizzleConfigDir}`);
190007
190013
  writeLog("drizzle-gateway", `PORT: ${port}`);
@@ -190103,16 +190109,16 @@ function detectSyncDatabases(config) {
190103
190109
  }
190104
190110
 
190105
190111
  // src/lib/dev/reshape-watcher.ts
190106
- import * as fs20 from "fs";
190112
+ import * as fs19 from "fs";
190107
190113
  import * as path16 from "path";
190108
190114
  import { spawnSync } from "child_process";
190109
190115
  function getMigrationFiles(dir, log) {
190110
190116
  log(`Scanning migrations directory: ${dir}`);
190111
- if (!fs20.existsSync(dir)) {
190117
+ if (!fs19.existsSync(dir)) {
190112
190118
  log(`Migrations directory does not exist: ${dir}`);
190113
190119
  return [];
190114
190120
  }
190115
- const files = fs20.readdirSync(dir);
190121
+ const files = fs19.readdirSync(dir);
190116
190122
  log(`Found ${files.length} files in directory`);
190117
190123
  const tomlFiles = files.filter((f) => f.endsWith(".toml")).sort((a, b) => a.localeCompare(b));
190118
190124
  log(`Found ${tomlFiles.length} .toml migration files: ${tomlFiles.join(", ") || "(none)"}`);
@@ -190162,7 +190168,7 @@ function runReshape(args, databaseUrl, migrationsDir, reshapeBinaryPath, log) {
190162
190168
  }
190163
190169
  function makeReadOnly(filePath, log) {
190164
190170
  try {
190165
- fs20.chmodSync(filePath, 292);
190171
+ fs19.chmodSync(filePath, 292);
190166
190172
  log(`Set file permissions to read-only (444): ${filePath}`);
190167
190173
  } catch (err) {
190168
190174
  const message = err instanceof Error ? err.message : String(err);
@@ -190248,9 +190254,9 @@ function createReshapeWatcher(options2) {
190248
190254
  };
190249
190255
  const startWatching = () => {
190250
190256
  log(`Starting file watcher for migrations directory...`);
190251
- if (!fs20.existsSync(migrationsDir)) {
190257
+ if (!fs19.existsSync(migrationsDir)) {
190252
190258
  log(`Migrations directory does not exist, creating: ${migrationsDir}`);
190253
- fs20.mkdirSync(migrationsDir, { recursive: true });
190259
+ fs19.mkdirSync(migrationsDir, { recursive: true });
190254
190260
  }
190255
190261
  log(`Watching directory: ${migrationsDir}`);
190256
190262
  watcher = chokidar_default.watch(migrationsDir, {
@@ -190385,7 +190391,7 @@ function createReshapeWatcher(options2) {
190385
190391
  }
190386
190392
 
190387
190393
  // src/lib/dev/temporal-manager.ts
190388
- import * as fs21 from "fs";
190394
+ import * as fs20 from "fs";
190389
190395
  import * as path17 from "path";
190390
190396
  import * as net4 from "net";
190391
190397
  import { spawn as spawn5 } from "child_process";
@@ -190393,8 +190399,8 @@ async function startTemporalDevServer(temporals, grpcPort, uiPort, dataDir, onPr
190393
190399
  const binary = await ensureBinary(temporalBinary, void 0, onProgress);
190394
190400
  const dbPath = path17.join(process.cwd(), dataDir, "temporal.db");
190395
190401
  const dbDir = path17.dirname(dbPath);
190396
- if (!fs21.existsSync(dbDir)) {
190397
- fs21.mkdirSync(dbDir, { recursive: true });
190402
+ if (!fs20.existsSync(dbDir)) {
190403
+ fs20.mkdirSync(dbDir, { recursive: true });
190398
190404
  }
190399
190405
  const host = "127.0.0.1";
190400
190406
  const namespaceArgs = temporals.flatMap((t) => ["--namespace", t.name]);
@@ -190723,7 +190729,7 @@ function watchConfigFile(configPath, debounceMs, onChange) {
190723
190729
  }
190724
190730
 
190725
190731
  // src/lib/dev/subdomain-generator.ts
190726
- import * as fs22 from "fs";
190732
+ import * as fs21 from "fs";
190727
190733
  import * as path18 from "path";
190728
190734
  import { generateSlug } from "random-word-slugs";
190729
190735
  var StableSubdomainAllocator = class {
@@ -190736,11 +190742,11 @@ var StableSubdomainAllocator = class {
190736
190742
  this.loadTunnels();
190737
190743
  }
190738
190744
  loadTunnels() {
190739
- if (!fs22.existsSync(this.tunnelsFilePath)) {
190745
+ if (!fs21.existsSync(this.tunnelsFilePath)) {
190740
190746
  return;
190741
190747
  }
190742
190748
  try {
190743
- const content = fs22.readFileSync(this.tunnelsFilePath, "utf-8");
190749
+ const content = fs21.readFileSync(this.tunnelsFilePath, "utf-8");
190744
190750
  const data = JSON.parse(content);
190745
190751
  if (data.version === 1 && data.baseSlug) {
190746
190752
  this.baseSlug = data.baseSlug;
@@ -190750,14 +190756,14 @@ var StableSubdomainAllocator = class {
190750
190756
  }
190751
190757
  }
190752
190758
  saveTunnels() {
190753
- if (!fs22.existsSync(this.tunnelsDir)) {
190754
- fs22.mkdirSync(this.tunnelsDir, { recursive: true });
190759
+ if (!fs21.existsSync(this.tunnelsDir)) {
190760
+ fs21.mkdirSync(this.tunnelsDir, { recursive: true });
190755
190761
  }
190756
190762
  const data = {
190757
190763
  version: 1,
190758
190764
  baseSlug: this.baseSlug
190759
190765
  };
190760
- fs22.writeFileSync(this.tunnelsFilePath, JSON.stringify(data, null, 2));
190766
+ fs21.writeFileSync(this.tunnelsFilePath, JSON.stringify(data, null, 2));
190761
190767
  }
190762
190768
  generateBaseSlug() {
190763
190769
  return generateSlug(2, {
@@ -190913,9 +190919,9 @@ async function startTunnel(serviceName, endpointName, port, subdomain, callbacks
190913
190919
  }
190914
190920
 
190915
190921
  // src/lib/dev/proxy-registry.ts
190916
- import * as fs23 from "fs";
190922
+ import * as fs22 from "fs";
190917
190923
  import * as path19 from "path";
190918
- import * as os9 from "os";
190924
+ import * as os8 from "os";
190919
190925
  import * as net6 from "net";
190920
190926
  var ProxyRegistryManager = class {
190921
190927
  proxyDir;
@@ -190925,14 +190931,14 @@ var ProxyRegistryManager = class {
190925
190931
  isOwner = false;
190926
190932
  registryWatcher = null;
190927
190933
  constructor() {
190928
- this.proxyDir = path19.join(os9.homedir(), ".specific", "proxy");
190934
+ this.proxyDir = path19.join(os8.homedir(), ".specific", "proxy");
190929
190935
  this.ownerPath = path19.join(this.proxyDir, "owner.json");
190930
190936
  this.registryPath = path19.join(this.proxyDir, "registry.json");
190931
190937
  this.lockPath = path19.join(this.proxyDir, "registry.lock");
190932
190938
  }
190933
190939
  ensureProxyDir() {
190934
- if (!fs23.existsSync(this.proxyDir)) {
190935
- fs23.mkdirSync(this.proxyDir, { recursive: true });
190940
+ if (!fs22.existsSync(this.proxyDir)) {
190941
+ fs22.mkdirSync(this.proxyDir, { recursive: true });
190936
190942
  }
190937
190943
  }
190938
190944
  isProcessRunning(pid) {
@@ -190989,15 +190995,15 @@ var ProxyRegistryManager = class {
190989
190995
  const startTime = Date.now();
190990
190996
  while (Date.now() - startTime < timeoutMs) {
190991
190997
  try {
190992
- const fd = fs23.openSync(
190998
+ const fd = fs22.openSync(
190993
190999
  this.lockPath,
190994
- fs23.constants.O_CREAT | fs23.constants.O_EXCL | fs23.constants.O_WRONLY
191000
+ fs22.constants.O_CREAT | fs22.constants.O_EXCL | fs22.constants.O_WRONLY
190995
191001
  );
190996
- fs23.writeSync(fd, String(process.pid));
190997
- fs23.closeSync(fd);
191002
+ fs22.writeSync(fd, String(process.pid));
191003
+ fs22.closeSync(fd);
190998
191004
  return () => {
190999
191005
  try {
191000
- fs23.unlinkSync(this.lockPath);
191006
+ fs22.unlinkSync(this.lockPath);
191001
191007
  } catch {
191002
191008
  }
191003
191009
  };
@@ -191006,16 +191012,16 @@ var ProxyRegistryManager = class {
191006
191012
  if (err.code === "EEXIST") {
191007
191013
  try {
191008
191014
  const lockPid = parseInt(
191009
- fs23.readFileSync(this.lockPath, "utf-8").trim(),
191015
+ fs22.readFileSync(this.lockPath, "utf-8").trim(),
191010
191016
  10
191011
191017
  );
191012
191018
  if (!this.isProcessRunning(lockPid)) {
191013
- fs23.unlinkSync(this.lockPath);
191019
+ fs22.unlinkSync(this.lockPath);
191014
191020
  continue;
191015
191021
  }
191016
191022
  } catch {
191017
191023
  try {
191018
- fs23.unlinkSync(this.lockPath);
191024
+ fs22.unlinkSync(this.lockPath);
191019
191025
  } catch {
191020
191026
  }
191021
191027
  continue;
@@ -191035,8 +191041,8 @@ var ProxyRegistryManager = class {
191035
191041
  async claimProxyOwnership(key) {
191036
191042
  const releaseLock = await this.acquireLock();
191037
191043
  try {
191038
- if (fs23.existsSync(this.ownerPath)) {
191039
- const content = fs23.readFileSync(this.ownerPath, "utf-8");
191044
+ if (fs22.existsSync(this.ownerPath)) {
191045
+ const content = fs22.readFileSync(this.ownerPath, "utf-8");
191040
191046
  const ownerFile2 = JSON.parse(content);
191041
191047
  if (await this.isProxyOwnerHealthy(ownerFile2.owner.pid)) {
191042
191048
  return false;
@@ -191066,11 +191072,11 @@ var ProxyRegistryManager = class {
191066
191072
  }
191067
191073
  const releaseLock = await this.acquireLock();
191068
191074
  try {
191069
- if (fs23.existsSync(this.ownerPath)) {
191070
- const content = fs23.readFileSync(this.ownerPath, "utf-8");
191075
+ if (fs22.existsSync(this.ownerPath)) {
191076
+ const content = fs22.readFileSync(this.ownerPath, "utf-8");
191071
191077
  const ownerFile = JSON.parse(content);
191072
191078
  if (ownerFile.owner.pid === process.pid) {
191073
- fs23.unlinkSync(this.ownerPath);
191079
+ fs22.unlinkSync(this.ownerPath);
191074
191080
  }
191075
191081
  }
191076
191082
  this.isOwner = false;
@@ -191082,12 +191088,12 @@ var ProxyRegistryManager = class {
191082
191088
  * Get the current proxy owner.
191083
191089
  */
191084
191090
  async getProxyOwner() {
191085
- if (!fs23.existsSync(this.ownerPath)) {
191091
+ if (!fs22.existsSync(this.ownerPath)) {
191086
191092
  return null;
191087
191093
  }
191088
191094
  const releaseLock = await this.acquireLock();
191089
191095
  try {
191090
- const content = fs23.readFileSync(this.ownerPath, "utf-8");
191096
+ const content = fs22.readFileSync(this.ownerPath, "utf-8");
191091
191097
  const ownerFile = JSON.parse(content);
191092
191098
  if (!await this.isProxyOwnerHealthy(ownerFile.owner.pid)) {
191093
191099
  return null;
@@ -191184,7 +191190,7 @@ var ProxyRegistryManager = class {
191184
191190
  */
191185
191191
  watchRegistry(onChange) {
191186
191192
  this.ensureProxyDir();
191187
- if (!fs23.existsSync(this.registryPath)) {
191193
+ if (!fs22.existsSync(this.registryPath)) {
191188
191194
  const emptyRegistry = {
191189
191195
  version: 1,
191190
191196
  keys: {},
@@ -191227,13 +191233,13 @@ var ProxyRegistryManager = class {
191227
191233
  async attemptElection(key) {
191228
191234
  const releaseLock = await this.acquireLock();
191229
191235
  try {
191230
- if (fs23.existsSync(this.ownerPath)) {
191231
- const content = fs23.readFileSync(this.ownerPath, "utf-8");
191236
+ if (fs22.existsSync(this.ownerPath)) {
191237
+ const content = fs22.readFileSync(this.ownerPath, "utf-8");
191232
191238
  const ownerFile2 = JSON.parse(content);
191233
191239
  if (await this.isProxyOwnerHealthy(ownerFile2.owner.pid)) {
191234
191240
  return false;
191235
191241
  }
191236
- fs23.unlinkSync(this.ownerPath);
191242
+ fs22.unlinkSync(this.ownerPath);
191237
191243
  }
191238
191244
  const ownerFile = {
191239
191245
  version: 1,
@@ -191251,7 +191257,7 @@ var ProxyRegistryManager = class {
191251
191257
  }
191252
191258
  }
191253
191259
  readRegistry() {
191254
- if (!fs23.existsSync(this.registryPath)) {
191260
+ if (!fs22.existsSync(this.registryPath)) {
191255
191261
  return {
191256
191262
  version: 1,
191257
191263
  keys: {},
@@ -191259,7 +191265,7 @@ var ProxyRegistryManager = class {
191259
191265
  };
191260
191266
  }
191261
191267
  try {
191262
- const content = fs23.readFileSync(this.registryPath, "utf-8");
191268
+ const content = fs22.readFileSync(this.registryPath, "utf-8");
191263
191269
  return JSON.parse(content);
191264
191270
  } catch {
191265
191271
  return {
@@ -191272,8 +191278,8 @@ var ProxyRegistryManager = class {
191272
191278
  writeFileAtomic(filePath, data) {
191273
191279
  this.ensureProxyDir();
191274
191280
  const tmpPath = filePath + ".tmp";
191275
- fs23.writeFileSync(tmpPath, JSON.stringify(data, null, 2));
191276
- fs23.renameSync(tmpPath, filePath);
191281
+ fs22.writeFileSync(tmpPath, JSON.stringify(data, null, 2));
191282
+ fs22.renameSync(tmpPath, filePath);
191277
191283
  }
191278
191284
  };
191279
191285
 
@@ -191596,7 +191602,7 @@ function DevUI({ instanceKey, tunnelEnabled }) {
191596
191602
  const configPath = path20.join(process.cwd(), "specific.hcl");
191597
191603
  const watcher = watchConfigFile(configPath, 1e3, () => {
191598
191604
  try {
191599
- const hcl = fs24.readFileSync(configPath, "utf-8");
191605
+ const hcl = fs23.readFileSync(configPath, "utf-8");
191600
191606
  parseConfig(hcl).then(() => {
191601
191607
  triggerReload();
191602
191608
  }).catch((err) => {
@@ -191722,7 +191728,7 @@ function DevUI({ instanceKey, tunnelEnabled }) {
191722
191728
  return;
191723
191729
  }
191724
191730
  const configPath = path20.join(process.cwd(), "specific.hcl");
191725
- if (!fs24.existsSync(configPath)) {
191731
+ if (!fs23.existsSync(configPath)) {
191726
191732
  writeLog("system", "Waiting for specific.hcl to appear");
191727
191733
  setState((s) => ({
191728
191734
  ...s,
@@ -191740,7 +191746,7 @@ function DevUI({ instanceKey, tunnelEnabled }) {
191740
191746
  return;
191741
191747
  }
191742
191748
  let config2;
191743
- const hcl = fs24.readFileSync(configPath, "utf-8");
191749
+ const hcl = fs23.readFileSync(configPath, "utf-8");
191744
191750
  try {
191745
191751
  config2 = await parseConfig(hcl);
191746
191752
  } catch (err) {
@@ -192067,7 +192073,7 @@ Add them to the config block in specific.local`);
192067
192073
  if (service.volumes) {
192068
192074
  for (const vol of service.volumes) {
192069
192075
  const volumeDir = path20.resolve(`.specific/keys/${instanceKey}/data/volumes/${service.name}/${vol.name}`);
192070
- fs24.mkdirSync(volumeDir, { recursive: true });
192076
+ fs23.mkdirSync(volumeDir, { recursive: true });
192071
192077
  volumePaths.set(vol.name, volumeDir);
192072
192078
  }
192073
192079
  }
@@ -192123,7 +192129,7 @@ Add them to the config block in specific.local`);
192123
192129
  if (service.volumes) {
192124
192130
  for (const vol of service.volumes) {
192125
192131
  const volumeDir = path20.resolve(`.specific/keys/${instanceKey}/data/volumes/${service.name}/${vol.name}`);
192126
- fs24.mkdirSync(volumeDir, { recursive: true });
192132
+ fs23.mkdirSync(volumeDir, { recursive: true });
192127
192133
  volumePaths.set(vol.name, volumeDir);
192128
192134
  }
192129
192135
  }
@@ -192694,12 +192700,12 @@ init_open();
192694
192700
  import React7, { useState as useState6, useEffect as useEffect4, useCallback } from "react";
192695
192701
  import { render as render5, Text as Text7, Box as Box7, useApp as useApp3, useInput as useInput5 } from "ink";
192696
192702
  import Spinner5 from "ink-spinner";
192697
- import * as fs26 from "fs";
192703
+ import * as fs25 from "fs";
192698
192704
  import * as path23 from "path";
192699
192705
 
192700
192706
  // src/lib/tarball/create.ts
192701
192707
  import { execSync as execSync4 } from "child_process";
192702
- import * as fs25 from "fs";
192708
+ import * as fs24 from "fs";
192703
192709
  import * as path22 from "path";
192704
192710
  import { createTarPacker, createEntryItemGenerator } from "tar-vern";
192705
192711
  function isInsideGitRepository(dir) {
@@ -192757,7 +192763,7 @@ var EXCLUDED_DIRS = [
192757
192763
  ];
192758
192764
  async function collectPaths(baseDir, currentDir, exclude) {
192759
192765
  const results = [];
192760
- const entries = await fs25.promises.readdir(currentDir, { withFileTypes: true });
192766
+ const entries = await fs24.promises.readdir(currentDir, { withFileTypes: true });
192761
192767
  for (const entry of entries) {
192762
192768
  const fullPath = path22.join(currentDir, entry.name);
192763
192769
  const relativePath = path22.relative(baseDir, fullPath);
@@ -192776,7 +192782,7 @@ async function collectPaths(baseDir, currentDir, exclude) {
192776
192782
  async function createTarArchive(projectDir) {
192777
192783
  writeLog("tarball", "Creating tarball using tar-vern (non-git project)");
192778
192784
  const configPath = path22.join(projectDir, "specific.hcl");
192779
- if (!fs25.existsSync(configPath)) {
192785
+ if (!fs24.existsSync(configPath)) {
192780
192786
  throw new Error("specific.hcl not found in project directory");
192781
192787
  }
192782
192788
  const relativePaths = await collectPaths(projectDir, projectDir, EXCLUDED_DIRS);
@@ -192866,22 +192872,35 @@ function PhaseIndicator({
192866
192872
  }
192867
192873
  return /* @__PURE__ */ React7.createElement(Text7, null, /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, " ", "\u25CB"), " ", /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, label));
192868
192874
  }
192875
+ function buildSelectorItems(projects, organizations) {
192876
+ const items = [];
192877
+ for (const org of organizations) {
192878
+ items.push({ type: "header", orgName: org.name });
192879
+ items.push({ type: "new", orgId: org.id });
192880
+ const orgProjects = projects.filter((p) => p.organizationId === org.id);
192881
+ for (const project of orgProjects) {
192882
+ items.push({ type: "project", project });
192883
+ }
192884
+ }
192885
+ return items;
192886
+ }
192869
192887
  function ProjectSelector({
192870
192888
  projects,
192889
+ organizations,
192871
192890
  selectedIndex,
192872
192891
  onSelect,
192873
192892
  onUp,
192874
192893
  onDown
192875
192894
  }) {
192895
+ const items = buildSelectorItems(projects, organizations);
192896
+ const selectableIndices = items.map((item, index) => item.type !== "header" ? index : -1).filter((i) => i >= 0);
192876
192897
  useInput5((input, key) => {
192877
192898
  if (key.return) {
192878
- if (selectedIndex === 0) {
192879
- onSelect("new");
192880
- } else {
192881
- const project = projects[selectedIndex - 1];
192882
- if (project) {
192883
- onSelect(project);
192884
- }
192899
+ const item = items[selectedIndex];
192900
+ if (item?.type === "new") {
192901
+ onSelect({ type: "new", orgId: item.orgId });
192902
+ } else if (item?.type === "project") {
192903
+ onSelect(item.project);
192885
192904
  }
192886
192905
  } else if (key.upArrow) {
192887
192906
  onUp();
@@ -192889,11 +192908,16 @@ function ProjectSelector({
192889
192908
  onDown();
192890
192909
  }
192891
192910
  });
192892
- const items = [
192893
- { id: "new", name: "Create new project", isNew: true },
192894
- ...projects.map((p) => ({ ...p, isNew: false }))
192895
- ];
192896
- return /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", gap: 1 }, /* @__PURE__ */ React7.createElement(Text7, { bold: true }, "Select a project to deploy:"), /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column" }, items.map((item, index) => /* @__PURE__ */ React7.createElement(Text7, { key: item.id }, index === selectedIndex ? /* @__PURE__ */ React7.createElement(Text7, { color: "cyan" }, "> ") : /* @__PURE__ */ React7.createElement(Text7, null, " "), item.isNew ? /* @__PURE__ */ React7.createElement(Text7, { color: "green" }, item.name) : /* @__PURE__ */ React7.createElement(Text7, null, item.name, " ", /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, "(", item.id, ")"))))), /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, "Use arrow keys to navigate, Enter to select"));
192911
+ return /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", gap: 1 }, /* @__PURE__ */ React7.createElement(Text7, { bold: true }, "Select a project to deploy:"), /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column" }, items.map((item, index) => {
192912
+ if (item.type === "header") {
192913
+ return /* @__PURE__ */ React7.createElement(Text7, { key: `header-${item.orgName}` }, index > 0 ? "\n" : "", /* @__PURE__ */ React7.createElement(Text7, { bold: true }, item.orgName));
192914
+ }
192915
+ const isSelected = index === selectedIndex;
192916
+ if (item.type === "new") {
192917
+ return /* @__PURE__ */ React7.createElement(Text7, { key: `new-${item.orgId}` }, isSelected ? /* @__PURE__ */ React7.createElement(Text7, { color: "cyan" }, " ", "> ") : /* @__PURE__ */ React7.createElement(Text7, null, " "), /* @__PURE__ */ React7.createElement(Text7, { color: "green" }, "Create new project"));
192918
+ }
192919
+ return /* @__PURE__ */ React7.createElement(Text7, { key: item.project.id }, isSelected ? /* @__PURE__ */ React7.createElement(Text7, { color: "cyan" }, " ", "> ") : /* @__PURE__ */ React7.createElement(Text7, null, " "), /* @__PURE__ */ React7.createElement(Text7, null, item.project.name, " ", /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, "(", item.project.id, ")")));
192920
+ })), /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, "Use arrow keys to navigate, Enter to select"));
192897
192921
  }
192898
192922
  function NameInput({ onSubmit, onCancel }) {
192899
192923
  const [value, setValue] = useState6("");
@@ -193040,12 +193064,18 @@ function DeployUI({ environment, config }) {
193040
193064
  async function loadProjects() {
193041
193065
  try {
193042
193066
  const client2 = new ApiClient();
193043
- const { projects: projects2 } = await client2.listProjects();
193067
+ const [{ projects: projects2 }, { organizations }] = await Promise.all([
193068
+ client2.listProjects(),
193069
+ client2.listOrganizations()
193070
+ ]);
193044
193071
  if (cancelled) return;
193072
+ const items = buildSelectorItems(projects2, organizations);
193073
+ const firstSelectable = items.findIndex((item) => item.type !== "header");
193045
193074
  setState({
193046
193075
  phase: "selecting-project",
193047
193076
  projects: projects2,
193048
- selectedIndex: 0
193077
+ organizations,
193078
+ selectedIndex: firstSelectable >= 0 ? firstSelectable : 0
193049
193079
  });
193050
193080
  } catch (err) {
193051
193081
  if (cancelled) return;
@@ -193062,13 +193092,14 @@ function DeployUI({ environment, config }) {
193062
193092
  }, [state.phase]);
193063
193093
  const handleProjectSelect = useCallback(
193064
193094
  (project) => {
193065
- if (project === "new") {
193066
- setState((s) => ({ ...s, phase: "entering-name" }));
193095
+ if ("type" in project && project.type === "new") {
193096
+ setState((s) => ({ ...s, phase: "entering-name", selectedOrganizationId: project.orgId }));
193067
193097
  } else {
193068
- writeProjectId(project.id);
193098
+ const proj = project;
193099
+ writeProjectId(proj.id);
193069
193100
  setState({
193070
193101
  phase: "creating-tarball",
193071
- projectId: project.id
193102
+ projectId: proj.id
193072
193103
  });
193073
193104
  }
193074
193105
  },
@@ -193086,7 +193117,7 @@ function DeployUI({ environment, config }) {
193086
193117
  async function createProject() {
193087
193118
  try {
193088
193119
  const client2 = new ApiClient();
193089
- const project = await client2.createProject(state.newProjectName);
193120
+ const project = await client2.createProject(state.newProjectName, state.selectedOrganizationId);
193090
193121
  if (cancelled) return;
193091
193122
  writeProjectId(project.id);
193092
193123
  setState({
@@ -193562,24 +193593,28 @@ function DeployUI({ environment, config }) {
193562
193593
  if (phase === "loading-projects") {
193563
193594
  return /* @__PURE__ */ React7.createElement(Box7, null, /* @__PURE__ */ React7.createElement(Text7, { color: "blue" }, /* @__PURE__ */ React7.createElement(Spinner5, { type: "dots" })), /* @__PURE__ */ React7.createElement(Text7, null, " Loading projects..."));
193564
193595
  }
193565
- if (phase === "selecting-project" && projects && selectedIndex !== void 0) {
193596
+ if (phase === "selecting-project" && projects && state.organizations && selectedIndex !== void 0) {
193597
+ const selectorItems = buildSelectorItems(projects, state.organizations);
193598
+ const selectableIndices = selectorItems.map((item, index) => item.type !== "header" ? index : -1).filter((i) => i >= 0);
193566
193599
  return /* @__PURE__ */ React7.createElement(
193567
193600
  ProjectSelector,
193568
193601
  {
193569
193602
  projects,
193603
+ organizations: state.organizations,
193570
193604
  selectedIndex,
193571
193605
  onSelect: handleProjectSelect,
193572
- onUp: () => setState((s) => ({
193573
- ...s,
193574
- selectedIndex: Math.max(0, (s.selectedIndex || 0) - 1)
193575
- })),
193576
- onDown: () => setState((s) => ({
193577
- ...s,
193578
- selectedIndex: Math.min(
193579
- s.projects?.length || 0,
193580
- (s.selectedIndex || 0) + 1
193581
- )
193582
- }))
193606
+ onUp: () => setState((s) => {
193607
+ const idx = s.selectedIndex ?? 0;
193608
+ const currentPos = selectableIndices.indexOf(idx);
193609
+ const prevPos = Math.max(0, currentPos - 1);
193610
+ return { ...s, selectedIndex: selectableIndices[prevPos] ?? idx };
193611
+ }),
193612
+ onDown: () => setState((s) => {
193613
+ const idx = s.selectedIndex ?? 0;
193614
+ const currentPos = selectableIndices.indexOf(idx);
193615
+ const nextPos = Math.min(selectableIndices.length - 1, currentPos + 1);
193616
+ return { ...s, selectedIndex: selectableIndices[nextPos] ?? idx };
193617
+ })
193583
193618
  }
193584
193619
  );
193585
193620
  }
@@ -193669,12 +193704,12 @@ function DeployUI({ environment, config }) {
193669
193704
  }
193670
193705
  async function deployCommand(environment) {
193671
193706
  const configPath = path23.join(process.cwd(), "specific.hcl");
193672
- if (!fs26.existsSync(configPath)) {
193707
+ if (!fs25.existsSync(configPath)) {
193673
193708
  console.error("Error: No specific.hcl found in current directory");
193674
193709
  process.exit(1);
193675
193710
  }
193676
193711
  let config;
193677
- const hcl = fs26.readFileSync(configPath, "utf-8");
193712
+ const hcl = fs25.readFileSync(configPath, "utf-8");
193678
193713
  try {
193679
193714
  config = await parseConfig(hcl);
193680
193715
  } catch (err) {
@@ -193695,7 +193730,7 @@ async function deployCommand(environment) {
193695
193730
 
193696
193731
  // src/commands/exec.tsx
193697
193732
  import { spawn as spawn6 } from "child_process";
193698
- import * as fs27 from "fs";
193733
+ import * as fs26 from "fs";
193699
193734
  import * as path24 from "path";
193700
193735
  async function execCommand(serviceName, command, instanceKey = "default") {
193701
193736
  if (command.length === 0) {
@@ -193725,12 +193760,12 @@ async function execCommand(serviceName, command, instanceKey = "default") {
193725
193760
  }
193726
193761
  };
193727
193762
  const configPath = path24.join(process.cwd(), "specific.hcl");
193728
- if (!fs27.existsSync(configPath)) {
193763
+ if (!fs26.existsSync(configPath)) {
193729
193764
  console.error("Error: No specific.hcl found in current directory");
193730
193765
  process.exit(1);
193731
193766
  }
193732
193767
  let config;
193733
- const hcl = fs27.readFileSync(configPath, "utf-8");
193768
+ const hcl = fs26.readFileSync(configPath, "utf-8");
193734
193769
  try {
193735
193770
  config = await parseConfig(hcl);
193736
193771
  } catch (err) {
@@ -193880,7 +193915,7 @@ async function execCommand(serviceName, command, instanceKey = "default") {
193880
193915
 
193881
193916
  // src/commands/psql.tsx
193882
193917
  import { spawn as spawn7 } from "child_process";
193883
- import * as fs28 from "fs";
193918
+ import * as fs27 from "fs";
193884
193919
  import * as path25 from "path";
193885
193920
  async function psqlCommand(databaseName, instanceKey = "default", extraArgs = []) {
193886
193921
  let startedResources = [];
@@ -193899,12 +193934,12 @@ async function psqlCommand(databaseName, instanceKey = "default", extraArgs = []
193899
193934
  }
193900
193935
  };
193901
193936
  const configPath = path25.join(process.cwd(), "specific.hcl");
193902
- if (!fs28.existsSync(configPath)) {
193937
+ if (!fs27.existsSync(configPath)) {
193903
193938
  console.error("Error: No specific.hcl found in current directory");
193904
193939
  process.exit(1);
193905
193940
  }
193906
193941
  let config;
193907
- const hcl = fs28.readFileSync(configPath, "utf-8");
193942
+ const hcl = fs27.readFileSync(configPath, "utf-8");
193908
193943
  try {
193909
193944
  config = await parseConfig(hcl);
193910
193945
  } catch (err) {
@@ -194028,7 +194063,7 @@ async function psqlCommand(databaseName, instanceKey = "default", extraArgs = []
194028
194063
 
194029
194064
  // src/commands/reshape.tsx
194030
194065
  import { spawn as spawn8 } from "child_process";
194031
- import * as fs29 from "fs";
194066
+ import * as fs28 from "fs";
194032
194067
  import * as path26 from "path";
194033
194068
  var VALID_ACTIONS = ["start", "complete", "status", "abort", "check"];
194034
194069
  var MIGRATION_SUBCOMMANDS = ["start", "complete", "abort"];
@@ -194046,8 +194081,8 @@ async function reshapeCommand(action, databaseName, instanceKey = "default") {
194046
194081
  let migrationsDir = "migrations";
194047
194082
  let targetDb;
194048
194083
  try {
194049
- if (fs29.existsSync(configPath)) {
194050
- const configContent = fs29.readFileSync(configPath, "utf-8");
194084
+ if (fs28.existsSync(configPath)) {
194085
+ const configContent = fs28.readFileSync(configPath, "utf-8");
194051
194086
  config = await parseConfig(configContent);
194052
194087
  if (databaseName) {
194053
194088
  const postgresConfig = config.postgres.find((p) => p.name === databaseName);
@@ -194183,7 +194218,7 @@ async function reshapeCommand(action, databaseName, instanceKey = "default") {
194183
194218
  const reshapeArgs = isMigrationSubcommand ? ["migration", action] : [action];
194184
194219
  const fullMigrationsPath = path26.join(process.cwd(), migrationsDir);
194185
194220
  if (action === "check" || action === "start") {
194186
- if (fs29.existsSync(fullMigrationsPath)) {
194221
+ if (fs28.existsSync(fullMigrationsPath)) {
194187
194222
  reshapeArgs.push("--dirs", fullMigrationsPath);
194188
194223
  } else if (action === "check") {
194189
194224
  console.error(`Error: Migrations directory not found: ${fullMigrationsPath}`);
@@ -194233,7 +194268,7 @@ async function reshapeCommand(action, databaseName, instanceKey = "default") {
194233
194268
  import React8, { useState as useState7, useEffect as useEffect5 } from "react";
194234
194269
  import { render as render6, Text as Text8, Box as Box8 } from "ink";
194235
194270
  import Spinner6 from "ink-spinner";
194236
- import * as fs30 from "fs";
194271
+ import * as fs29 from "fs";
194237
194272
  import * as path27 from "path";
194238
194273
  function CleanUI({ instanceKey }) {
194239
194274
  const [state, setState] = useState7({ status: "checking" });
@@ -194241,13 +194276,13 @@ function CleanUI({ instanceKey }) {
194241
194276
  async function clean() {
194242
194277
  const projectRoot = process.cwd();
194243
194278
  const specificDir = path27.join(projectRoot, ".specific");
194244
- if (!fs30.existsSync(specificDir)) {
194279
+ if (!fs29.existsSync(specificDir)) {
194245
194280
  setState({ status: "nothing" });
194246
194281
  return;
194247
194282
  }
194248
194283
  if (instanceKey) {
194249
194284
  const keyDir = path27.join(specificDir, "keys", instanceKey);
194250
- if (!fs30.existsSync(keyDir)) {
194285
+ if (!fs29.existsSync(keyDir)) {
194251
194286
  setState({ status: "nothing" });
194252
194287
  return;
194253
194288
  }
@@ -194263,7 +194298,7 @@ function CleanUI({ instanceKey }) {
194263
194298
  await stateManager.cleanStaleState();
194264
194299
  setState({ status: "cleaning" });
194265
194300
  try {
194266
- fs30.rmSync(keyDir, { recursive: true, force: true });
194301
+ fs29.rmSync(keyDir, { recursive: true, force: true });
194267
194302
  setState({ status: "success" });
194268
194303
  } catch (err) {
194269
194304
  setState({
@@ -194273,12 +194308,12 @@ function CleanUI({ instanceKey }) {
194273
194308
  }
194274
194309
  } else {
194275
194310
  const keysDir = path27.join(specificDir, "keys");
194276
- if (!fs30.existsSync(keysDir)) {
194311
+ if (!fs29.existsSync(keysDir)) {
194277
194312
  setState({ status: "nothing" });
194278
194313
  return;
194279
194314
  }
194280
- const keys = fs30.readdirSync(keysDir).filter(
194281
- (f) => fs30.statSync(path27.join(keysDir, f)).isDirectory()
194315
+ const keys = fs29.readdirSync(keysDir).filter(
194316
+ (f) => fs29.statSync(path27.join(keysDir, f)).isDirectory()
194282
194317
  );
194283
194318
  for (const key of keys) {
194284
194319
  const stateManager2 = new InstanceStateManager(projectRoot, key);
@@ -194302,7 +194337,7 @@ function CleanUI({ instanceKey }) {
194302
194337
  }
194303
194338
  setState({ status: "cleaning" });
194304
194339
  try {
194305
- fs30.rmSync(keysDir, { recursive: true, force: true });
194340
+ fs29.rmSync(keysDir, { recursive: true, force: true });
194306
194341
  setState({ status: "success" });
194307
194342
  } catch (err) {
194308
194343
  setState({
@@ -194467,7 +194502,7 @@ import { render as render9, Text as Text11, Box as Box10, useApp as useApp6 } fr
194467
194502
  import Spinner7 from "ink-spinner";
194468
194503
 
194469
194504
  // src/lib/update.ts
194470
- import * as fs31 from "fs";
194505
+ import * as fs30 from "fs";
194471
194506
  import * as path28 from "path";
194472
194507
  var BINARIES_BASE_URL = "https://binaries.specific.dev/cli";
194473
194508
  function compareVersions(a, b) {
@@ -194482,7 +194517,7 @@ function compareVersions(a, b) {
194482
194517
  return 0;
194483
194518
  }
194484
194519
  async function checkForUpdate() {
194485
- const currentVersion = "0.1.74";
194520
+ const currentVersion = "0.1.76";
194486
194521
  const response = await fetch(`${BINARIES_BASE_URL}/latest?t=${Date.now()}`);
194487
194522
  if (!response.ok) {
194488
194523
  throw new Error(`Failed to check for updates: HTTP ${response.status}`);
@@ -194498,7 +194533,7 @@ function isBinaryWritable() {
194498
194533
  const binaryPath = getCurrentBinaryPath();
194499
194534
  const dir = path28.dirname(binaryPath);
194500
194535
  try {
194501
- fs31.accessSync(dir, fs31.constants.W_OK);
194536
+ fs30.accessSync(dir, fs30.constants.W_OK);
194502
194537
  return true;
194503
194538
  } catch {
194504
194539
  return false;
@@ -194509,21 +194544,21 @@ async function performUpdate(version, onProgress) {
194509
194544
  const binaryDir = path28.dirname(binaryPath);
194510
194545
  const tempPath = path28.join(binaryDir, `.specific-update-${process.pid}`);
194511
194546
  try {
194512
- const { platform: platform6, arch: arch3 } = getPlatformInfo();
194513
- const url = `${BINARIES_BASE_URL}/${version}/specific-${platform6}-${arch3}`;
194547
+ const { platform: platform5, arch: arch3 } = getPlatformInfo();
194548
+ const url = `${BINARIES_BASE_URL}/${version}/specific-${platform5}-${arch3}`;
194514
194549
  await downloadFile(url, tempPath, onProgress);
194515
- const stat4 = fs31.statSync(tempPath);
194550
+ const stat4 = fs30.statSync(tempPath);
194516
194551
  if (stat4.size === 0) {
194517
194552
  throw new Error("Downloaded binary is empty");
194518
194553
  }
194519
- fs31.chmodSync(tempPath, 493);
194554
+ fs30.chmodSync(tempPath, 493);
194520
194555
  onProgress?.({ phase: "finalizing" });
194521
- fs31.unlinkSync(binaryPath);
194522
- fs31.renameSync(tempPath, binaryPath);
194556
+ fs30.unlinkSync(binaryPath);
194557
+ fs30.renameSync(tempPath, binaryPath);
194523
194558
  } catch (error) {
194524
194559
  try {
194525
- if (fs31.existsSync(tempPath)) {
194526
- fs31.unlinkSync(tempPath);
194560
+ if (fs30.existsSync(tempPath)) {
194561
+ fs30.unlinkSync(tempPath);
194527
194562
  }
194528
194563
  } catch {
194529
194564
  }
@@ -194533,21 +194568,21 @@ async function performUpdate(version, onProgress) {
194533
194568
 
194534
194569
  // src/lib/background-update.ts
194535
194570
  import { spawn as spawn9 } from "child_process";
194536
- import * as fs32 from "fs";
194571
+ import * as fs31 from "fs";
194537
194572
  import * as path29 from "path";
194538
- import * as os10 from "os";
194539
- var SPECIFIC_DIR = path29.join(os10.homedir(), ".specific");
194573
+ import * as os9 from "os";
194574
+ var SPECIFIC_DIR = path29.join(os9.homedir(), ".specific");
194540
194575
  var RATE_LIMIT_FILE = path29.join(SPECIFIC_DIR, "last-update-check");
194541
194576
  var LOCK_FILE = path29.join(SPECIFIC_DIR, "update.lock");
194542
194577
  var RATE_LIMIT_MS = 60 * 60 * 1e3;
194543
194578
  var STALE_LOCK_MS = 10 * 60 * 1e3;
194544
194579
  function writeCheckTimestamp() {
194545
- fs32.mkdirSync(SPECIFIC_DIR, { recursive: true });
194546
- fs32.writeFileSync(RATE_LIMIT_FILE, String(Date.now()), "utf-8");
194580
+ fs31.mkdirSync(SPECIFIC_DIR, { recursive: true });
194581
+ fs31.writeFileSync(RATE_LIMIT_FILE, String(Date.now()), "utf-8");
194547
194582
  }
194548
194583
  function isRateLimited() {
194549
194584
  try {
194550
- const content = fs32.readFileSync(RATE_LIMIT_FILE, "utf-8").trim();
194585
+ const content = fs31.readFileSync(RATE_LIMIT_FILE, "utf-8").trim();
194551
194586
  const lastCheck = parseInt(content, 10);
194552
194587
  if (isNaN(lastCheck)) return false;
194553
194588
  return Date.now() - lastCheck < RATE_LIMIT_MS;
@@ -194681,7 +194716,7 @@ function updateCommand() {
194681
194716
  var program = new Command();
194682
194717
  var env = "production";
194683
194718
  var envLabel = env !== "production" ? `[${env.toUpperCase()}] ` : "";
194684
- program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.74").enablePositionalOptions();
194719
+ program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.76").enablePositionalOptions();
194685
194720
  program.command("init").description("Initialize project for use with a coding agent").option("--agent <name...>", "Agents to configure (cursor, claude, codex, other)").action((options2) => initCommand(options2));
194686
194721
  program.command("docs [topic]").description("Fetch LLM-optimized documentation").action(docsCommand);
194687
194722
  program.command("check").description("Validate specific.hcl configuration").action(checkCommand);