@flisk-sh/flisk 1.3.190 → 1.3.192

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/CHANGELOG.md +9 -9
  2. package/LICENSE +1 -1
  3. package/README.md +41 -41
  4. package/Tiltfile +2 -2
  5. package/cli/bin/{flisk.js → tdk.js} +1 -1
  6. package/cli/dist/cli.js +59 -0
  7. package/cli/dist/commands/__tests__/project-e2e-helpers.js +2 -2
  8. package/cli/dist/commands/completion.js +26 -26
  9. package/cli/dist/commands/config.js +1 -1
  10. package/cli/dist/commands/import.js +4 -4
  11. package/cli/dist/commands/maintainers.js +1 -1
  12. package/cli/dist/commands/mcp.js +1 -4
  13. package/cli/dist/commands/project.js +10 -2
  14. package/cli/dist/commands/resource.js +1 -1
  15. package/cli/dist/commands/ui.js +1 -1
  16. package/cli/dist/commands/up.js +77 -3
  17. package/cli/dist/commands/upgrade.js +28 -14
  18. package/cli/dist/generator/extension-fetch.js +3 -3
  19. package/cli/dist/generator/template-engine.js +8 -8
  20. package/cli/dist/mcp/tools.js +2 -5
  21. package/cli/dist/program.js +2 -0
  22. package/cli/dist/utils/cli-command.js +107 -0
  23. package/cli/dist/utils/cold-preflight.js +2 -1
  24. package/cli/dist/utils/constants.js +1 -1
  25. package/cli/dist/utils/doctor-fix.js +4 -5
  26. package/cli/dist/utils/doctor-runtime.js +1 -1
  27. package/cli/dist/utils/doctor-starlark.js +1 -1
  28. package/cli/dist/utils/doctor-wiring.js +2 -2
  29. package/cli/dist/utils/env-selection.js +201 -0
  30. package/cli/dist/utils/env-validator.js +6 -0
  31. package/cli/dist/utils/one-command.js +50 -0
  32. package/cli/dist/utils/platform.js +2 -6
  33. package/cli/dist/utils/project-templates.js +11 -7
  34. package/cli/dist/utils/secret-redaction.js +15 -6
  35. package/cli/dist/utils/service-manifest.js +1 -1
  36. package/cli/dist/utils/smoke.js +2 -2
  37. package/cli/dist/utils/tar.js +1 -1
  38. package/cli/dist-bundle/{chunk-BZ4H7MM4.js → chunk-42IVF3YT.js} +2 -2
  39. package/cli/dist-bundle/chunk-GOEBYLFN.js +2 -0
  40. package/cli/dist-bundle/chunk-KGKKDD4K.js +2 -0
  41. package/cli/dist-bundle/chunk-QR6O2A7L.js +34 -0
  42. package/cli/dist-bundle/chunk-RHSMS45X.js +438 -0
  43. package/cli/dist-bundle/chunk-XYFVXSEO.js +75 -0
  44. package/cli/dist-bundle/cli.js +342 -370
  45. package/cli/dist-bundle/cold-preflight-ZJAU3E7K.js +2 -0
  46. package/cli/dist-bundle/{extension-fetch-J4FFH7TJ.js → extension-fetch-6XNTDF44.js} +1 -1
  47. package/cli/dist-bundle/one-command-A4R272U3.js +4 -0
  48. package/cli/dist-bundle/project-FOAR7E55.js +2 -0
  49. package/cli/dist-bundle/project-templates-BHURA3LT.js +2 -0
  50. package/cli/dist-bundle/url-actions-D6ROTHZG.js +2 -0
  51. package/cli/package.json +2 -4
  52. package/cli/shared-platform-engineering/docker-templates/bun-hoisted-symlink-fix.sh +1 -1
  53. package/cli/shared-platform-engineering/docker-templates/infisical-entrypoint.sh +1 -1
  54. package/cli/shared-platform-engineering/docker-templates/install-deps.sh +1 -1
  55. package/cli/shared-platform-engineering/docker-templates/prisma-bun-client-link-fix.sh +1 -1
  56. package/cli/shared-platform-engineering/docker-templates/prisma-normalize-client.sh +1 -1
  57. package/cli/templates/Tiltfile.hbs +1 -1
  58. package/discovery/AGENTS.md +1 -1
  59. package/discovery/TILT_DISCOVERY.star +3 -3
  60. package/discovery/Tiltfile +3 -3
  61. package/discovery/config.star +1 -1
  62. package/discovery/constants.star +1 -1
  63. package/discovery/discovery_orchestrator.star +1 -1
  64. package/discovery/identity-management-frontend/service.yaml +1 -1
  65. package/discovery/json_manifest_scanner.star +1 -1
  66. package/discovery/manifest/constants.star +1 -1
  67. package/discovery/manifest/loading.star +2 -2
  68. package/discovery/manifest/normalize.star +1 -1
  69. package/discovery/registry.star +1 -1
  70. package/discovery/resource_snapshot.py +1 -1
  71. package/discovery/resource_snapshot.star +1 -1
  72. package/discovery/test_resource_snapshot.py +2 -2
  73. package/engine/AGENTS.md +7 -7
  74. package/engine/README.md +1 -1
  75. package/engine/Tiltfile +3 -3
  76. package/engine/assets/docker/wake-gateway/decide.ts +1 -1
  77. package/engine/assets/docker/wake-gateway/server.ts +1 -1
  78. package/engine/assets/scripts/mac-m1-resource-monitor.sh +8 -8
  79. package/engine/lifecycle/orchestrator.star +6 -6
  80. package/engine/paths.star +1 -1
  81. package/engine/schemas/project-schema.json +2 -2
  82. package/engine/schemas/service-schema.json +3 -3
  83. package/engine/scripts/debug-container.sh +2 -2
  84. package/engine/spec.master +1 -1
  85. package/engine/topologies/platform/docker/compose/compose.star +1 -1
  86. package/engine/topologies/platform/docker/compose/traefik_standalone.star +1 -1
  87. package/engine/topologies/platform/docker/config/healthcheck.star +1 -1
  88. package/engine/topologies/platform/docker/constants.star +2 -2
  89. package/engine/topologies/platform/docker/dockerfile/language_dockerfile.star +3 -3
  90. package/engine/topologies/platform/docker/layers/l1_base_layers.star +1 -1
  91. package/engine/topologies/platform/docker/layers/l2_dependency_layers.star +1 -1
  92. package/engine/topologies/platform/docker/layers/l3_builder_layers.star +1 -1
  93. package/engine/topologies/platform/docker/layers/l4_runtime_layers.star +1 -1
  94. package/engine/topologies/platform/docker/layers/prisma/constants.star +1 -1
  95. package/engine/topologies/platform/docker/layers/prisma/prisma_build.star +2 -2
  96. package/engine/topologies/platform/docker/networking/api_path_constants.star +1 -1
  97. package/engine/topologies/platform/docker/networking/traefik_static_routes.star +1 -1
  98. package/engine/topologies/platform/docker/secrets/env_secrets.star +1 -1
  99. package/engine/topologies/platform/docker/secrets/infisical.star +1 -1
  100. package/engine/topologies/platform/security/secrets.star +1 -1
  101. package/engine/topologies/tilt/common/utils.star +5 -3
  102. package/engine/topologies/tilt/common/utils_debug.star +1 -1
  103. package/engine/topologies/tilt/common/utils_deterministic.star +1 -1
  104. package/engine/topologies/tilt/common/utils_env.star +23 -3
  105. package/engine/topologies/tilt/config/profiles.star +1 -1
  106. package/engine/topologies/tilt/generators/infisical/organization.star +1 -1
  107. package/engine/topologies/tilt/generators/npmrc.star +4 -4
  108. package/engine/topologies/tilt/generators/typescript/backend_tsconfig.star +1 -1
  109. package/engine/topologies/tilt/generators/vite/helpers.star +1 -1
  110. package/engine/topologies/tilt/generators/vite/templates.star +1 -1
  111. package/engine/topologies/tilt/manifest/json_to_yaml.py +2 -2
  112. package/engine/topologies/tilt/manifest/loader.star +1 -1
  113. package/engine/topologies/tilt/manifest/schema.star +2 -2
  114. package/engine/topologies/tilt/manifest/tests/test_loader_parser.star +3 -3
  115. package/engine/topologies/tilt/manifest/tests/test_validator.star +2 -2
  116. package/engine/topologies/tilt/manifest/yaml_to_json.py +1 -1
  117. package/engine/topologies/tilt/resources/databases.star +1 -1
  118. package/engine/topologies/tilt/resources/infra-loader.star +8 -6
  119. package/engine/topologies/tilt/resources/libs_paths.star +1 -1
  120. package/engine/topologies/tilt/resources/libs_resource_definition.star +1 -1
  121. package/engine/topologies/tilt/resources/libs_setup.star +1 -1
  122. package/engine/topologies/tilt/resources/orchestrator/apply_compose_resource_registration.star +13 -8
  123. package/engine/topologies/tilt/resources/orchestrator/generators/frontend.star +1 -1
  124. package/engine/topologies/tilt/resources/orchestrator/generators/manifest_resource.star +1 -1
  125. package/engine/topologies/tilt/resources/watchers.star +7 -7
  126. package/engine/where-things-live.star +1 -1
  127. package/examples/tdk-example/LICENSE +1 -1
  128. package/examples/tdk-example/Tiltfile +7 -7
  129. package/examples/tdk-example/services/shop/orders-api/service.json +1 -1
  130. package/examples/tdk-example/services/shop/orders-app/index.html +1 -1
  131. package/examples/tdk-example/services/shop/orders-app/service.json +1 -1
  132. package/examples/tdk-example/services/shop/orders-worker/service.json +1 -1
  133. package/ext/Tiltfile +3 -3
  134. package/ext/ide-components/code_viewer/server.py +1 -1
  135. package/ext/ide-components/config_inspector/server.py +1 -1
  136. package/ext/ide-components/file_browser/server.py +1 -1
  137. package/ext/ide-components/shared/config_service.py +2 -2
  138. package/ext/ide-components/shared/file_utils.py +2 -2
  139. package/ext/ide-components/shared/http_utils.py +1 -1
  140. package/ext/ide-components/shared/syntax_highlighter.py +1 -1
  141. package/ext/ide-components/shared/template_engine.py +1 -1
  142. package/ext/ide-components/shared/templates/base.html +1 -1
  143. package/ext/ide-components/shared/test_config_service.py +1 -1
  144. package/ext/ide-components/shared/tilt_integration.py +1 -1
  145. package/ext/ui-enhancements/tiltfile.py +1 -1
  146. package/package.json +6 -10
  147. package/shared-platform-engineering/docker-templates/bun-hoisted-symlink-fix.sh +1 -1
  148. package/shared-platform-engineering/docker-templates/infisical-entrypoint.sh +1 -1
  149. package/shared-platform-engineering/docker-templates/install-deps.sh +1 -1
  150. package/shared-platform-engineering/docker-templates/prisma-bun-client-link-fix.sh +1 -1
  151. package/shared-platform-engineering/docker-templates/prisma-normalize-client.sh +1 -1
  152. package/cli/dist-bundle/chunk-CLCUIDBH.js +0 -510
  153. package/cli/dist-bundle/cold-preflight-SY26O2IG.js +0 -2
@@ -79,7 +79,7 @@ function shellTypeCondition(types) {
79
79
  return parts.join(" || ");
80
80
  }
81
81
  /** The name of the variable that holds the `--type` of the command line. */
82
- const TYPE_VARIABLE = "flisk_type";
82
+ const TYPE_VARIABLE = "tdk_type";
83
83
  /** The stacks of the current project, read from the machine-readable CLI output. */
84
84
  const BASH_STACKS = `flisk stacks --json 2>/dev/null | grep -o '"name":"[^"]*"' | sed 's/"name":"//;s/"$//'`;
85
85
  const BASH_RESOURCES = `flisk resources --json 2>/dev/null | grep -o '"name":"[^"]*"' | sed 's/"name":"//;s/"$//'`;
@@ -106,7 +106,7 @@ const ZSH_TYPE = ` local ${TYPE_VARIABLE}=""
106
106
  fi
107
107
  done`;
108
108
  /** The `--type` of the current command line, in fish. */
109
- const FISH_TYPE = `function __flisk_resource_type
109
+ const FISH_TYPE = `function __tdk_resource_type
110
110
  set -l tokens (commandline -opc)
111
111
  set -l ${TYPE_VARIABLE} ""
112
112
  set -l token_count (count $tokens)
@@ -156,7 +156,7 @@ function zshTypeValues(flag, values) {
156
156
  }
157
157
  /** The values of a flag that depend on the `--type`, in fish. */
158
158
  function fishTypeValues(values) {
159
- const lines = [" switch (__flisk_resource_type)"];
159
+ const lines = [" switch (__tdk_resource_type)"];
160
160
  for (const arm of typeValueArms(values)) {
161
161
  lines.push(` case ${arm.types.map((type) => (type === "" ? "''" : type)).join(" ")}`);
162
162
  lines.push(` printf '%s\\n' ${arm.values.join(" ")}`);
@@ -252,7 +252,7 @@ function renderBash(candidates) {
252
252
  .join("\n");
253
253
  return `# Flisk CLI Bash Completion
254
254
  # Generated by "flisk completion bash". The command and flag lists come from the CLI itself.
255
- _flisk_completions() {
255
+ _tdk_completions() {
256
256
  local cur prev cmd sub options words commands stacks resources path ${TYPE_VARIABLE} ${TYPE_VARIABLE}_values
257
257
  COMPREPLY=()
258
258
  cur="\${COMP_WORDS[COMP_CWORD]}"
@@ -335,24 +335,24 @@ ${positionalCases}
335
335
  return 0
336
336
  }
337
337
 
338
- complete -F _flisk_completions flisk
338
+ complete -F _tdk_completions flisk
339
339
  `;
340
340
  }
341
341
  /** The `_arguments` spec of the positional argument of a command. */
342
342
  function zshPositionalSpecs(entry) {
343
343
  // A command with sub-commands completes the name of the sub-command, not a value.
344
344
  if (entry.subcommands.length > 0) {
345
- return [`'1: :_flisk_${entry.name}_subcommands'`];
345
+ return [`'1: :_tdk_${entry.name}_subcommands'`];
346
346
  }
347
347
  switch (entry.positional) {
348
348
  case "stacks":
349
- return ["'1:stack:_flisk_stacks'"];
349
+ return ["'1:stack:_tdk_stacks'"];
350
350
  case "resources":
351
- return ["'1:resource:_flisk_resources'"];
351
+ return ["'1:resource:_tdk_resources'"];
352
352
  case "stacks-and-resources":
353
- return ["'1:target:_flisk_stacks'"];
353
+ return ["'1:target:_tdk_stacks'"];
354
354
  case "commands":
355
- return ["'1:command:_flisk_commands'"];
355
+ return ["'1:command:_tdk_commands'"];
356
356
  default:
357
357
  break;
358
358
  }
@@ -411,25 +411,25 @@ function renderZsh(candidates) {
411
411
  .join("\n");
412
412
  const subCommandLists = entries
413
413
  .filter((entry) => entry.subcommands.length > 0)
414
- .map((entry) => `_flisk_${entry.name}_subcommands() {\n local commands=(\n${entry.subcommands
414
+ .map((entry) => `_tdk_${entry.name}_subcommands() {\n local commands=(\n${entry.subcommands
415
415
  .map((subcommand) => ` '${subcommand.name}:${shortDescription(subcommand.description)}'`)
416
416
  .join("\n")}\n )\n _describe -t commands '${entry.name} command' commands\n}`)
417
417
  .join("\n\n");
418
418
  const typeValueFunctions = Object.entries(candidates.typeValues)
419
- .map(([flag, values]) => `_flisk_${flag.slice(2)}_values() {\n${ZSH_TYPE}\n${zshTypeValues(flag, values)}\n}`)
419
+ .map(([flag, values]) => `_tdk_${flag.slice(2)}_values() {\n${ZSH_TYPE}\n${zshTypeValues(flag, values)}\n}`)
420
420
  .join("\n\n");
421
421
  return `#compdef flisk
422
422
 
423
423
  # Flisk CLI Zsh Completion
424
424
  # Generated by "flisk completion zsh". The command and flag lists come from the CLI itself.
425
425
 
426
- _flisk() {
426
+ _tdk() {
427
427
  local curcontext="$curcontext" state line
428
428
  typeset -A opt_args
429
429
 
430
430
  _arguments -C \\
431
431
  ${globalFlags} \\
432
- '1: :_flisk_commands' \\
432
+ '1: :_tdk_commands' \\
433
433
  '*:: :->args'
434
434
 
435
435
  case "$line[1]" in
@@ -441,20 +441,20 @@ ${subCommandStates}
441
441
  esac
442
442
  }
443
443
 
444
- _flisk_commands() {
444
+ _tdk_commands() {
445
445
  local commands=(
446
446
  ${commandList}
447
447
  )
448
448
  _describe -t commands 'flisk command' commands
449
449
  }
450
450
 
451
- _flisk_stacks() {
451
+ _tdk_stacks() {
452
452
  local stacks
453
453
  stacks=($(flisk stacks --json 2>/dev/null | grep -o '"name":"[^"]*"' | sed 's/"name":"//;s/"$//'))
454
454
  _describe -t stacks 'stack' stacks
455
455
  }
456
456
 
457
- _flisk_resources() {
457
+ _tdk_resources() {
458
458
  local resources
459
459
  resources=($(flisk resources --json 2>/dev/null | grep -o '"name":"[^"]*"' | sed 's/"name":"//;s/"$//'))
460
460
  _describe -t resources 'resource' resources
@@ -463,24 +463,24 @@ _flisk_resources() {
463
463
  ${subCommandLists}
464
464
 
465
465
  ${typeValueFunctions}
466
- compdef _flisk flisk
466
+ compdef _tdk flisk
467
467
  `;
468
468
  }
469
469
  /** The `_arguments` spec of one flag, with the values it completes when it has them. */
470
470
  function zshOptionSpec(option, candidates, entry) {
471
471
  const description = shortDescription(option.description);
472
472
  if (candidates.typeValues[option.flag]) {
473
- return `'${option.flag}[${description}]:${option.flag.slice(2)}:_flisk_${option.flag.slice(2)}_values'`;
473
+ return `'${option.flag}[${description}]:${option.flag.slice(2)}:_tdk_${option.flag.slice(2)}_values'`;
474
474
  }
475
475
  const values = valuesOf(option.flag, candidates, entry);
476
476
  if (values) {
477
477
  return `'${option.flag}[${description}]:${option.flag.slice(2)}:(${values.join(" ")})'`;
478
478
  }
479
479
  if (option.flag === "--stack") {
480
- return `'${option.flag}[${description}]:stack:_flisk_stacks'`;
480
+ return `'${option.flag}[${description}]:stack:_tdk_stacks'`;
481
481
  }
482
482
  if (option.flag === "--only") {
483
- return `'${option.flag}[${description}]:service:_flisk_resources'`;
483
+ return `'${option.flag}[${description}]:service:_tdk_resources'`;
484
484
  }
485
485
  return option.takesValue
486
486
  ? `'${option.flag}[${description}]:${option.flag.slice(2)}:'`
@@ -526,7 +526,7 @@ function renderFish(candidates) {
526
526
  .filter((entry) => entry.positional === "commands")
527
527
  .map((entry) => `complete -c flisk -f -n '${fishCondition(entry)}' -a '${commandWords(entries).join(" ")}'`);
528
528
  const typeValueFunctions = Object.entries(candidates.typeValues)
529
- .map(([flag, values]) => `function __flisk_${flag.slice(2)}_values\n${fishTypeValues(values)}\nend`)
529
+ .map(([flag, values]) => `function __tdk_${flag.slice(2)}_values\n${fishTypeValues(values)}\nend`)
530
530
  .join("\n\n");
531
531
  return `# Flisk CLI Fish Completion
532
532
  # Generated by "flisk completion fish". The command and flag lists come from the CLI itself.
@@ -571,7 +571,7 @@ function fishCondition(entry) {
571
571
  /** The fish argument that lists the values of a flag. */
572
572
  function fishValueArgument(option, candidates, entry) {
573
573
  if (candidates.typeValues[option.flag]) {
574
- return ` -r -a '(__flisk_${option.flag.slice(2)}_values)'`;
574
+ return ` -r -a '(__tdk_${option.flag.slice(2)}_values)'`;
575
575
  }
576
576
  const values = valuesOf(option.flag, candidates, entry);
577
577
  return values ? ` -r -a '${values.join(" ")}'` : "";
@@ -761,11 +761,11 @@ export const completionCommand = new Command("completion")
761
761
  const candidates = buildCompletionCandidates(program);
762
762
  const completionScript = renderCompletionScript(shell, candidates);
763
763
  const filename = shell === "bash"
764
- ? "flisk-completion.bash"
764
+ ? "tdk-completion.bash"
765
765
  : shell === "zsh"
766
- ? "_flisk"
766
+ ? "_tdk"
767
767
  : shell === "fish"
768
- ? "flisk.fish"
768
+ ? "tdk.fish"
769
769
  : "Microsoft.PowerShell_profile.ps1";
770
770
  if (options.install) {
771
771
  const home = homedir();
@@ -325,7 +325,7 @@ async function toggleInfraService(service, enabled) {
325
325
  const granted = await hasVerdaccioLicense(projectRoot);
326
326
  if (!granted) {
327
327
  throw new Error("Verdaccio is a Premium feature and requires a license key that grants it. " +
328
- "Set export TDK_LICENSE_KEY=<key> (request a Premium license at https://tdk-landscape.github.io/tdk-website/#waitlist) and try again.");
328
+ "Set export TDK_LICENSE_KEY=<key> (request a Premium license at https://flisk.sh/#waitlist) and try again.");
329
329
  }
330
330
  }
331
331
  const config = readProjectConfig(projectRoot);
@@ -9,7 +9,7 @@ import { getPackageVersion } from "../utils/paths.js";
9
9
  * pinned version so a push to its main branch cannot change what `flisk import` does. Move the pin
10
10
  * when a new importer is published. `TDK_IMPORT_PACKAGE` overrides the package spec.
11
11
  */
12
- export const IMPORT_PACKAGE = "@tdk-landscape/tdk-import@0.2.1";
12
+ export const IMPORT_PACKAGE = "flisk-import@0.2.2";
13
13
  /** Minimum Flisk core release supporting buildContext required by flisk import (#634). */
14
14
  export const MIN_CORE_VERSION = "1.3.104";
15
15
  /** Recommended core version with automatic Tiltfile bootstrapping for imported stacks (#1018). */
@@ -109,7 +109,7 @@ export function importInvocation(args, env = process.env, platform = process.pla
109
109
  shell: platform === "win32",
110
110
  };
111
111
  }
112
- /** Runs tdk-import with the caller's terminal and resolves to its exit code. */
112
+ /** Runs flisk-import with the caller's terminal and resolves to its exit code. */
113
113
  export function runImport(args, spawnFn = spawn, getVersionFn = getPackageVersion) {
114
114
  const check = checkCoreVersion(getVersionFn(), args);
115
115
  if (!check.ok) {
@@ -153,8 +153,8 @@ export function buildForwardedImportArgs(args, options = {}) {
153
153
  return filtered;
154
154
  }
155
155
  export const importCommand = addYesOption(new Command("import"))
156
- .description("Import the services in a directory's root docker-compose.yml (runs tdk-import)")
157
- .argument("[args...]", "Passed to tdk-import: [dir] --dry-run --yes --force")
156
+ .description("Import the services in a directory's root docker-compose.yml (runs flisk-import)")
157
+ .argument("[args...]", "Passed to flisk-import: [dir] --dry-run --yes --force")
158
158
  .option("-f, --force", "Overwrite an existing service.json", false)
159
159
  .allowUnknownOption()
160
160
  .helpOption(false)
@@ -6,7 +6,7 @@ import { Command } from "commander";
6
6
  export const MIN_MAINTAINERS = 3;
7
7
  export const MIN_COMPANIES = 2;
8
8
  const REQUIRED_COLUMNS = ["name", "github id", "company"];
9
- const PLACEHOLDER_COMPANIES = new Set(["", "tbd", "unknown", "tdk-landscape"]);
9
+ const PLACEHOLDER_COMPANIES = new Set(["", "tbd", "unknown", "flisk-sh"]);
10
10
  function splitRow(line) {
11
11
  return line
12
12
  .trim()
@@ -8,10 +8,7 @@ import { getPackageVersion } from "../utils/paths.js";
8
8
  export const mcpCommand = new Command("mcp")
9
9
  .description("Run a Model Context Protocol server over stdio for coding agents")
10
10
  .action(async () => {
11
- const server = createMcpServer(createTdkTools(), {
12
- name: "flisk",
13
- version: getPackageVersion(),
14
- });
11
+ const server = createMcpServer(createTdkTools(), { name: "flisk", version: getPackageVersion() });
15
12
  // Stdout is the protocol channel. Nothing else may write to it; diagnostics go to stderr.
16
13
  const lines = createInterface({ input: process.stdin });
17
14
  const pending = new Set();
@@ -78,7 +78,15 @@ function getDefaultCoreServices() {
78
78
  .filter((f) => f.enabled_by_default && f.category === "core")
79
79
  .map((f) => f.name);
80
80
  }
81
- async function cloneProjectTemplate(templateName, targetDir, runtimeNextSteps) {
81
+ /** The directory a template lands in: the requested path, or the template's repository name. */
82
+ export function templateTargetDir(templateName, targetDir) {
83
+ if (targetDir)
84
+ return targetDir;
85
+ const template = PROJECT_TEMPLATES[templateName];
86
+ const fromRepo = template?.repo.split("/").pop() ?? templateName;
87
+ return fromRepo.replace(/\.git$/, "");
88
+ }
89
+ export async function cloneProjectTemplate(templateName, targetDir, runtimeNextSteps) {
82
90
  const template = PROJECT_TEMPLATES[templateName];
83
91
  if (!template) {
84
92
  console.log(chalk.red(`\n❌ Unknown template: "${templateName}"`));
@@ -89,7 +97,7 @@ async function cloneProjectTemplate(templateName, targetDir, runtimeNextSteps) {
89
97
  console.log(chalk.gray("\nOr run `flisk project` with no template for a blank project."));
90
98
  process.exit(1);
91
99
  }
92
- const dirName = targetDir || (template.repo.split("/").pop() ?? templateName).replace(/\.git$/, "");
100
+ const dirName = templateTargetDir(templateName, targetDir);
93
101
  if (!isPathSafe(dirName)) {
94
102
  errorFactories.invalidPath(dirName).exit();
95
103
  }
@@ -499,7 +499,7 @@ export const resourceCommand = addYesOption(new Command("resource"))
499
499
  const granted = await hasDddLicense(projectRoot);
500
500
  if (!granted) {
501
501
  throw new Error("DDD scaffolding is a Premium feature and requires a license key that grants it. " +
502
- "Set export TDK_LICENSE_KEY=<key> (request a Premium license at https://tdk-landscape.github.io/tdk-website/#waitlist) and try again.");
502
+ "Set export TDK_LICENSE_KEY=<key> (request a Premium license at https://flisk.sh/#waitlist) and try again.");
503
503
  }
504
504
  dddEnabled = true;
505
505
  }
@@ -45,7 +45,7 @@ export const LoadingScreen = ({ message = "Discovering resources...", animated =
45
45
  // biome-ignore lint/correctness/noUnusedFunctionParameters: reserved callback prop kept in the component API
46
46
  const ErrorScreen = ({ error, onRetry }) => {
47
47
  const theme = useTUITheme();
48
- return (_jsxs(Box, { flexDirection: "column", padding: 2, alignItems: "center", children: [_jsx(Text, { bold: true, color: theme.error, children: "Could Not Load Services" }), _jsx(Box, { marginY: 1 }), _jsxs(Text, { color: theme.error, children: [theme.ascii ? "[x]" : "\u2717", " ", error] }), _jsx(Box, { marginY: 1 }), _jsx(Text, { color: theme.muted, children: "Troubleshooting:" }), _jsx(Text, { color: theme.muted, children: " 1. Check that every service.json is valid JSON" }), _jsxs(Text, { color: theme.muted, children: [" ", "2. Run flisk from your project (the folder with the Tiltfile)"] }), _jsx(Text, { color: theme.muted, children: " 3. Try: flisk status --verbose" }), _jsx(Box, { marginY: 1 }), _jsx(Text, { color: theme.accent, children: "Press [r] to retry or [q] to quit" })] }));
48
+ return (_jsxs(Box, { flexDirection: "column", padding: 2, alignItems: "center", children: [_jsx(Text, { bold: true, color: theme.error, children: "Could Not Load Services" }), _jsx(Box, { marginY: 1 }), _jsxs(Text, { color: theme.error, children: [theme.ascii ? "[x]" : "\u2717", " ", error] }), _jsx(Box, { marginY: 1 }), _jsx(Text, { color: theme.muted, children: "Troubleshooting:" }), _jsx(Text, { color: theme.muted, children: " 1. Check that every service.json is valid JSON" }), _jsx(Text, { color: theme.muted, children: " 2. Run flisk from your project (the folder with the Tiltfile)" }), _jsx(Text, { color: theme.muted, children: " 3. Try: flisk status --verbose" }), _jsx(Box, { marginY: 1 }), _jsx(Text, { color: theme.accent, children: "Press [r] to retry or [q] to quit" })] }));
49
49
  };
50
50
  const EmptyState = ({ message }) => {
51
51
  const theme = useTUITheme();
@@ -10,8 +10,9 @@ import { DEVCONTAINER_DOCKER_FIX, detectHost, isContainerHost, WEBCONTAINER_UP_M
10
10
  import { handleDryRun } from "../utils/command-helpers.js";
11
11
  import { STANDARD_PORTS } from "../utils/constants.js";
12
12
  import { getDeferredResourceNames, summarizeTiltBuildError } from "../utils/doctor-runtime.js";
13
+ import { applyEnvFileSelection, assertEngineSupportsEnvFile, EnvFileError, envFileWarning, PROJECT_ENV_FILE_VAR, selectEnvFile, } from "../utils/env-selection.js";
13
14
  import { completeEnvFile } from "../utils/env-validator.js";
14
- import { errorFactories, handleTiltFailure, requireProjectRoot, runCommand, showError, showErrorAndExit, withTiltCheck, } from "../utils/errors.js";
15
+ import { errorFactories, getErrorMessage, handleTiltFailure, requireProjectRoot, runCommand, showError, showErrorAndExit, TdkError, withTiltCheck, } from "../utils/errors.js";
15
16
  import { ensureSmokeRecordsIgnored } from "../utils/file-helpers.js";
16
17
  import { formatCount } from "../utils/formatting.js";
17
18
  import { exportHostPortPlan, getHostPortPlan, writeSavedHostPortPlan, } from "../utils/host-port-config.js";
@@ -162,6 +163,37 @@ function waitForTiltUi(port, timeoutMs = 30_000) {
162
163
  attempt();
163
164
  });
164
165
  }
166
+ /**
167
+ * The env file of the run. `flisk up --env-file <path>` replaces the project `.env` for the run, so the
168
+ * file is resolved, read and checked before anything is written or started. Without the option the
169
+ * project `.env` stays the env file of the run, exactly as before.
170
+ *
171
+ * @throws TdkError when the file cannot be used; the run stops before it starts
172
+ */
173
+ export function selectRunEnvFile(projectRoot, requested) {
174
+ if (requested === undefined)
175
+ return undefined;
176
+ if (!projectRoot) {
177
+ throw errorFactories.notInProject();
178
+ }
179
+ const selection = selectEnvFile(projectRoot, requested);
180
+ // A project created before this option vendored an engine that ignores the selection, so the run
181
+ // would silently use the project .env instead.
182
+ assertEngineSupportsEnvFile(projectRoot);
183
+ return selection;
184
+ }
185
+ /** The machine-readable failure of a refused `--env-file`, and the exit code it stops the run with. */
186
+ function envFileFailure(error) {
187
+ const suggestions = error instanceof TdkError ? error.suggestions : [];
188
+ return {
189
+ failure: {
190
+ code: error instanceof EnvFileError ? error.code : "ENV_FILE_INVALID",
191
+ message: getErrorMessage(error),
192
+ ...(suggestions.length > 0 ? { suggestions } : {}),
193
+ },
194
+ exitCode: error instanceof TdkError ? error.exitCode : 2,
195
+ };
196
+ }
165
197
  export const upCommand = new Command("up")
166
198
  .description("Start all services (optionally filtered by stack)")
167
199
  .alias("deploy")
@@ -173,6 +205,7 @@ export const upCommand = new Command("up")
173
205
  .option("--ignore-drift", "Start even if generated files differ from service.json", false)
174
206
  .option("--ignore-version", "Start even if this flisk is older than minTdkVersion in .tdk/project.json", false)
175
207
  .option("--only <services...>", "Start only these services plus what the Tiltfile enables for them (their dependsOn services and shared infrastructure). With a stack, names must belong to that stack; dependencies may cross stacks")
208
+ .option("--env-file <path>", "Use this project env file for the run instead of .env (for example: --env-file .env.integration)")
176
209
  .option("--json", "Print one JSON object on stdout when the stack is ready or the command fails; implies --quiet", false)
177
210
  .action(async (stackName, options) => {
178
211
  const emit = options.json ? createJsonEmitter("UP_FAILED", "flisk up") : undefined;
@@ -192,6 +225,35 @@ export const upCommand = new Command("up")
192
225
  onFail: (message) => emit?.({ ok: false }, [{ code: "TDK_VERSION_TOO_OLD", message }]),
193
226
  });
194
227
  }
228
+ // The env file of the run. `--env-file` replaces the project .env for this run, so the file is
229
+ // resolved and read before any prerequisite check, any write and any service starts.
230
+ const envFileRoot = versionRoot;
231
+ let envFileSelection;
232
+ if (options.envFile === undefined) {
233
+ // Without the option the project .env is the env file of the run, whatever the environment
234
+ // carries: an inherited TDK_ENV_FILE must not change the default.
235
+ delete process.env[PROJECT_ENV_FILE_VAR];
236
+ }
237
+ if (options.envFile !== undefined) {
238
+ try {
239
+ envFileSelection = selectRunEnvFile(envFileRoot, options.envFile);
240
+ }
241
+ catch (error) {
242
+ const { failure, exitCode } = envFileFailure(error);
243
+ emit?.({ ok: false }, [failure]);
244
+ showErrorAndExit(failure.message, exitCode, failure.suggestions);
245
+ }
246
+ if (envFileSelection && envFileRoot) {
247
+ applyEnvFileSelection(envFileSelection);
248
+ if (!options.quiet) {
249
+ console.log(chalk.gray(`Using env file: ${envFileSelection.relativePath} (the project .env is not read in this run)`));
250
+ }
251
+ const warning = envFileWarning(envFileRoot, envFileSelection);
252
+ // stderr, not stdout: in --json mode stdout carries the JSON envelope only.
253
+ if (warning)
254
+ console.warn(chalk.yellow(warning));
255
+ }
256
+ }
195
257
  const hostRefusal = options.dryRun ? null : await hostUpRefusal();
196
258
  if (hostRefusal) {
197
259
  emit?.({ ok: false }, [{ code: "HOST_UNSUPPORTED", message: hostRefusal }]);
@@ -281,7 +343,8 @@ export const upCommand = new Command("up")
281
343
  if (!options.dryRun) {
282
344
  // An older project's .env predates keys such as JWT_SECRET, which Compose now requires. Add what is missing (never
283
345
  // changing an existing value) before anything starts. Only inside a real project, so a stray run never writes a .env.
284
- if (foundRoot) {
346
+ // A selected env file replaces the project .env for this run: the run does not read it, so it is not completed either.
347
+ if (foundRoot && !envFileSelection) {
285
348
  const addedEnvKeys = completeEnvFile(projectRoot);
286
349
  if (addedEnvKeys.length > 0 && !options.quiet) {
287
350
  console.log(chalk.gray(`Added ${addedEnvKeys.join(", ")} to .env (generated; existing values unchanged)`));
@@ -418,6 +481,14 @@ export const upCommand = new Command("up")
418
481
  only: Boolean(options.only),
419
482
  });
420
483
  if (decision.action === "already-running") {
484
+ // The env file of the run belongs to the Tilt process this run starts. A stack that is
485
+ // already running keeps the env file it started with, so the selection would be ignored
486
+ // silently - say so instead of reporting a run that never happened.
487
+ if (envFileSelection) {
488
+ const message = `A Tilt is already running on port ${decision.ports.join(", ")}. --env-file applies to a new run only: run \`flisk down\` first, or pass --force to replace the running stack.`;
489
+ emit?.({ ok: false }, [{ code: "ENV_FILE_ALREADY_RUNNING", message }]);
490
+ showErrorAndExit(message);
491
+ }
421
492
  const message = `Environment is already running on port ${decision.ports.join(", ")}.`;
422
493
  emit?.({
423
494
  ok: true,
@@ -553,7 +624,10 @@ export const upCommand = new Command("up")
553
624
  console.warn(chalk.yellow(ignoreWarning));
554
625
  const results = await runSmokePlans(smokePlans, {
555
626
  recordDir: join(projectRoot, ".tdk", "smoke"),
556
- ...safeSmokeDeps(projectRoot, (message) => console.warn(chalk.yellow(message))),
627
+ ...safeSmokeDeps(projectRoot, (message) => console.warn(chalk.yellow(message)), {
628
+ // The selected env file holds secrets as much as the project .env.
629
+ envFiles: envFileSelection ? [envFileSelection.path] : [],
630
+ }),
557
631
  });
558
632
  for (const smokeResult of results) {
559
633
  if (smokeResult.ok) {
@@ -12,7 +12,7 @@ import { PACKAGE_JSON } from "../utils/constants.js";
12
12
  import { getErrorMessage, logVerbose, showErrorAndExit } from "../utils/errors.js";
13
13
  import { showCancelled } from "../utils/formatting.js";
14
14
  import { getPackageVersion } from "../utils/paths.js";
15
- import { binaryAssetName, executableName, isWindows, legacyExecutableName, } from "../utils/platform.js";
15
+ import { binaryAssetName, executableName, isWindows } from "../utils/platform.js";
16
16
  import { promptConfirm } from "../utils/prompt.js";
17
17
  import { startSpinner } from "../utils/spinner.js";
18
18
  import { extractTarball } from "../utils/tar.js";
@@ -33,11 +33,7 @@ export function isStandaloneBinary(tdkPath) {
33
33
  /** @internal Exported for unit tests only; not part of the package API. */
34
34
  export function classifyRunningInstall(execPath, scriptPath, platformName = process.platform) {
35
35
  const runningName = (platformName === "win32" ? win32.basename(execPath) : basename(execPath)).toLowerCase();
36
- const isFliskBinary = runningName === "flisk" ||
37
- runningName === "flisk.exe" ||
38
- runningName === "tdk" ||
39
- runningName === "tdk.exe";
40
- if (isFliskBinary) {
36
+ if (runningName === "flisk" || runningName === "tdk.exe") {
41
37
  return { method: "binary", path: execPath };
42
38
  }
43
39
  if (runningName === "node" || runningName === "node.exe") {
@@ -61,7 +57,7 @@ export function detectInstallation() {
61
57
  if (runningInstall)
62
58
  return runningInstall;
63
59
  try {
64
- const tdkPath = findOnPath(executableName()) ?? findOnPath(legacyExecutableName());
60
+ const tdkPath = findOnPath(executableName());
65
61
  if (!tdkPath)
66
62
  return { method: "unknown" };
67
63
  // `readlink -f` is not available on macOS. Use Node's cross-platform
@@ -84,7 +80,7 @@ export function detectInstallation() {
84
80
  if (existsSync(join(cliRoot, ".git"))) {
85
81
  return { method: "git", path: cliRoot };
86
82
  }
87
- // Standalone prebuilt binary from tdk-cli-releases (installed to e.g. /usr/local/bin),
83
+ // Standalone prebuilt binary from flisk-sh/releases (installed to e.g. /usr/local/bin),
88
84
  // not a node_modules/.bun link and not sitting inside a git checkout.
89
85
  if (isStandaloneBinary(realPath)) {
90
86
  return { method: "binary", path: realPath };
@@ -138,8 +134,8 @@ export function detectAllInstallations() {
138
134
  }
139
135
  return [...unique.values()];
140
136
  }
141
- const BINARY_RELEASE_REPO = "flisk-sh/tdk-cli-releases";
142
- const ENGINE_ASSET_NAME = "flisk-cli-engine.tar.gz";
137
+ const BINARY_RELEASE_REPO = "flisk-sh/releases";
138
+ const ENGINE_ASSET_NAME = "tdk-cli-engine.tar.gz";
143
139
  const CHECKSUMS_ASSET_NAME = "checksums.txt";
144
140
  /** Parses `shasum -a 256` / `sha256sum` output ("<hash> <name>" or "<hash> *<name>"). */
145
141
  /** @internal Exported for unit tests only; not part of the package API. */
@@ -361,10 +357,27 @@ export async function getLatestVersion() {
361
357
  return null;
362
358
  }
363
359
  }
360
+ /**
361
+ * Removes the package the CLI shipped under before the rename. It owns the old `flisk` command,
362
+ * so npm and bun refuse to install @flisk-sh/flisk next to it (EEXIST) and the upgrade dies
363
+ * before it starts. The removal is best effort: the package is often not installed at all.
364
+ */
365
+ function removeLegacyInstallation(manager) {
366
+ const command = manager === "npm"
367
+ ? "npm uninstall -g @tdk-landscape/tdk-cli-core"
368
+ : "bun remove -g @tdk-landscape/tdk-cli-core";
369
+ try {
370
+ execSync(command, { stdio: ["ignore", "ignore", "ignore"], timeout: 60000 });
371
+ }
372
+ catch {
373
+ // Not installed under the old name, or the manager is missing. Nothing to remove.
374
+ }
375
+ }
364
376
  /** @internal Exported for unit tests only; not part of the package API. */
365
377
  export async function upgradeViaNpm() {
366
378
  const spinner = startSpinner("Upgrading via npm...");
367
379
  try {
380
+ removeLegacyInstallation("npm");
368
381
  execSync("npm install -g @flisk-sh/flisk@latest", {
369
382
  stdio: ["inherit", "inherit", "pipe"],
370
383
  timeout: 120000,
@@ -389,8 +402,8 @@ export async function upgradeViaNpm() {
389
402
  console.log(chalk.gray("\nFor EACCES or EPERM, fix npm's global prefix or use the binary installer:"));
390
403
  console.log(chalk.cyan(" https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally/"));
391
404
  console.log(chalk.cyan(isWindows()
392
- ? " irm https://tdk-landscape.github.io/install.ps1 | iex"
393
- : " curl -fsSL https://tdk-landscape.github.io/install.sh | sh"));
405
+ ? " irm https://flisk.sh/install.ps1 | iex"
406
+ : " curl -fsSL https://flisk.sh/install.sh | sh"));
394
407
  }
395
408
  return false;
396
409
  }
@@ -399,6 +412,7 @@ export async function upgradeViaNpm() {
399
412
  export async function upgradeViaBun() {
400
413
  const spinner = startSpinner("Upgrading via bun...");
401
414
  try {
415
+ removeLegacyInstallation("bun");
402
416
  execFileSync(findOnPath("bun") ?? "bun", ["install", "-g", "@flisk-sh/flisk@latest"], {
403
417
  stdio: "inherit",
404
418
  timeout: 120000,
@@ -639,7 +653,7 @@ export function createUpgradeCommand() {
639
653
  showErrorAndExit("Flisk Windows v1 supports AMD64 only. Use WSL2 Ubuntu or a 64-bit Intel/AMD PC.");
640
654
  }
641
655
  if (process.platform === "win32") {
642
- showErrorAndExit("No Windows AMD64 binary in this Flisk release. Need asset flisk-windows-amd64.exe.");
656
+ showErrorAndExit("No Windows AMD64 binary in this Flisk release. Need asset tdk-windows-amd64.exe.");
643
657
  }
644
658
  showErrorAndExit(`Unsupported OS: Flisk does not support this OS: ${process.platform}. Supported: linux, darwin, win32.`);
645
659
  }
@@ -771,7 +785,7 @@ export function createUpgradeCommand() {
771
785
  else if (installInfo.method === "binary" && binaryRelease && installInfo.path) {
772
786
  const engineDir = join(dirname(installInfo.path), "tdk-cli");
773
787
  if (isWindows()) {
774
- console.log(chalk.cyan(" irm https://tdk-landscape.github.io/install.ps1 | iex"));
788
+ console.log(chalk.cyan(" irm https://flisk.sh/install.ps1 | iex"));
775
789
  }
776
790
  else {
777
791
  console.log(chalk.cyan(` curl -fsSL -o ${installInfo.path} ${binaryRelease.downloadUrl}`));
@@ -17,14 +17,14 @@
17
17
  // template-engine.ts - Verdaccio and Sablier's real gate is the file
18
18
  // overlay above (their public files are disabled stubs, not gated code).
19
19
  //
20
- // The worker (tdk-extension-dist) is the real access-control boundary: it
20
+ // The worker (flisk-extension-dist) is the real access-control boundary: it
21
21
  // checks the key against BUNDLES_REPO/keys/*.json - existence, activation/
22
22
  // expiry dates, granted resources, and a per-key project limit - before
23
23
  // serving anything. This client just asks and, if granted, unpacks the
24
24
  // result over the vendored stub files so the generator pipeline picks up
25
25
  // the real implementations transparently. See
26
- // tdk-extension-dist/src/index.ts for the server-side enforcement and
27
- // tdk-extension-dist/src/project-limit.ts for the project-limit logic.
26
+ // flisk-extension-dist/src/index.ts for the server-side enforcement and
27
+ // flisk-extension-dist/src/project-limit.ts for the project-limit logic.
28
28
  import { randomUUID } from "node:crypto";
29
29
  import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
30
30
  import { homedir } from "node:os";
@@ -23,12 +23,12 @@ export function loadTemplate(filename) {
23
23
  path.join(__dirname, "..", "..", "templates"), // Standard: dist/generator -> templates (also covers src/generator -> ../../templates in dev/test)
24
24
  path.join(__dirname, "..", "templates"), // Installed: dist/generator -> dist/templates
25
25
  path.join(__dirname, "..", "..", "..", "templates"), // Development: cli/dist/generator -> cli/templates
26
- path.join(process.cwd(), "node_modules", "flisk", "templates"), // Monorepo root
26
+ path.join(process.cwd(), "node_modules", "@flisk-sh", "flisk", "templates"), // Monorepo root
27
27
  // Compiled single-file binary (bun build --compile): __dirname resolves inside the
28
28
  // virtual $bunfs filesystem, not a real path, so fall back to the directory the actual
29
- // executable lives in. release-binaries.sh bundles cli/templates at flisk/cli/templates
29
+ // executable lives in. release-binaries.sh bundles cli/templates at tdk-cli/cli/templates
30
30
  // next to the platform binaries.
31
- path.join(path.dirname(process.execPath), "flisk", "cli", "templates"),
31
+ path.join(path.dirname(process.execPath), "tdk-cli", "cli", "templates"),
32
32
  ];
33
33
  const triedPaths = [];
34
34
  for (const templateDir of templateDirs) {
@@ -587,8 +587,8 @@ export function findCliAssetRoot() {
587
587
  }
588
588
  const exeDir = path.dirname(process.execPath);
589
589
  const candidates = [
590
- path.join(exeDir, "flisk"),
591
- path.join(process.cwd(), "node_modules", "flisk"),
590
+ path.join(exeDir, "tdk-cli"),
591
+ path.join(process.cwd(), "node_modules", "@flisk-sh", "flisk"),
592
592
  ];
593
593
  return (candidates.find((candidate) => fs.existsSync(path.join(candidate, "shared-platform-engineering", "docker-templates"))) ?? null);
594
594
  }
@@ -624,7 +624,7 @@ async function vendorTdkExtension(projectRoot) {
624
624
  // 1. $TDK_EXTENSION_SOURCE (explicit override)
625
625
  // 2. Self-contained repo (engine/ ships next to cli/ - public flisk)
626
626
  // 3. Executable-adjacent checkout (bundled installs)
627
- // 4. Relative ../flisk sibling (monorepo maintainer layout)
627
+ // 4. Relative ../tdk-cli sibling (monorepo maintainer layout)
628
628
  const sources = [];
629
629
  if (process.env.TDK_EXTENSION_SOURCE) {
630
630
  sources.push(process.env.TDK_EXTENSION_SOURCE);
@@ -641,8 +641,8 @@ async function vendorTdkExtension(projectRoot) {
641
641
  // Bun's process object - it was always undefined, silently falling
642
642
  // back to cwd() instead of the binary's real location.
643
643
  const exeDir = path.dirname(process.execPath);
644
- sources.push(path.join(exeDir, "flisk"));
645
- sources.push(path.join(projectRoot, "..", "flisk"));
644
+ sources.push(path.join(exeDir, "tdk-cli"));
645
+ sources.push(path.join(projectRoot, "..", "tdk-cli"));
646
646
  let sourceRoot = "";
647
647
  for (const candidate of sources) {
648
648
  if (candidate &&
@@ -79,10 +79,7 @@ export function toToolResult(run) {
79
79
  return {
80
80
  data: {
81
81
  errors: [
82
- {
83
- code: "NO_JSON",
84
- message: run.stderr.trim() || `flisk exited with code ${run.exitCode}`,
85
- },
82
+ { code: "NO_JSON", message: run.stderr.trim() || `flisk exited with code ${run.exitCode}` },
86
83
  ],
87
84
  },
88
85
  isError: true,
@@ -123,7 +120,7 @@ export const defaultUpDeps = {
123
120
  },
124
121
  sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
125
122
  now: () => Date.now(),
126
- logFile: () => join(tmpdir(), `flisk-mcp-up-${Date.now()}.log`),
123
+ logFile: () => join(tmpdir(), `tdk-mcp-up-${Date.now()}.log`),
127
124
  };
128
125
  export function buildUpArgs(args) {
129
126
  const stack = optionalName(args.stack, "stack");
@@ -20,6 +20,8 @@ export function createProgram() {
20
20
  .description("Flisk CLI — start services on your machine.")
21
21
  .version(pkg.version, "-v, --version", "Display version number")
22
22
  .option("--verbose", "Enable verbose output", false)
23
+ .option("--template <name>", "Create a project from a starter template in one command (restaurant, saas, erp, ecommerce, example)")
24
+ .option("--project <dir>", "Directory to create the project in (default: the template name)")
23
25
  .configureOutput({
24
26
  outputError: (str, write) => write(chalk.red(str)),
25
27
  writeOut: (str) => process.stdout.write(str),