@specific.dev/cli 0.1.107 → 0.1.108

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 (67) 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 +136 -33
  64. package/package.json +5 -2
  65. /package/dist/admin/_next/static/{Zu_1z5_BR3qjEF5OmxQ4k → -uB2tvCTW06hUMOZfRURZ}/_buildManifest.js +0 -0
  66. /package/dist/admin/_next/static/{Zu_1z5_BR3qjEF5OmxQ4k → -uB2tvCTW06hUMOZfRURZ}/_clientMiddlewareManifest.json +0 -0
  67. /package/dist/admin/_next/static/{Zu_1z5_BR3qjEF5OmxQ4k → -uB2tvCTW06hUMOZfRURZ}/_ssgManifest.js +0 -0
package/dist/cli.js CHANGED
@@ -602,12 +602,12 @@ var init_is_wsl = __esm({
602
602
  // node_modules/.pnpm/powershell-utils@0.1.0/node_modules/powershell-utils/index.js
603
603
  import process3 from "node:process";
604
604
  import { Buffer as Buffer2 } from "node:buffer";
605
- import { promisify } from "node:util";
605
+ import { promisify as promisify2 } from "node:util";
606
606
  import childProcess from "node:child_process";
607
- var execFile, powerShellPath, executePowerShell;
607
+ var execFile2, powerShellPath, executePowerShell;
608
608
  var init_powershell_utils = __esm({
609
609
  "node_modules/.pnpm/powershell-utils@0.1.0/node_modules/powershell-utils/index.js"() {
610
- execFile = promisify(childProcess.execFile);
610
+ execFile2 = promisify2(childProcess.execFile);
611
611
  powerShellPath = () => `${process3.env.SYSTEMROOT || process3.env.windir || String.raw`C:\Windows`}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`;
612
612
  executePowerShell = async (command, options2 = {}) => {
613
613
  const {
@@ -615,7 +615,7 @@ var init_powershell_utils = __esm({
615
615
  ...execFileOptions
616
616
  } = options2;
617
617
  const encodedCommand = executePowerShell.encodeCommand(command);
618
- return execFile(
618
+ return execFile2(
619
619
  psPath ?? powerShellPath(),
620
620
  [
621
621
  ...executePowerShell.argumentsPrefix,
@@ -658,17 +658,17 @@ var init_utilities = __esm({
658
658
  });
659
659
 
660
660
  // node_modules/.pnpm/wsl-utils@0.3.1/node_modules/wsl-utils/index.js
661
- import { promisify as promisify2 } from "node:util";
661
+ import { promisify as promisify3 } from "node:util";
662
662
  import childProcess2 from "node:child_process";
663
663
  import fs17, { constants as fsConstants } from "node:fs/promises";
664
- var execFile2, wslDrivesMountPoint, powerShellPathFromWsl, powerShellPath2, canAccessPowerShellPromise, canAccessPowerShell, wslDefaultBrowser, convertWslPathToWindows;
664
+ var execFile3, wslDrivesMountPoint, powerShellPathFromWsl, powerShellPath2, canAccessPowerShellPromise, canAccessPowerShell, wslDefaultBrowser, convertWslPathToWindows;
665
665
  var init_wsl_utils = __esm({
666
666
  "node_modules/.pnpm/wsl-utils@0.3.1/node_modules/wsl-utils/index.js"() {
667
667
  init_is_wsl();
668
668
  init_powershell_utils();
669
669
  init_utilities();
670
670
  init_is_wsl();
671
- execFile2 = promisify2(childProcess2.execFile);
671
+ execFile3 = promisify3(childProcess2.execFile);
672
672
  wslDrivesMountPoint = /* @__PURE__ */ (() => {
673
673
  const defaultMountPoint = "/mnt/";
674
674
  let mountPoint;
@@ -724,7 +724,7 @@ var init_wsl_utils = __esm({
724
724
  return path27;
725
725
  }
726
726
  try {
727
- const { stdout } = await execFile2("wslpath", ["-aw", path27], { encoding: "utf8" });
727
+ const { stdout } = await execFile3("wslpath", ["-aw", path27], { encoding: "utf8" });
728
728
  return stdout.trim();
729
729
  } catch {
730
730
  return path27;
@@ -756,14 +756,14 @@ var init_define_lazy_prop = __esm({
756
756
  });
757
757
 
758
758
  // node_modules/.pnpm/default-browser-id@5.0.1/node_modules/default-browser-id/index.js
759
- import { promisify as promisify3 } from "node:util";
759
+ import { promisify as promisify4 } from "node:util";
760
760
  import process4 from "node:process";
761
- import { execFile as execFile3 } from "node:child_process";
761
+ import { execFile as execFile4 } from "node:child_process";
762
762
  async function defaultBrowserId() {
763
763
  if (process4.platform !== "darwin") {
764
764
  throw new Error("macOS only");
765
765
  }
766
- const { stdout } = await execFileAsync("defaults", ["read", "com.apple.LaunchServices/com.apple.launchservices.secure", "LSHandlers"]);
766
+ const { stdout } = await execFileAsync2("defaults", ["read", "com.apple.LaunchServices/com.apple.launchservices.secure", "LSHandlers"]);
767
767
  const match = /LSHandlerRoleAll = "(?!-)(?<id>[^"]+?)";\s+?LSHandlerURLScheme = (?:http|https);/.exec(stdout);
768
768
  const browserId = match?.groups.id ?? "com.apple.Safari";
769
769
  if (browserId === "com.apple.safari") {
@@ -771,17 +771,17 @@ async function defaultBrowserId() {
771
771
  }
772
772
  return browserId;
773
773
  }
774
- var execFileAsync;
774
+ var execFileAsync2;
775
775
  var init_default_browser_id = __esm({
776
776
  "node_modules/.pnpm/default-browser-id@5.0.1/node_modules/default-browser-id/index.js"() {
777
- execFileAsync = promisify3(execFile3);
777
+ execFileAsync2 = promisify4(execFile4);
778
778
  }
779
779
  });
780
780
 
781
781
  // node_modules/.pnpm/run-applescript@7.1.0/node_modules/run-applescript/index.js
782
782
  import process5 from "node:process";
783
- import { promisify as promisify4 } from "node:util";
784
- import { execFile as execFile4, execFileSync } from "node:child_process";
783
+ import { promisify as promisify5 } from "node:util";
784
+ import { execFile as execFile5, execFileSync } from "node:child_process";
785
785
  async function runAppleScript(script, { humanReadableOutput = true, signal } = {}) {
786
786
  if (process5.platform !== "darwin") {
787
787
  throw new Error("macOS only");
@@ -791,13 +791,13 @@ async function runAppleScript(script, { humanReadableOutput = true, signal } = {
791
791
  if (signal) {
792
792
  execOptions.signal = signal;
793
793
  }
794
- const { stdout } = await execFileAsync2("osascript", ["-e", script, outputArguments], execOptions);
794
+ const { stdout } = await execFileAsync3("osascript", ["-e", script, outputArguments], execOptions);
795
795
  return stdout.trim();
796
796
  }
797
- var execFileAsync2;
797
+ var execFileAsync3;
798
798
  var init_run_applescript = __esm({
799
799
  "node_modules/.pnpm/run-applescript@7.1.0/node_modules/run-applescript/index.js"() {
800
- execFileAsync2 = promisify4(execFile4);
800
+ execFileAsync3 = promisify5(execFile5);
801
801
  }
802
802
  });
803
803
 
@@ -813,9 +813,9 @@ var init_bundle_name = __esm({
813
813
  });
814
814
 
815
815
  // node_modules/.pnpm/default-browser@5.4.0/node_modules/default-browser/windows.js
816
- import { promisify as promisify5 } from "node:util";
817
- import { execFile as execFile5 } from "node:child_process";
818
- async function defaultBrowser(_execFileAsync = execFileAsync3) {
816
+ import { promisify as promisify6 } from "node:util";
817
+ import { execFile as execFile6 } from "node:child_process";
818
+ async function defaultBrowser(_execFileAsync = execFileAsync4) {
819
819
  const { stdout } = await _execFileAsync("reg", [
820
820
  "QUERY",
821
821
  " HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice",
@@ -833,10 +833,10 @@ async function defaultBrowser(_execFileAsync = execFileAsync3) {
833
833
  }
834
834
  return browser;
835
835
  }
836
- var execFileAsync3, windowsBrowserProgIds, _windowsBrowserProgIdMap, UnknownBrowserError;
836
+ var execFileAsync4, windowsBrowserProgIds, _windowsBrowserProgIdMap, UnknownBrowserError;
837
837
  var init_windows = __esm({
838
838
  "node_modules/.pnpm/default-browser@5.4.0/node_modules/default-browser/windows.js"() {
839
- execFileAsync3 = promisify5(execFile5);
839
+ execFileAsync4 = promisify6(execFile6);
840
840
  windowsBrowserProgIds = {
841
841
  MSEdgeHTM: { name: "Edge", id: "com.microsoft.edge" },
842
842
  // The missing `L` is correct.
@@ -863,9 +863,9 @@ var init_windows = __esm({
863
863
  });
864
864
 
865
865
  // node_modules/.pnpm/default-browser@5.4.0/node_modules/default-browser/index.js
866
- import { promisify as promisify6 } from "node:util";
866
+ import { promisify as promisify7 } from "node:util";
867
867
  import process6 from "node:process";
868
- import { execFile as execFile6 } from "node:child_process";
868
+ import { execFile as execFile7 } from "node:child_process";
869
869
  async function defaultBrowser2() {
870
870
  if (process6.platform === "darwin") {
871
871
  const id = await defaultBrowserId();
@@ -873,7 +873,7 @@ async function defaultBrowser2() {
873
873
  return { name, id };
874
874
  }
875
875
  if (process6.platform === "linux") {
876
- const { stdout } = await execFileAsync4("xdg-mime", ["query", "default", "x-scheme-handler/http"]);
876
+ const { stdout } = await execFileAsync5("xdg-mime", ["query", "default", "x-scheme-handler/http"]);
877
877
  const id = stdout.trim();
878
878
  const name = titleize(id.replace(/.desktop$/, "").replace("-", " "));
879
879
  return { name, id };
@@ -883,14 +883,14 @@ async function defaultBrowser2() {
883
883
  }
884
884
  throw new Error("Only macOS, Linux, and Windows are supported");
885
885
  }
886
- var execFileAsync4, titleize;
886
+ var execFileAsync5, titleize;
887
887
  var init_default_browser = __esm({
888
888
  "node_modules/.pnpm/default-browser@5.4.0/node_modules/default-browser/index.js"() {
889
889
  init_default_browser_id();
890
890
  init_bundle_name();
891
891
  init_windows();
892
892
  init_windows();
893
- execFileAsync4 = promisify6(execFile6);
893
+ execFileAsync5 = promisify7(execFile7);
894
894
  titleize = (string) => string.toLowerCase().replaceAll(/(?:^|\s|-)\S/g, (x) => x.toUpperCase());
895
895
  }
896
896
  });
@@ -185191,6 +185191,8 @@ import { readFile, writeFile } from "fs/promises";
185191
185191
  import { existsSync as existsSync5 } from "fs";
185192
185192
  import * as fs6 from "fs";
185193
185193
  import * as path6 from "path";
185194
+ import { execFile } from "child_process";
185195
+ import { promisify } from "util";
185194
185196
  import * as http from "http";
185195
185197
  import * as fs7 from "fs";
185196
185198
  import * as path7 from "path";
@@ -369936,6 +369938,7 @@ function startService(service, resources, secrets, configs, endpointPorts, servi
369936
369938
  }
369937
369939
  };
369938
369940
  }
369941
+ var execFileAsync = promisify(execFile);
369939
369942
  var InstanceStateManager = class {
369940
369943
  stateDir;
369941
369944
  statePath;
@@ -370036,6 +370039,7 @@ var InstanceStateManager = class {
370036
370039
  const content = fs6.readFileSync(this.statePath, "utf-8");
370037
370040
  const state = JSON.parse(content);
370038
370041
  if (!this.isProcessRunning(state.owner.pid)) {
370042
+ await this.killOrphanedProcesses(state);
370039
370043
  fs6.unlinkSync(this.statePath);
370040
370044
  return true;
370041
370045
  }
@@ -370051,6 +370055,35 @@ var InstanceStateManager = class {
370051
370055
  releaseLock();
370052
370056
  }
370053
370057
  }
370058
+ /**
370059
+ * Kill orphaned child processes left behind by a dead owner.
370060
+ * Best-effort: failures are silently ignored.
370061
+ */
370062
+ async killOrphanedProcesses(state) {
370063
+ for (const service of Object.values(state.services)) {
370064
+ if (service.pid && this.isProcessRunning(service.pid)) {
370065
+ try {
370066
+ process.kill(-service.pid, "SIGKILL");
370067
+ } catch {
370068
+ }
370069
+ }
370070
+ }
370071
+ for (const db of Object.values(state.databases)) {
370072
+ if (db.syncUrl) {
370073
+ try {
370074
+ const url = new URL(db.syncUrl);
370075
+ const port = parseInt(url.port, 10);
370076
+ if (!isNaN(port)) {
370077
+ const pid = await findPidOnPort(port);
370078
+ if (pid !== void 0) {
370079
+ process.kill(pid, "SIGKILL");
370080
+ }
370081
+ }
370082
+ } catch {
370083
+ }
370084
+ }
370085
+ }
370086
+ }
370054
370087
  async claimOwnership(command) {
370055
370088
  const releaseLock = await this.acquireLock();
370056
370089
  try {
@@ -370143,6 +370176,19 @@ var InstanceStateManager = class {
370143
370176
  fs6.renameSync(tmpPath, this.statePath);
370144
370177
  }
370145
370178
  };
370179
+ async function findPidOnPort(port) {
370180
+ try {
370181
+ const { stdout } = await execFileAsync(
370182
+ "lsof",
370183
+ ["-i", `:${port}`, "-t", "-sTCP:LISTEN"],
370184
+ { timeout: 5e3 }
370185
+ );
370186
+ const pid = parseInt(stdout.trim().split("\n")[0], 10);
370187
+ return isNaN(pid) ? void 0 : pid;
370188
+ } catch {
370189
+ return void 0;
370190
+ }
370191
+ }
370146
370192
  var __dirname = path7.dirname(fileURLToPath(import.meta.url));
370147
370193
  var adminDir = path7.join(__dirname, "admin");
370148
370194
  var _embeddedAdmin = null;
@@ -370399,6 +370445,22 @@ async function startElectric(postgres, port, dataDir, options2) {
370399
370445
  );
370400
370446
  const secret = generateRandomString(32);
370401
370447
  const host = "127.0.0.1";
370448
+ if (await checkTcpPort2(host, port)) {
370449
+ let freed = false;
370450
+ for (let i = 0; i < 30; i++) {
370451
+ await sleep2(100);
370452
+ if (!await checkTcpPort2(host, port)) {
370453
+ freed = true;
370454
+ break;
370455
+ }
370456
+ }
370457
+ if (!freed) {
370458
+ throw new Error(
370459
+ `Electric port ${port} is already in use. This may be an orphaned process from a previous session \u2014 find it with \`lsof -i :${port}\` and kill it, then retry.`
370460
+ );
370461
+ }
370462
+ writeLog("electric", `Port ${port} was occupied but is now free`);
370463
+ }
370402
370464
  const storageDir = path9.join(process.cwd(), dataDir, `electric-${postgres.name}`);
370403
370465
  fs8.rmSync(storageDir, { recursive: true, force: true });
370404
370466
  writeLog("electric", `Starting Electric for database "${postgres.name}"`);
@@ -370423,6 +370485,7 @@ async function startElectric(postgres, port, dataDir, options2) {
370423
370485
  await waitForTcpPort2(host, port);
370424
370486
  return {
370425
370487
  databaseName: postgres.name,
370488
+ pid: electric.pid,
370426
370489
  port,
370427
370490
  url: `http://${host}:${port}`,
370428
370491
  secret,
@@ -371720,6 +371783,9 @@ var DevEnvironment = class extends TypedEventEmitter {
371720
371783
  collectedSecrets = {};
371721
371784
  collectedConfigs = {};
371722
371785
  inputResolve = null;
371786
+ // Last-resort exit handler to kill child processes when the process exits
371787
+ // unexpectedly (e.g. SIGKILL from an agent). Runs synchronously.
371788
+ exitHandler = null;
371723
371789
  constructor(options2) {
371724
371790
  super();
371725
371791
  this.projectDir = options2?.projectDir ?? process.cwd();
@@ -371922,6 +371988,7 @@ var DevEnvironment = class extends TypedEventEmitter {
371922
371988
  if (this.stateManager) {
371923
371989
  await this.stateManager.releaseOwnership();
371924
371990
  }
371991
+ this.removeExitHandler();
371925
371992
  this.systemLog("Shutdown complete");
371926
371993
  closeDebugLog();
371927
371994
  this.setStatus("idle");
@@ -371931,6 +371998,41 @@ var DevEnvironment = class extends TypedEventEmitter {
371931
371998
  this.startResolve = null;
371932
371999
  }
371933
372000
  }
372001
+ // ── Private: exit handler ─────────────────────────────────────────────────
372002
+ /**
372003
+ * Register a synchronous process 'exit' handler that kills all known child
372004
+ * PIDs. This is a last resort for when the process exits without going
372005
+ * through shutdownInternal (e.g. parent sends SIGKILL).
372006
+ */
372007
+ registerExitHandler() {
372008
+ this.removeExitHandler();
372009
+ this.exitHandler = () => {
372010
+ for (const electric of this.electricInstances) {
372011
+ if (electric.pid) {
372012
+ try {
372013
+ process.kill(electric.pid, "SIGKILL");
372014
+ } catch {
372015
+ }
372016
+ }
372017
+ }
372018
+ for (const service of this.services) {
372019
+ const pid = service.process.pid;
372020
+ if (pid) {
372021
+ try {
372022
+ process.kill(-pid, "SIGKILL");
372023
+ } catch {
372024
+ }
372025
+ }
372026
+ }
372027
+ };
372028
+ process.on("exit", this.exitHandler);
372029
+ }
372030
+ removeExitHandler() {
372031
+ if (this.exitHandler) {
372032
+ process.removeListener("exit", this.exitHandler);
372033
+ this.exitHandler = null;
372034
+ }
372035
+ }
371934
372036
  // ── Private: config file watcher ───────────────────────────────────────────
371935
372037
  startConfigWatcher() {
371936
372038
  const configPath = path14.join(this.projectDir, "specific.hcl");
@@ -372108,6 +372210,7 @@ var DevEnvironment = class extends TypedEventEmitter {
372108
372210
  if (result.cancelled) return;
372109
372211
  resources = result.resources;
372110
372212
  this.mailServers = result.mail;
372213
+ this.registerExitHandler();
372111
372214
  } catch (err) {
372112
372215
  const errorMsg = `Failed to start resources: ${err instanceof Error ? err.message : String(err)}`;
372113
372216
  writeLog("system:error", errorMsg);
@@ -373084,7 +373187,7 @@ function trackEvent(event, properties) {
373084
373187
  event,
373085
373188
  properties: {
373086
373189
  ...properties,
373087
- cli_version: "0.1.107",
373190
+ cli_version: "0.1.108",
373088
373191
  platform: process.platform,
373089
373192
  node_version: process.version,
373090
373193
  project_id: getProjectId()
@@ -373521,7 +373624,7 @@ import { render as render3, Text as Text3, Box as Box3 } from "ink";
373521
373624
  import Spinner2 from "ink-spinner";
373522
373625
  import * as fs21 from "fs";
373523
373626
  import * as path19 from "path";
373524
- import { execFile as execFile7 } from "child_process";
373627
+ import { execFile as execFile8 } from "child_process";
373525
373628
 
373526
373629
  // node_modules/.pnpm/@specific+config@file+..+config/node_modules/@specific/config/dist/parser.js
373527
373630
  var import_hcl2_json_parser3 = __toESM(require_dist2(), 1);
@@ -374175,7 +374278,7 @@ async function runReshapeCheck(migrationsDir) {
374175
374278
  const binary = await ensureBinary(reshapeBinary);
374176
374279
  const reshapePath = binary.executables["reshape"];
374177
374280
  return new Promise((resolve9) => {
374178
- execFile7(reshapePath, ["check", "--dirs", migrationsDir], (err, _stdout, stderr) => {
374281
+ execFile8(reshapePath, ["check", "--dirs", migrationsDir], (err, _stdout, stderr) => {
374179
374282
  if (err) {
374180
374283
  const errorMsg = stderr.trim() || err.message;
374181
374284
  resolve9({ success: false, error: errorMsg });
@@ -376763,7 +376866,7 @@ function compareVersions(a, b) {
376763
376866
  return 0;
376764
376867
  }
376765
376868
  async function checkForUpdate() {
376766
- const currentVersion = "0.1.107";
376869
+ const currentVersion = "0.1.108";
376767
376870
  const response = await fetch(`${BINARIES_BASE_URL}/latest?t=${Date.now()}`);
376768
376871
  if (!response.ok) {
376769
376872
  throw new Error(`Failed to check for updates: HTTP ${response.status}`);
@@ -377031,7 +377134,7 @@ async function projectListCommand() {
377031
377134
  var program = new Command();
377032
377135
  var env = "production";
377033
377136
  var envLabel = env !== "production" ? `[${env.toUpperCase()}] ` : "";
377034
- program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.107").enablePositionalOptions();
377137
+ program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.108").enablePositionalOptions();
377035
377138
  program.command("init").description("Initialize project for use with a coding agent").option("--agent <name...>", "Agents to configure (cursor, claude, codex, other)").addHelpText("after", `
377036
377139
  Examples:
377037
377140
  $ specific init
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@specific.dev/cli",
3
- "version": "0.1.107",
3
+ "version": "0.1.108",
4
4
  "description": "CLI for Specific infrastructure-as-code",
5
5
  "type": "module",
6
6
  "main": "dist/cli.js",
@@ -17,7 +17,10 @@
17
17
  "link:dev": "npm run build:dev && npm link",
18
18
  "link:staging": "npm run build:staging && npm link",
19
19
  "link:prod": "npm run build && npm link",
20
- "build:binary": "npx tsx scripts/build-binary.ts"
20
+ "build:binary": "npx tsx scripts/build-binary.ts",
21
+ "link:binary:dev": "NODE_ENV=development npm run build:binary && codesign -s - dist/specific && cp dist/specific ~/.local/bin/specific",
22
+ "link:binary:staging": "NODE_ENV=staging npm run build:binary && codesign -s - dist/specific && cp dist/specific ~/.local/bin/specific",
23
+ "link:binary:prod": "npm run build:binary && codesign -s - dist/specific && cp dist/specific ~/.local/bin/specific"
21
24
  },
22
25
  "keywords": [
23
26
  "infrastructure",