@fluenti/cli 0.1.0

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 ADDED
@@ -0,0 +1,590 @@
1
+ #!/usr/bin/env node
2
+ import { a as e, c as t, i as n, l as r, n as i, o as a, r as o, s, t as c, u as l } from "./compile-McMlpGSK.js";
3
+ import { defineCommand as u, runMain as d } from "citty";
4
+ import f from "consola";
5
+ import p from "fast-glob";
6
+ import { existsSync as m, mkdirSync as h, readFileSync as g, writeFileSync as _ } from "node:fs";
7
+ import { dirname as v, extname as y, join as b, resolve as x } from "node:path";
8
+ import { execFile as S } from "node:child_process";
9
+ import { promisify as C } from "node:util";
10
+ //#region src/translate.ts
11
+ var w = C(S);
12
+ function T(e, t, n) {
13
+ let r = JSON.stringify(n, null, 2);
14
+ return [
15
+ `You are a professional translator. Translate the following messages from "${e}" to "${t}".`,
16
+ "",
17
+ "Input (JSON):",
18
+ r,
19
+ "",
20
+ "Rules:",
21
+ "- Output ONLY valid JSON with the same keys and translated values.",
22
+ "- Keep ICU MessageFormat placeholders like {name}, {count}, {gender} unchanged.",
23
+ "- Keep HTML tags unchanged.",
24
+ "- Do not add any explanation or markdown formatting, output raw JSON only."
25
+ ].join("\n");
26
+ }
27
+ async function E(e, t) {
28
+ let n = 10 * 1024 * 1024;
29
+ try {
30
+ if (e === "claude") {
31
+ let { stdout: e } = await w("claude", ["-p", t], { maxBuffer: n });
32
+ return e;
33
+ } else {
34
+ let { stdout: e } = await w("codex", [
35
+ "-p",
36
+ t,
37
+ "--full-auto"
38
+ ], { maxBuffer: n });
39
+ return e;
40
+ }
41
+ } catch (t) {
42
+ throw t.code === "ENOENT" ? Error(`"${e}" CLI not found. Please install it first:\n` + (e === "claude" ? " npm install -g @anthropic-ai/claude-code" : " npm install -g @openai/codex")) : t;
43
+ }
44
+ }
45
+ function D(e) {
46
+ let t = e.match(/\{[\s\S]*\}/);
47
+ if (!t) throw Error("No JSON object found in AI response");
48
+ let n = JSON.parse(t[0]);
49
+ if (typeof n != "object" || !n || Array.isArray(n)) throw Error("AI response is not a valid JSON object");
50
+ return n;
51
+ }
52
+ function O(e) {
53
+ let t = {};
54
+ for (let [n, r] of Object.entries(e)) r.obsolete || (!r.translation || r.translation.length === 0) && (t[n] = r.message ?? n);
55
+ return t;
56
+ }
57
+ function k(e, t) {
58
+ let n = Object.keys(e), r = [];
59
+ for (let i = 0; i < n.length; i += t) {
60
+ let a = {};
61
+ for (let r of n.slice(i, i + t)) a[r] = e[r];
62
+ r.push(a);
63
+ }
64
+ return r;
65
+ }
66
+ async function A(e) {
67
+ let { provider: t, sourceLocale: n, targetLocale: r, catalog: i, batchSize: a } = e, o = O(i), s = Object.keys(o).length;
68
+ if (s === 0) return {
69
+ catalog: i,
70
+ translated: 0
71
+ };
72
+ f.info(` ${s} untranslated messages, translating with ${t}...`);
73
+ let c = k(o, a), l = 0;
74
+ for (let e = 0; e < c.length; e++) {
75
+ let a = c[e], o = Object.keys(a);
76
+ c.length > 1 && f.info(` Batch ${e + 1}/${c.length} (${o.length} messages)`);
77
+ let s = D(await E(t, T(n, r, a)));
78
+ for (let e of o) s[e] && typeof s[e] == "string" ? (i[e] = {
79
+ ...i[e],
80
+ translation: s[e]
81
+ }, l++) : f.warn(` Missing translation for key: ${e}`);
82
+ }
83
+ return {
84
+ catalog: i,
85
+ translated: l
86
+ };
87
+ }
88
+ //#endregion
89
+ //#region src/migrate.ts
90
+ var j = C(S), M = {
91
+ "vue-i18n": {
92
+ name: "vue-i18n",
93
+ framework: "Vue",
94
+ configPatterns: [
95
+ "i18n.ts",
96
+ "i18n.js",
97
+ "i18n/index.ts",
98
+ "i18n/index.js",
99
+ "src/i18n.ts",
100
+ "src/i18n.js",
101
+ "src/i18n/index.ts",
102
+ "src/plugins/i18n.ts"
103
+ ],
104
+ localePatterns: [
105
+ "locales/*.json",
106
+ "src/locales/*.json",
107
+ "i18n/*.json",
108
+ "src/i18n/*.json",
109
+ "lang/*.json",
110
+ "src/lang/*.json",
111
+ "locales/*.yaml",
112
+ "locales/*.yml"
113
+ ],
114
+ sourcePatterns: ["src/**/*.vue"],
115
+ migrationGuide: "vue/llms-migration.txt"
116
+ },
117
+ "nuxt-i18n": {
118
+ name: "nuxt-i18n",
119
+ framework: "Nuxt",
120
+ configPatterns: [
121
+ "nuxt.config.ts",
122
+ "nuxt.config.js",
123
+ "i18n.config.ts",
124
+ "i18n.config.js"
125
+ ],
126
+ localePatterns: [
127
+ "locales/*.json",
128
+ "lang/*.json",
129
+ "i18n/*.json",
130
+ "locales/*.yaml",
131
+ "locales/*.yml"
132
+ ],
133
+ sourcePatterns: [
134
+ "pages/**/*.vue",
135
+ "components/**/*.vue",
136
+ "layouts/**/*.vue"
137
+ ],
138
+ migrationGuide: "nuxt/llms-migration.txt"
139
+ },
140
+ "react-i18next": {
141
+ name: "react-i18next",
142
+ framework: "React",
143
+ configPatterns: [
144
+ "i18n.ts",
145
+ "i18n.js",
146
+ "src/i18n.ts",
147
+ "src/i18n.js",
148
+ "src/i18n/index.ts",
149
+ "src/i18n/config.ts"
150
+ ],
151
+ localePatterns: [
152
+ "locales/*.json",
153
+ "src/locales/*.json",
154
+ "public/locales/**/*.json",
155
+ "translations/*.json",
156
+ "src/translations/*.json"
157
+ ],
158
+ sourcePatterns: [
159
+ "src/**/*.tsx",
160
+ "src/**/*.jsx",
161
+ "src/**/*.ts"
162
+ ],
163
+ migrationGuide: "react/llms-migration.txt"
164
+ },
165
+ "next-intl": {
166
+ name: "next-intl",
167
+ framework: "Next.js",
168
+ configPatterns: [
169
+ "next.config.ts",
170
+ "next.config.js",
171
+ "next.config.mjs",
172
+ "i18n.ts",
173
+ "src/i18n.ts",
174
+ "i18n/request.ts",
175
+ "src/i18n/request.ts"
176
+ ],
177
+ localePatterns: [
178
+ "messages/*.json",
179
+ "locales/*.json",
180
+ "src/messages/*.json",
181
+ "src/locales/*.json"
182
+ ],
183
+ sourcePatterns: [
184
+ "app/**/*.tsx",
185
+ "src/app/**/*.tsx",
186
+ "pages/**/*.tsx",
187
+ "components/**/*.tsx"
188
+ ],
189
+ migrationGuide: "next-plugin/llms-migration.txt"
190
+ },
191
+ "next-i18next": {
192
+ name: "next-i18next",
193
+ framework: "Next.js",
194
+ configPatterns: [
195
+ "next-i18next.config.js",
196
+ "next-i18next.config.mjs",
197
+ "next.config.ts",
198
+ "next.config.js"
199
+ ],
200
+ localePatterns: ["public/locales/**/*.json"],
201
+ sourcePatterns: [
202
+ "pages/**/*.tsx",
203
+ "src/pages/**/*.tsx",
204
+ "components/**/*.tsx",
205
+ "src/components/**/*.tsx"
206
+ ],
207
+ migrationGuide: "next-plugin/llms-migration.txt"
208
+ },
209
+ lingui: {
210
+ name: "lingui",
211
+ framework: "React",
212
+ configPatterns: [
213
+ "lingui.config.ts",
214
+ "lingui.config.js",
215
+ ".linguirc"
216
+ ],
217
+ localePatterns: [
218
+ "locales/*.po",
219
+ "src/locales/*.po",
220
+ "locales/*/messages.po",
221
+ "src/locales/*/messages.po"
222
+ ],
223
+ sourcePatterns: [
224
+ "src/**/*.tsx",
225
+ "src/**/*.jsx",
226
+ "src/**/*.ts"
227
+ ],
228
+ migrationGuide: "react/llms-migration.txt"
229
+ }
230
+ }, N = Object.keys(M);
231
+ function P(e) {
232
+ let t = e.toLowerCase().replace(/^@nuxtjs\//, "nuxt-").replace(/^@/, "");
233
+ return N.find((e) => e === t);
234
+ }
235
+ async function F(e) {
236
+ let t = {
237
+ configFiles: [],
238
+ localeFiles: [],
239
+ sampleSources: [],
240
+ packageJson: void 0
241
+ }, n = x("package.json");
242
+ m(n) && (t.packageJson = g(n, "utf-8"));
243
+ for (let n of e.configPatterns) {
244
+ let e = x(n);
245
+ m(e) && t.configFiles.push({
246
+ path: n,
247
+ content: g(e, "utf-8")
248
+ });
249
+ }
250
+ let r = await p(e.localePatterns, { absolute: !1 });
251
+ for (let e of r.slice(0, 10)) {
252
+ let n = g(x(e), "utf-8");
253
+ t.localeFiles.push({
254
+ path: e,
255
+ content: n.length > 5e3 ? n.slice(0, 5e3) + "\n... (truncated)" : n
256
+ });
257
+ }
258
+ let i = await p(e.sourcePatterns, { absolute: !1 });
259
+ for (let e of i.slice(0, 5)) {
260
+ let n = g(x(e), "utf-8");
261
+ t.sampleSources.push({
262
+ path: e,
263
+ content: n.length > 3e3 ? n.slice(0, 3e3) + "\n... (truncated)" : n
264
+ });
265
+ }
266
+ return t;
267
+ }
268
+ function I(e) {
269
+ let t = [
270
+ x("node_modules", "@fluenti", "cli", "..", "..", e),
271
+ b(__dirname, "..", "..", "..", e),
272
+ b(__dirname, "..", "..", e)
273
+ ];
274
+ for (let e of t) if (m(e)) return g(e, "utf-8");
275
+ return "";
276
+ }
277
+ function L(e, t, n) {
278
+ let r = [];
279
+ if (r.push(`You are a migration assistant helping convert a ${e.framework} project from "${e.name}" to Fluenti (@fluenti).`, "", "Your task:", "1. Generate a `fluenti.config.ts` file based on the existing i18n configuration", "2. Convert each locale/translation file to Fluenti PO format", "3. List the code changes needed (file by file) to migrate source code from the old API to Fluenti API", ""), n && r.push("=== MIGRATION GUIDE ===", n, ""), t.packageJson && r.push("=== package.json ===", t.packageJson, ""), t.configFiles.length > 0) {
280
+ r.push("=== EXISTING CONFIG FILES ===");
281
+ for (let e of t.configFiles) r.push(`--- ${e.path} ---`, e.content, "");
282
+ }
283
+ if (t.localeFiles.length > 0) {
284
+ r.push("=== EXISTING LOCALE FILES ===");
285
+ for (let e of t.localeFiles) r.push(`--- ${e.path} ---`, e.content, "");
286
+ }
287
+ if (t.sampleSources.length > 0) {
288
+ r.push("=== SAMPLE SOURCE FILES ===");
289
+ for (let e of t.sampleSources) r.push(`--- ${e.path} ---`, e.content, "");
290
+ }
291
+ return r.push("", "=== OUTPUT FORMAT ===", "Respond with the following sections, each starting with the exact header shown:", "", "### FLUENTI_CONFIG", "```ts", "// The fluenti.config.ts content", "```", "", "### LOCALE_FILES", "For each locale file, output:", "#### LOCALE: {locale_code}", "```po", "// The PO file content", "```", "", "### MIGRATION_STEPS", "A numbered checklist of specific code changes needed, with before/after examples.", "", "### INSTALL_COMMANDS", "```bash", "// The install and uninstall commands", "```"), r.join("\n");
292
+ }
293
+ async function R(e, t) {
294
+ let n = 10 * 1024 * 1024;
295
+ try {
296
+ if (e === "claude") {
297
+ let { stdout: e } = await j("claude", ["-p", t], { maxBuffer: n });
298
+ return e;
299
+ } else {
300
+ let { stdout: e } = await j("codex", [
301
+ "-p",
302
+ t,
303
+ "--full-auto"
304
+ ], { maxBuffer: n });
305
+ return e;
306
+ }
307
+ } catch (t) {
308
+ throw t.code === "ENOENT" ? Error(`"${e}" CLI not found. Please install it first:\n` + (e === "claude" ? " npm install -g @anthropic-ai/claude-code" : " npm install -g @openai/codex")) : t;
309
+ }
310
+ }
311
+ function z(e) {
312
+ let t = {
313
+ config: void 0,
314
+ localeFiles: [],
315
+ steps: void 0,
316
+ installCommands: void 0
317
+ }, n = e.match(/### FLUENTI_CONFIG[\s\S]*?```(?:ts|typescript)?\n([\s\S]*?)```/);
318
+ n && (t.config = n[1].trim());
319
+ let r = e.match(/### LOCALE_FILES([\s\S]*?)(?=### MIGRATION_STEPS|### INSTALL_COMMANDS|$)/);
320
+ if (r) {
321
+ let e = /#### LOCALE:\s*(\S+)\s*\n```(?:po)?\n([\s\S]*?)```/g, n;
322
+ for (; (n = e.exec(r[1])) !== null;) t.localeFiles.push({
323
+ locale: n[1],
324
+ content: n[2].trim()
325
+ });
326
+ }
327
+ let i = e.match(/### MIGRATION_STEPS\s*\n([\s\S]*?)(?=### INSTALL_COMMANDS|$)/);
328
+ i && (t.steps = i[1].trim());
329
+ let a = e.match(/### INSTALL_COMMANDS[\s\S]*?```(?:bash|sh)?\n([\s\S]*?)```/);
330
+ return a && (t.installCommands = a[1].trim()), t;
331
+ }
332
+ async function B(e) {
333
+ let { from: t, provider: n, write: r } = e, i = P(t);
334
+ if (!i) {
335
+ f.error(`Unsupported library "${t}". Supported libraries:`);
336
+ for (let e of N) f.log(` - ${e}`);
337
+ return;
338
+ }
339
+ let a = M[i];
340
+ f.info(`Migrating from ${a.name} (${a.framework}) to Fluenti`), f.info("Scanning project for existing i18n files...");
341
+ let o = await F(a);
342
+ if (o.configFiles.length === 0 && o.localeFiles.length === 0) {
343
+ f.warn(`No ${a.name} configuration or locale files found.`), f.info("Make sure you are running this command from the project root directory.");
344
+ return;
345
+ }
346
+ f.info(`Found: ${o.configFiles.length} config file(s), ${o.localeFiles.length} locale file(s), ${o.sampleSources.length} source file(s)`);
347
+ let s = I(a.migrationGuide);
348
+ f.info(`Generating migration plan with ${n}...`);
349
+ let c = z(await R(n, L(a, o, s)));
350
+ if (c.installCommands && (f.log(""), f.box({
351
+ title: "Install Commands",
352
+ message: c.installCommands
353
+ })), c.config) if (r) {
354
+ let { writeFileSync: e } = await import("node:fs"), t = x("fluenti.config.ts");
355
+ e(t, c.config, "utf-8"), f.success(`Written: ${t}`);
356
+ } else f.log(""), f.box({
357
+ title: "fluenti.config.ts",
358
+ message: c.config
359
+ });
360
+ if (c.localeFiles.length > 0) if (r) {
361
+ let { writeFileSync: e, mkdirSync: t } = await import("node:fs"), n = "./locales";
362
+ t(x(n), { recursive: !0 });
363
+ for (let t of c.localeFiles) {
364
+ let r = x(n, `${t.locale}.po`);
365
+ e(r, t.content, "utf-8"), f.success(`Written: ${r}`);
366
+ }
367
+ } else for (let e of c.localeFiles) f.log(""), f.box({
368
+ title: `locales/${e.locale}.po`,
369
+ message: e.content.length > 500 ? e.content.slice(0, 500) + "\n... (use --write to save full file)" : e.content
370
+ });
371
+ c.steps && (f.log(""), f.box({
372
+ title: "Migration Steps",
373
+ message: c.steps
374
+ })), !r && (c.config || c.localeFiles.length > 0) && (f.log(""), f.info("Run with --write to save generated files to disk:"), f.log(` fluenti migrate --from ${t} --write`));
375
+ }
376
+ //#endregion
377
+ //#region src/cli.ts
378
+ var V = {
379
+ sourceLocale: "en",
380
+ locales: ["en"],
381
+ catalogDir: "./locales",
382
+ format: "po",
383
+ include: ["./src/**/*.{vue,tsx,jsx,ts,js}"],
384
+ compileOutDir: "./locales/compiled"
385
+ };
386
+ async function H(e) {
387
+ let t = e ? [x(e)] : [
388
+ x("fluenti.config.ts"),
389
+ x("fluenti.config.js"),
390
+ x("fluenti.config.mjs")
391
+ ];
392
+ for (let e of t) if (m(e)) try {
393
+ let { createJiti: t } = await import("jiti"), n = await t(import.meta.url).import(e), r = n.default ?? n;
394
+ return {
395
+ ...V,
396
+ ...r
397
+ };
398
+ } catch {
399
+ f.warn(`Failed to load config from ${e}, using defaults`);
400
+ }
401
+ return V;
402
+ }
403
+ function U(e, t) {
404
+ if (!m(e)) return {};
405
+ let r = g(e, "utf-8");
406
+ return t === "json" ? a(r) : n(r);
407
+ }
408
+ function W(t, n, r) {
409
+ h(v(t), { recursive: !0 }), _(t, r === "json" ? s(n) : e(n), "utf-8");
410
+ }
411
+ function G(e, t) {
412
+ return y(e) === ".vue" ? r(t, e) : l(t, e);
413
+ }
414
+ d(u({
415
+ meta: {
416
+ name: "fluenti",
417
+ version: "0.0.1",
418
+ description: "Compile-time i18n for modern frameworks"
419
+ },
420
+ subCommands: {
421
+ extract: u({
422
+ meta: {
423
+ name: "extract",
424
+ description: "Extract messages from source files"
425
+ },
426
+ args: { config: {
427
+ type: "string",
428
+ description: "Path to config file"
429
+ } },
430
+ async run({ args: e }) {
431
+ let n = await H(e.config);
432
+ f.info(`Extracting messages from ${n.include.join(", ")}`);
433
+ let r = await p(n.include, { absolute: !0 }), i = [];
434
+ for (let e of r) {
435
+ let t = G(e, g(e, "utf-8"));
436
+ i.push(...t);
437
+ }
438
+ f.info(`Found ${i.length} messages in ${r.length} files`);
439
+ let a = n.format === "json" ? ".json" : ".po";
440
+ for (let e of n.locales) {
441
+ let r = x(n.catalogDir, `${e}${a}`), { catalog: o, result: s } = t(U(r, n.format), i);
442
+ W(r, o, n.format), f.success(`${e}: ${s.added} added, ${s.unchanged} unchanged, ${s.obsolete} obsolete`);
443
+ }
444
+ }
445
+ }),
446
+ compile: u({
447
+ meta: {
448
+ name: "compile",
449
+ description: "Compile message catalogs to JS modules"
450
+ },
451
+ args: { config: {
452
+ type: "string",
453
+ description: "Path to config file"
454
+ } },
455
+ async run({ args: e }) {
456
+ let t = await H(e.config), n = t.format === "json" ? ".json" : ".po";
457
+ h(t.compileOutDir, { recursive: !0 });
458
+ let r = {};
459
+ for (let e of t.locales) r[e] = U(x(t.catalogDir, `${e}${n}`), t.format);
460
+ let a = c(r);
461
+ f.info(`Compiling ${a.length} messages across ${t.locales.length} locales`);
462
+ for (let e of t.locales) {
463
+ let n = i(r[e], e, a, t.sourceLocale), o = x(t.compileOutDir, `${e}.js`);
464
+ _(o, n, "utf-8"), f.success(`Compiled ${e} → ${o}`);
465
+ }
466
+ let s = o(t.locales, t.compileOutDir), l = x(t.compileOutDir, "index.js");
467
+ _(l, s, "utf-8"), f.success(`Generated index → ${l}`);
468
+ }
469
+ }),
470
+ stats: u({
471
+ meta: {
472
+ name: "stats",
473
+ description: "Show translation progress"
474
+ },
475
+ args: { config: {
476
+ type: "string",
477
+ description: "Path to config file"
478
+ } },
479
+ async run({ args: e }) {
480
+ let t = await H(e.config), n = t.format === "json" ? ".json" : ".po", r = [];
481
+ for (let e of t.locales) {
482
+ let i = U(x(t.catalogDir, `${e}${n}`), t.format), a = Object.values(i).filter((e) => !e.obsolete), o = a.length, s = a.filter((e) => e.translation && e.translation.length > 0).length, c = o > 0 ? (s / o * 100).toFixed(1) + "%" : "—";
483
+ r.push({
484
+ locale: e,
485
+ total: o,
486
+ translated: s,
487
+ pct: c
488
+ });
489
+ }
490
+ f.log(""), f.log(" Locale │ Total │ Translated │ Progress"), f.log(" ────────┼───────┼────────────┼─────────");
491
+ for (let e of r) f.log(` ${e.locale.padEnd(8)}│ ${String(e.total).padStart(5)} │ ${String(e.translated).padStart(10)} │ ${e.pct}`);
492
+ f.log("");
493
+ }
494
+ }),
495
+ translate: u({
496
+ meta: {
497
+ name: "translate",
498
+ description: "Translate messages using AI (Claude Code or Codex CLI)"
499
+ },
500
+ args: {
501
+ config: {
502
+ type: "string",
503
+ description: "Path to config file"
504
+ },
505
+ provider: {
506
+ type: "string",
507
+ description: "AI provider: claude or codex",
508
+ default: "claude"
509
+ },
510
+ locale: {
511
+ type: "string",
512
+ description: "Translate a specific locale only"
513
+ },
514
+ "batch-size": {
515
+ type: "string",
516
+ description: "Messages per batch",
517
+ default: "50"
518
+ }
519
+ },
520
+ async run({ args: e }) {
521
+ let t = await H(e.config), n = e.provider;
522
+ if (n !== "claude" && n !== "codex") {
523
+ f.error(`Invalid provider "${n}". Use "claude" or "codex".`);
524
+ return;
525
+ }
526
+ let r = parseInt(e["batch-size"] ?? "50", 10);
527
+ if (isNaN(r) || r < 1) {
528
+ f.error("Invalid batch-size. Must be a positive integer.");
529
+ return;
530
+ }
531
+ let i = e.locale ? [e.locale] : t.locales.filter((e) => e !== t.sourceLocale);
532
+ if (i.length === 0) {
533
+ f.warn("No target locales to translate.");
534
+ return;
535
+ }
536
+ f.info(`Translating with ${n} (batch size: ${r})`);
537
+ let a = t.format === "json" ? ".json" : ".po";
538
+ for (let e of i) {
539
+ f.info(`\n[${e}]`);
540
+ let i = x(t.catalogDir, `${e}${a}`), o = U(i, t.format), { catalog: s, translated: c } = await A({
541
+ provider: n,
542
+ sourceLocale: t.sourceLocale,
543
+ targetLocale: e,
544
+ catalog: o,
545
+ batchSize: r
546
+ });
547
+ c > 0 ? (W(i, s, t.format), f.success(` ${e}: ${c} messages translated`)) : f.success(` ${e}: already fully translated`);
548
+ }
549
+ }
550
+ }),
551
+ migrate: u({
552
+ meta: {
553
+ name: "migrate",
554
+ description: "Migrate from another i18n library using AI"
555
+ },
556
+ args: {
557
+ from: {
558
+ type: "string",
559
+ description: "Source library: vue-i18n, nuxt-i18n, react-i18next, next-intl, next-i18next, lingui",
560
+ required: !0
561
+ },
562
+ provider: {
563
+ type: "string",
564
+ description: "AI provider: claude or codex",
565
+ default: "claude"
566
+ },
567
+ write: {
568
+ type: "boolean",
569
+ description: "Write generated files to disk",
570
+ default: !1
571
+ }
572
+ },
573
+ async run({ args: e }) {
574
+ let t = e.provider;
575
+ if (t !== "claude" && t !== "codex") {
576
+ f.error(`Invalid provider "${t}". Use "claude" or "codex".`);
577
+ return;
578
+ }
579
+ await B({
580
+ from: e.from,
581
+ provider: t,
582
+ write: e.write ?? !1
583
+ });
584
+ }
585
+ })
586
+ }
587
+ }));
588
+ //#endregion
589
+
590
+ //# sourceMappingURL=cli.js.map