kenzoboard 0.1.1 → 0.1.3

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/index.js CHANGED
@@ -1,5 +1,4 @@
1
- #!/usr/bin/env bun
2
- // @bun
1
+ #!/usr/bin/env node
3
2
  import { createRequire } from "node:module";
4
3
  var __create = Object.create;
5
4
  var __getProtoOf = Object.getPrototypeOf;
@@ -29,146 +28,65 @@ var __export = (target, all) => {
29
28
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
30
29
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
31
30
 
32
- // ../shared/dist/adapters/sqlite-adapter.js
33
- var exports_sqlite_adapter = {};
34
- __export(exports_sqlite_adapter, {
35
- createSqliteAdapter: () => createSqliteAdapter
36
- });
37
- import { Database } from "bun:sqlite";
38
- import { existsSync as existsSync2, mkdirSync as mkdirSync2 } from "fs";
39
- import { dirname as dirname2 } from "path";
40
- function createSqliteAdapter(filePath) {
41
- const dir = dirname2(filePath);
42
- if (!existsSync2(dir)) {
43
- mkdirSync2(dir, { recursive: true });
44
- }
45
- const db2 = new Database(filePath, { create: true });
46
- db2.exec("PRAGMA journal_mode = WAL");
47
- db2.exec("CREATE TABLE IF NOT EXISTS store (id INTEGER PRIMARY KEY CHECK (id = 1), data TEXT NOT NULL)");
48
- const selectStmt = db2.prepare("SELECT data FROM store WHERE id = 1");
49
- const insertStmt = db2.prepare("INSERT INTO store (id, data) VALUES (1, ?)");
50
- const updateStmt = db2.prepare("UPDATE store SET data = ? WHERE id = 1");
51
- let _data = { ...defaultData2 };
52
- const readFromDb = () => {
53
- const row = selectStmt.get();
54
- if (row?.data) {
55
- try {
56
- return JSON.parse(row.data);
57
- } catch {
58
- return { ...defaultData2 };
59
- }
60
- }
61
- return { ...defaultData2 };
62
- };
63
- return {
64
- get data() {
65
- return _data;
66
- },
67
- read() {
68
- _data = readFromDb();
69
- if (!selectStmt.get()) {
70
- insertStmt.run(JSON.stringify(_data));
71
- }
72
- },
73
- write() {
74
- db2.transaction(() => {
75
- const current = readFromDb();
76
- const merged = {
77
- projects: mergeById(current.projects, _data.projects),
78
- epics: mergeById(current.epics, _data.epics),
79
- tasks: mergeById(current.tasks, _data.tasks),
80
- blobs: mergeById(current.blobs || [], _data.blobs || [])
81
- };
82
- const serialized = JSON.stringify(merged);
83
- const row = selectStmt.get();
84
- if (row) {
85
- updateStmt.run(serialized);
86
- } else {
87
- insertStmt.run(serialized);
88
- }
89
- _data = merged;
90
- })();
91
- }
92
- };
93
- }
94
- function mergeById(current, updated) {
95
- const result = new Map;
96
- for (const item of current) {
97
- result.set(item.id, item);
98
- }
99
- for (const item of updated) {
100
- result.set(item.id, item);
101
- }
102
- return Array.from(result.values());
103
- }
104
- var defaultData2;
105
- var init_sqlite_adapter = __esm(() => {
106
- defaultData2 = {
107
- projects: [],
108
- epics: [],
109
- tasks: []
110
- };
111
- });
112
-
113
31
  // ../shared/dist/blob-storage.js
114
32
  var exports_blob_storage = {};
115
33
  __export(exports_blob_storage, {
116
- setBlobStorage: () => setBlobStorage2,
34
+ setBlobStorage: () => setBlobStorage,
117
35
  getBlobStorage: () => getBlobStorage,
118
- createFilesystemBlobStorage: () => createFilesystemBlobStorage2
36
+ createFilesystemBlobStorage: () => createFilesystemBlobStorage
119
37
  });
120
- import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4, unlinkSync as unlinkSync2 } from "fs";
121
- import { join as join2 } from "path";
122
- import { createHash as createHash2 } from "crypto";
123
- function blobPath2(blobsDir, hash) {
38
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, unlinkSync } from "fs";
39
+ import { join } from "path";
40
+ import { createHash } from "crypto";
41
+ function blobPath(blobsDir, hash) {
124
42
  const prefix = hash.slice(0, 2);
125
- return join2(blobsDir, prefix, hash);
43
+ return join(blobsDir, prefix, hash);
126
44
  }
127
- function createFilesystemBlobStorage2(blobsDir) {
128
- mkdirSync4(blobsDir, { recursive: true });
45
+ function createFilesystemBlobStorage(blobsDir) {
46
+ mkdirSync2(blobsDir, { recursive: true });
129
47
  return {
130
48
  write(content) {
131
- const hash = createHash2("sha256").update(content).digest("hex");
49
+ const hash = createHash("sha256").update(content).digest("hex");
132
50
  const size = content.length;
133
- const filePath = blobPath2(blobsDir, hash);
134
- if (!existsSync5(filePath)) {
135
- const prefixDir = join2(blobsDir, hash.slice(0, 2));
136
- mkdirSync4(prefixDir, { recursive: true });
137
- writeFileSync4(filePath, content);
51
+ const filePath = blobPath(blobsDir, hash);
52
+ if (!existsSync2(filePath)) {
53
+ const prefixDir = join(blobsDir, hash.slice(0, 2));
54
+ mkdirSync2(prefixDir, { recursive: true });
55
+ writeFileSync2(filePath, content);
138
56
  }
139
57
  return { hash, size };
140
58
  },
141
59
  read(hash) {
142
- const filePath = blobPath2(blobsDir, hash);
143
- if (!existsSync5(filePath))
60
+ const filePath = blobPath(blobsDir, hash);
61
+ if (!existsSync2(filePath))
144
62
  return null;
145
- return readFileSync4(filePath);
63
+ return readFileSync2(filePath);
146
64
  },
147
65
  exists(hash) {
148
- return existsSync5(blobPath2(blobsDir, hash));
66
+ return existsSync2(blobPath(blobsDir, hash));
149
67
  },
150
68
  remove(hash) {
151
- const filePath = blobPath2(blobsDir, hash);
152
- if (!existsSync5(filePath))
69
+ const filePath = blobPath(blobsDir, hash);
70
+ if (!existsSync2(filePath))
153
71
  return false;
154
- unlinkSync2(filePath);
72
+ unlinkSync(filePath);
155
73
  return true;
156
74
  }
157
75
  };
158
76
  }
159
- function setBlobStorage2(bs) {
160
- blobStorage2 = bs;
77
+ function setBlobStorage(bs) {
78
+ blobStorage = bs;
161
79
  }
162
80
  function getBlobStorage() {
163
- return blobStorage2;
81
+ return blobStorage;
164
82
  }
165
- var blobStorage2 = null;
83
+ var blobStorage = null;
166
84
  var init_blob_storage = () => {};
167
85
 
168
86
  // src/index.ts
169
- import { resolve as resolve4, dirname as dirname5, basename as basename2 } from "path";
87
+ import { resolve as resolve4, dirname as dirname4, basename as basename2 } from "path";
170
88
  import { execSync } from "child_process";
171
- import { existsSync as existsSync9, readFileSync as readFileSync7, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, appendFileSync, cpSync, realpathSync } from "fs";
89
+ import { existsSync as existsSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync5, mkdirSync as mkdirSync3, appendFileSync, cpSync, realpathSync } from "fs";
172
90
  import { fileURLToPath as fileURLToPath2, pathToFileURL } from "url";
173
91
  import { createInterface } from "readline";
174
92
 
@@ -680,11 +598,14 @@ function createJsonAdapter(filePath) {
680
598
 
681
599
  // ../shared/dist/adapters/index.js
682
600
  var _createSqliteAdapter;
683
- try {
684
- const mod = await Promise.resolve().then(() => (init_sqlite_adapter(), exports_sqlite_adapter));
685
- _createSqliteAdapter = mod.createSqliteAdapter;
686
- } catch {}
687
- function createSqliteAdapter2(filePath) {
601
+ if ("Bun" in globalThis) {
602
+ try {
603
+ const runtimeImport = new Function("specifier", "return import(specifier)");
604
+ const mod = await runtimeImport("./sqlite-adapter.js");
605
+ _createSqliteAdapter = mod.createSqliteAdapter;
606
+ } catch {}
607
+ }
608
+ function createSqliteAdapter(filePath) {
688
609
  if (!_createSqliteAdapter) {
689
610
  throw new Error("SQLite adapter requires Bun runtime");
690
611
  }
@@ -692,59 +613,17 @@ function createSqliteAdapter2(filePath) {
692
613
  }
693
614
  function createAdapter(filePath) {
694
615
  if (filePath.endsWith(".sqlite") || filePath.endsWith(".db")) {
695
- return createSqliteAdapter2(filePath);
616
+ return createSqliteAdapter(filePath);
696
617
  }
697
618
  return createJsonAdapter(filePath);
698
619
  }
699
620
 
700
- // ../shared/dist/blob-storage.js
701
- import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2, unlinkSync } from "fs";
702
- import { join } from "path";
703
- import { createHash } from "crypto";
704
- function blobPath(blobsDir, hash) {
705
- const prefix = hash.slice(0, 2);
706
- return join(blobsDir, prefix, hash);
707
- }
708
- function createFilesystemBlobStorage(blobsDir) {
709
- mkdirSync3(blobsDir, { recursive: true });
710
- return {
711
- write(content) {
712
- const hash = createHash("sha256").update(content).digest("hex");
713
- const size = content.length;
714
- const filePath = blobPath(blobsDir, hash);
715
- if (!existsSync3(filePath)) {
716
- const prefixDir = join(blobsDir, hash.slice(0, 2));
717
- mkdirSync3(prefixDir, { recursive: true });
718
- writeFileSync2(filePath, content);
719
- }
720
- return { hash, size };
721
- },
722
- read(hash) {
723
- const filePath = blobPath(blobsDir, hash);
724
- if (!existsSync3(filePath))
725
- return null;
726
- return readFileSync2(filePath);
727
- },
728
- exists(hash) {
729
- return existsSync3(blobPath(blobsDir, hash));
730
- },
731
- remove(hash) {
732
- const filePath = blobPath(blobsDir, hash);
733
- if (!existsSync3(filePath))
734
- return false;
735
- unlinkSync(filePath);
736
- return true;
737
- }
738
- };
739
- }
740
- var blobStorage = null;
741
- function setBlobStorage(bs) {
742
- blobStorage = bs;
743
- }
621
+ // src/index.ts
622
+ init_blob_storage();
744
623
 
745
624
  // ../shared/dist/config.js
746
- import { resolve, dirname as dirname3 } from "path";
747
- import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync3, chmodSync } from "fs";
625
+ import { resolve, dirname as dirname2 } from "path";
626
+ import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3, chmodSync } from "fs";
748
627
  function expandEnv(value) {
749
628
  if (!value?.startsWith("$"))
750
629
  return value;
@@ -755,20 +634,20 @@ function findFluxDir() {
755
634
  return process.env.FLUX_DIR;
756
635
  }
757
636
  let dir = process.cwd();
758
- while (dirname3(dir) !== dir) {
637
+ while (dirname2(dir) !== dir) {
759
638
  const fluxDir = resolve(dir, ".flux");
760
- if (existsSync4(fluxDir)) {
639
+ if (existsSync3(fluxDir)) {
761
640
  return fluxDir;
762
641
  }
763
- dir = dirname3(dir);
642
+ dir = dirname2(dir);
764
643
  }
765
644
  const homeDir = process.env.HOME || process.env.USERPROFILE || "";
766
645
  return resolve(homeDir, ".flux");
767
646
  }
768
647
  function loadEnvLocal(fluxDir) {
769
- const repoRoot = dirname3(fluxDir);
648
+ const repoRoot = dirname2(fluxDir);
770
649
  const envPath = resolve(repoRoot, ".env.local");
771
- if (existsSync4(envPath)) {
650
+ if (existsSync3(envPath)) {
772
651
  const content = readFileSync3(envPath, "utf-8");
773
652
  for (const line of content.split(`
774
653
  `)) {
@@ -788,7 +667,7 @@ function loadEnvLocal(fluxDir) {
788
667
  }
789
668
  function readConfigRaw(fluxDir) {
790
669
  const configPath = resolve(fluxDir, "config.json");
791
- if (existsSync4(configPath)) {
670
+ if (existsSync3(configPath)) {
792
671
  try {
793
672
  return JSON.parse(readFileSync3(configPath, "utf-8"));
794
673
  } catch {
@@ -2302,8 +2181,8 @@ var _baseMimes = {
2302
2181
  var baseMimes = _baseMimes;
2303
2182
 
2304
2183
  // ../../node_modules/.bun/@hono+node-server@1.19.8+fd698e00a3b2abce/node_modules/@hono/node-server/dist/serve-static.mjs
2305
- import { createReadStream, statSync, existsSync as existsSync6 } from "fs";
2306
- import { join as join3 } from "path";
2184
+ import { createReadStream, statSync, existsSync as existsSync4 } from "fs";
2185
+ import { join as join2 } from "path";
2307
2186
  import { versions } from "process";
2308
2187
  import { Readable as Readable2 } from "stream";
2309
2188
  var COMPRESSIBLE_CONTENT_TYPE_REGEX = /^\s*(?:text\/[^;\s]+|application\/(?:javascript|json|xml|xml-dtd|ecmascript|dart|postscript|rtf|tar|toml|vnd\.dart|vnd\.ms-fontobject|vnd\.ms-opentype|wasm|x-httpd-php|x-javascript|x-ns-proxy-autoconfig|x-sh|x-tar|x-virtualbox-hdd|x-virtualbox-ova|x-virtualbox-ovf|x-virtualbox-vbox|x-virtualbox-vdi|x-virtualbox-vhd|x-virtualbox-vmdk|x-www-form-urlencoded)|font\/(?:otf|ttf)|image\/(?:bmp|vnd\.adobe\.photoshop|vnd\.microsoft\.icon|vnd\.ms-dds|x-icon|x-ms-bmp)|message\/rfc822|model\/gltf-binary|x-shader\/x-fragment|x-shader\/x-vertex|[^;\s]+?\+(?:json|text|xml|yaml))(?:[;\s]|$)/i;
@@ -2350,7 +2229,7 @@ var getStats = (path) => {
2350
2229
  var serveStatic = (options = { root: "" }) => {
2351
2230
  const root = options.root || "";
2352
2231
  const optionPath = options.path;
2353
- if (root !== "" && !existsSync6(root)) {
2232
+ if (root !== "" && !existsSync4(root)) {
2354
2233
  console.error(`serveStatic: root path '${root}' is not found, are you sure it's correct?`);
2355
2234
  }
2356
2235
  return async (c, next) => {
@@ -2371,11 +2250,11 @@ var serveStatic = (options = { root: "" }) => {
2371
2250
  return next();
2372
2251
  }
2373
2252
  }
2374
- let path = join3(root, !optionPath && options.rewriteRequestPath ? options.rewriteRequestPath(filename, c) : filename);
2253
+ let path = join2(root, !optionPath && options.rewriteRequestPath ? options.rewriteRequestPath(filename, c) : filename);
2375
2254
  let stats = getStats(path);
2376
2255
  if (stats && stats.isDirectory()) {
2377
2256
  const indexFile = options.index ?? "index.html";
2378
- path = join3(path, indexFile);
2257
+ path = join2(path, indexFile);
2379
2258
  stats = getStats(path);
2380
2259
  }
2381
2260
  if (!stats) {
@@ -4033,32 +3912,12 @@ var cors = (options) => {
4033
3912
  };
4034
3913
 
4035
3914
  // src/commands/serve.ts
4036
- import { join as join4, dirname as dirname4, resolve as resolve2, sep } from "path";
3915
+ import { join as join3, dirname as dirname3, resolve as resolve2, sep } from "path";
4037
3916
  import { fileURLToPath } from "url";
4038
- import { existsSync as existsSync7, readFileSync as readFileSync5, statSync as statSync2 } from "fs";
3917
+ import { existsSync as existsSync5, readFileSync as readFileSync4, statSync as statSync2 } from "fs";
4039
3918
  import { spawn } from "child_process";
4040
-
4041
- // ../shared/dist/adapters/index.js
4042
- var _createSqliteAdapter2;
4043
- try {
4044
- const mod = await Promise.resolve().then(() => (init_sqlite_adapter(), exports_sqlite_adapter));
4045
- _createSqliteAdapter2 = mod.createSqliteAdapter;
4046
- } catch {}
4047
- function createSqliteAdapter3(filePath) {
4048
- if (!_createSqliteAdapter2) {
4049
- throw new Error("SQLite adapter requires Bun runtime");
4050
- }
4051
- return _createSqliteAdapter2(filePath);
4052
- }
4053
- function createAdapter2(filePath) {
4054
- if (filePath.endsWith(".sqlite") || filePath.endsWith(".db")) {
4055
- return createSqliteAdapter3(filePath);
4056
- }
4057
- return createJsonAdapter(filePath);
4058
- }
4059
-
4060
- // src/commands/serve.ts
4061
- var __dirname2 = dirname4(fileURLToPath(import.meta.url));
3919
+ import { createServer } from "net";
3920
+ var __dirname2 = dirname3(fileURLToPath(import.meta.url));
4062
3921
  function openBrowser(url) {
4063
3922
  const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
4064
3923
  const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
@@ -4177,8 +4036,7 @@ function createApp() {
4177
4036
  }
4178
4037
  function isPortAvailable(port) {
4179
4038
  return new Promise((resolve3) => {
4180
- const net = __require("net");
4181
- const server = net.createServer();
4039
+ const server = createServer();
4182
4040
  server.once("error", () => resolve3(false));
4183
4041
  server.once("listening", () => {
4184
4042
  server.close();
@@ -4212,25 +4070,27 @@ async function serveCommand(args, flags, options = {}) {
4212
4070
  console.error(e.message);
4213
4071
  process.exit(1);
4214
4072
  }
4215
- const adapter = createAdapter2(dataFile);
4073
+ const adapter = createAdapter(dataFile);
4216
4074
  setStorageAdapter(adapter);
4217
4075
  initStore();
4218
4076
  const app = createApp();
4219
4077
  const webDistPaths = [
4220
- join4(__dirname2, "../../../web/dist"),
4221
- join4(__dirname2, "../../web/dist"),
4222
- join4(process.cwd(), "packages/web/dist")
4078
+ join3(__dirname2, "web"),
4079
+ join3(__dirname2, "../web"),
4080
+ join3(__dirname2, "../../../web/dist"),
4081
+ join3(__dirname2, "../../web/dist"),
4082
+ join3(process.cwd(), "packages/web/dist")
4223
4083
  ];
4224
4084
  let webDistPath = null;
4225
4085
  for (const p of webDistPaths) {
4226
- if (existsSync7(join4(p, "index.html"))) {
4086
+ if (existsSync5(join3(p, "index.html"))) {
4227
4087
  webDistPath = p;
4228
4088
  break;
4229
4089
  }
4230
4090
  }
4231
4091
  app.all("/api/*", (c) => c.json({ error: "Not found" }, 404));
4232
4092
  if (webDistPath) {
4233
- const indexHtml = readFileSync5(join4(webDistPath, "index.html"), "utf-8");
4093
+ const indexHtml = readFileSync4(join3(webDistPath, "index.html"), "utf-8");
4234
4094
  const staticHandler = serveStatic({ root: webDistPath });
4235
4095
  const staticExtensions = /\.(js|css|png|jpg|jpeg|gif|svg|ico|woff2?|ttf|eot|map|json|webp|webm|mp4|mp3|pdf)$/i;
4236
4096
  app.use("/*", async (c, next) => {
@@ -4239,11 +4099,11 @@ async function serveCommand(args, flags, options = {}) {
4239
4099
  return next();
4240
4100
  }
4241
4101
  if (staticExtensions.test(path)) {
4242
- const filePath = join4(webDistPath, path);
4102
+ const filePath = join3(webDistPath, path);
4243
4103
  if (!filePath.startsWith(webDistPath + sep)) {
4244
4104
  return c.notFound();
4245
4105
  }
4246
- if (existsSync7(filePath) && statSync2(filePath).isFile()) {
4106
+ if (existsSync5(filePath) && statSync2(filePath).isFile()) {
4247
4107
  return staticHandler(c, next);
4248
4108
  }
4249
4109
  return c.notFound();
@@ -4254,15 +4114,22 @@ async function serveCommand(args, flags, options = {}) {
4254
4114
  app.get("/", (c) => c.text("Web UI not found. API available at /api/*"));
4255
4115
  }
4256
4116
  const url = `http://localhost:${port}`;
4257
- console.log(`Starting Kenzo on ${url}`);
4258
- console.log(`Data file: ${dataFile}`);
4259
- if (webDistPath) {
4260
- console.log(`Web UI: ${webDistPath}`);
4117
+ if (options.compact) {
4118
+ console.log("");
4119
+ console.log(`Kenzo is running at ${url}`);
4261
4120
  } else {
4262
- console.log("Web UI: not found (API only mode)");
4121
+ console.log(`Starting Kenzo on ${url}`);
4122
+ console.log(`Data file: ${dataFile}`);
4123
+ if (webDistPath) {
4124
+ console.log(`Web UI: ${webDistPath}`);
4125
+ } else {
4126
+ console.log("Web UI: not found (API only mode)");
4127
+ }
4263
4128
  }
4264
4129
  if (options.open || flags.open === true) {
4265
- console.log(`Opening ${url}`);
4130
+ if (!options.compact) {
4131
+ console.log(`Opening ${url}`);
4132
+ }
4266
4133
  openBrowser(url);
4267
4134
  }
4268
4135
  console.log("");
@@ -4494,11 +4361,11 @@ ${c.red}✗${c.reset} Auth timed out. Try again.`);
4494
4361
  }
4495
4362
 
4496
4363
  // src/commands/blob.ts
4497
- import { readFileSync as readFileSync6, writeFileSync as writeFileSync5, existsSync as existsSync8 } from "fs";
4364
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync6 } from "fs";
4498
4365
  import { basename, resolve as resolve3, extname } from "path";
4499
4366
  function guessMimeType(filename) {
4500
4367
  const ext = extname(filename).toLowerCase();
4501
- const types3 = {
4368
+ const types2 = {
4502
4369
  ".png": "image/png",
4503
4370
  ".jpg": "image/jpeg",
4504
4371
  ".jpeg": "image/jpeg",
@@ -4528,7 +4395,7 @@ function guessMimeType(filename) {
4528
4395
  ".xls": "application/vnd.ms-excel",
4529
4396
  ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
4530
4397
  };
4531
- return types3[ext] || "application/octet-stream";
4398
+ return types2[ext] || "application/octet-stream";
4532
4399
  }
4533
4400
  async function blobCommand(subcommand, args, flags, json) {
4534
4401
  switch (subcommand) {
@@ -4539,11 +4406,11 @@ async function blobCommand(subcommand, args, flags, json) {
4539
4406
  console.error("Usage: kenzoboard blob attach <task-id> <file-path>");
4540
4407
  process.exit(1);
4541
4408
  }
4542
- if (!existsSync8(filePath)) {
4409
+ if (!existsSync6(filePath)) {
4543
4410
  console.error(`File not found: ${filePath}`);
4544
4411
  process.exit(1);
4545
4412
  }
4546
- const content = readFileSync6(filePath);
4413
+ const content = readFileSync5(filePath);
4547
4414
  const filename = basename(filePath);
4548
4415
  const mime_type = guessMimeType(filename);
4549
4416
  const blob = await uploadBlob(Buffer.from(content), filename, mime_type, taskId);
@@ -4568,7 +4435,7 @@ async function blobCommand(subcommand, args, flags, json) {
4568
4435
  process.exit(1);
4569
4436
  }
4570
4437
  const destPath = outputPath || resolve3(process.cwd(), result.blob.filename);
4571
- writeFileSync5(destPath, result.content);
4438
+ writeFileSync4(destPath, result.content);
4572
4439
  if (json) {
4573
4440
  output({ path: destPath, ...result.blob }, true);
4574
4441
  } else {
@@ -4626,6 +4493,7 @@ function formatSize(bytes) {
4626
4493
  return `${(bytes / 1024).toFixed(1)}KB`;
4627
4494
  return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
4628
4495
  }
4496
+
4629
4497
  // src/index.ts
4630
4498
  var c2 = {
4631
4499
  reset: "\x1B[0m",
@@ -4649,7 +4517,7 @@ function prompt(question) {
4649
4517
  function isInteractive() {
4650
4518
  return process.stdin.isTTY === true;
4651
4519
  }
4652
- var __dirname3 = dirname5(fileURLToPath2(import.meta.url));
4520
+ var __dirname3 = dirname4(fileURLToPath2(import.meta.url));
4653
4521
  function publicCommandName() {
4654
4522
  const invoked = basename2(process.argv[1] || "");
4655
4523
  return invoked === "flux" ? "flux" : "kenzoboard";
@@ -4666,22 +4534,11 @@ function isCliEntrypoint() {
4666
4534
  function defaultServePort() {
4667
4535
  return publicCommandName() === "flux" ? 3589 : 3000;
4668
4536
  }
4669
- function findExistingFluxDirFromCwd() {
4670
- let dir = process.cwd();
4671
- while (dirname5(dir) !== dir) {
4672
- const fluxDir = resolve4(dir, ".flux");
4673
- if (existsSync9(fluxDir)) {
4674
- return fluxDir;
4675
- }
4676
- dir = dirname5(dir);
4677
- }
4678
- return null;
4679
- }
4680
4537
  function ensureFluxIgnored() {
4681
4538
  const gitRoot = findGitRoot();
4682
4539
  const gitignorePath = gitRoot ? resolve4(gitRoot, ".gitignore") : resolve4(process.cwd(), ".gitignore");
4683
4540
  const gitignoreEntry = ".flux/";
4684
- let gitignoreContent = existsSync9(gitignorePath) ? readFileSync7(gitignorePath, "utf-8") : "";
4541
+ let gitignoreContent = existsSync7(gitignorePath) ? readFileSync6(gitignorePath, "utf-8") : "";
4685
4542
  if (!gitignoreContent.split(`
4686
4543
  `).some((line) => line.trim() === gitignoreEntry)) {
4687
4544
  const newline = gitignoreContent.length > 0 && !gitignoreContent.endsWith(`
@@ -4689,26 +4546,30 @@ function ensureFluxIgnored() {
4689
4546
  ` : "";
4690
4547
  appendFileSync(gitignorePath, `${newline}${gitignoreEntry}
4691
4548
  `);
4692
- console.log(`Added .flux/ to ${gitRoot ? gitignorePath : ".gitignore"}`);
4549
+ return true;
4693
4550
  }
4551
+ return false;
4694
4552
  }
4695
4553
  async function ensureKenzoWorkspace() {
4696
- const fluxDir = findExistingFluxDirFromCwd() || resolve4(process.cwd(), ".flux");
4554
+ const fluxDir = process.env.FLUX_DIR || resolve4(process.cwd(), ".flux");
4697
4555
  const configPath = resolve4(fluxDir, "config.json");
4698
4556
  const jsonPath = resolve4(fluxDir, "data.json");
4699
4557
  const sqlitePath = resolve4(fluxDir, "data.sqlite");
4700
- if (!existsSync9(fluxDir)) {
4701
- mkdirSync5(fluxDir, { recursive: true });
4558
+ let createdWorkspace = false;
4559
+ let createdProject = false;
4560
+ let gitignoreUpdated = false;
4561
+ if (!existsSync7(fluxDir)) {
4562
+ mkdirSync3(fluxDir, { recursive: true });
4702
4563
  writeConfig(fluxDir, {});
4703
- writeFileSync6(jsonPath, JSON.stringify({ projects: [], epics: [], tasks: [] }, null, 2));
4704
- ensureFluxIgnored();
4705
- console.log(`Created local Kenzo workspace at ${fluxDir}`);
4706
- } else if (!existsSync9(configPath)) {
4564
+ writeFileSync5(jsonPath, JSON.stringify({ projects: [], epics: [], tasks: [] }, null, 2));
4565
+ gitignoreUpdated = ensureFluxIgnored();
4566
+ createdWorkspace = true;
4567
+ } else if (!existsSync7(configPath)) {
4707
4568
  writeConfig(fluxDir, {});
4708
4569
  }
4709
4570
  const config = readConfigRaw(fluxDir);
4710
- if (!config.server && !existsSync9(jsonPath) && !existsSync9(sqlitePath)) {
4711
- writeFileSync6(jsonPath, JSON.stringify({ projects: [], epics: [], tasks: [] }, null, 2));
4571
+ if (!config.server && !existsSync7(jsonPath) && !existsSync7(sqlitePath)) {
4572
+ writeFileSync5(jsonPath, JSON.stringify({ projects: [], epics: [], tasks: [] }, null, 2));
4712
4573
  }
4713
4574
  const storage = initStorage();
4714
4575
  const projects = await getProjects2();
@@ -4722,7 +4583,7 @@ async function ensureKenzoWorkspace() {
4722
4583
  const nextConfig = readConfigRaw(fluxDir);
4723
4584
  nextConfig.project = project.id;
4724
4585
  writeConfig(fluxDir, nextConfig);
4725
- console.log(`Created first project: ${project.name} (${project.id})`);
4586
+ createdProject = true;
4726
4587
  } else if (!projectId || !projects.some((project) => project.id === projectId)) {
4727
4588
  const project = projects[0];
4728
4589
  projectId = project.id;
@@ -4730,39 +4591,75 @@ async function ensureKenzoWorkspace() {
4730
4591
  const nextConfig = readConfigRaw(fluxDir);
4731
4592
  nextConfig.project = project.id;
4732
4593
  writeConfig(fluxDir, nextConfig);
4733
- console.log(`Using project: ${project.name} (${project.id})`);
4734
4594
  }
4735
- return { projectId, projectName };
4595
+ return { fluxDir, projectId, projectName, createdWorkspace, createdProject, gitignoreUpdated };
4736
4596
  }
4737
- function printMcpSetup(command = publicCommandName()) {
4738
- const dockerCommand = 'docker run -i --rm -v "$(pwd)/.flux:/app/packages/data" -e FLUX_DATA=/app/packages/data/flux.sqlite flux-mcp bun packages/mcp/dist/index.js';
4597
+ function codexCliCommand() {
4598
+ const macAppCli = "/Applications/Codex.app/Contents/Resources/codex";
4599
+ return process.platform === "darwin" && existsSync7(macAppCli) ? macAppCli : "codex";
4600
+ }
4601
+ function quoteShell(value) {
4602
+ return `"${value.replace(/(["\\$`])/g, "\\$1")}"`;
4603
+ }
4604
+ function mcpPackageCommand() {
4739
4605
  const localMcpPath = resolve4(process.cwd(), "packages/mcp/dist/index.js");
4740
- console.log(`${c2.bold}Agent setup${c2.reset} ${c2.dim}(MCP resources remain flux:// for compatibility)${c2.reset}
4741
- `);
4742
- if (existsSync9(localMcpPath)) {
4743
- console.log(`${c2.bold}Codex:${c2.reset}`);
4744
- console.log(` codex mcp add flux -- bun ${localMcpPath}`);
4745
- console.log(`${c2.bold}Claude Code:${c2.reset}`);
4746
- console.log(` claude mcp add flux -- bun ${localMcpPath}`);
4747
- } else {
4748
- console.log(`${c2.bold}Codex:${c2.reset}`);
4749
- console.log(` codex mcp add flux -- ${dockerCommand}`);
4750
- console.log(`${c2.bold}Claude Code:${c2.reset}`);
4751
- console.log(` claude mcp add flux -- ${dockerCommand}`);
4606
+ return existsSync7(localMcpPath) ? `bun ${quoteShell(localMcpPath)}` : "npx -y --package kenzoboard kenzoboard-mcp";
4607
+ }
4608
+ function codexMcpCommand(fluxDir) {
4609
+ return `${codexCliCommand()} mcp add flux --env FLUX_DIR=${quoteShell(fluxDir)} -- ${mcpPackageCommand()}`;
4610
+ }
4611
+ function claudeMcpCommand(fluxDir) {
4612
+ return `claude mcp add flux --env FLUX_DIR=${quoteShell(fluxDir)} -- ${mcpPackageCommand()}`;
4613
+ }
4614
+ function printLaunchSummary(workspace, command = publicCommandName()) {
4615
+ const projectLabel = workspace.projectName && workspace.projectId ? `${workspace.projectName} (${workspace.projectId})` : "No project selected";
4616
+ console.log(`${c2.green}${c2.bold}Kenzo is ready.${c2.reset}`);
4617
+ console.log(`Project: ${projectLabel}`);
4618
+ if (workspace.createdWorkspace || workspace.createdProject || workspace.gitignoreUpdated) {
4619
+ const details = [
4620
+ workspace.createdWorkspace ? "local workspace" : undefined,
4621
+ workspace.createdProject ? "first project" : undefined,
4622
+ workspace.gitignoreUpdated ? ".flux/ in .gitignore" : undefined
4623
+ ].filter(Boolean).join(", ");
4624
+ console.log(`${c2.dim}Set up ${details}.${c2.reset}`);
4752
4625
  }
4753
4626
  console.log("");
4754
- console.log(`Run ${c2.cyan}${command} ready${c2.reset} to see agent-ready work.`);
4627
+ console.log(`${c2.bold}Connect Codex:${c2.reset}`);
4628
+ console.log(` ${codexMcpCommand(workspace.fluxDir)}`);
4629
+ console.log("");
4630
+ console.log(`${c2.bold}Then ask Codex:${c2.reset}`);
4631
+ console.log(" Pick the next ready Kenzo task, implement it, and mark it done.");
4632
+ console.log("");
4633
+ console.log(`CLI fallback: ${c2.cyan}${command} ready${c2.reset}`);
4634
+ console.log(`More setup: ${c2.cyan}${command} mcp${c2.reset}`);
4635
+ }
4636
+ function printMcpSetup(command = publicCommandName(), fluxDir = findFluxDir()) {
4637
+ const installedMcpCommand = "kenzoboard-mcp";
4638
+ const dockerCommand = 'docker run -i --rm -v "$(pwd)/.flux:/app/packages/data" -e FLUX_DATA=/app/packages/data/flux.sqlite flux-mcp bun packages/mcp/dist/index.js';
4639
+ console.log(`${c2.bold}Agent setup${c2.reset} ${c2.dim}(MCP resources remain flux:// for compatibility)${c2.reset}`);
4640
+ console.log(`${c2.dim}Using Kenzo workspace: ${fluxDir}${c2.reset}
4641
+ `);
4642
+ console.log(`${c2.bold}Codex:${c2.reset}`);
4643
+ console.log(` ${codexMcpCommand(fluxDir)}`);
4644
+ console.log(`${c2.bold}Claude Code:${c2.reset}`);
4645
+ console.log(` ${claudeMcpCommand(fluxDir)}`);
4646
+ console.log("");
4647
+ console.log(`${c2.bold}Global install:${c2.reset}`);
4648
+ console.log(` ${installedMcpCommand}`);
4649
+ console.log("");
4650
+ console.log(`${c2.bold}Advanced Docker:${c2.reset}`);
4651
+ console.log(` ${dockerCommand}`);
4652
+ console.log("");
4653
+ console.log(`${c2.bold}Agent workflow:${c2.reset}`);
4654
+ console.log(` 1. Run ${c2.cyan}${command} ready${c2.reset} or ask the MCP server for ready tasks.`);
4655
+ console.log(" 2. Start one task, implement it, add notes as needed, then mark it done.");
4656
+ console.log(" 3. If MCP is not connected yet, Codex can still use the CLI commands from AGENTS.md.");
4755
4657
  }
4756
4658
  async function launchKenzoApp() {
4757
4659
  const command = publicCommandName();
4758
- const { projectId, projectName } = await ensureKenzoWorkspace();
4759
- if (projectId && projectName) {
4760
- console.log(`Opening project: ${projectName} (${projectId})`);
4761
- }
4762
- console.log("");
4763
- console.log(`${c2.bold}Next step after Kenzo opens:${c2.reset}`);
4764
- printMcpSetup(command);
4765
- await serveCommand([], { port: String(defaultServePort()) }, { defaultPort: defaultServePort(), open: true });
4660
+ const workspace = await ensureKenzoWorkspace();
4661
+ printLaunchSummary(workspace, command);
4662
+ await serveCommand([], { port: String(defaultServePort()) }, { defaultPort: defaultServePort(), open: true, compact: true });
4766
4663
  }
4767
4664
  var FLUX_INSTRUCTIONS = `<!-- FLUX:START -->
4768
4665
  ## Flux Task Management
@@ -4788,7 +4685,7 @@ function updateAgentInstructions() {
4788
4685
  let targetFile = null;
4789
4686
  for (const name of candidates) {
4790
4687
  const path = resolve4(cwd, name);
4791
- if (existsSync9(path)) {
4688
+ if (existsSync7(path)) {
4792
4689
  targetFile = path;
4793
4690
  break;
4794
4691
  }
@@ -4796,7 +4693,7 @@ function updateAgentInstructions() {
4796
4693
  if (!targetFile) {
4797
4694
  targetFile = resolve4(cwd, "AGENTS.md");
4798
4695
  }
4799
- let content = existsSync9(targetFile) ? readFileSync7(targetFile, "utf-8") : "";
4696
+ let content = existsSync7(targetFile) ? readFileSync6(targetFile, "utf-8") : "";
4800
4697
  const startMarker = "<!-- FLUX:START -->";
4801
4698
  const endMarker = "<!-- FLUX:END -->";
4802
4699
  const startIdx = content.indexOf(startMarker);
@@ -4809,7 +4706,7 @@ function updateAgentInstructions() {
4809
4706
  ` + FLUX_INSTRUCTIONS + `
4810
4707
  `;
4811
4708
  }
4812
- writeFileSync6(targetFile, content.trimStart());
4709
+ writeFileSync5(targetFile, content.trimStart());
4813
4710
  return targetFile;
4814
4711
  }
4815
4712
  function findGitRoot() {
@@ -4821,7 +4718,7 @@ function findGitRoot() {
4821
4718
  }
4822
4719
  function ensureWorktree(gitRoot) {
4823
4720
  const worktreePath = resolve4(gitRoot, ".git", "flux-worktree");
4824
- if (existsSync9(worktreePath)) {
4721
+ if (existsSync7(worktreePath)) {
4825
4722
  return worktreePath;
4826
4723
  }
4827
4724
  const branchExists = ["flux-data", "origin/flux-data"].some((ref) => {
@@ -4875,7 +4772,7 @@ async function doctorCommand(flags) {
4875
4772
  `);
4876
4773
  return;
4877
4774
  }
4878
- const fluxDirExists = existsSync9(fluxDir);
4775
+ const fluxDirExists = existsSync7(fluxDir);
4879
4776
  if (!fluxDirExists) {
4880
4777
  console.log(`${c2.yellow}!${c2.reset} .flux directory not found at ${fluxDir}`);
4881
4778
  console.log(` Run ${c2.cyan}${publicCommandName()} init${c2.reset} to initialize
@@ -4884,7 +4781,7 @@ async function doctorCommand(flags) {
4884
4781
  }
4885
4782
  console.log(`${c2.green}OK${c2.reset} .flux directory: ${fluxDir}`);
4886
4783
  const configPath = resolve4(fluxDir, "config.json");
4887
- const configExists = existsSync9(configPath);
4784
+ const configExists = existsSync7(configPath);
4888
4785
  if (configExists) {
4889
4786
  const config2 = readConfig(fluxDir);
4890
4787
  const mode = config2.server ? "server" : "local";
@@ -4896,8 +4793,8 @@ async function doctorCommand(flags) {
4896
4793
  }
4897
4794
  const jsonPath = resolve4(fluxDir, "data.json");
4898
4795
  const sqlitePath = resolve4(fluxDir, "data.sqlite");
4899
- const jsonExists = existsSync9(jsonPath);
4900
- const sqliteExists = existsSync9(sqlitePath);
4796
+ const jsonExists = existsSync7(jsonPath);
4797
+ const sqliteExists = existsSync7(sqlitePath);
4901
4798
  const countRecords = (path) => {
4902
4799
  try {
4903
4800
  const adapter = createAdapter(path);
@@ -4968,8 +4865,8 @@ ${c2.cyan}Merging ${otherFile} into ${configuredFile}...${c2.reset}`);
4968
4865
  console.log(`
4969
4866
  ${c2.dim}data.json is empty (likely created by old MCP/Server bug)${c2.reset}`);
4970
4867
  if (fix) {
4971
- const { unlinkSync: unlinkSync3 } = await import("fs");
4972
- unlinkSync3(jsonPath);
4868
+ const { unlinkSync: unlinkSync2 } = await import("fs");
4869
+ unlinkSync2(jsonPath);
4973
4870
  console.log(`${c2.green}OK${c2.reset} Removed empty data.json`);
4974
4871
  fixed++;
4975
4872
  } else {
@@ -4980,8 +4877,8 @@ ${c2.dim}data.json is empty (likely created by old MCP/Server bug)${c2.reset}`);
4980
4877
  console.log(`
4981
4878
  ${c2.dim}data.sqlite is empty${c2.reset}`);
4982
4879
  if (fix) {
4983
- const { unlinkSync: unlinkSync3 } = await import("fs");
4984
- unlinkSync3(sqlitePath);
4880
+ const { unlinkSync: unlinkSync2 } = await import("fs");
4881
+ unlinkSync2(sqlitePath);
4985
4882
  console.log(`${c2.green}OK${c2.reset} Removed empty data.sqlite`);
4986
4883
  fixed++;
4987
4884
  } else {
@@ -5073,14 +4970,14 @@ async function main() {
5073
4970
  const dataFileName = useSqlite ? "data.sqlite" : "data.json";
5074
4971
  const dataPath = resolve4(fluxDir, dataFileName);
5075
4972
  const configPath = resolve4(fluxDir, "config.json");
5076
- const isNew = !existsSync9(resolve4(fluxDir, "data.json")) && !existsSync9(resolve4(fluxDir, "data.sqlite"));
5077
- mkdirSync5(fluxDir, { recursive: true });
4973
+ const isNew = !existsSync7(resolve4(fluxDir, "data.json")) && !existsSync7(resolve4(fluxDir, "data.sqlite"));
4974
+ mkdirSync3(fluxDir, { recursive: true });
5078
4975
  let serverUrl2 = parsed.flags.server;
5079
4976
  let apiKey2 = parsed.flags["api-key"];
5080
4977
  const useGit = parsed.flags.git === true;
5081
- if (existsSync9(configPath)) {
4978
+ if (existsSync7(configPath)) {
5082
4979
  try {
5083
- const existing = JSON.parse(readFileSync7(configPath, "utf-8"));
4980
+ const existing = JSON.parse(readFileSync6(configPath, "utf-8"));
5084
4981
  const warnings = [];
5085
4982
  if (existing.server && (useGit || parsed.flags.sqlite)) {
5086
4983
  warnings.push(`Repo uses server mode (${existing.server}), you're setting up git mode`);
@@ -5150,7 +5047,7 @@ Overwrite existing config? [y/N]: `);
5150
5047
  const gitRoot = findGitRoot();
5151
5048
  const gitignorePath = gitRoot ? resolve4(gitRoot, ".gitignore") : resolve4(process.cwd(), ".gitignore");
5152
5049
  const gitignoreEntry = ".flux/";
5153
- let gitignoreContent = existsSync9(gitignorePath) ? readFileSync7(gitignorePath, "utf-8") : "";
5050
+ let gitignoreContent = existsSync7(gitignorePath) ? readFileSync6(gitignorePath, "utf-8") : "";
5154
5051
  if (!gitignoreContent.split(`
5155
5052
  `).some((line) => line.trim() === gitignoreEntry)) {
5156
5053
  const newline = gitignoreContent.length > 0 && !gitignoreContent.endsWith(`
@@ -5160,13 +5057,13 @@ Overwrite existing config? [y/N]: `);
5160
5057
  `);
5161
5058
  console.log(`Added .flux/ to ${gitRoot ? gitignorePath : ".gitignore"}`);
5162
5059
  }
5163
- if (!serverUrl2 && !existsSync9(dataPath)) {
5060
+ if (!serverUrl2 && !existsSync7(dataPath)) {
5164
5061
  if (useSqlite) {
5165
5062
  const adapter = createAdapter(dataPath);
5166
5063
  setStorageAdapter(adapter);
5167
5064
  initStore();
5168
5065
  } else {
5169
- writeFileSync6(dataPath, JSON.stringify({ projects: [], epics: [], tasks: [] }, null, 2));
5066
+ writeFileSync5(dataPath, JSON.stringify({ projects: [], epics: [], tasks: [] }, null, 2));
5170
5067
  }
5171
5068
  }
5172
5069
  if (isNew) {
@@ -5268,15 +5165,15 @@ Select a project:`);
5268
5165
  const localBlobs = resolve4(fluxDir, "blobs");
5269
5166
  execSync("git fetch origin flux-data", { stdio: "pipe", cwd: worktree });
5270
5167
  execSync("git reset --hard origin/flux-data", { stdio: "pipe", cwd: worktree });
5271
- if (existsSync9(worktreeData)) {
5272
- mkdirSync5(fluxDir, { recursive: true });
5273
- writeFileSync6(dataPath, readFileSync7(worktreeData, "utf-8"));
5168
+ if (existsSync7(worktreeData)) {
5169
+ mkdirSync3(fluxDir, { recursive: true });
5170
+ writeFileSync5(dataPath, readFileSync6(worktreeData, "utf-8"));
5274
5171
  console.log("Pulled latest tasks from flux-data branch");
5275
5172
  } else {
5276
5173
  console.log("No .flux/data.json in flux-data branch yet");
5277
5174
  }
5278
- if (existsSync9(worktreeBlobs)) {
5279
- mkdirSync5(localBlobs, { recursive: true });
5175
+ if (existsSync7(worktreeBlobs)) {
5176
+ mkdirSync3(localBlobs, { recursive: true });
5280
5177
  cpSync(worktreeBlobs, localBlobs, { recursive: true });
5281
5178
  console.log("Pulled blobs from flux-data branch");
5282
5179
  }
@@ -5286,7 +5183,7 @@ Select a project:`);
5286
5183
  }
5287
5184
  } else {
5288
5185
  const msg = parsed.subcommand || "update tasks";
5289
- if (!existsSync9(dataPath)) {
5186
+ if (!existsSync7(dataPath)) {
5290
5187
  console.error(`No .flux/data.json found. Run: ${publicCommandName()} init`);
5291
5188
  process.exit(1);
5292
5189
  }
@@ -5296,14 +5193,14 @@ Select a project:`);
5296
5193
  const worktreeData = resolve4(worktreeFlux, "data.json");
5297
5194
  const localBlobs = resolve4(fluxDir, "blobs");
5298
5195
  const worktreeBlobs = resolve4(worktreeFlux, "blobs");
5299
- mkdirSync5(worktreeFlux, { recursive: true });
5300
- writeFileSync6(worktreeData, readFileSync7(dataPath, "utf-8"));
5301
- if (existsSync9(localBlobs)) {
5302
- mkdirSync5(worktreeBlobs, { recursive: true });
5196
+ mkdirSync3(worktreeFlux, { recursive: true });
5197
+ writeFileSync5(worktreeData, readFileSync6(dataPath, "utf-8"));
5198
+ if (existsSync7(localBlobs)) {
5199
+ mkdirSync3(worktreeBlobs, { recursive: true });
5303
5200
  cpSync(localBlobs, worktreeBlobs, { recursive: true });
5304
5201
  }
5305
5202
  execSync("git add .flux/data.json", { stdio: "pipe", cwd: worktree });
5306
- if (existsSync9(worktreeBlobs)) {
5203
+ if (existsSync7(worktreeBlobs)) {
5307
5204
  execSync("git add .flux/blobs", { stdio: "pipe", cwd: worktree });
5308
5205
  }
5309
5206
  try {
@@ -5338,7 +5235,7 @@ Select a project:`);
5338
5235
  if (parsed.command === "prime") {
5339
5236
  const fluxDir = findFluxDir();
5340
5237
  const configPath = resolve4(fluxDir, "config.json");
5341
- if (!existsSync9(configPath)) {
5238
+ if (!existsSync7(configPath)) {
5342
5239
  return;
5343
5240
  }
5344
5241
  try {
@@ -5382,7 +5279,7 @@ Select a project:`);
5382
5279
  const output2 = JSON.stringify(data, null, 2);
5383
5280
  const outFile = parsed.flags.o || parsed.flags.output;
5384
5281
  if (outFile) {
5385
- writeFileSync6(outFile, output2);
5282
+ writeFileSync5(outFile, output2);
5386
5283
  console.log(`Exported to ${outFile}`);
5387
5284
  } else {
5388
5285
  console.log(output2);
@@ -5403,11 +5300,11 @@ Select a project:`);
5403
5300
  }
5404
5301
  content = Buffer.concat(chunks).toString("utf-8");
5405
5302
  } else {
5406
- if (!existsSync9(file)) {
5303
+ if (!existsSync7(file)) {
5407
5304
  console.error(`File not found: ${file}`);
5408
5305
  process.exit(1);
5409
5306
  }
5410
- content = readFileSync7(file, "utf-8");
5307
+ content = readFileSync6(file, "utf-8");
5411
5308
  }
5412
5309
  const data = JSON.parse(content);
5413
5310
  const merge = parsed.flags.merge === true;