codebyplan 1.13.14 → 1.13.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -14,7 +14,7 @@ var VERSION, PACKAGE_NAME;
14
14
  var init_version = __esm({
15
15
  "src/lib/version.ts"() {
16
16
  "use strict";
17
- VERSION = "1.13.14";
17
+ VERSION = "1.13.16";
18
18
  PACKAGE_NAME = "codebyplan";
19
19
  }
20
20
  });
@@ -697,7 +697,7 @@ function isRetryable(err) {
697
697
  return false;
698
698
  }
699
699
  function delay(ms) {
700
- return new Promise((resolve7) => setTimeout(resolve7, ms));
700
+ return new Promise((resolve8) => setTimeout(resolve8, ms));
701
701
  }
702
702
  async function request(method, path8, options) {
703
703
  const url = buildUrl(path8, options?.params);
@@ -1055,7 +1055,7 @@ var init_device_flow = __esm({
1055
1055
  this.name = "OAuthInvalidClientError";
1056
1056
  }
1057
1057
  };
1058
- defaultSleep = (ms) => new Promise((resolve7) => setTimeout(resolve7, ms));
1058
+ defaultSleep = (ms) => new Promise((resolve8) => setTimeout(resolve8, ms));
1059
1059
  }
1060
1060
  });
1061
1061
 
@@ -1880,9 +1880,9 @@ async function writeMcpConfig(scope) {
1880
1880
  return configPath;
1881
1881
  }
1882
1882
  async function fetchRepos(auth) {
1883
- const baseUrl2 = (process.env.CODEBYPLAN_API_URL ?? "https://www.codebyplan.com").replace(/\/$/, "");
1883
+ const baseUrl3 = (process.env.CODEBYPLAN_API_URL ?? "https://www.codebyplan.com").replace(/\/$/, "");
1884
1884
  const headers = auth.kind === "oauth" ? { Authorization: `Bearer ${await getAccessToken()}` } : { "x-api-key": auth.apiKey };
1885
- const res = await fetch(`${baseUrl2}/api/repos`, {
1885
+ const res = await fetch(`${baseUrl3}/api/repos`, {
1886
1886
  headers,
1887
1887
  signal: AbortSignal.timeout(1e4)
1888
1888
  });
@@ -1987,6 +1987,11 @@ async function writeCodebyplanDirectory(projectPath, selectedRepo, deviceId) {
1987
1987
  JSON.stringify({}, null, 2) + "\n",
1988
1988
  "utf-8"
1989
1989
  );
1990
+ await writeFile6(
1991
+ join9(codebyplanDir, "cmux.json"),
1992
+ JSON.stringify({}, null, 2) + "\n",
1993
+ "utf-8"
1994
+ );
1990
1995
  const statuslinePath = join9(codebyplanDir, "statusline.json");
1991
1996
  let statuslineExists = false;
1992
1997
  try {
@@ -2004,7 +2009,7 @@ async function writeCodebyplanDirectory(projectPath, selectedRepo, deviceId) {
2004
2009
  await writeLocalConfig(projectPath, { device_id: deviceId });
2005
2010
  console.log(` Created ${codebyplanDir}/`);
2006
2011
  console.log(
2007
- ` repo.json, server.json, git.json, shipment.json, vendor.json, e2e.json, eslint.json, statusline.json`
2012
+ ` repo.json, server.json, git.json, shipment.json, vendor.json, e2e.json, eslint.json, cmux.json, statusline.json`
2008
2013
  );
2009
2014
  console.log(` device.local.json (gitignored)`);
2010
2015
  const gitignoreAction = await ensureManagedGitignoreBlock(projectPath);
@@ -2081,8 +2086,8 @@ async function runSetup() {
2081
2086
  const deviceId = await getOrCreateDeviceId(projectPath);
2082
2087
  let branch = "main";
2083
2088
  try {
2084
- const { execSync: execSync8 } = await import("node:child_process");
2085
- branch = execSync8("git symbolic-ref --short HEAD", {
2089
+ const { execSync: execSync11 } = await import("node:child_process");
2090
+ branch = execSync11("git symbolic-ref --short HEAD", {
2086
2091
  cwd: projectPath,
2087
2092
  encoding: "utf-8"
2088
2093
  }).trim();
@@ -3720,9 +3725,9 @@ async function eslintInit(repoId, projectPath) {
3720
3725
  Install ${missingPkgs.length} missing packages? [Y/n] `
3721
3726
  );
3722
3727
  if (confirmed) {
3723
- const { execSync: execSync8 } = await import("node:child_process");
3728
+ const { execSync: execSync11 } = await import("node:child_process");
3724
3729
  try {
3725
- execSync8(installCmd, { cwd: projectPath, stdio: "inherit" });
3730
+ execSync11(installCmd, { cwd: projectPath, stdio: "inherit" });
3726
3731
  console.log(" Packages installed.\n");
3727
3732
  } catch (err) {
3728
3733
  console.error(
@@ -4157,7 +4162,7 @@ function setRetryDelayMs(ms) {
4157
4162
  RETRY_DELAY_MS = ms;
4158
4163
  }
4159
4164
  function sleep(ms) {
4160
- return new Promise((resolve7) => setTimeout(resolve7, ms));
4165
+ return new Promise((resolve8) => setTimeout(resolve8, ms));
4161
4166
  }
4162
4167
  function isTransientMcpError(err) {
4163
4168
  if (!(err instanceof McpError)) return false;
@@ -6374,32 +6379,318 @@ var init_version_status = __esm({
6374
6379
  }
6375
6380
  });
6376
6381
 
6382
+ // src/cli/upload-e2e-images.ts
6383
+ var upload_e2e_images_exports = {};
6384
+ __export(upload_e2e_images_exports, {
6385
+ runUploadE2eImagesCommand: () => runUploadE2eImagesCommand
6386
+ });
6387
+ import { readFile as readFile15 } from "node:fs/promises";
6388
+ import { join as join21, basename, resolve as resolve5 } from "node:path";
6389
+ import { execSync as execSync7 } from "node:child_process";
6390
+ function baseUrl2() {
6391
+ return (process.env.CODEBYPLAN_API_URL ?? "https://www.codebyplan.com").replace(/\/$/, "");
6392
+ }
6393
+ function parseArgs(args) {
6394
+ const flags = {};
6395
+ const booleans = /* @__PURE__ */ new Set();
6396
+ const positionals = [];
6397
+ for (let i = 0; i < args.length; i++) {
6398
+ const arg = args[i];
6399
+ if (arg.startsWith("--")) {
6400
+ const key = arg.slice(2);
6401
+ const next = args[i + 1];
6402
+ if (next !== void 0 && !next.startsWith("--")) {
6403
+ flags[key] = next;
6404
+ i++;
6405
+ } else {
6406
+ booleans.add(key);
6407
+ }
6408
+ } else {
6409
+ positionals.push(arg);
6410
+ }
6411
+ }
6412
+ return {
6413
+ checkpointId: positionals[0],
6414
+ repoId: flags["repo-id"],
6415
+ baseBranch: flags["base-branch"] ?? "main",
6416
+ json: booleans.has("json"),
6417
+ dryRun: booleans.has("dry-run")
6418
+ };
6419
+ }
6420
+ async function readE2eConfig(projectPath) {
6421
+ try {
6422
+ const raw = await readFile15(
6423
+ join21(projectPath, ".codebyplan", "e2e.json"),
6424
+ "utf-8"
6425
+ );
6426
+ return JSON.parse(raw);
6427
+ } catch {
6428
+ return {};
6429
+ }
6430
+ }
6431
+ function collectPngsFromGitDiff(projectPath, frameworkName, frameworkConfig, baseBranch) {
6432
+ const pathspec = frameworkConfig.test_dir ?? frameworkConfig.app;
6433
+ if (!pathspec) {
6434
+ return [];
6435
+ }
6436
+ let stdout7;
6437
+ try {
6438
+ stdout7 = execSync7(
6439
+ `git diff --name-status --diff-filter=AM "${baseBranch}...HEAD" -- "${pathspec}"`,
6440
+ { cwd: projectPath, encoding: "utf-8" }
6441
+ );
6442
+ } catch (err) {
6443
+ const msg = err instanceof Error ? err.message : String(err);
6444
+ if (msg.includes("unknown revision") || msg.includes("ambiguous argument") || msg.includes("not a git repository")) {
6445
+ return [];
6446
+ }
6447
+ process.stderr.write(`upload-e2e-images: git diff failed: ${msg}
6448
+ `);
6449
+ return [];
6450
+ }
6451
+ const results = [];
6452
+ for (const line of stdout7.split("\n")) {
6453
+ const trimmed = line.trim();
6454
+ if (!trimmed) continue;
6455
+ const tab = trimmed.indexOf(" ");
6456
+ if (tab === -1) continue;
6457
+ const status = trimmed.slice(0, tab).trim();
6458
+ const filePath = trimmed.slice(tab + 1).trim();
6459
+ if (!filePath.endsWith(".png")) continue;
6460
+ if (frameworkName === "playwright" && !filePath.includes(".spec.ts-snapshots/"))
6461
+ continue;
6462
+ const isNew = status === "A";
6463
+ results.push({
6464
+ absolutePath: join21(projectPath, filePath),
6465
+ filename: basename(filePath),
6466
+ framework: frameworkName,
6467
+ is_new: isNew
6468
+ });
6469
+ }
6470
+ return results;
6471
+ }
6472
+ function deriveTestName(absolutePath) {
6473
+ const segments = absolutePath.replace(/\\/g, "/").split("/");
6474
+ for (let i = segments.length - 2; i >= 0; i--) {
6475
+ const seg = segments[i];
6476
+ if (seg && seg.endsWith(".spec.ts-snapshots")) {
6477
+ return seg.replace(".spec.ts-snapshots", "");
6478
+ }
6479
+ }
6480
+ return basename(absolutePath, ".png");
6481
+ }
6482
+ function buildManifestItem(png) {
6483
+ const testName = deriveTestName(png.absolutePath);
6484
+ const pageOrScreen = basename(png.absolutePath, ".png");
6485
+ return {
6486
+ filename: png.filename,
6487
+ test_name: testName,
6488
+ page_or_screen: pageOrScreen,
6489
+ framework: png.framework,
6490
+ is_new: png.is_new,
6491
+ baseline_diff_pct: null
6492
+ };
6493
+ }
6494
+ async function runUploadE2eImagesCommand(args) {
6495
+ const parsed = parseArgs(args);
6496
+ if (!parsed.checkpointId) {
6497
+ process.stderr.write(
6498
+ "upload-e2e-images: missing required argument <checkpointId>\n\nUsage: codebyplan upload-e2e-images <checkpointId> [--repo-id <uuid>]\n [--base-branch <name>] [--json] [--dry-run]\n\nExample: codebyplan upload-e2e-images chk-abc-123 --base-branch main\n"
6499
+ );
6500
+ process.exit(1);
6501
+ }
6502
+ const checkpointId = parsed.checkpointId;
6503
+ const projectPath = resolve5(process.cwd());
6504
+ let repoId = parsed.repoId;
6505
+ if (!repoId) {
6506
+ const found = await findCodebyplanConfig(projectPath);
6507
+ repoId = found?.contents.repo_id;
6508
+ }
6509
+ if (!repoId) {
6510
+ process.stderr.write(
6511
+ "upload-e2e-images: could not determine repo_id.\nPass --repo-id <uuid> or ensure .codebyplan/repo.json exists.\n"
6512
+ );
6513
+ process.exit(1);
6514
+ }
6515
+ const e2eConfig = await readE2eConfig(projectPath);
6516
+ const frameworks = e2eConfig.frameworks ?? {};
6517
+ const allPngs = [];
6518
+ for (const [name, cfg] of Object.entries(frameworks)) {
6519
+ if (!cfg.enabled || !cfg.auto_run) continue;
6520
+ const pngs = collectPngsFromGitDiff(
6521
+ projectPath,
6522
+ name,
6523
+ cfg,
6524
+ parsed.baseBranch
6525
+ );
6526
+ allPngs.push(...pngs);
6527
+ }
6528
+ if (allPngs.length === 0) {
6529
+ process.stdout.write(
6530
+ `No new/changed e2e screenshots found for ${checkpointId}
6531
+ `
6532
+ );
6533
+ process.exit(0);
6534
+ }
6535
+ const manifest = allPngs.map(buildManifestItem);
6536
+ if (parsed.dryRun) {
6537
+ if (parsed.json) {
6538
+ process.stdout.write(JSON.stringify(manifest, null, 2) + "\n");
6539
+ } else {
6540
+ process.stdout.write(
6541
+ `[dry-run] Would upload ${manifest.length} screenshot(s) for checkpoint ${checkpointId}:
6542
+ `
6543
+ );
6544
+ for (const item of manifest) {
6545
+ const label = item.is_new ? "NEW" : "CHANGED";
6546
+ process.stdout.write(
6547
+ ` [${label}] ${item.filename} (${item.framework}, test: ${item.test_name})
6548
+ `
6549
+ );
6550
+ }
6551
+ }
6552
+ process.exit(0);
6553
+ }
6554
+ const formData = new FormData();
6555
+ formData.append("checkpointId", checkpointId);
6556
+ formData.append("repoId", repoId);
6557
+ formData.append("manifest", JSON.stringify(manifest));
6558
+ for (const png of allPngs) {
6559
+ let bytes;
6560
+ try {
6561
+ bytes = await readFile15(png.absolutePath);
6562
+ } catch {
6563
+ process.stderr.write(
6564
+ `upload-e2e-images: could not read file: ${png.absolutePath}
6565
+ `
6566
+ );
6567
+ process.exit(1);
6568
+ }
6569
+ const blob = new Blob([bytes], { type: "image/png" });
6570
+ formData.append("files", blob, png.filename);
6571
+ }
6572
+ const auth = await getAuthHeaders();
6573
+ const url = `${baseUrl2()}/api/checkpoint-images`;
6574
+ let res;
6575
+ try {
6576
+ res = await fetch(url, {
6577
+ method: "POST",
6578
+ headers: auth.headers,
6579
+ body: formData
6580
+ });
6581
+ } catch (err) {
6582
+ process.stderr.write(
6583
+ `upload-e2e-images: network error: ${err instanceof Error ? err.message : String(err)}
6584
+ `
6585
+ );
6586
+ process.exit(1);
6587
+ }
6588
+ if (!res.ok) {
6589
+ let bodyText = "";
6590
+ try {
6591
+ bodyText = await res.text();
6592
+ } catch {
6593
+ }
6594
+ process.stderr.write(
6595
+ `upload-e2e-images: API returned ${res.status}: ${bodyText}
6596
+ `
6597
+ );
6598
+ process.exit(1);
6599
+ }
6600
+ let result;
6601
+ try {
6602
+ result = await res.json();
6603
+ } catch {
6604
+ process.stderr.write(
6605
+ "upload-e2e-images: failed to parse API response as JSON\n"
6606
+ );
6607
+ process.exit(1);
6608
+ }
6609
+ if (parsed.json) {
6610
+ process.stdout.write(JSON.stringify(result, null, 2) + "\n");
6611
+ return;
6612
+ }
6613
+ process.stdout.write(
6614
+ `Uploaded ${manifest.length} screenshot(s) for checkpoint ${checkpointId}
6615
+ `
6616
+ );
6617
+ const paths = result.data.stored_paths ?? [];
6618
+ for (const p of paths) {
6619
+ process.stdout.write(` ${p}
6620
+ `);
6621
+ }
6622
+ }
6623
+ var init_upload_e2e_images = __esm({
6624
+ "src/cli/upload-e2e-images.ts"() {
6625
+ "use strict";
6626
+ init_api();
6627
+ init_flags();
6628
+ }
6629
+ });
6630
+
6631
+ // src/lib/cmux.ts
6632
+ import { readFileSync as readFileSync6 } from "node:fs";
6633
+ import { join as join22 } from "node:path";
6634
+ function insideCmux() {
6635
+ return !!process.env.CMUX_WORKSPACE_ID;
6636
+ }
6637
+ function resolveCmuxBin() {
6638
+ return process.env.CMUX_BUNDLED_CLI_PATH || process.env.CMUX_CLAUDE_HOOK_CMUX_BIN || "cmux";
6639
+ }
6640
+ function readCmuxConfig(projectRoot) {
6641
+ let raw = {};
6642
+ try {
6643
+ const text = readFileSync6(
6644
+ join22(projectRoot, ".codebyplan", "cmux.json"),
6645
+ "utf-8"
6646
+ );
6647
+ raw = JSON.parse(text);
6648
+ } catch {
6649
+ raw = {};
6650
+ }
6651
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
6652
+ raw = {};
6653
+ }
6654
+ const config = raw;
6655
+ return {
6656
+ ...config,
6657
+ auto_status: config.auto_status ?? true,
6658
+ auto_dev_server: config.auto_dev_server ?? true
6659
+ };
6660
+ }
6661
+ var init_cmux = __esm({
6662
+ "src/lib/cmux.ts"() {
6663
+ "use strict";
6664
+ }
6665
+ });
6666
+
6377
6667
  // src/cli/cmux-sync.ts
6378
6668
  var cmux_sync_exports = {};
6379
6669
  __export(cmux_sync_exports, {
6380
6670
  runCmuxSync: () => runCmuxSync
6381
6671
  });
6382
- import { execSync as execSync7, execFileSync as execFileSync2 } from "node:child_process";
6383
- import { basename } from "node:path";
6672
+ import { execSync as execSync8, execFileSync as execFileSync2 } from "node:child_process";
6673
+ import { basename as basename2 } from "node:path";
6384
6674
  async function runCmuxSync() {
6385
6675
  try {
6386
- if (!process.env.CMUX_WORKSPACE_ID) {
6676
+ if (!insideCmux()) {
6387
6677
  process.exit(0);
6388
6678
  }
6389
- const bin = process.env.CMUX_BUNDLED_CLI_PATH || process.env.CMUX_CLAUDE_HOOK_CMUX_BIN || "cmux";
6679
+ const bin = resolveCmuxBin();
6390
6680
  let branch = "";
6391
6681
  try {
6392
- branch = execSync7("git rev-parse --abbrev-ref HEAD", {
6682
+ branch = execSync8("git rev-parse --abbrev-ref HEAD", {
6393
6683
  encoding: "utf8"
6394
6684
  }).trim();
6395
6685
  } catch {
6396
6686
  }
6397
6687
  let folder = "";
6688
+ let toplevel = "";
6398
6689
  try {
6399
- const toplevel = execSync7("git rev-parse --show-toplevel", {
6690
+ toplevel = execSync8("git rev-parse --show-toplevel", {
6400
6691
  encoding: "utf8"
6401
6692
  }).trim();
6402
- folder = basename(toplevel);
6693
+ folder = basename2(toplevel);
6403
6694
  } catch {
6404
6695
  }
6405
6696
  if (branch) {
@@ -6426,6 +6717,26 @@ async function runCmuxSync() {
6426
6717
  } catch {
6427
6718
  }
6428
6719
  }
6720
+ try {
6721
+ const cmuxCfg = readCmuxConfig(toplevel || process.cwd());
6722
+ if (typeof cmuxCfg.workspace_color === "string" && cmuxCfg.workspace_color !== "") {
6723
+ try {
6724
+ execFileSync2(bin, [
6725
+ "workspace-action",
6726
+ "--action",
6727
+ "set-color",
6728
+ "--color",
6729
+ cmuxCfg.workspace_color
6730
+ ]);
6731
+ } catch {
6732
+ }
6733
+ } else {
6734
+ process.stdout.write(
6735
+ "cmux: no workspace color set \u2014 run /cbp-setup-cmux\n"
6736
+ );
6737
+ }
6738
+ } catch {
6739
+ }
6429
6740
  process.exit(0);
6430
6741
  } catch (err) {
6431
6742
  if (err instanceof ProcessExitSignal) throw err;
@@ -6436,23 +6747,346 @@ var init_cmux_sync = __esm({
6436
6747
  "src/cli/cmux-sync.ts"() {
6437
6748
  "use strict";
6438
6749
  init_process_exit_signal();
6750
+ init_cmux();
6751
+ }
6752
+ });
6753
+
6754
+ // src/cli/cmux-status.ts
6755
+ var cmux_status_exports = {};
6756
+ __export(cmux_status_exports, {
6757
+ normalizeProgress: () => normalizeProgress,
6758
+ runCmuxStatus: () => runCmuxStatus
6759
+ });
6760
+ import { execSync as execSync9, execFileSync as execFileSync3 } from "node:child_process";
6761
+ function normalizeProgress(raw) {
6762
+ if (raw.includes("/")) {
6763
+ const [numStr, denStr] = raw.split("/", 2);
6764
+ const num = parseInt(numStr ?? "", 10);
6765
+ const den = parseInt(denStr ?? "", 10);
6766
+ if (!Number.isFinite(num) || !Number.isFinite(den) || den === 0) return "0";
6767
+ const ratio = num / den;
6768
+ const clamped2 = Math.max(0, Math.min(1, ratio));
6769
+ return String(clamped2);
6770
+ }
6771
+ const f = parseFloat(raw);
6772
+ if (!Number.isFinite(f)) return null;
6773
+ const clamped = Math.max(0, Math.min(1, f));
6774
+ return String(clamped);
6775
+ }
6776
+ async function runCmuxStatus(args) {
6777
+ try {
6778
+ if (!insideCmux()) {
6779
+ process.exit(0);
6780
+ }
6781
+ let toplevel = "";
6782
+ try {
6783
+ toplevel = execSync9("git rev-parse --show-toplevel", {
6784
+ encoding: "utf8"
6785
+ }).trim();
6786
+ } catch {
6787
+ toplevel = process.cwd();
6788
+ }
6789
+ const cfg = readCmuxConfig(toplevel);
6790
+ if (cfg.auto_status === false) {
6791
+ process.exit(0);
6792
+ }
6793
+ let checkpoint;
6794
+ let task;
6795
+ let qa;
6796
+ let progress;
6797
+ let clear = false;
6798
+ for (let i = 0; i < args.length; i++) {
6799
+ const flag = args[i];
6800
+ if (flag === "--checkpoint" && i + 1 < args.length) {
6801
+ checkpoint = args[++i];
6802
+ } else if (flag === "--task" && i + 1 < args.length) {
6803
+ task = args[++i];
6804
+ } else if (flag === "--qa" && i + 1 < args.length) {
6805
+ qa = args[++i];
6806
+ } else if (flag === "--progress" && i + 1 < args.length) {
6807
+ progress = args[++i];
6808
+ } else if (flag === "--clear") {
6809
+ clear = true;
6810
+ }
6811
+ }
6812
+ const bin = resolveCmuxBin();
6813
+ if (clear) {
6814
+ try {
6815
+ execFileSync3(bin, ["clear-status", "cbp-checkpoint"]);
6816
+ } catch {
6817
+ }
6818
+ try {
6819
+ execFileSync3(bin, ["clear-status", "cbp-task"]);
6820
+ } catch {
6821
+ }
6822
+ try {
6823
+ execFileSync3(bin, ["clear-status", "cbp-qa"]);
6824
+ } catch {
6825
+ }
6826
+ try {
6827
+ execFileSync3(bin, ["clear-progress"]);
6828
+ } catch {
6829
+ }
6830
+ } else {
6831
+ if (checkpoint !== void 0) {
6832
+ try {
6833
+ execFileSync3(bin, ["set-status", "cbp-checkpoint", checkpoint]);
6834
+ } catch {
6835
+ }
6836
+ }
6837
+ if (task !== void 0) {
6838
+ try {
6839
+ execFileSync3(bin, ["set-status", "cbp-task", task]);
6840
+ } catch {
6841
+ }
6842
+ }
6843
+ if (qa !== void 0) {
6844
+ try {
6845
+ execFileSync3(bin, ["set-status", "cbp-qa", qa]);
6846
+ } catch {
6847
+ }
6848
+ }
6849
+ if (progress !== void 0) {
6850
+ const decimalStr = normalizeProgress(progress);
6851
+ if (decimalStr !== null) {
6852
+ try {
6853
+ execFileSync3(bin, ["set-progress", decimalStr]);
6854
+ } catch {
6855
+ }
6856
+ }
6857
+ }
6858
+ }
6859
+ process.exit(0);
6860
+ } catch (err) {
6861
+ if (err instanceof ProcessExitSignal) throw err;
6862
+ process.exit(0);
6863
+ }
6864
+ }
6865
+ var init_cmux_status = __esm({
6866
+ "src/cli/cmux-status.ts"() {
6867
+ "use strict";
6868
+ init_process_exit_signal();
6869
+ init_cmux();
6870
+ }
6871
+ });
6872
+
6873
+ // src/cli/cmux-serve.ts
6874
+ var cmux_serve_exports = {};
6875
+ __export(cmux_serve_exports, {
6876
+ probePort: () => probePort,
6877
+ runCmuxServe: () => runCmuxServe
6878
+ });
6879
+ import { execSync as execSync10, execFileSync as execFileSync4 } from "node:child_process";
6880
+ import { readFileSync as readFileSync7 } from "node:fs";
6881
+ import * as net from "node:net";
6882
+ import { join as join23 } from "node:path";
6883
+ function resolveAppDir(allocation, toplevel) {
6884
+ if (allocation.command !== null && allocation.working_dir !== null) {
6885
+ const wd = allocation.working_dir;
6886
+ const dir = wd.startsWith(toplevel + "/") ? wd.slice(toplevel.length + 1) : wd;
6887
+ return { appDir: dir, devCommand: allocation.command };
6888
+ }
6889
+ const label = allocation.label ?? "";
6890
+ if (label === "E2E Tests") return { skip: "skip-e2e" };
6891
+ if (label.includes("Web Dev") && !label.toLowerCase().includes("desktop")) {
6892
+ return { appDir: "apps/web", devCommand: null };
6893
+ }
6894
+ if (label.toLowerCase().includes("desktop")) {
6895
+ return { appDir: "apps/desktop", devCommand: null };
6896
+ }
6897
+ const appDir = LABEL_APP_MAP[label];
6898
+ if (appDir !== void 0) {
6899
+ return { appDir, devCommand: null };
6900
+ }
6901
+ return { skip: "no-match" };
6902
+ }
6903
+ function probePort(port) {
6904
+ return new Promise((resolve8) => {
6905
+ const socket = new net.Socket();
6906
+ let settled = false;
6907
+ const settle = (result) => {
6908
+ if (!settled) {
6909
+ settled = true;
6910
+ socket.destroy();
6911
+ resolve8(result);
6912
+ }
6913
+ };
6914
+ socket.setTimeout(500);
6915
+ socket.on("connect", () => settle(true));
6916
+ socket.on("error", () => settle(false));
6917
+ socket.on("timeout", () => settle(false));
6918
+ socket.connect({ port, host: "127.0.0.1" });
6919
+ });
6920
+ }
6921
+ async function runCmuxServe(args) {
6922
+ try {
6923
+ if (!insideCmux()) {
6924
+ process.exit(0);
6925
+ }
6926
+ let toplevel = "";
6927
+ try {
6928
+ toplevel = execSync10("git rev-parse --show-toplevel", {
6929
+ encoding: "utf8"
6930
+ }).trim();
6931
+ } catch {
6932
+ toplevel = process.cwd();
6933
+ }
6934
+ const cfg = readCmuxConfig(toplevel);
6935
+ if (cfg.auto_dev_server === false) {
6936
+ process.exit(0);
6937
+ }
6938
+ let filesArg;
6939
+ let appArg;
6940
+ for (let i = 0; i < args.length; i++) {
6941
+ const flag = args[i];
6942
+ if (flag === "--files" && i + 1 < args.length) {
6943
+ filesArg = args[++i];
6944
+ } else if (flag === "--app" && i + 1 < args.length) {
6945
+ appArg = args[++i];
6946
+ }
6947
+ }
6948
+ const changedFiles = filesArg !== void 0 ? filesArg.split(",").map((f) => f.trim()).filter(Boolean) : [];
6949
+ let serverConfig = null;
6950
+ try {
6951
+ const raw = readFileSync7(
6952
+ join23(toplevel, ".codebyplan", "server.json"),
6953
+ "utf-8"
6954
+ );
6955
+ serverConfig = JSON.parse(raw);
6956
+ } catch {
6957
+ process.exit(0);
6958
+ }
6959
+ const allocations = serverConfig?.port_allocations ?? [];
6960
+ if (allocations.length === 0) {
6961
+ process.exit(0);
6962
+ }
6963
+ const bin = resolveCmuxBin();
6964
+ for (const allocation of allocations) {
6965
+ try {
6966
+ const resolved = resolveAppDir(allocation, toplevel);
6967
+ if ("skip" in resolved) {
6968
+ if (resolved.skip === "no-match") {
6969
+ process.stdout.write(
6970
+ `cmux-serve: no app mapping for allocation "${allocation.label ?? ""}" \u2014 skipped
6971
+ `
6972
+ );
6973
+ }
6974
+ continue;
6975
+ }
6976
+ const { appDir, devCommand } = resolved;
6977
+ const appDirWithSlash = appDir + "/";
6978
+ const intersects = appArg !== void 0 && (appArg === appDir || appArg.startsWith(appDirWithSlash)) || changedFiles.some(
6979
+ (f) => f === appDir || f.startsWith(appDirWithSlash)
6980
+ );
6981
+ if (!intersects) {
6982
+ continue;
6983
+ }
6984
+ const port = allocation.port;
6985
+ const listening = await probePort(port);
6986
+ if (!listening) {
6987
+ let shellCommand = null;
6988
+ if (devCommand !== null) {
6989
+ shellCommand = `cd "${join23(toplevel, appDir)}" && ${devCommand}`;
6990
+ } else {
6991
+ let hasDev = false;
6992
+ try {
6993
+ const pkgRaw = readFileSync7(
6994
+ join23(toplevel, appDir, "package.json"),
6995
+ "utf-8"
6996
+ );
6997
+ const pkg = JSON.parse(pkgRaw);
6998
+ hasDev = typeof pkg.scripts?.dev === "string";
6999
+ } catch {
7000
+ }
7001
+ if (!hasDev) {
7002
+ process.stdout.write(
7003
+ `cmux-serve: no "dev" script in ${appDir}/package.json \u2014 skipped
7004
+ `
7005
+ );
7006
+ continue;
7007
+ }
7008
+ shellCommand = `cd "${join23(toplevel, appDir)}" && pnpm run dev`;
7009
+ }
7010
+ let splitSurfaceRef = null;
7011
+ try {
7012
+ const splitOut = execFileSync4(
7013
+ bin,
7014
+ ["new-split", "down", "--json"],
7015
+ {
7016
+ encoding: "utf8"
7017
+ }
7018
+ );
7019
+ const parsed = JSON.parse(splitOut);
7020
+ if (typeof parsed.surface_ref === "string" && parsed.surface_ref) {
7021
+ splitSurfaceRef = parsed.surface_ref;
7022
+ }
7023
+ } catch {
7024
+ }
7025
+ if (splitSurfaceRef !== null) {
7026
+ try {
7027
+ execFileSync4(bin, [
7028
+ "send",
7029
+ "--surface",
7030
+ splitSurfaceRef,
7031
+ `${shellCommand}
7032
+ `
7033
+ ]);
7034
+ } catch {
7035
+ }
7036
+ } else {
7037
+ process.stdout.write(
7038
+ `cmux-serve: could not resolve new split surface for ${appDir} \u2014 dev server not auto-started (open it manually)
7039
+ `
7040
+ );
7041
+ }
7042
+ }
7043
+ try {
7044
+ execFileSync4(bin, [
7045
+ "new-pane",
7046
+ "--type",
7047
+ "browser",
7048
+ "--url",
7049
+ `http://localhost:${port}`
7050
+ ]);
7051
+ } catch {
7052
+ }
7053
+ } catch {
7054
+ }
7055
+ }
7056
+ process.exit(0);
7057
+ } catch (err) {
7058
+ if (err instanceof ProcessExitSignal) throw err;
7059
+ process.exit(0);
7060
+ }
7061
+ }
7062
+ var LABEL_APP_MAP;
7063
+ var init_cmux_serve = __esm({
7064
+ "src/cli/cmux-serve.ts"() {
7065
+ "use strict";
7066
+ init_process_exit_signal();
7067
+ init_cmux();
7068
+ LABEL_APP_MAP = {
7069
+ "Backend Dev": "apps/backend",
7070
+ "MCP Dev": "apps/mcp",
7071
+ "Docs Ingest": "apps/docs-ingest"
7072
+ };
6439
7073
  }
6440
7074
  });
6441
7075
 
6442
7076
  // src/lib/migrate-local-config.ts
6443
- import { mkdir as mkdir6, readFile as readFile15, unlink as unlink2, writeFile as writeFile12 } from "node:fs/promises";
6444
- import { join as join21 } from "node:path";
7077
+ import { mkdir as mkdir6, readFile as readFile16, unlink as unlink2, writeFile as writeFile12 } from "node:fs/promises";
7078
+ import { join as join24 } from "node:path";
6445
7079
  function legacySharedPath(projectPath) {
6446
- return join21(projectPath, ".codebyplan.json");
7080
+ return join24(projectPath, ".codebyplan.json");
6447
7081
  }
6448
7082
  function legacyLocalPath(projectPath) {
6449
- return join21(projectPath, ".codebyplan.local.json");
7083
+ return join24(projectPath, ".codebyplan.local.json");
6450
7084
  }
6451
7085
  function newDirPath(projectPath) {
6452
- return join21(projectPath, ".codebyplan");
7086
+ return join24(projectPath, ".codebyplan");
6453
7087
  }
6454
7088
  function sentinelPath(projectPath) {
6455
- return join21(projectPath, ".codebyplan", "repo.json");
7089
+ return join24(projectPath, ".codebyplan", "repo.json");
6456
7090
  }
6457
7091
  async function statSafe(p) {
6458
7092
  const { stat: stat2 } = await import("node:fs/promises");
@@ -6491,7 +7125,7 @@ async function runLocalMigration(projectPath) {
6491
7125
  }
6492
7126
  let legacyRaw;
6493
7127
  try {
6494
- legacyRaw = await readFile15(legacySharedPath(projectPath), "utf-8");
7128
+ legacyRaw = await readFile16(legacySharedPath(projectPath), "utf-8");
6495
7129
  } catch {
6496
7130
  return {
6497
7131
  migrated: true,
@@ -6518,7 +7152,7 @@ async function runLocalMigration(projectPath) {
6518
7152
  let deviceId;
6519
7153
  let deviceWrittenByHelper = false;
6520
7154
  try {
6521
- const localRaw = await readFile15(legacyLocalPath(projectPath), "utf-8");
7155
+ const localRaw = await readFile16(legacyLocalPath(projectPath), "utf-8");
6522
7156
  const localParsed = JSON.parse(localRaw);
6523
7157
  if (typeof localParsed.device_id === "string") {
6524
7158
  deviceId = localParsed.device_id;
@@ -6546,7 +7180,7 @@ async function runLocalMigration(projectPath) {
6546
7180
  if ("organization_id" in cfg) repoJson.organization_id = cfg.organization_id;
6547
7181
  if ("project_id" in cfg) repoJson.project_id = cfg.project_id;
6548
7182
  await writeFile12(
6549
- join21(projectPath, ".codebyplan", "repo.json"),
7183
+ join24(projectPath, ".codebyplan", "repo.json"),
6550
7184
  JSON.stringify(repoJson, null, 2) + "\n",
6551
7185
  "utf-8"
6552
7186
  );
@@ -6559,7 +7193,7 @@ async function runLocalMigration(projectPath) {
6559
7193
  if ("port_allocations" in cfg)
6560
7194
  serverJson.port_allocations = cfg.port_allocations;
6561
7195
  await writeFile12(
6562
- join21(projectPath, ".codebyplan", "server.json"),
7196
+ join24(projectPath, ".codebyplan", "server.json"),
6563
7197
  JSON.stringify(serverJson, null, 2) + "\n",
6564
7198
  "utf-8"
6565
7199
  );
@@ -6568,7 +7202,7 @@ async function runLocalMigration(projectPath) {
6568
7202
  if ("git_branch" in cfg) gitJson.git_branch = cfg.git_branch;
6569
7203
  if ("branch_config" in cfg) gitJson.branch_config = cfg.branch_config;
6570
7204
  await writeFile12(
6571
- join21(projectPath, ".codebyplan", "git.json"),
7205
+ join24(projectPath, ".codebyplan", "git.json"),
6572
7206
  JSON.stringify(gitJson, null, 2) + "\n",
6573
7207
  "utf-8"
6574
7208
  );
@@ -6576,35 +7210,35 @@ async function runLocalMigration(projectPath) {
6576
7210
  const shipmentJson = {};
6577
7211
  if ("shipment" in cfg) shipmentJson.shipment = cfg.shipment;
6578
7212
  await writeFile12(
6579
- join21(projectPath, ".codebyplan", "shipment.json"),
7213
+ join24(projectPath, ".codebyplan", "shipment.json"),
6580
7214
  JSON.stringify(shipmentJson, null, 2) + "\n",
6581
7215
  "utf-8"
6582
7216
  );
6583
7217
  filesChanged.push(".codebyplan/shipment.json");
6584
7218
  const vendorJson = {};
6585
7219
  await writeFile12(
6586
- join21(projectPath, ".codebyplan", "vendor.json"),
7220
+ join24(projectPath, ".codebyplan", "vendor.json"),
6587
7221
  JSON.stringify(vendorJson, null, 2) + "\n",
6588
7222
  "utf-8"
6589
7223
  );
6590
7224
  filesChanged.push(".codebyplan/vendor.json");
6591
7225
  const e2eJson = {};
6592
7226
  await writeFile12(
6593
- join21(projectPath, ".codebyplan", "e2e.json"),
7227
+ join24(projectPath, ".codebyplan", "e2e.json"),
6594
7228
  JSON.stringify(e2eJson, null, 2) + "\n",
6595
7229
  "utf-8"
6596
7230
  );
6597
7231
  filesChanged.push(".codebyplan/e2e.json");
6598
7232
  const eslintJson = {};
6599
7233
  await writeFile12(
6600
- join21(projectPath, ".codebyplan", "eslint.json"),
7234
+ join24(projectPath, ".codebyplan", "eslint.json"),
6601
7235
  JSON.stringify(eslintJson, null, 2) + "\n",
6602
7236
  "utf-8"
6603
7237
  );
6604
7238
  filesChanged.push(".codebyplan/eslint.json");
6605
7239
  if (!deviceWrittenByHelper) {
6606
7240
  await writeFile12(
6607
- join21(projectPath, ".codebyplan", "device.local.json"),
7241
+ join24(projectPath, ".codebyplan", "device.local.json"),
6608
7242
  JSON.stringify({ device_id: deviceId }, null, 2) + "\n",
6609
7243
  "utf-8"
6610
7244
  );
@@ -6616,9 +7250,9 @@ async function runLocalMigration(projectPath) {
6616
7250
  "Migration write incomplete: .codebyplan/repo.json was not persisted. Re-run migration to retry from a clean state."
6617
7251
  );
6618
7252
  }
6619
- const gitignorePath = join21(projectPath, ".gitignore");
7253
+ const gitignorePath = join24(projectPath, ".gitignore");
6620
7254
  try {
6621
- const gitignoreContent = await readFile15(gitignorePath, "utf-8");
7255
+ const gitignoreContent = await readFile16(gitignorePath, "utf-8");
6622
7256
  const legacyLine = ".codebyplan.local.json";
6623
7257
  const newLine = ".codebyplan/device.local.json";
6624
7258
  const hasLegacy = gitignoreContent.split("\n").some((l) => l.trimEnd() === legacyLine);
@@ -6669,7 +7303,7 @@ var init_migrate_local_config = __esm({
6669
7303
  // src/cli/config.ts
6670
7304
  var config_exports = {};
6671
7305
  __export(config_exports, {
6672
- readE2eConfig: () => readE2eConfig,
7306
+ readE2eConfig: () => readE2eConfig2,
6673
7307
  readGitConfig: () => readGitConfig,
6674
7308
  readRepoConfig: () => readRepoConfig,
6675
7309
  readServerConfig: () => readServerConfig,
@@ -6677,8 +7311,8 @@ __export(config_exports, {
6677
7311
  readVendorConfig: () => readVendorConfig,
6678
7312
  runConfig: () => runConfig
6679
7313
  });
6680
- import { mkdir as mkdir7, readFile as readFile16, writeFile as writeFile13 } from "node:fs/promises";
6681
- import { join as join22 } from "node:path";
7314
+ import { mkdir as mkdir7, readFile as readFile17, writeFile as writeFile13 } from "node:fs/promises";
7315
+ import { join as join25 } from "node:path";
6682
7316
  async function runConfig() {
6683
7317
  const flags = parseFlags(3);
6684
7318
  const dryRun = hasFlag("dry-run", 3);
@@ -6711,14 +7345,14 @@ async function runConfig() {
6711
7345
  console.log("\n Config complete.\n");
6712
7346
  }
6713
7347
  async function syncConfigToFile(repoId, projectPath, dryRun) {
6714
- const codebyplanDir = join22(projectPath, ".codebyplan");
7348
+ const codebyplanDir = join25(projectPath, ".codebyplan");
6715
7349
  let resolvedWorktreeId;
6716
7350
  try {
6717
7351
  const deviceId = await getOrCreateDeviceId(projectPath);
6718
7352
  let branch = "main";
6719
7353
  try {
6720
- const { execSync: execSync8 } = await import("node:child_process");
6721
- branch = execSync8("git symbolic-ref --short HEAD", {
7354
+ const { execSync: execSync11 } = await import("node:child_process");
7355
+ branch = execSync11("git symbolic-ref --short HEAD", {
6722
7356
  cwd: projectPath,
6723
7357
  encoding: "utf-8"
6724
7358
  }).trim();
@@ -6838,6 +7472,7 @@ async function syncConfigToFile(repoId, projectPath, dryRun) {
6838
7472
  const vendorPayload = {};
6839
7473
  const e2ePayload = {};
6840
7474
  const eslintPayload = {};
7475
+ const cmuxPayload = {};
6841
7476
  if (dryRun) {
6842
7477
  console.log(" Config would be updated (dry-run).");
6843
7478
  return;
@@ -6850,15 +7485,16 @@ async function syncConfigToFile(repoId, projectPath, dryRun) {
6850
7485
  { name: "shipment.json", payload: shipmentPayload },
6851
7486
  { name: "vendor.json", payload: vendorPayload },
6852
7487
  { name: "e2e.json", payload: e2ePayload, createOnly: true },
6853
- { name: "eslint.json", payload: eslintPayload, createOnly: true }
7488
+ { name: "eslint.json", payload: eslintPayload, createOnly: true },
7489
+ { name: "cmux.json", payload: cmuxPayload, createOnly: true }
6854
7490
  ];
6855
7491
  let anyUpdated = false;
6856
7492
  for (const { name, payload, createOnly } of files) {
6857
- const filePath = join22(codebyplanDir, name);
7493
+ const filePath = join25(codebyplanDir, name);
6858
7494
  const newJson = JSON.stringify(payload, null, 2) + "\n";
6859
7495
  let currentJson = "";
6860
7496
  try {
6861
- currentJson = await readFile16(filePath, "utf-8");
7497
+ currentJson = await readFile17(filePath, "utf-8");
6862
7498
  } catch {
6863
7499
  }
6864
7500
  if (createOnly && currentJson !== "") continue;
@@ -6873,8 +7509,8 @@ async function syncConfigToFile(repoId, projectPath, dryRun) {
6873
7509
  }
6874
7510
  async function readRepoConfig(projectPath) {
6875
7511
  try {
6876
- const raw = await readFile16(
6877
- join22(projectPath, ".codebyplan", "repo.json"),
7512
+ const raw = await readFile17(
7513
+ join25(projectPath, ".codebyplan", "repo.json"),
6878
7514
  "utf-8"
6879
7515
  );
6880
7516
  return JSON.parse(raw);
@@ -6884,8 +7520,8 @@ async function readRepoConfig(projectPath) {
6884
7520
  }
6885
7521
  async function readServerConfig(projectPath) {
6886
7522
  try {
6887
- const raw = await readFile16(
6888
- join22(projectPath, ".codebyplan", "server.json"),
7523
+ const raw = await readFile17(
7524
+ join25(projectPath, ".codebyplan", "server.json"),
6889
7525
  "utf-8"
6890
7526
  );
6891
7527
  return JSON.parse(raw);
@@ -6895,8 +7531,8 @@ async function readServerConfig(projectPath) {
6895
7531
  }
6896
7532
  async function readGitConfig(projectPath) {
6897
7533
  try {
6898
- const raw = await readFile16(
6899
- join22(projectPath, ".codebyplan", "git.json"),
7534
+ const raw = await readFile17(
7535
+ join25(projectPath, ".codebyplan", "git.json"),
6900
7536
  "utf-8"
6901
7537
  );
6902
7538
  return JSON.parse(raw);
@@ -6906,8 +7542,8 @@ async function readGitConfig(projectPath) {
6906
7542
  }
6907
7543
  async function readShipmentConfig(projectPath) {
6908
7544
  try {
6909
- const raw = await readFile16(
6910
- join22(projectPath, ".codebyplan", "shipment.json"),
7545
+ const raw = await readFile17(
7546
+ join25(projectPath, ".codebyplan", "shipment.json"),
6911
7547
  "utf-8"
6912
7548
  );
6913
7549
  return JSON.parse(raw);
@@ -6917,8 +7553,8 @@ async function readShipmentConfig(projectPath) {
6917
7553
  }
6918
7554
  async function readVendorConfig(projectPath) {
6919
7555
  try {
6920
- const raw = await readFile16(
6921
- join22(projectPath, ".codebyplan", "vendor.json"),
7556
+ const raw = await readFile17(
7557
+ join25(projectPath, ".codebyplan", "vendor.json"),
6922
7558
  "utf-8"
6923
7559
  );
6924
7560
  return JSON.parse(raw);
@@ -6926,10 +7562,10 @@ async function readVendorConfig(projectPath) {
6926
7562
  return null;
6927
7563
  }
6928
7564
  }
6929
- async function readE2eConfig(projectPath) {
7565
+ async function readE2eConfig2(projectPath) {
6930
7566
  try {
6931
- const raw = await readFile16(
6932
- join22(projectPath, ".codebyplan", "e2e.json"),
7567
+ const raw = await readFile17(
7568
+ join25(projectPath, ".codebyplan", "e2e.json"),
6933
7569
  "utf-8"
6934
7570
  );
6935
7571
  return JSON.parse(raw);
@@ -6985,14 +7621,14 @@ var init_server_detect = __esm({
6985
7621
  });
6986
7622
 
6987
7623
  // src/lib/port-verify.ts
6988
- import { readFile as readFile17 } from "node:fs/promises";
7624
+ import { readFile as readFile18 } from "node:fs/promises";
6989
7625
  async function verifyPorts(projectPath, portAllocations) {
6990
7626
  const mismatches = [];
6991
7627
  const allocatedPorts = new Set(portAllocations.map((a) => a.port));
6992
7628
  const packageJsonPaths = await findPackageJsonFiles(projectPath, projectPath);
6993
7629
  for (const pkgPath of packageJsonPaths) {
6994
7630
  try {
6995
- const raw = await readFile17(pkgPath, "utf-8");
7631
+ const raw = await readFile18(pkgPath, "utf-8");
6996
7632
  const pkg = JSON.parse(raw);
6997
7633
  const scriptPort = detectPortFromScripts(pkg);
6998
7634
  if (scriptPort !== null && !allocatedPorts.has(scriptPort)) {
@@ -7055,7 +7691,7 @@ async function findUnallocatedApps(projectPath, portAllocations) {
7055
7691
  }
7056
7692
  let pkg;
7057
7693
  try {
7058
- const raw = await readFile17(`${app.absPath}/package.json`, "utf-8");
7694
+ const raw = await readFile18(`${app.absPath}/package.json`, "utf-8");
7059
7695
  pkg = JSON.parse(raw);
7060
7696
  } catch {
7061
7697
  continue;
@@ -7263,10 +7899,10 @@ async function runTechStack() {
7263
7899
  );
7264
7900
  }
7265
7901
  try {
7266
- const { execSync: execSync8 } = await import("node:child_process");
7902
+ const { execSync: execSync11 } = await import("node:child_process");
7267
7903
  let branch = "main";
7268
7904
  try {
7269
- branch = execSync8("git symbolic-ref --short HEAD", {
7905
+ branch = execSync11("git symbolic-ref --short HEAD", {
7270
7906
  cwd: projectPath,
7271
7907
  encoding: "utf-8"
7272
7908
  }).trim();
@@ -7429,11 +8065,11 @@ async function ask(q, opts) {
7429
8065
  try {
7430
8066
  while (true) {
7431
8067
  const choices = q.choices.map((c) => `[${c.key}] ${c.label}`).join(" ");
7432
- const answer = await new Promise((resolve7) => {
8068
+ const answer = await new Promise((resolve8) => {
7433
8069
  rl.question(`${q.message}
7434
8070
  ${choices}
7435
8071
  > `, (input) => {
7436
- resolve7(input.trim().toLowerCase());
8072
+ resolve8(input.trim().toLowerCase());
7437
8073
  });
7438
8074
  });
7439
8075
  const match = q.choices.find(
@@ -8065,13 +8701,13 @@ var init_uninstall = __esm({
8065
8701
 
8066
8702
  // src/index.ts
8067
8703
  init_version();
8068
- import { readFileSync as readFileSync8 } from "node:fs";
8069
- import { resolve as resolve6 } from "node:path";
8704
+ import { readFileSync as readFileSync10 } from "node:fs";
8705
+ import { resolve as resolve7 } from "node:path";
8070
8706
  void (async () => {
8071
8707
  if (!process.env.CODEBYPLAN_API_KEY) {
8072
8708
  try {
8073
- const envPath = resolve6(process.cwd(), ".env.local");
8074
- const content = readFileSync8(envPath, "utf-8");
8709
+ const envPath = resolve7(process.cwd(), ".env.local");
8710
+ const content = readFileSync10(envPath, "utf-8");
8075
8711
  for (const line of content.split("\n")) {
8076
8712
  const trimmed = line.trim();
8077
8713
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -8203,11 +8839,29 @@ void (async () => {
8203
8839
  await runVersionStatus2();
8204
8840
  process.exit(0);
8205
8841
  }
8842
+ if (arg === "upload-e2e-images") {
8843
+ const { runUploadE2eImagesCommand: runUploadE2eImagesCommand2 } = await Promise.resolve().then(() => (init_upload_e2e_images(), upload_e2e_images_exports));
8844
+ const rest = process.argv.slice(3);
8845
+ await runUploadE2eImagesCommand2(rest);
8846
+ process.exit(0);
8847
+ }
8206
8848
  if (arg === "cmux-sync") {
8207
8849
  const { runCmuxSync: runCmuxSync2 } = await Promise.resolve().then(() => (init_cmux_sync(), cmux_sync_exports));
8208
8850
  await runCmuxSync2();
8209
8851
  process.exit(0);
8210
8852
  }
8853
+ if (arg === "cmux-status") {
8854
+ const { runCmuxStatus: runCmuxStatus2 } = await Promise.resolve().then(() => (init_cmux_status(), cmux_status_exports));
8855
+ const rest = process.argv.slice(3);
8856
+ await runCmuxStatus2(rest);
8857
+ process.exit(0);
8858
+ }
8859
+ if (arg === "cmux-serve") {
8860
+ const { runCmuxServe: runCmuxServe2 } = await Promise.resolve().then(() => (init_cmux_serve(), cmux_serve_exports));
8861
+ const rest = process.argv.slice(3);
8862
+ await runCmuxServe2(rest);
8863
+ process.exit(0);
8864
+ }
8211
8865
  if (arg === "config") {
8212
8866
  const { runConfig: runConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
8213
8867
  await runConfig2();
@@ -8304,6 +8958,7 @@ void (async () => {
8304
8958
  codebyplan round sync-approvals Sync git diff and approvals with round/task state
8305
8959
  codebyplan bump Detect changed packages and patch-bump versions
8306
8960
  codebyplan ship Ship current feat branch to production via PR
8961
+ codebyplan upload-e2e-images Upload new/changed committed e2e PNGs for a checkpoint
8307
8962
  codebyplan scaffold-publish-workflow Write the publish-on-main GitHub workflow into ./.github/workflows/
8308
8963
  codebyplan branch migrate Rewrite branch_config from 3-branch to 2-tier model
8309
8964
  codebyplan claude Claude asset management (install/update/uninstall)
@@ -8311,6 +8966,8 @@ void (async () => {
8311
8966
  codebyplan resolve-worktree Resolve active worktree UUID from device+path+branch tuple
8312
8967
  codebyplan version-status Report installed vs latest version + update guard (JSON)
8313
8968
  codebyplan cmux-sync Sync cmux workspace title/description to current git branch and repo folder
8969
+ codebyplan cmux-status Push checkpoint/task/QA + progress to the cmux workspace sidebar
8970
+ codebyplan cmux-serve Auto-start dev server + browser pane for the round's app files (cmux)
8314
8971
  codebyplan help Show this help message
8315
8972
  codebyplan --version Print version
8316
8973