@getmonoceros/workbench 1.22.1 → 1.23.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/bin.js CHANGED
@@ -2457,9 +2457,156 @@ var init_claude_settings = __esm({
2457
2457
  }
2458
2458
  });
2459
2459
 
2460
- // src/create/scaffold.ts
2461
- import { existsSync as existsSync6, promises as fs7 } from "fs";
2460
+ // src/create/opencode-config.ts
2461
+ import { existsSync as existsSync6, promises as fsp3 } from "fs";
2462
2462
  import path9 from "path";
2463
+ import { consola } from "consola";
2464
+ function parseOpencodeModel(model) {
2465
+ const idx = model.indexOf("/");
2466
+ if (idx <= 0 || idx === model.length - 1) return void 0;
2467
+ return { provider: model.slice(0, idx), modelId: model.slice(idx + 1) };
2468
+ }
2469
+ async function writeOpencodeConfig(targetDir, containerName2, features) {
2470
+ if (!features) return;
2471
+ const entry2 = Object.entries(features).find(
2472
+ ([ref]) => matchMonocerosFeature(ref)?.name === "opencode"
2473
+ );
2474
+ if (!entry2) return;
2475
+ const options = entry2[1] ?? {};
2476
+ const str = (key) => typeof options[key] === "string" ? options[key].trim() : "";
2477
+ const model = str("model");
2478
+ const apiToken = str("apiToken");
2479
+ const npm = str("npm");
2480
+ const baseUrl = str("baseUrl");
2481
+ const file = path9.join(
2482
+ targetDir,
2483
+ "home",
2484
+ ".config",
2485
+ "opencode",
2486
+ "opencode.json"
2487
+ );
2488
+ await fsp3.mkdir(path9.dirname(file), { recursive: true });
2489
+ let config = {};
2490
+ if (existsSync6(file)) {
2491
+ try {
2492
+ const txt = await fsp3.readFile(file, "utf8");
2493
+ if (txt.trim()) {
2494
+ const parsed2 = JSON.parse(txt);
2495
+ if (typeof parsed2 === "object" && parsed2 !== null) {
2496
+ config = parsed2;
2497
+ }
2498
+ }
2499
+ } catch {
2500
+ config = {};
2501
+ }
2502
+ }
2503
+ if (typeof config.$schema !== "string") {
2504
+ config.$schema = "https://opencode.ai/config.json";
2505
+ }
2506
+ const workspaceRoot = `/workspaces/${containerName2}`;
2507
+ const managedInstructions = [
2508
+ `${workspaceRoot}/AGENTS.md`,
2509
+ `${workspaceRoot}/.monoceros/commands.md`
2510
+ ];
2511
+ const existingInstructions = Array.isArray(config.instructions) ? config.instructions.filter(
2512
+ (i) => typeof i === "string"
2513
+ ) : [];
2514
+ config.instructions = [
2515
+ ...managedInstructions,
2516
+ ...existingInstructions.filter((i) => !managedInstructions.includes(i))
2517
+ ];
2518
+ if (model) {
2519
+ config.model = model;
2520
+ }
2521
+ const parsed = parseOpencodeModel(model);
2522
+ if (npm) {
2523
+ if (!parsed) {
2524
+ consola.warn(
2525
+ "[opencode] `npm` is set but `model` is empty or has no provider prefix \u2014 set `model: <provider>/<model-id>` to configure a custom provider."
2526
+ );
2527
+ } else {
2528
+ writeCustomProvider(config, parsed, { npm, baseUrl, apiToken });
2529
+ }
2530
+ } else if (parsed) {
2531
+ if (KNOWN_APIKEY_PROVIDERS.includes(parsed.provider)) {
2532
+ if (apiToken) {
2533
+ writeHostedApiKey(config, parsed.provider, apiToken);
2534
+ }
2535
+ } else {
2536
+ consola.warn(
2537
+ `[opencode] '${parsed.provider}' is not a known single-key provider (${KNOWN_APIKEY_PROVIDERS.join(", ")}). For a custom or local provider (e.g. Ollama), set the \`npm\` and \`baseUrl\` options on the opencode feature.`
2538
+ );
2539
+ }
2540
+ }
2541
+ await fsp3.writeFile(file, `${JSON.stringify(config, null, 2)}
2542
+ `);
2543
+ }
2544
+ function providersOf(config) {
2545
+ if (typeof config.provider === "object" && config.provider !== null) {
2546
+ return config.provider;
2547
+ }
2548
+ const fresh = {};
2549
+ config.provider = fresh;
2550
+ return fresh;
2551
+ }
2552
+ function providerEntry(providers, id) {
2553
+ if (typeof providers[id] === "object" && providers[id] !== null) {
2554
+ return providers[id];
2555
+ }
2556
+ const fresh = {};
2557
+ providers[id] = fresh;
2558
+ return fresh;
2559
+ }
2560
+ function optionsOf(entry2) {
2561
+ if (typeof entry2.options === "object" && entry2.options !== null) {
2562
+ return entry2.options;
2563
+ }
2564
+ const fresh = {};
2565
+ entry2.options = fresh;
2566
+ return fresh;
2567
+ }
2568
+ function writeHostedApiKey(config, provider, apiToken) {
2569
+ const entry2 = providerEntry(providersOf(config), provider);
2570
+ optionsOf(entry2).apiKey = apiToken;
2571
+ }
2572
+ function writeCustomProvider(config, parsed, {
2573
+ npm,
2574
+ baseUrl,
2575
+ apiToken
2576
+ }) {
2577
+ const entry2 = providerEntry(providersOf(config), parsed.provider);
2578
+ entry2.npm = npm;
2579
+ if (typeof entry2.name !== "string") entry2.name = parsed.provider;
2580
+ const opts = optionsOf(entry2);
2581
+ if (baseUrl) opts.baseURL = baseUrl;
2582
+ if (apiToken) opts.apiKey = apiToken;
2583
+ const models = typeof entry2.models === "object" && entry2.models !== null ? entry2.models : {};
2584
+ if (models[parsed.modelId] === void 0) {
2585
+ models[parsed.modelId] = { name: parsed.modelId };
2586
+ }
2587
+ entry2.models = models;
2588
+ }
2589
+ var KNOWN_APIKEY_PROVIDERS;
2590
+ var init_opencode_config = __esm({
2591
+ "src/create/opencode-config.ts"() {
2592
+ "use strict";
2593
+ init_ref();
2594
+ KNOWN_APIKEY_PROVIDERS = [
2595
+ "anthropic",
2596
+ "openai",
2597
+ "google",
2598
+ "openrouter",
2599
+ "mistral",
2600
+ "groq",
2601
+ "deepseek",
2602
+ "xai"
2603
+ ];
2604
+ }
2605
+ });
2606
+
2607
+ // src/create/scaffold.ts
2608
+ import { existsSync as existsSync7, promises as fs7 } from "fs";
2609
+ import path10 from "path";
2463
2610
  function deriveRepoName(url) {
2464
2611
  const lastSep = Math.max(url.lastIndexOf("/"), url.lastIndexOf(":"));
2465
2612
  const tail = url.slice(lastSep + 1);
@@ -2590,7 +2737,7 @@ function featuresSourceRoot() {
2590
2737
  const override2 = process.env.MONOCEROS_FEATURES_DIR_OVERRIDE?.trim();
2591
2738
  if (override2 && override2.length > 0) return override2;
2592
2739
  const checkout = workbenchCheckoutRoot();
2593
- return checkout ? path9.join(checkout, "components", "features") : null;
2740
+ return checkout ? path10.join(checkout, "components", "features") : null;
2594
2741
  }
2595
2742
  function resolveFeatures(opts) {
2596
2743
  const resolved = [];
@@ -2630,8 +2777,8 @@ function resolveFeatures(opts) {
2630
2777
  const descriptor = featureDescriptor(name);
2631
2778
  const { paths, files } = descriptorPersistentHome(descriptor);
2632
2779
  const sourceRoot = featuresSourceRoot();
2633
- const localSourceDir = sourceRoot ? path9.join(sourceRoot, name) : null;
2634
- if (descriptor && localSourceDir && existsSync6(localSourceDir)) {
2780
+ const localSourceDir = sourceRoot ? path10.join(sourceRoot, name) : null;
2781
+ if (descriptor && localSourceDir && existsSync7(localSourceDir)) {
2635
2782
  resolved.push({
2636
2783
  devcontainerKey: `./features/${name}`,
2637
2784
  options,
@@ -3076,7 +3223,7 @@ function buildPostCreateScript(opts) {
3076
3223
  return lines.join("\n") + "\n";
3077
3224
  }
3078
3225
  async function writePostCreateScript(devcontainerDir, opts) {
3079
- const dest = path9.join(devcontainerDir, "post-create.sh");
3226
+ const dest = path10.join(devcontainerDir, "post-create.sh");
3080
3227
  await fs7.writeFile(dest, buildPostCreateScript(opts));
3081
3228
  await fs7.chmod(dest, 493);
3082
3229
  }
@@ -3090,11 +3237,11 @@ async function writeIfChanged(filePath, content) {
3090
3237
  }
3091
3238
  async function writeScaffold(opts, targetDir, scaffoldOpts = {}) {
3092
3239
  const dockerMode = scaffoldOpts.dockerMode ?? "rootful";
3093
- const devcontainerDir = path9.join(targetDir, ".devcontainer");
3094
- const monocerosDir = path9.join(targetDir, ".monoceros");
3095
- const projectsDir = path9.join(targetDir, "projects");
3096
- const homeDir = path9.join(targetDir, "home");
3097
- const dataDir = path9.join(targetDir, "data");
3240
+ const devcontainerDir = path10.join(targetDir, ".devcontainer");
3241
+ const monocerosDir = path10.join(targetDir, ".monoceros");
3242
+ const projectsDir = path10.join(targetDir, "projects");
3243
+ const homeDir = path10.join(targetDir, "home");
3244
+ const dataDir = path10.join(targetDir, "data");
3098
3245
  await fs7.mkdir(devcontainerDir, { recursive: true });
3099
3246
  await fs7.mkdir(monocerosDir, { recursive: true });
3100
3247
  await fs7.mkdir(projectsDir, { recursive: true });
@@ -3104,36 +3251,36 @@ async function writeScaffold(opts, targetDir, scaffoldOpts = {}) {
3104
3251
  for (const svc of opts.services) {
3105
3252
  const hasDataVolume = svc.volumes.some((v) => v.split(":")[0] === "data");
3106
3253
  if (hasDataVolume) {
3107
- await fs7.mkdir(path9.join(dataDir, svc.name), { recursive: true });
3254
+ await fs7.mkdir(path10.join(dataDir, svc.name), { recursive: true });
3108
3255
  }
3109
3256
  }
3110
3257
  }
3111
- const containerGitignore = path9.join(targetDir, ".gitignore");
3258
+ const containerGitignore = path10.join(targetDir, ".gitignore");
3112
3259
  await fs7.writeFile(
3113
3260
  containerGitignore,
3114
3261
  "/home/\n/.monoceros/\n/data/\n/AGENTS.md\n/CLAUDE.md\n"
3115
3262
  );
3116
- const gitkeep = path9.join(projectsDir, ".gitkeep");
3117
- if (!existsSync6(gitkeep)) {
3263
+ const gitkeep = path10.join(projectsDir, ".gitkeep");
3264
+ if (!existsSync7(gitkeep)) {
3118
3265
  await fs7.writeFile(gitkeep, "");
3119
3266
  }
3120
3267
  await fs7.writeFile(
3121
- path9.join(monocerosDir, ".gitignore"),
3268
+ path10.join(monocerosDir, ".gitignore"),
3122
3269
  "git-credentials*\ngitconfig\n"
3123
3270
  );
3124
3271
  const devcontainerJson = buildDevcontainerJson(opts, dockerMode);
3125
3272
  await writeIfChanged(
3126
- path9.join(devcontainerDir, "devcontainer.json"),
3273
+ path10.join(devcontainerDir, "devcontainer.json"),
3127
3274
  JSON.stringify(devcontainerJson, null, 2) + "\n"
3128
3275
  );
3129
- const featuresDir = path9.join(devcontainerDir, "features");
3130
- if (existsSync6(featuresDir)) {
3276
+ const featuresDir = path10.join(devcontainerDir, "features");
3277
+ if (existsSync7(featuresDir)) {
3131
3278
  await fs7.rm(featuresDir, { recursive: true, force: true });
3132
3279
  }
3133
3280
  const resolvedFeatures = resolveFeatures(opts);
3134
3281
  for (const f of resolvedFeatures) {
3135
3282
  if (!f.localSourceDir || !f.localName) continue;
3136
- const dest = path9.join(featuresDir, f.localName);
3283
+ const dest = path10.join(featuresDir, f.localName);
3137
3284
  await fs7.mkdir(dest, { recursive: true });
3138
3285
  const entries = await fs7.readdir(f.localSourceDir, { withFileTypes: true });
3139
3286
  for (const entry2 of entries) {
@@ -3142,38 +3289,39 @@ async function writeScaffold(opts, targetDir, scaffoldOpts = {}) {
3142
3289
  continue;
3143
3290
  }
3144
3291
  await fs7.cp(
3145
- path9.join(f.localSourceDir, entry2.name),
3146
- path9.join(dest, entry2.name)
3292
+ path10.join(f.localSourceDir, entry2.name),
3293
+ path10.join(dest, entry2.name)
3147
3294
  );
3148
3295
  }
3149
3296
  if (f.generatedManifest) {
3150
3297
  await fs7.writeFile(
3151
- path9.join(dest, "devcontainer-feature.json"),
3298
+ path10.join(dest, "devcontainer-feature.json"),
3152
3299
  JSON.stringify(f.generatedManifest, null, 2) + "\n"
3153
3300
  );
3154
3301
  }
3155
3302
  }
3156
3303
  for (const f of resolvedFeatures) {
3157
3304
  for (const sub of f.persistentHomePaths) {
3158
- await fs7.mkdir(path9.join(homeDir, sub), { recursive: true });
3305
+ await fs7.mkdir(path10.join(homeDir, sub), { recursive: true });
3159
3306
  }
3160
3307
  for (const entry2 of f.persistentHomeFiles) {
3161
- const filePath = path9.join(homeDir, entry2.path);
3162
- await fs7.mkdir(path9.dirname(filePath), { recursive: true });
3163
- if (!existsSync6(filePath)) {
3308
+ const filePath = path10.join(homeDir, entry2.path);
3309
+ await fs7.mkdir(path10.dirname(filePath), { recursive: true });
3310
+ if (!existsSync7(filePath)) {
3164
3311
  await fs7.writeFile(filePath, entry2.initialContent);
3165
3312
  }
3166
3313
  }
3167
3314
  }
3168
3315
  await writeClaudePermissionMode(targetDir, opts.features);
3316
+ await writeOpencodeConfig(targetDir, opts.name, opts.features);
3169
3317
  await writePostCreateScript(devcontainerDir, opts);
3170
- const composePath = path9.join(devcontainerDir, "compose.yaml");
3318
+ const composePath = path10.join(devcontainerDir, "compose.yaml");
3171
3319
  if (needsCompose(opts)) {
3172
3320
  await writeIfChanged(composePath, buildComposeYaml(opts, dockerMode));
3173
- } else if (existsSync6(composePath)) {
3321
+ } else if (existsSync7(composePath)) {
3174
3322
  await fs7.rm(composePath);
3175
3323
  }
3176
- const workspacePath = path9.join(targetDir, `${opts.name}.code-workspace`);
3324
+ const workspacePath = path10.join(targetDir, `${opts.name}.code-workspace`);
3177
3325
  let existingWorkspace;
3178
3326
  try {
3179
3327
  const raw = await fs7.readFile(workspacePath, "utf8");
@@ -3184,8 +3332,8 @@ async function writeScaffold(opts, targetDir, scaffoldOpts = {}) {
3184
3332
  const generated = buildCodeWorkspaceJson(opts);
3185
3333
  const merged = mergeCodeWorkspace(existingWorkspace, generated);
3186
3334
  await fs7.writeFile(workspacePath, JSON.stringify(merged, null, 2) + "\n");
3187
- const vscodeDir = path9.join(targetDir, ".vscode");
3188
- const settingsPath = path9.join(vscodeDir, "settings.json");
3335
+ const vscodeDir = path10.join(targetDir, ".vscode");
3336
+ const settingsPath = path10.join(vscodeDir, "settings.json");
3189
3337
  let existingSettings;
3190
3338
  try {
3191
3339
  existingSettings = JSON.parse(await fs7.readFile(settingsPath, "utf8"));
@@ -3207,6 +3355,7 @@ var init_scaffold = __esm({
3207
3355
  init_load_sync();
3208
3356
  init_generate_manifest();
3209
3357
  init_claude_settings();
3358
+ init_opencode_config();
3210
3359
  init_catalog();
3211
3360
  APT_PACKAGE_NAME_RE2 = /^[a-z0-9][a-z0-9.+-]*$/;
3212
3361
  FEATURE_REF_RE2 = /^[a-z0-9.-]+(\/[a-z0-9._-]+)+:[a-z0-9._-]+$/;
@@ -3660,8 +3809,8 @@ function removeRepoFromDoc(doc, urlOrPath) {
3660
3809
  if (!isMap2(item)) return false;
3661
3810
  const url = item.get("url");
3662
3811
  if (url === urlOrPath) return true;
3663
- const path27 = item.get("path");
3664
- const effectivePath = typeof path27 === "string" ? path27 : typeof url === "string" ? deriveRepoName(url) : void 0;
3812
+ const path28 = item.get("path");
3813
+ const effectivePath = typeof path28 === "string" ? path28 : typeof url === "string" ? deriveRepoName(url) : void 0;
3665
3814
  return effectivePath === urlOrPath;
3666
3815
  });
3667
3816
  if (idx < 0) return false;
@@ -3696,9 +3845,9 @@ var init_yml = __esm({
3696
3845
 
3697
3846
  // src/modify/index.ts
3698
3847
  import { promises as fs8 } from "fs";
3699
- import { consola } from "consola";
3848
+ import { consola as consola2 } from "consola";
3700
3849
  import { createPatch } from "diff";
3701
- import path10 from "path";
3850
+ import path11 from "path";
3702
3851
  function runAddLanguage(input) {
3703
3852
  const spec = parseLanguageSpec(input.language);
3704
3853
  if (!spec || !BUILTIN_LANGUAGES.has(spec.name) && !LANGUAGE_CATALOG[spec.name]) {
@@ -3783,7 +3932,7 @@ async function runAddRepo(input) {
3783
3932
  "Missing repo URL. Usage: monoceros add-repo <containername> <url>."
3784
3933
  );
3785
3934
  }
3786
- const path27 = (input.path ?? deriveRepoName(url)).trim();
3935
+ const path28 = (input.path ?? deriveRepoName(url)).trim();
3787
3936
  const hasName = typeof input.gitName === "string" && input.gitName.trim().length > 0;
3788
3937
  const hasEmail = typeof input.gitEmail === "string" && input.gitEmail.trim().length > 0;
3789
3938
  if (hasName !== hasEmail) {
@@ -3820,7 +3969,7 @@ async function runAddRepo(input) {
3820
3969
  const providerToWrite = !canonical && explicitProvider ? explicitProvider : void 0;
3821
3970
  const entry2 = {
3822
3971
  url,
3823
- path: path27,
3972
+ path: path28,
3824
3973
  ...hasName && hasEmail ? {
3825
3974
  gitUser: {
3826
3975
  name: input.gitName.trim(),
@@ -3952,7 +4101,7 @@ async function tryCloneInRunningContainer(input, entry2) {
3952
4101
  logger.info(
3953
4102
  `Cloned ${entry2.url} into /workspaces/${containerName2}/${targetRel} inside the running container.`
3954
4103
  );
3955
- void path10;
4104
+ void path11;
3956
4105
  }
3957
4106
  function shquote(value) {
3958
4107
  return `'${value.replace(/'/g, `'\\''`)}'`;
@@ -4194,9 +4343,9 @@ async function mutate(opts, apply) {
4194
4343
  }
4195
4344
  function defaultLogger() {
4196
4345
  return {
4197
- info: (m) => consola.info(m),
4198
- success: (m) => consola.success(m),
4199
- warn: (m) => consola.warn(m)
4346
+ info: (m) => consola2.info(m),
4347
+ success: (m) => consola2.success(m),
4348
+ warn: (m) => consola2.warn(m)
4200
4349
  };
4201
4350
  }
4202
4351
  async function syncPortsToProxy(input) {
@@ -4276,7 +4425,7 @@ var init_modify = __esm({
4276
4425
  init_scaffold();
4277
4426
  init_yml();
4278
4427
  defaultConfirm = async (message) => {
4279
- const result = await consola.prompt(message, {
4428
+ const result = await consola2.prompt(message, {
4280
4429
  type: "confirm",
4281
4430
  initial: false
4282
4431
  });
@@ -4287,7 +4436,7 @@ var init_modify = __esm({
4287
4436
 
4288
4437
  // src/commands/add-apt-packages.ts
4289
4438
  import { defineCommand } from "citty";
4290
- import { consola as consola2 } from "consola";
4439
+ import { consola as consola3 } from "consola";
4291
4440
  var addAptPackagesCommand;
4292
4441
  var init_add_apt_packages = __esm({
4293
4442
  "src/commands/add-apt-packages.ts"() {
@@ -4316,7 +4465,7 @@ var init_add_apt_packages = __esm({
4316
4465
  async run({ args }) {
4317
4466
  const packages = [...getInnerArgs()];
4318
4467
  if (packages.length === 0) {
4319
- consola2.error(
4468
+ consola3.error(
4320
4469
  "No package names given. Usage: `monoceros add-apt-packages <containername> [--yes] -- <pkg> [<pkg> \u2026]`."
4321
4470
  );
4322
4471
  process.exit(1);
@@ -4329,7 +4478,7 @@ var init_add_apt_packages = __esm({
4329
4478
  });
4330
4479
  process.exit(result.status === "aborted" ? 1 : 0);
4331
4480
  } catch (err) {
4332
- consola2.error(err instanceof Error ? err.message : String(err));
4481
+ consola3.error(err instanceof Error ? err.message : String(err));
4333
4482
  process.exit(1);
4334
4483
  }
4335
4484
  }
@@ -4339,7 +4488,7 @@ var init_add_apt_packages = __esm({
4339
4488
 
4340
4489
  // src/commands/add-feature.ts
4341
4490
  import { defineCommand as defineCommand2 } from "citty";
4342
- import { consola as consola3 } from "consola";
4491
+ import { consola as consola4 } from "consola";
4343
4492
  function parseOptionsAfterDashes(tokens) {
4344
4493
  const result = {};
4345
4494
  for (const token of tokens) {
@@ -4399,7 +4548,7 @@ var init_add_feature = __esm({
4399
4548
  try {
4400
4549
  options = parseOptionsAfterDashes(getInnerArgs());
4401
4550
  } catch (err) {
4402
- consola3.error(err instanceof Error ? err.message : String(err));
4551
+ consola4.error(err instanceof Error ? err.message : String(err));
4403
4552
  process.exit(1);
4404
4553
  }
4405
4554
  try {
@@ -4411,7 +4560,7 @@ var init_add_feature = __esm({
4411
4560
  });
4412
4561
  process.exit(result.status === "aborted" ? 1 : 0);
4413
4562
  } catch (err) {
4414
- consola3.error(err instanceof Error ? err.message : String(err));
4563
+ consola4.error(err instanceof Error ? err.message : String(err));
4415
4564
  process.exit(1);
4416
4565
  }
4417
4566
  }
@@ -4421,7 +4570,7 @@ var init_add_feature = __esm({
4421
4570
 
4422
4571
  // src/commands/add-from-url.ts
4423
4572
  import { defineCommand as defineCommand3 } from "citty";
4424
- import { consola as consola4 } from "consola";
4573
+ import { consola as consola5 } from "consola";
4425
4574
  function printSecurityWarning(url) {
4426
4575
  const w = (line) => process.stderr.write(line + "\n");
4427
4576
  w("");
@@ -4490,7 +4639,7 @@ var init_add_from_url = __esm({
4490
4639
  });
4491
4640
  process.exit(result.status === "aborted" ? 1 : 0);
4492
4641
  } catch (err) {
4493
- consola4.error(err instanceof Error ? err.message : String(err));
4642
+ consola5.error(err instanceof Error ? err.message : String(err));
4494
4643
  process.exit(1);
4495
4644
  }
4496
4645
  }
@@ -4500,7 +4649,7 @@ var init_add_from_url = __esm({
4500
4649
 
4501
4650
  // src/commands/add-repo.ts
4502
4651
  import { defineCommand as defineCommand4 } from "citty";
4503
- import { consola as consola5 } from "consola";
4652
+ import { consola as consola6 } from "consola";
4504
4653
  var addRepoCommand;
4505
4654
  var init_add_repo = __esm({
4506
4655
  "src/commands/add-repo.ts"() {
@@ -4559,7 +4708,7 @@ var init_add_repo = __esm({
4559
4708
  });
4560
4709
  process.exit(result.status === "aborted" ? 1 : 0);
4561
4710
  } catch (err) {
4562
- consola5.error(err instanceof Error ? err.message : String(err));
4711
+ consola6.error(err instanceof Error ? err.message : String(err));
4563
4712
  process.exit(1);
4564
4713
  }
4565
4714
  }
@@ -4569,7 +4718,7 @@ var init_add_repo = __esm({
4569
4718
 
4570
4719
  // src/commands/add-language.ts
4571
4720
  import { defineCommand as defineCommand5 } from "citty";
4572
- import { consola as consola6 } from "consola";
4721
+ import { consola as consola7 } from "consola";
4573
4722
  var addLanguageCommand;
4574
4723
  var init_add_language = __esm({
4575
4724
  "src/commands/add-language.ts"() {
@@ -4608,7 +4757,7 @@ var init_add_language = __esm({
4608
4757
  });
4609
4758
  process.exit(result.status === "aborted" ? 1 : 0);
4610
4759
  } catch (err) {
4611
- consola6.error(err instanceof Error ? err.message : String(err));
4760
+ consola7.error(err instanceof Error ? err.message : String(err));
4612
4761
  process.exit(1);
4613
4762
  }
4614
4763
  }
@@ -4618,7 +4767,7 @@ var init_add_language = __esm({
4618
4767
 
4619
4768
  // src/commands/add-port.ts
4620
4769
  import { defineCommand as defineCommand6 } from "citty";
4621
- import { consola as consola7 } from "consola";
4770
+ import { consola as consola8 } from "consola";
4622
4771
  function coerceToken(raw) {
4623
4772
  const n = Number(raw);
4624
4773
  return Number.isFinite(n) ? n : raw;
@@ -4656,7 +4805,7 @@ var init_add_port = __esm({
4656
4805
  async run({ args }) {
4657
4806
  const tokens = [...getInnerArgs()];
4658
4807
  if (tokens.length === 0) {
4659
- consola7.error(
4808
+ consola8.error(
4660
4809
  "No ports given. Usage: `monoceros add-port <containername> [--yes] [--default] -- <port> [<port> \u2026]`."
4661
4810
  );
4662
4811
  process.exit(1);
@@ -4670,7 +4819,7 @@ var init_add_port = __esm({
4670
4819
  });
4671
4820
  process.exit(result.status === "aborted" ? 1 : 0);
4672
4821
  } catch (err) {
4673
- consola7.error(err instanceof Error ? err.message : String(err));
4822
+ consola8.error(err instanceof Error ? err.message : String(err));
4674
4823
  process.exit(1);
4675
4824
  }
4676
4825
  }
@@ -4680,7 +4829,7 @@ var init_add_port = __esm({
4680
4829
 
4681
4830
  // src/commands/add-service.ts
4682
4831
  import { defineCommand as defineCommand7 } from "citty";
4683
- import { consola as consola8 } from "consola";
4832
+ import { consola as consola9 } from "consola";
4684
4833
  var addServiceCommand;
4685
4834
  var init_add_service = __esm({
4686
4835
  "src/commands/add-service.ts"() {
@@ -4724,7 +4873,7 @@ var init_add_service = __esm({
4724
4873
  });
4725
4874
  process.exit(result.status === "aborted" ? 1 : 0);
4726
4875
  } catch (err) {
4727
- consola8.error(err instanceof Error ? err.message : String(err));
4876
+ consola9.error(err instanceof Error ? err.message : String(err));
4728
4877
  process.exit(1);
4729
4878
  }
4730
4879
  }
@@ -4734,7 +4883,7 @@ var init_add_service = __esm({
4734
4883
 
4735
4884
  // src/config/state.ts
4736
4885
  import { promises as fs9 } from "fs";
4737
- import path11 from "path";
4886
+ import path12 from "path";
4738
4887
  function buildStateFile(opts) {
4739
4888
  return {
4740
4889
  schemaVersion: CONFIG_SCHEMA_VERSION,
@@ -4745,7 +4894,7 @@ function buildStateFile(opts) {
4745
4894
  };
4746
4895
  }
4747
4896
  function stateFilePath(targetDir) {
4748
- return path11.join(targetDir, ".monoceros", "state.json");
4897
+ return path12.join(targetDir, ".monoceros", "state.json");
4749
4898
  }
4750
4899
  async function readStateFile(targetDir) {
4751
4900
  try {
@@ -4756,7 +4905,7 @@ async function readStateFile(targetDir) {
4756
4905
  }
4757
4906
  }
4758
4907
  async function writeStateFile(targetDir, state) {
4759
- const monocerosDir = path11.join(targetDir, ".monoceros");
4908
+ const monocerosDir = path12.join(targetDir, ".monoceros");
4760
4909
  await fs9.mkdir(monocerosDir, { recursive: true });
4761
4910
  await fs9.writeFile(
4762
4911
  stateFilePath(targetDir),
@@ -4868,7 +5017,7 @@ var init_transform = __esm({
4868
5017
 
4869
5018
  // src/apply/apply-log.ts
4870
5019
  import { createWriteStream, mkdirSync } from "fs";
4871
- import path12 from "path";
5020
+ import path13 from "path";
4872
5021
  import { Writable } from "stream";
4873
5022
  function safeIsoStamp(d) {
4874
5023
  return d.toISOString().replace(/[:.]/g, "-");
@@ -4878,7 +5027,7 @@ function createApplyLog(opts) {
4878
5027
  const dir = containerLogsDir(opts.name, opts.home);
4879
5028
  mkdirSync(dir, { recursive: true });
4880
5029
  const file = `apply-${opts.name}-${safeIsoStamp(now)}.log`;
4881
- const fullPath = path12.join(dir, file);
5030
+ const fullPath = path13.join(dir, file);
4882
5031
  const stream = createWriteStream(fullPath, { flags: "w" });
4883
5032
  const header = [
4884
5033
  `# monoceros apply log`,
@@ -5364,11 +5513,17 @@ function generateAgentsMd(input) {
5364
5513
  " repo already listed above), add it to the VS Code multi-root workspace so",
5365
5514
  ` it shows up in the Explorer. Open \`/workspaces/${input.containerName}/${input.containerName}.code-workspace\``,
5366
5515
  " and append an entry to the `folders` array, for example",
5367
- ' `{ "path": "projects/<app>", "name": "<app>" }`. Cloned repos are added',
5368
- " there automatically by the apply; projects you create yourself are not, so",
5369
- " without this step VS Code (opened on the host from the workspace file) would",
5370
- " not list them. Hand-added folder entries survive `monoceros apply`: the",
5371
- " apply merges into the file, it does not overwrite your edits.",
5516
+ ' `{ "path": "projects/<app>", "name": "<app>" }`.',
5517
+ " Add **exactly one** folder entry per directory directly under `projects/`:",
5518
+ " the top-level project directory itself, even when it contains several",
5519
+ " sub-projects (e.g. a `backend/` and a `frontend/`, or a multi-module",
5520
+ " layout). Do **not** register those sub-directories as separate roots \u2014 one",
5521
+ " root per top-level project keeps the Explorer readable as more projects",
5522
+ " land in the container. Cloned repos are added there automatically by the",
5523
+ " apply; projects you create yourself are not, so without this step VS Code",
5524
+ " (opened on the host from the workspace file) would not list them.",
5525
+ " Hand-added folder entries survive `monoceros apply`: the apply merges into",
5526
+ " the file, it does not overwrite your edits.",
5372
5527
  "- You run as the `node` user. `sudo` is available but its effects do",
5373
5528
  " not persist across rebuilds.",
5374
5529
  "- A bare `EXPOSE` directive has no effect on host reachability. Ports",
@@ -5739,7 +5894,7 @@ var init_markers = __esm({
5739
5894
 
5740
5895
  // src/briefing/index.ts
5741
5896
  import { promises as fs10 } from "fs";
5742
- import path13 from "path";
5897
+ import path14 from "path";
5743
5898
  async function writeBriefing(input) {
5744
5899
  const subCommands = input.subCommands ?? await loadSubCommandsDynamic();
5745
5900
  const manifestLoader = input.manifestLoader ?? ((ref) => loadFeatureManifestSummary(ref));
@@ -5752,12 +5907,12 @@ async function writeBriefing(input) {
5752
5907
  );
5753
5908
  const claudeBody = generateClaudeMd();
5754
5909
  const commandsBody = generateCommandsMd(subCommands);
5755
- await writeMarkerAware(path13.join(input.targetDir, "AGENTS.md"), agentsBody);
5756
- await writeMarkerAware(path13.join(input.targetDir, "CLAUDE.md"), claudeBody);
5757
- const monocerosDir = path13.join(input.targetDir, ".monoceros");
5910
+ await writeMarkerAware(path14.join(input.targetDir, "AGENTS.md"), agentsBody);
5911
+ await writeMarkerAware(path14.join(input.targetDir, "CLAUDE.md"), claudeBody);
5912
+ const monocerosDir = path14.join(input.targetDir, ".monoceros");
5758
5913
  await fs10.mkdir(monocerosDir, { recursive: true });
5759
5914
  await fs10.writeFile(
5760
- path13.join(monocerosDir, "commands.md"),
5915
+ path14.join(monocerosDir, "commands.md"),
5761
5916
  commandsBody,
5762
5917
  "utf8"
5763
5918
  );
@@ -5916,7 +6071,7 @@ var init_runtime_pull_hint = __esm({
5916
6071
  import { spawn as spawn4 } from "child_process";
5917
6072
  import { readFileSync as readFileSync4 } from "fs";
5918
6073
  import { createRequire } from "module";
5919
- import path14 from "path";
6074
+ import path15 from "path";
5920
6075
  function devcontainerCliPath() {
5921
6076
  if (cachedBinaryPath) return cachedBinaryPath;
5922
6077
  const pkgJsonPath = require_.resolve("@devcontainers/cli/package.json");
@@ -5925,7 +6080,7 @@ function devcontainerCliPath() {
5925
6080
  if (!binEntry) {
5926
6081
  throw new Error("Could not resolve @devcontainers/cli bin entry.");
5927
6082
  }
5928
- cachedBinaryPath = path14.resolve(path14.dirname(pkgJsonPath), binEntry);
6083
+ cachedBinaryPath = path15.resolve(path15.dirname(pkgJsonPath), binEntry);
5929
6084
  return cachedBinaryPath;
5930
6085
  }
5931
6086
  var require_, cachedBinaryPath, spawnDevcontainer;
@@ -5999,10 +6154,10 @@ var init_cli = __esm({
5999
6154
 
6000
6155
  // src/devcontainer/compose.ts
6001
6156
  import { spawn as spawn5 } from "child_process";
6002
- import { existsSync as existsSync7 } from "fs";
6003
- import path15 from "path";
6157
+ import { existsSync as existsSync8 } from "fs";
6158
+ import path16 from "path";
6004
6159
  import { Writable as Writable3 } from "stream";
6005
- import { consola as consola9 } from "consola";
6160
+ import { consola as consola10 } from "consola";
6006
6161
  async function findContainerIds(filters, exec = spawnDocker) {
6007
6162
  const ids = /* @__PURE__ */ new Set();
6008
6163
  for (const filter of filters) {
@@ -6050,16 +6205,16 @@ async function cleanupDockerObjects(opts) {
6050
6205
  return { exitCode: rmExit, removedIds: ids };
6051
6206
  }
6052
6207
  function composeProjectName(root) {
6053
- return `${path15.basename(root)}_devcontainer`;
6208
+ return `${path16.basename(root)}_devcontainer`;
6054
6209
  }
6055
6210
  function resolveCompose(root) {
6056
- if (!existsSync7(path15.join(root, ".devcontainer"))) {
6211
+ if (!existsSync8(path16.join(root, ".devcontainer"))) {
6057
6212
  throw new Error(
6058
6213
  `No .devcontainer/ at ${root}. Run \`monoceros apply <name>\` first.`
6059
6214
  );
6060
6215
  }
6061
- const composeFile = path15.join(root, ".devcontainer", "compose.yaml");
6062
- if (!existsSync7(composeFile)) {
6216
+ const composeFile = path16.join(root, ".devcontainer", "compose.yaml");
6217
+ if (!existsSync8(composeFile)) {
6063
6218
  throw new Error(
6064
6219
  `No compose.yaml at ${composeFile}. \`start\` / \`stop\` / \`status\` / \`logs\` require services configured via \`monoceros add-service <name> <svc>\`. Use \`monoceros shell <name>\` to enter the container directly.`
6065
6220
  );
@@ -6074,7 +6229,7 @@ async function runComposeAction(buildSubArgs, opts) {
6074
6229
  }
6075
6230
  async function runStart(opts) {
6076
6231
  resolveCompose(opts.root);
6077
- const logger = opts.logger ?? { info: (msg) => consola9.info(msg) };
6232
+ const logger = opts.logger ?? { info: (msg) => consola10.info(msg) };
6078
6233
  const spawnFn = opts.spawn ?? spawnDevcontainer;
6079
6234
  logger.info(`Bringing devcontainer up at ${opts.root}\u2026`);
6080
6235
  return spawnFn(
@@ -6320,14 +6475,14 @@ var init_images = __esm({
6320
6475
  });
6321
6476
 
6322
6477
  // src/config/machine-state.ts
6323
- import { promises as fsp3 } from "fs";
6324
- import path16 from "path";
6478
+ import { promises as fsp4 } from "fs";
6479
+ import path17 from "path";
6325
6480
  function machineStatePath(home = monocerosHome()) {
6326
- return path16.join(home, ".machine-state.json");
6481
+ return path17.join(home, ".machine-state.json");
6327
6482
  }
6328
6483
  async function readMachineState(home = monocerosHome()) {
6329
6484
  try {
6330
- const raw = await fsp3.readFile(machineStatePath(home), "utf8");
6485
+ const raw = await fsp4.readFile(machineStatePath(home), "utf8");
6331
6486
  const parsed = JSON.parse(raw);
6332
6487
  if (typeof parsed === "object" && parsed !== null) {
6333
6488
  return parsed;
@@ -6337,7 +6492,7 @@ async function readMachineState(home = monocerosHome()) {
6337
6492
  return {};
6338
6493
  }
6339
6494
  async function writeMachineState(state, home = monocerosHome()) {
6340
- await fsp3.writeFile(
6495
+ await fsp4.writeFile(
6341
6496
  machineStatePath(home),
6342
6497
  `${JSON.stringify(state, null, 2)}
6343
6498
  `
@@ -6449,8 +6604,8 @@ var init_docker_mode = __esm({
6449
6604
  // src/devcontainer/identity.ts
6450
6605
  import { spawn as spawn7 } from "child_process";
6451
6606
  import { promises as fs11 } from "fs";
6452
- import path17 from "path";
6453
- import { consola as consola10 } from "consola";
6607
+ import path18 from "path";
6608
+ import { consola as consola11 } from "consola";
6454
6609
  async function resolveIdentityWithPrompt(options = {}) {
6455
6610
  const spawnFn = options.spawn ?? realGitConfigGet;
6456
6611
  const promptFn = options.prompt ?? realIdentityPrompt;
@@ -6505,8 +6660,8 @@ async function resolveIdentityWithPrompt(options = {}) {
6505
6660
  };
6506
6661
  }
6507
6662
  async function collectGitIdentity(devContainerRoot, options = {}) {
6508
- const gitconfigDir = path17.join(devContainerRoot, ".monoceros");
6509
- const gitconfigPath = path17.join(gitconfigDir, "gitconfig");
6663
+ const gitconfigDir = path18.join(devContainerRoot, ".monoceros");
6664
+ const gitconfigPath = path18.join(gitconfigDir, "gitconfig");
6510
6665
  const logger = options.logger ?? { info: () => {
6511
6666
  }, warn: () => {
6512
6667
  } };
@@ -6599,7 +6754,7 @@ var init_identity = __esm({
6599
6754
  return void 0;
6600
6755
  }
6601
6756
  const label = key === "user.name" ? "Git user.name for this dev container (full name)" : "Git user.email for this dev container";
6602
- const value = await consola10.prompt(`${label}:`, { type: "text" });
6757
+ const value = await consola11.prompt(`${label}:`, { type: "text" });
6603
6758
  if (typeof value !== "string") return void 0;
6604
6759
  const trimmed = value.trim();
6605
6760
  return trimmed.length > 0 ? trimmed : void 0;
@@ -6609,7 +6764,7 @@ var init_identity = __esm({
6609
6764
  return ctx.reason === "prompt" ? "g" : "n";
6610
6765
  }
6611
6766
  const heading = ctx.reason === "persisted" ? `Found identity in .monoceros/gitconfig: ${ctx.name} <${ctx.email}>. Promote where?` : "Save this identity where?";
6612
- const choice = await consola10.prompt(heading, {
6767
+ const choice = await consola11.prompt(heading, {
6613
6768
  type: "select",
6614
6769
  options: [
6615
6770
  {
@@ -6640,14 +6795,14 @@ var init_identity = __esm({
6640
6795
  });
6641
6796
 
6642
6797
  // src/apply/index.ts
6643
- import { existsSync as existsSync8, promises as fs12 } from "fs";
6644
- import { consola as consola11 } from "consola";
6798
+ import { existsSync as existsSync9, promises as fs12 } from "fs";
6799
+ import { consola as consola12 } from "consola";
6645
6800
  async function runApply(opts) {
6646
6801
  const home = opts.monocerosHome ?? monocerosHome();
6647
6802
  const logger = opts.logger ?? {
6648
- info: (msg) => consola11.info(msg),
6649
- success: (msg) => consola11.success(msg),
6650
- warn: (msg) => consola11.warn(msg),
6803
+ info: (msg) => consola12.info(msg),
6804
+ success: (msg) => consola12.success(msg),
6805
+ warn: (msg) => consola12.warn(msg),
6651
6806
  // Default section renderer: empty line, bold-underlined "▸ Label",
6652
6807
  // empty line. Mirrors install.sh's section visuals.
6653
6808
  section: (label) => process.stderr.write(`
@@ -6662,7 +6817,7 @@ ${sectionLine(label)}
6662
6817
  );
6663
6818
  }
6664
6819
  const ymlPath = containerConfigPath(opts.name, home);
6665
- if (!existsSync8(ymlPath)) {
6820
+ if (!existsSync9(ymlPath)) {
6666
6821
  throw new Error(
6667
6822
  `No such config: ${ymlPath}. Run \`monoceros init <template> ${opts.name}\` first.`
6668
6823
  );
@@ -6935,7 +7090,7 @@ ${stripAnsi(formatted)}
6935
7090
  return { targetDir, configPath: ymlPath, containerExitCode: exitCode };
6936
7091
  }
6937
7092
  async function assertSafeTargetDir(targetDir, expectedOrigin) {
6938
- if (!existsSync8(targetDir)) return;
7093
+ if (!existsSync9(targetDir)) return;
6939
7094
  const entries = await fs12.readdir(targetDir);
6940
7095
  if (entries.length === 0) return;
6941
7096
  const state = await readStateFile(targetDir);
@@ -7065,18 +7220,18 @@ var CLI_VERSION;
7065
7220
  var init_version = __esm({
7066
7221
  "src/version.ts"() {
7067
7222
  "use strict";
7068
- CLI_VERSION = true ? "1.22.1" : "dev";
7223
+ CLI_VERSION = true ? "1.23.0" : "dev";
7069
7224
  }
7070
7225
  });
7071
7226
 
7072
7227
  // src/commands/_dispatch.ts
7073
- import { consola as consola12 } from "consola";
7228
+ import { consola as consola13 } from "consola";
7074
7229
  async function dispatch(runner) {
7075
7230
  try {
7076
7231
  const exitCode = await runner();
7077
7232
  process.exit(exitCode);
7078
7233
  } catch (err) {
7079
- consola12.error(err instanceof Error ? err.message : String(err));
7234
+ consola13.error(err instanceof Error ? err.message : String(err));
7080
7235
  process.exit(1);
7081
7236
  }
7082
7237
  }
@@ -7255,8 +7410,8 @@ var init_completion = __esm({
7255
7410
  });
7256
7411
 
7257
7412
  // src/completion/resolve.ts
7258
- import { existsSync as existsSync9, promises as fs13 } from "fs";
7259
- import path18 from "path";
7413
+ import { existsSync as existsSync10, promises as fs13 } from "fs";
7414
+ import path19 from "path";
7260
7415
  async function resolveCompletions(line, point, opts = {}) {
7261
7416
  const { prev, current } = parseCompletionLine(line, point);
7262
7417
  const ctx = { prev, current, opts };
@@ -7405,8 +7560,8 @@ function filterPrefix(values, fragment) {
7405
7560
  }
7406
7561
  async function listContainerNames(ctx) {
7407
7562
  const home = ctx.opts.monocerosHome ?? monocerosHome();
7408
- const dir = path18.join(home, "container-configs");
7409
- if (!existsSync9(dir)) return [];
7563
+ const dir = path19.join(home, "container-configs");
7564
+ if (!existsSync10(dir)) return [];
7410
7565
  const entries = await fs13.readdir(dir);
7411
7566
  return entries.filter((e) => e.endsWith(".yml")).map((e) => e.slice(0, -".yml".length)).sort();
7412
7567
  }
@@ -8074,14 +8229,14 @@ var init_generator = __esm({
8074
8229
  });
8075
8230
 
8076
8231
  // src/init/index.ts
8077
- import { existsSync as existsSync10, promises as fs14 } from "fs";
8078
- import path19 from "path";
8079
- import { consola as consola13 } from "consola";
8232
+ import { existsSync as existsSync11, promises as fs14 } from "fs";
8233
+ import path20 from "path";
8234
+ import { consola as consola14 } from "consola";
8080
8235
  async function runInit(opts) {
8081
8236
  const home = opts.monocerosHome ?? monocerosHome();
8082
8237
  const logger = opts.logger ?? {
8083
- success: (msg) => consola13.success(msg),
8084
- info: (msg) => consola13.info(msg)
8238
+ success: (msg) => consola14.success(msg),
8239
+ info: (msg) => consola14.info(msg)
8085
8240
  };
8086
8241
  if (!REGEX.solutionName.test(opts.name)) {
8087
8242
  throw new Error(
@@ -8089,12 +8244,12 @@ async function runInit(opts) {
8089
8244
  );
8090
8245
  }
8091
8246
  const dest = containerConfigPath(opts.name, home);
8092
- if (existsSync10(dest)) {
8247
+ if (existsSync11(dest)) {
8093
8248
  throw new Error(
8094
8249
  `Config already exists: ${dest}. Delete it manually before re-running \`monoceros init\` \u2014 this protects any hand-edits.`
8095
8250
  );
8096
8251
  }
8097
- const componentsRoot = opts.workbenchRoot ? path19.join(opts.workbenchRoot, "components") : componentsRootDir();
8252
+ const componentsRoot = opts.workbenchRoot ? path20.join(opts.workbenchRoot, "components") : componentsRootDir();
8098
8253
  const catalog = await loadComponentCatalog(componentsRoot);
8099
8254
  if (catalog.size === 0) {
8100
8255
  throw new Error(
@@ -8185,8 +8340,8 @@ async function runInit(opts) {
8185
8340
  }
8186
8341
  await ensureEnvVars(envPath, opts.name, seedVars);
8187
8342
  const documented = !anyComposed;
8188
- const ymlRel = path19.relative(home, dest);
8189
- const envRel = path19.relative(home, envPath);
8343
+ const ymlRel = path20.relative(home, dest);
8344
+ const envRel = path20.relative(home, envPath);
8190
8345
  if (documented) {
8191
8346
  logger.success(`Wrote documented default to ${ymlRel} and ${envRel}.`);
8192
8347
  logger.info(
@@ -8330,7 +8485,7 @@ var init_init = __esm({
8330
8485
 
8331
8486
  // src/commands/init.ts
8332
8487
  import { defineCommand as defineCommand11 } from "citty";
8333
- import { consola as consola14 } from "consola";
8488
+ import { consola as consola15 } from "consola";
8334
8489
  function collectListFlag(flag, rawArgs) {
8335
8490
  const eq = `${flag}=`;
8336
8491
  const pieces = [];
@@ -8456,7 +8611,7 @@ var init_init2 = __esm({
8456
8611
  ...ports && ports.length > 0 ? { withPorts: ports } : {}
8457
8612
  });
8458
8613
  } catch (err) {
8459
- consola14.error(err instanceof Error ? err.message : String(err));
8614
+ consola15.error(err instanceof Error ? err.message : String(err));
8460
8615
  process.exit(1);
8461
8616
  }
8462
8617
  }
@@ -8505,7 +8660,7 @@ var init_expand = __esm({
8505
8660
 
8506
8661
  // src/commands/list-components.ts
8507
8662
  import { defineCommand as defineCommand12 } from "citty";
8508
- import { consola as consola15 } from "consola";
8663
+ import { consola as consola16 } from "consola";
8509
8664
  var CATEGORY_LABELS, CATEGORY_ORDER, listComponentsCommand;
8510
8665
  var init_list_components = __esm({
8511
8666
  "src/commands/list-components.ts"() {
@@ -8534,7 +8689,7 @@ var init_list_components = __esm({
8534
8689
  try {
8535
8690
  const catalog = expandSelectable(await loadDescriptorCatalog());
8536
8691
  if (catalog.size === 0) {
8537
- consola15.warn(
8692
+ consola16.warn(
8538
8693
  "No components found. The workbench checkout looks incomplete."
8539
8694
  );
8540
8695
  process.exit(0);
@@ -8585,7 +8740,7 @@ var init_list_components = __esm({
8585
8740
  }
8586
8741
  process.exit(0);
8587
8742
  } catch (err) {
8588
- consola15.error(err instanceof Error ? err.message : String(err));
8743
+ consola16.error(err instanceof Error ? err.message : String(err));
8589
8744
  process.exit(1);
8590
8745
  }
8591
8746
  }
@@ -8595,8 +8750,8 @@ var init_list_components = __esm({
8595
8750
 
8596
8751
  // src/commands/logs.ts
8597
8752
  import { spawn as spawn8 } from "child_process";
8598
- import { existsSync as existsSync11 } from "fs";
8599
- import path20 from "path";
8753
+ import { existsSync as existsSync12 } from "fs";
8754
+ import path21 from "path";
8600
8755
  import { defineCommand as defineCommand13 } from "citty";
8601
8756
  function tailLogFile(file, follow) {
8602
8757
  const [cmd, args] = follow ? ["tail", ["-F", file]] : ["cat", [file]];
@@ -8639,8 +8794,8 @@ var init_logs = __esm({
8639
8794
  run({ args }) {
8640
8795
  const service = typeof args.service === "string" ? args.service : void 0;
8641
8796
  if (service) {
8642
- const logFile = path20.join(containerLogsDir(args.name), `${service}.log`);
8643
- if (existsSync11(logFile)) {
8797
+ const logFile = path21.join(containerLogsDir(args.name), `${service}.log`);
8798
+ if (existsSync12(logFile)) {
8644
8799
  return dispatch(() => tailLogFile(logFile, args.follow));
8645
8800
  }
8646
8801
  }
@@ -8658,10 +8813,10 @@ var init_logs = __esm({
8658
8813
 
8659
8814
  // src/commands/port.ts
8660
8815
  import { defineCommand as defineCommand14 } from "citty";
8661
- import { consola as consola16 } from "consola";
8816
+ import { consola as consola17 } from "consola";
8662
8817
  async function runPortListing(opts) {
8663
8818
  const out = opts.out ?? process.stdout;
8664
- const info = opts.info ?? ((m) => consola16.info(m));
8819
+ const info = opts.info ?? ((m) => consola17.info(m));
8665
8820
  const parsed = await readConfig(
8666
8821
  containerConfigPath(opts.name, opts.monocerosHome)
8667
8822
  );
@@ -8737,7 +8892,7 @@ var init_port = __esm({
8737
8892
  const code = await runPortListing({ name: args.name });
8738
8893
  process.exit(code);
8739
8894
  } catch (err) {
8740
- consola16.error(err instanceof Error ? err.message : String(err));
8895
+ consola17.error(err instanceof Error ? err.message : String(err));
8741
8896
  process.exit(1);
8742
8897
  }
8743
8898
  }
@@ -8747,7 +8902,7 @@ var init_port = __esm({
8747
8902
 
8748
8903
  // src/commands/remove-apt-packages.ts
8749
8904
  import { defineCommand as defineCommand15 } from "citty";
8750
- import { consola as consola17 } from "consola";
8905
+ import { consola as consola18 } from "consola";
8751
8906
  var removeAptPackagesCommand;
8752
8907
  var init_remove_apt_packages = __esm({
8753
8908
  "src/commands/remove-apt-packages.ts"() {
@@ -8776,7 +8931,7 @@ var init_remove_apt_packages = __esm({
8776
8931
  async run({ args }) {
8777
8932
  const packages = [...getInnerArgs()];
8778
8933
  if (packages.length === 0) {
8779
- consola17.error(
8934
+ consola18.error(
8780
8935
  "No package names given. Usage: `monoceros remove-apt-packages <containername> [--yes] -- <pkg> [<pkg> \u2026]`."
8781
8936
  );
8782
8937
  process.exit(1);
@@ -8789,7 +8944,7 @@ var init_remove_apt_packages = __esm({
8789
8944
  });
8790
8945
  process.exit(result.status === "aborted" ? 1 : 0);
8791
8946
  } catch (err) {
8792
- consola17.error(err instanceof Error ? err.message : String(err));
8947
+ consola18.error(err instanceof Error ? err.message : String(err));
8793
8948
  process.exit(1);
8794
8949
  }
8795
8950
  }
@@ -8799,7 +8954,7 @@ var init_remove_apt_packages = __esm({
8799
8954
 
8800
8955
  // src/commands/remove-feature.ts
8801
8956
  import { defineCommand as defineCommand16 } from "citty";
8802
- import { consola as consola18 } from "consola";
8957
+ import { consola as consola19 } from "consola";
8803
8958
  var removeFeatureCommand;
8804
8959
  var init_remove_feature = __esm({
8805
8960
  "src/commands/remove-feature.ts"() {
@@ -8838,7 +8993,7 @@ var init_remove_feature = __esm({
8838
8993
  });
8839
8994
  process.exit(result.status === "aborted" ? 1 : 0);
8840
8995
  } catch (err) {
8841
- consola18.error(err instanceof Error ? err.message : String(err));
8996
+ consola19.error(err instanceof Error ? err.message : String(err));
8842
8997
  process.exit(1);
8843
8998
  }
8844
8999
  }
@@ -8847,15 +9002,15 @@ var init_remove_feature = __esm({
8847
9002
  });
8848
9003
 
8849
9004
  // src/remove/index.ts
8850
- import { existsSync as existsSync12, promises as fs15 } from "fs";
8851
- import path21 from "path";
8852
- import { consola as consola19 } from "consola";
9005
+ import { existsSync as existsSync13, promises as fs15 } from "fs";
9006
+ import path22 from "path";
9007
+ import { consola as consola20 } from "consola";
8853
9008
  async function runRemove(opts) {
8854
9009
  const home = opts.monocerosHome ?? monocerosHome();
8855
9010
  const logger = opts.logger ?? {
8856
- info: (msg) => consola19.info(msg),
8857
- success: (msg) => consola19.success(msg),
8858
- warn: (msg) => consola19.warn(msg)
9011
+ info: (msg) => consola20.info(msg),
9012
+ success: (msg) => consola20.success(msg),
9013
+ warn: (msg) => consola20.warn(msg)
8859
9014
  };
8860
9015
  if (!REGEX.solutionName.test(opts.name)) {
8861
9016
  throw new Error(
@@ -8865,9 +9020,9 @@ async function runRemove(opts) {
8865
9020
  const ymlPath = containerConfigPath(opts.name, home);
8866
9021
  const envPath = containerEnvPath(opts.name, home);
8867
9022
  const containerPath = containerDir(opts.name, home);
8868
- const hasYml = existsSync12(ymlPath);
8869
- const hasEnv = existsSync12(envPath);
8870
- const hasContainer = existsSync12(containerPath);
9023
+ const hasYml = existsSync13(ymlPath);
9024
+ const hasEnv = existsSync13(envPath);
9025
+ const hasContainer = existsSync13(containerPath);
8871
9026
  if (!hasYml && !hasContainer) {
8872
9027
  throw new Error(
8873
9028
  `Nothing to remove for '${opts.name}': neither ${ymlPath} nor ${containerPath} exists.`
@@ -8893,16 +9048,16 @@ async function runRemove(opts) {
8893
9048
  let backupPath = null;
8894
9049
  if (!opts.noBackup && (hasYml || hasContainer)) {
8895
9050
  const ts = (opts.now ?? /* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
8896
- backupPath = path21.join(home, "container-backups", `${opts.name}-${ts}`);
9051
+ backupPath = path22.join(home, "container-backups", `${opts.name}-${ts}`);
8897
9052
  await fs15.mkdir(backupPath, { recursive: true });
8898
9053
  if (hasYml) {
8899
- await fs15.copyFile(ymlPath, path21.join(backupPath, `${opts.name}.yml`));
9054
+ await fs15.copyFile(ymlPath, path22.join(backupPath, `${opts.name}.yml`));
8900
9055
  }
8901
9056
  if (hasEnv) {
8902
- await fs15.copyFile(envPath, path21.join(backupPath, `${opts.name}.env`));
9057
+ await fs15.copyFile(envPath, path22.join(backupPath, `${opts.name}.env`));
8903
9058
  }
8904
9059
  if (hasContainer) {
8905
- await fs15.cp(containerPath, path21.join(backupPath, "container"), {
9060
+ await fs15.cp(containerPath, path22.join(backupPath, "container"), {
8906
9061
  recursive: true
8907
9062
  });
8908
9063
  }
@@ -8992,7 +9147,7 @@ var init_remove = __esm({
8992
9147
 
8993
9148
  // src/commands/remove.ts
8994
9149
  import { defineCommand as defineCommand17 } from "citty";
8995
- import { consola as consola20 } from "consola";
9150
+ import { consola as consola21 } from "consola";
8996
9151
  import { createInterface } from "readline/promises";
8997
9152
  var removeCommand;
8998
9153
  var init_remove2 = __esm({
@@ -9036,7 +9191,7 @@ var init_remove2 = __esm({
9036
9191
  const skipPrompt = args.yes === true;
9037
9192
  if (!skipPrompt) {
9038
9193
  const warning = noBackup ? `About to remove '${args.name}' WITHOUT a backup. Docker objects, container-configs entry, and container directory will all be deleted.` : `About to remove '${args.name}'. A backup will be written to container-backups/ first, then docker objects, container-configs entry, and container directory will all be deleted.`;
9039
- consola20.warn(warning);
9194
+ consola21.warn(warning);
9040
9195
  const rl = createInterface({
9041
9196
  input: process.stdin,
9042
9197
  output: process.stdout
@@ -9044,7 +9199,7 @@ var init_remove2 = __esm({
9044
9199
  const answer = await rl.question("Continue? [y/N] ");
9045
9200
  rl.close();
9046
9201
  if (!/^y(es)?$/i.test(answer.trim())) {
9047
- consola20.info("Aborted. Nothing changed.");
9202
+ consola21.info("Aborted. Nothing changed.");
9048
9203
  process.exit(0);
9049
9204
  }
9050
9205
  }
@@ -9053,7 +9208,7 @@ var init_remove2 = __esm({
9053
9208
  ...noBackup ? { noBackup: true } : {}
9054
9209
  });
9055
9210
  } catch (err) {
9056
- consola20.error(err instanceof Error ? err.message : String(err));
9211
+ consola21.error(err instanceof Error ? err.message : String(err));
9057
9212
  process.exit(1);
9058
9213
  }
9059
9214
  }
@@ -9062,17 +9217,17 @@ var init_remove2 = __esm({
9062
9217
  });
9063
9218
 
9064
9219
  // src/restore/index.ts
9065
- import { existsSync as existsSync13, promises as fs16 } from "fs";
9066
- import path22 from "path";
9067
- import { consola as consola21 } from "consola";
9220
+ import { existsSync as existsSync14, promises as fs16 } from "fs";
9221
+ import path23 from "path";
9222
+ import { consola as consola22 } from "consola";
9068
9223
  async function runRestore(opts) {
9069
9224
  const home = opts.monocerosHome ?? monocerosHome();
9070
9225
  const logger = opts.logger ?? {
9071
- info: (msg) => consola21.info(msg),
9072
- success: (msg) => consola21.success(msg)
9226
+ info: (msg) => consola22.info(msg),
9227
+ success: (msg) => consola22.success(msg)
9073
9228
  };
9074
- const backup = path22.resolve(opts.backupPath);
9075
- if (!existsSync13(backup)) {
9229
+ const backup = path23.resolve(opts.backupPath);
9230
+ if (!existsSync14(backup)) {
9076
9231
  throw new Error(`Backup not found: ${backup}.`);
9077
9232
  }
9078
9233
  const stat = await fs16.stat(backup);
@@ -9093,24 +9248,24 @@ async function runRestore(opts) {
9093
9248
  }
9094
9249
  const ymlFile = ymlFiles[0];
9095
9250
  const name = ymlFile.replace(/\.yml$/, "");
9096
- const containerInBackup = path22.join(backup, "container");
9097
- const hasContainer = existsSync13(containerInBackup);
9098
- const envInBackup = path22.join(backup, `${name}.env`);
9099
- const hasEnv = existsSync13(envInBackup);
9251
+ const containerInBackup = path23.join(backup, "container");
9252
+ const hasContainer = existsSync14(containerInBackup);
9253
+ const envInBackup = path23.join(backup, `${name}.env`);
9254
+ const hasEnv = existsSync14(envInBackup);
9100
9255
  const destYml = containerConfigPath(name, home);
9101
9256
  const destContainer = containerDir(name, home);
9102
- if (existsSync13(destYml)) {
9257
+ if (existsSync14(destYml)) {
9103
9258
  throw new Error(
9104
9259
  `Refusing to restore: ${destYml} already exists. Remove the current container first (\`monoceros remove ${name}\`) or rename the existing config.`
9105
9260
  );
9106
9261
  }
9107
- if (hasContainer && existsSync13(destContainer)) {
9262
+ if (hasContainer && existsSync14(destContainer)) {
9108
9263
  throw new Error(
9109
9264
  `Refusing to restore: ${destContainer} already exists. Remove the current container first (\`monoceros remove ${name}\`).`
9110
9265
  );
9111
9266
  }
9112
9267
  await fs16.mkdir(containerConfigsDir(home), { recursive: true });
9113
- await fs16.copyFile(path22.join(backup, ymlFile), destYml);
9268
+ await fs16.copyFile(path23.join(backup, ymlFile), destYml);
9114
9269
  if (hasEnv) {
9115
9270
  await fs16.copyFile(envInBackup, containerEnvPath(name, home));
9116
9271
  }
@@ -9136,7 +9291,7 @@ var init_restore = __esm({
9136
9291
 
9137
9292
  // src/commands/restore.ts
9138
9293
  import { defineCommand as defineCommand18 } from "citty";
9139
- import { consola as consola22 } from "consola";
9294
+ import { consola as consola23 } from "consola";
9140
9295
  var restoreCommand;
9141
9296
  var init_restore2 = __esm({
9142
9297
  "src/commands/restore.ts"() {
@@ -9159,7 +9314,7 @@ var init_restore2 = __esm({
9159
9314
  try {
9160
9315
  await runRestore({ backupPath: args["backup-path"] });
9161
9316
  } catch (err) {
9162
- consola22.error(err instanceof Error ? err.message : String(err));
9317
+ consola23.error(err instanceof Error ? err.message : String(err));
9163
9318
  process.exit(1);
9164
9319
  }
9165
9320
  }
@@ -9169,7 +9324,7 @@ var init_restore2 = __esm({
9169
9324
 
9170
9325
  // src/commands/remove-from-url.ts
9171
9326
  import { defineCommand as defineCommand19 } from "citty";
9172
- import { consola as consola23 } from "consola";
9327
+ import { consola as consola24 } from "consola";
9173
9328
  var removeFromUrlCommand;
9174
9329
  var init_remove_from_url = __esm({
9175
9330
  "src/commands/remove-from-url.ts"() {
@@ -9208,7 +9363,7 @@ var init_remove_from_url = __esm({
9208
9363
  });
9209
9364
  process.exit(result.status === "aborted" ? 1 : 0);
9210
9365
  } catch (err) {
9211
- consola23.error(err instanceof Error ? err.message : String(err));
9366
+ consola24.error(err instanceof Error ? err.message : String(err));
9212
9367
  process.exit(1);
9213
9368
  }
9214
9369
  }
@@ -9218,7 +9373,7 @@ var init_remove_from_url = __esm({
9218
9373
 
9219
9374
  // src/commands/remove-language.ts
9220
9375
  import { defineCommand as defineCommand20 } from "citty";
9221
- import { consola as consola24 } from "consola";
9376
+ import { consola as consola25 } from "consola";
9222
9377
  var removeLanguageCommand;
9223
9378
  var init_remove_language = __esm({
9224
9379
  "src/commands/remove-language.ts"() {
@@ -9257,7 +9412,7 @@ var init_remove_language = __esm({
9257
9412
  });
9258
9413
  process.exit(result.status === "aborted" ? 1 : 0);
9259
9414
  } catch (err) {
9260
- consola24.error(err instanceof Error ? err.message : String(err));
9415
+ consola25.error(err instanceof Error ? err.message : String(err));
9261
9416
  process.exit(1);
9262
9417
  }
9263
9418
  }
@@ -9267,7 +9422,7 @@ var init_remove_language = __esm({
9267
9422
 
9268
9423
  // src/commands/remove-port.ts
9269
9424
  import { defineCommand as defineCommand21 } from "citty";
9270
- import { consola as consola25 } from "consola";
9425
+ import { consola as consola26 } from "consola";
9271
9426
  function coerceToken2(raw) {
9272
9427
  const n = Number(raw);
9273
9428
  return Number.isFinite(n) ? n : raw;
@@ -9300,7 +9455,7 @@ var init_remove_port = __esm({
9300
9455
  async run({ args }) {
9301
9456
  const tokens = [...getInnerArgs()];
9302
9457
  if (tokens.length === 0) {
9303
- consola25.error(
9458
+ consola26.error(
9304
9459
  "No ports given. Usage: `monoceros remove-port <containername> [--yes] -- <port> [<port> \u2026]`."
9305
9460
  );
9306
9461
  process.exit(1);
@@ -9313,7 +9468,7 @@ var init_remove_port = __esm({
9313
9468
  });
9314
9469
  process.exit(result.status === "aborted" ? 1 : 0);
9315
9470
  } catch (err) {
9316
- consola25.error(err instanceof Error ? err.message : String(err));
9471
+ consola26.error(err instanceof Error ? err.message : String(err));
9317
9472
  process.exit(1);
9318
9473
  }
9319
9474
  }
@@ -9323,7 +9478,7 @@ var init_remove_port = __esm({
9323
9478
 
9324
9479
  // src/commands/remove-repo.ts
9325
9480
  import { defineCommand as defineCommand22 } from "citty";
9326
- import { consola as consola26 } from "consola";
9481
+ import { consola as consola27 } from "consola";
9327
9482
  var removeRepoCommand;
9328
9483
  var init_remove_repo = __esm({
9329
9484
  "src/commands/remove-repo.ts"() {
@@ -9362,7 +9517,7 @@ var init_remove_repo = __esm({
9362
9517
  });
9363
9518
  process.exit(result.status === "aborted" ? 1 : 0);
9364
9519
  } catch (err) {
9365
- consola26.error(err instanceof Error ? err.message : String(err));
9520
+ consola27.error(err instanceof Error ? err.message : String(err));
9366
9521
  process.exit(1);
9367
9522
  }
9368
9523
  }
@@ -9372,7 +9527,7 @@ var init_remove_repo = __esm({
9372
9527
 
9373
9528
  // src/commands/remove-service.ts
9374
9529
  import { defineCommand as defineCommand23 } from "citty";
9375
- import { consola as consola27 } from "consola";
9530
+ import { consola as consola28 } from "consola";
9376
9531
  var removeServiceCommand;
9377
9532
  var init_remove_service = __esm({
9378
9533
  "src/commands/remove-service.ts"() {
@@ -9411,7 +9566,7 @@ var init_remove_service = __esm({
9411
9566
  });
9412
9567
  process.exit(result.status === "aborted" ? 1 : 0);
9413
9568
  } catch (err) {
9414
- consola27.error(err instanceof Error ? err.message : String(err));
9569
+ consola28.error(err instanceof Error ? err.message : String(err));
9415
9570
  process.exit(1);
9416
9571
  }
9417
9572
  }
@@ -9421,9 +9576,9 @@ var init_remove_service = __esm({
9421
9576
 
9422
9577
  // src/devcontainer/browser-bridge.ts
9423
9578
  import { spawn as spawn9 } from "child_process";
9424
- import { existsSync as existsSync14, promises as fsp4, readFileSync as readFileSync5 } from "fs";
9579
+ import { existsSync as existsSync15, promises as fsp5, readFileSync as readFileSync5 } from "fs";
9425
9580
  import http from "http";
9426
- import path23 from "path";
9581
+ import path24 from "path";
9427
9582
  function parseCallbackTarget(authUrl) {
9428
9583
  try {
9429
9584
  const u = new URL(authUrl);
@@ -9457,12 +9612,12 @@ function openInBrowser(url) {
9457
9612
  }
9458
9613
  }
9459
9614
  async function startBrowserBridge(opts) {
9460
- const relayDir = path23.join(opts.root, RELAY_DIRNAME);
9461
- const relayScript = path23.join(relayDir, "xdg-open");
9462
- const urlFile = path23.join(relayDir, "url");
9463
- await fsp4.mkdir(relayDir, { recursive: true });
9464
- await fsp4.rm(urlFile, { force: true });
9465
- await fsp4.writeFile(
9615
+ const relayDir = path24.join(opts.root, RELAY_DIRNAME);
9616
+ const relayScript = path24.join(relayDir, "xdg-open");
9617
+ const urlFile = path24.join(relayDir, "url");
9618
+ await fsp5.mkdir(relayDir, { recursive: true });
9619
+ await fsp5.rm(urlFile, { force: true });
9620
+ await fsp5.writeFile(
9466
9621
  relayScript,
9467
9622
  `#!/bin/sh
9468
9623
  printf '%s\\n' "$1" > "$(dirname "$0")/url"
@@ -9470,7 +9625,7 @@ exit 0
9470
9625
  `,
9471
9626
  { mode: 493 }
9472
9627
  );
9473
- await fsp4.chmod(relayScript, 493);
9628
+ await fsp5.chmod(relayScript, 493);
9474
9629
  const servers = [];
9475
9630
  let lastOpened = null;
9476
9631
  const onUrl = (url) => {
@@ -9503,7 +9658,7 @@ exit 0
9503
9658
  servers.push(server);
9504
9659
  };
9505
9660
  const poll = setInterval(() => {
9506
- if (!existsSync14(urlFile)) return;
9661
+ if (!existsSync15(urlFile)) return;
9507
9662
  let content = "";
9508
9663
  try {
9509
9664
  content = readFileSync5(urlFile, "utf8");
@@ -9520,7 +9675,7 @@ exit 0
9520
9675
  async dispose() {
9521
9676
  clearInterval(poll);
9522
9677
  for (const s of servers) s.close();
9523
- await fsp4.rm(relayDir, { recursive: true, force: true });
9678
+ await fsp5.rm(relayDir, { recursive: true, force: true });
9524
9679
  }
9525
9680
  };
9526
9681
  }
@@ -9533,18 +9688,18 @@ var init_browser_bridge = __esm({
9533
9688
  });
9534
9689
 
9535
9690
  // src/devcontainer/claude-trust.ts
9536
- import { existsSync as existsSync15, promises as fsp5 } from "fs";
9537
- import path24 from "path";
9691
+ import { existsSync as existsSync16, promises as fsp6 } from "fs";
9692
+ import path25 from "path";
9538
9693
  function resolveContainerCwd(name, cwd) {
9539
9694
  const workspace = `/workspaces/${name}`;
9540
9695
  if (!cwd) return workspace;
9541
- return path24.posix.isAbsolute(cwd) ? cwd : path24.posix.join(workspace, cwd);
9696
+ return path25.posix.isAbsolute(cwd) ? cwd : path25.posix.join(workspace, cwd);
9542
9697
  }
9543
9698
  async function preApproveClaudeProject(opts) {
9544
- const file = path24.join(opts.root, "home", ".claude.json");
9545
- if (!existsSync15(file)) return;
9699
+ const file = path25.join(opts.root, "home", ".claude.json");
9700
+ if (!existsSync16(file)) return;
9546
9701
  try {
9547
- const raw = await fsp5.readFile(file, "utf8");
9702
+ const raw = await fsp6.readFile(file, "utf8");
9548
9703
  const config = raw.trim() ? JSON.parse(raw) : {};
9549
9704
  if (typeof config !== "object" || config === null) return;
9550
9705
  const dir = resolveContainerCwd(opts.name, opts.cwd);
@@ -9564,7 +9719,7 @@ async function preApproveClaudeProject(opts) {
9564
9719
  if (typeof entry2.projectOnboardingSeenCount !== "number") {
9565
9720
  entry2.projectOnboardingSeenCount = 1;
9566
9721
  }
9567
- await fsp5.writeFile(file, `${JSON.stringify(config, null, 2)}
9722
+ await fsp6.writeFile(file, `${JSON.stringify(config, null, 2)}
9568
9723
  `);
9569
9724
  } catch {
9570
9725
  }
@@ -9576,8 +9731,8 @@ var init_claude_trust = __esm({
9576
9731
  });
9577
9732
 
9578
9733
  // src/devcontainer/shell.ts
9579
- import { existsSync as existsSync16 } from "fs";
9580
- import path25 from "path";
9734
+ import { existsSync as existsSync17 } from "fs";
9735
+ import path26 from "path";
9581
9736
  async function runShell(opts) {
9582
9737
  assertContainerExists(opts.root);
9583
9738
  const spawnFn = opts.spawn ?? spawnDevcontainer;
@@ -9600,7 +9755,7 @@ async function runShell(opts) {
9600
9755
  );
9601
9756
  }
9602
9757
  function assertContainerExists(root) {
9603
- if (!existsSync16(path25.join(root, ".devcontainer"))) {
9758
+ if (!existsSync17(path26.join(root, ".devcontainer"))) {
9604
9759
  throw new Error(
9605
9760
  `No .devcontainer/ at ${root}. Run \`monoceros apply <name>\` first.`
9606
9761
  );
@@ -9690,7 +9845,7 @@ var init_run = __esm({
9690
9845
 
9691
9846
  // src/commands/run.ts
9692
9847
  import { defineCommand as defineCommand24 } from "citty";
9693
- import { consola as consola28 } from "consola";
9848
+ import { consola as consola29 } from "consola";
9694
9849
  var runCommand;
9695
9850
  var init_run2 = __esm({
9696
9851
  "src/commands/run.ts"() {
@@ -9718,7 +9873,7 @@ var init_run2 = __esm({
9718
9873
  async run({ args }) {
9719
9874
  const command = [...getInnerArgs()];
9720
9875
  if (command.length === 0) {
9721
- consola28.error(
9876
+ consola29.error(
9722
9877
  "No command provided. Usage: `monoceros run <containername> -- <cmd> [args\u2026]`."
9723
9878
  );
9724
9879
  process.exit(1);
@@ -9732,7 +9887,7 @@ var init_run2 = __esm({
9732
9887
  });
9733
9888
  process.exit(exitCode);
9734
9889
  } catch (err) {
9735
- consola28.error(err instanceof Error ? err.message : String(err));
9890
+ consola29.error(err instanceof Error ? err.message : String(err));
9736
9891
  process.exit(1);
9737
9892
  }
9738
9893
  }
@@ -9742,7 +9897,7 @@ var init_run2 = __esm({
9742
9897
 
9743
9898
  // src/commands/shell.ts
9744
9899
  import { defineCommand as defineCommand25 } from "citty";
9745
- import { consola as consola29 } from "consola";
9900
+ import { consola as consola30 } from "consola";
9746
9901
  var shellCommand;
9747
9902
  var init_shell2 = __esm({
9748
9903
  "src/commands/shell.ts"() {
@@ -9767,7 +9922,7 @@ var init_shell2 = __esm({
9767
9922
  const exitCode = await runShell({ root: containerDir(args.name) });
9768
9923
  process.exit(exitCode);
9769
9924
  } catch (err) {
9770
- consola29.error(err instanceof Error ? err.message : String(err));
9925
+ consola30.error(err instanceof Error ? err.message : String(err));
9771
9926
  process.exit(1);
9772
9927
  }
9773
9928
  }
@@ -9777,7 +9932,7 @@ var init_shell2 = __esm({
9777
9932
 
9778
9933
  // src/commands/start.ts
9779
9934
  import { defineCommand as defineCommand26 } from "citty";
9780
- import { consola as consola30 } from "consola";
9935
+ import { consola as consola31 } from "consola";
9781
9936
  var startCommand;
9782
9937
  var init_start = __esm({
9783
9938
  "src/commands/start.ts"() {
@@ -9814,7 +9969,7 @@ var init_start = __esm({
9814
9969
  hostPort = proxyHostPort(global);
9815
9970
  }
9816
9971
  } catch (err) {
9817
- consola30.warn(
9972
+ consola31.warn(
9818
9973
  `Could not read container yml ahead of start: ${err instanceof Error ? err.message : String(err)}. Skipping Traefik pre-flight.`
9819
9974
  );
9820
9975
  }
@@ -9869,7 +10024,7 @@ var init_status = __esm({
9869
10024
 
9870
10025
  // src/commands/stop.ts
9871
10026
  import { defineCommand as defineCommand28 } from "citty";
9872
- import { consola as consola31 } from "consola";
10027
+ import { consola as consola32 } from "consola";
9873
10028
  var stopCommand;
9874
10029
  var init_stop = __esm({
9875
10030
  "src/commands/stop.ts"() {
@@ -9903,10 +10058,10 @@ var init_stop = __esm({
9903
10058
  });
9904
10059
  try {
9905
10060
  await maybeStopProxy({
9906
- logger: { info: (msg) => consola31.info(msg) }
10061
+ logger: { info: (msg) => consola32.info(msg) }
9907
10062
  });
9908
10063
  } catch (err) {
9909
- consola31.warn(
10064
+ consola32.warn(
9910
10065
  `Could not tear down the Traefik proxy: ${err instanceof Error ? err.message : String(err)}. Ignored.`
9911
10066
  );
9912
10067
  }
@@ -9918,11 +10073,11 @@ var init_stop = __esm({
9918
10073
  });
9919
10074
 
9920
10075
  // src/tunnel/resolve.ts
9921
- import { existsSync as existsSync17 } from "fs";
9922
- import path26 from "path";
10076
+ import { existsSync as existsSync18 } from "fs";
10077
+ import path27 from "path";
9923
10078
  async function resolveTunnelTarget(opts) {
9924
10079
  const ymlPath = containerConfigPath(opts.name, opts.monocerosHome);
9925
- if (!existsSync17(ymlPath)) {
10080
+ if (!existsSync18(ymlPath)) {
9926
10081
  throw new Error(
9927
10082
  `No yml profile for '${opts.name}' at ${ymlPath}. Run \`monoceros init ${opts.name}\` first.`
9928
10083
  );
@@ -9930,13 +10085,13 @@ async function resolveTunnelTarget(opts) {
9930
10085
  const parsed = await readConfig(ymlPath);
9931
10086
  const config = parsed.config;
9932
10087
  const containerRoot = containerDir(opts.name, opts.monocerosHome);
9933
- if (!existsSync17(containerRoot)) {
10088
+ if (!existsSync18(containerRoot)) {
9934
10089
  throw new Error(
9935
10090
  `Container '${opts.name}' is not materialised at ${containerRoot}. Run \`monoceros apply ${opts.name}\` first.`
9936
10091
  );
9937
10092
  }
9938
- const composePath = path26.join(containerRoot, ".devcontainer", "compose.yaml");
9939
- const isCompose = existsSync17(composePath);
10093
+ const composePath = path27.join(containerRoot, ".devcontainer", "compose.yaml");
10094
+ const isCompose = existsSync18(composePath);
9940
10095
  const parsedTarget = parseTargetArg(opts.target, config);
9941
10096
  const docker = opts.docker ?? defaultDockerExec;
9942
10097
  if (isCompose) {
@@ -10172,7 +10327,7 @@ var init_port_check2 = __esm({
10172
10327
 
10173
10328
  // src/tunnel/run.ts
10174
10329
  import { spawn as spawn10 } from "child_process";
10175
- import { consola as consola32 } from "consola";
10330
+ import { consola as consola33 } from "consola";
10176
10331
  function signalNumber(signal) {
10177
10332
  switch (signal) {
10178
10333
  case "SIGINT":
@@ -10185,8 +10340,8 @@ function signalNumber(signal) {
10185
10340
  }
10186
10341
  async function runTunnel(opts) {
10187
10342
  const log = opts.logger ?? {
10188
- info: (m) => consola32.info(m),
10189
- warn: (m) => consola32.warn(m)
10343
+ info: (m) => consola33.info(m),
10344
+ warn: (m) => consola33.warn(m)
10190
10345
  };
10191
10346
  const resolve = opts.resolve ?? resolveTunnelTarget;
10192
10347
  const resolveArgs3 = {
@@ -10293,7 +10448,7 @@ var init_run3 = __esm({
10293
10448
 
10294
10449
  // src/commands/tunnel.ts
10295
10450
  import { defineCommand as defineCommand29 } from "citty";
10296
- import { consola as consola33 } from "consola";
10451
+ import { consola as consola34 } from "consola";
10297
10452
  function parseLocalPort(raw) {
10298
10453
  if (raw === void 0) return void 0;
10299
10454
  const n = Number(raw);
@@ -10346,7 +10501,7 @@ var init_tunnel = __esm({
10346
10501
  });
10347
10502
  process.exit(exitCode);
10348
10503
  } catch (err) {
10349
- consola33.error(err instanceof Error ? err.message : String(err));
10504
+ consola34.error(err instanceof Error ? err.message : String(err));
10350
10505
  process.exit(1);
10351
10506
  }
10352
10507
  }
@@ -10416,8 +10571,8 @@ var init_prune = __esm({
10416
10571
  });
10417
10572
 
10418
10573
  // src/upgrade/index.ts
10419
- import { existsSync as existsSync18, promises as fs17 } from "fs";
10420
- import { consola as consola34 } from "consola";
10574
+ import { existsSync as existsSync19, promises as fs17 } from "fs";
10575
+ import { consola as consola35 } from "consola";
10421
10576
  async function fetchRuntimeVersions() {
10422
10577
  const tokenUrl = `https://ghcr.io/token?service=ghcr.io&scope=repository:${RUNTIME_REPO}:pull`;
10423
10578
  const tokenRes = await fetch(tokenUrl);
@@ -10455,7 +10610,7 @@ ${yml}`;
10455
10610
  }
10456
10611
  async function runUpgrade(opts) {
10457
10612
  const home = opts.monocerosHome ?? monocerosHome();
10458
- const logger = opts.logger ?? consola34;
10613
+ const logger = opts.logger ?? consola35;
10459
10614
  const fetchVersions = opts.fetchVersions ?? fetchRuntimeVersions;
10460
10615
  if (opts.list) {
10461
10616
  const versions = await fetchVersions();
@@ -10481,7 +10636,7 @@ async function runUpgrade(opts) {
10481
10636
  );
10482
10637
  }
10483
10638
  }
10484
- if (opts.name && !existsSync18(containerConfigPath(opts.name, home))) {
10639
+ if (opts.name && !existsSync19(containerConfigPath(opts.name, home))) {
10485
10640
  throw new Error(
10486
10641
  `No such config: ${containerConfigPath(opts.name, home)}. Run \`monoceros init <template> ${opts.name}\` first.`
10487
10642
  );
@@ -10532,7 +10687,7 @@ async function runUpgrade(opts) {
10532
10687
  let bumped = 0;
10533
10688
  for (const name of targets) {
10534
10689
  const ymlPath = containerConfigPath(name, home);
10535
- if (!existsSync18(ymlPath)) continue;
10690
+ if (!existsSync19(ymlPath)) continue;
10536
10691
  const raw = await fs17.readFile(ymlPath, "utf8");
10537
10692
  const updated = setRuntimeVersion(raw, pinVersion);
10538
10693
  if (updated !== raw) {
@@ -10983,25 +11138,25 @@ function detectHelpRequest(argv, main2) {
10983
11138
  const separatorIdx = argv.indexOf("--");
10984
11139
  if (helpIdx === -1) return null;
10985
11140
  if (separatorIdx !== -1 && separatorIdx < helpIdx) return null;
10986
- const path27 = [];
11141
+ const path28 = [];
10987
11142
  const tokens = argv.slice(
10988
11143
  0,
10989
11144
  separatorIdx === -1 ? argv.length : separatorIdx
10990
11145
  );
10991
11146
  let cursor = main2;
10992
11147
  const mainName = (main2.meta ?? {}).name ?? "monoceros";
10993
- path27.push(mainName);
11148
+ path28.push(mainName);
10994
11149
  for (const tok of tokens) {
10995
11150
  if (tok.startsWith("-")) continue;
10996
11151
  const subs = cursor.subCommands ?? {};
10997
11152
  if (tok in subs) {
10998
11153
  cursor = subs[tok];
10999
- path27.push(tok);
11154
+ path28.push(tok);
11000
11155
  continue;
11001
11156
  }
11002
11157
  break;
11003
11158
  }
11004
- return { path: path27, cmd: cursor };
11159
+ return { path: path28, cmd: cursor };
11005
11160
  }
11006
11161
  async function maybeRenderHelp(argv, main2) {
11007
11162
  const hit = detectHelpRequest(argv, main2);