@flisk-sh/flisk 1.4.0 → 1.4.2

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 (44) hide show
  1. package/README.md +305 -52
  2. package/cli/dist/commands/doctor.js +62 -0
  3. package/cli/dist/commands/runtime.js +6 -3
  4. package/cli/dist/generator/template-engine.js +7 -4
  5. package/cli/dist/utils/runtime-layout.js +7 -0
  6. package/cli/dist-bundle/{chunk-QQEV6D74.js → chunk-3XODDLRJ.js} +1 -1
  7. package/cli/dist-bundle/{chunk-VMB5673O.js → chunk-43XWL2PB.js} +30 -26
  8. package/cli/dist-bundle/{chunk-5EZ4EX6U.js → chunk-53L2JN7G.js} +1 -1
  9. package/cli/dist-bundle/{chunk-BWK6MPCB.js → chunk-5F7YP5IR.js} +1 -1
  10. package/cli/dist-bundle/{chunk-36SOQVAL.js → chunk-5QBYM33Q.js} +1 -1
  11. package/cli/dist-bundle/{chunk-HEMPQKD6.js → chunk-DU2BN46C.js} +1 -1
  12. package/cli/dist-bundle/{chunk-ICXF6PXA.js → chunk-ETKUVKJ2.js} +2 -2
  13. package/cli/dist-bundle/{chunk-PVBAGX5X.js → chunk-I7TGIK5N.js} +1 -1
  14. package/cli/dist-bundle/{chunk-B6Q5VKL7.js → chunk-IGN5UC3P.js} +1 -1
  15. package/cli/dist-bundle/chunk-MWOVYIBB.js +54 -0
  16. package/cli/dist-bundle/{chunk-D7N2GGJH.js → chunk-YHYRGWUH.js} +1 -1
  17. package/cli/dist-bundle/{chunk-VHFFSBVJ.js → chunk-YNCBBJ4V.js} +1 -1
  18. package/cli/dist-bundle/cli.js +153 -153
  19. package/cli/dist-bundle/{cold-preflight-ABU26DYW.js → cold-preflight-ZOPR7PWJ.js} +1 -1
  20. package/cli/dist-bundle/{demo-stage-EBIUCJBX.js → demo-stage-OHNTP2UJ.js} +1 -1
  21. package/cli/dist-bundle/{open-2KSAF6M2.js → open-XROJ6YEY.js} +1 -1
  22. package/cli/dist-bundle/project-7PTIOHGF.js +2 -0
  23. package/cli/dist-bundle/{services-V6Q55JR5.js → services-BIMF6MVU.js} +1 -1
  24. package/cli/dist-bundle/{tilt-port-owner-MWJ7P6NB.js → tilt-port-owner-ZY5M2JC4.js} +1 -1
  25. package/cli/package.json +1 -1
  26. package/package.json +12 -2
  27. package/runtime/platform/services/platform/proxy/service.yaml +14 -0
  28. package/cli/dist/commands/__tests__/project-e2e-helpers.js +0 -49
  29. package/cli/dist/commands/__tests__/ui-loading-screen.test.js +0 -16
  30. package/cli/dist/generator/__tests__/golden-helpers.js +0 -43
  31. package/cli/dist-bundle/chunk-763VK575.js +0 -54
  32. package/cli/dist-bundle/project-YD3C4ZV3.js +0 -2
  33. package/runtime/discovery/test_resource_snapshot.py +0 -253
  34. package/runtime/engine/assets/docker/wake-gateway/decide.test.ts +0 -177
  35. package/runtime/engine/topologies/tilt/manifest/tests/test_integration.star +0 -278
  36. package/runtime/engine/topologies/tilt/manifest/tests/test_loader_parser.star +0 -475
  37. package/runtime/engine/topologies/tilt/manifest/tests/test_manifest.star +0 -319
  38. package/runtime/engine/topologies/tilt/manifest/tests/test_validator.star +0 -472
  39. package/runtime/ext/ide-components/shared/test_config_service.py +0 -328
  40. /package/{shared-platform-engineering → runtime/shared-platform-engineering}/docker-templates/bun-hoisted-symlink-fix.sh +0 -0
  41. /package/{shared-platform-engineering → runtime/shared-platform-engineering}/docker-templates/infisical-entrypoint.sh +0 -0
  42. /package/{shared-platform-engineering → runtime/shared-platform-engineering}/docker-templates/install-deps.sh +0 -0
  43. /package/{shared-platform-engineering → runtime/shared-platform-engineering}/docker-templates/prisma-bun-client-link-fix.sh +0 -0
  44. /package/{shared-platform-engineering → runtime/shared-platform-engineering}/docker-templates/prisma-normalize-client.sh +0 -0
package/README.md CHANGED
@@ -1,24 +1,145 @@
1
1
  <div align="center">
2
2
 
3
- # Flisk CLI — generate and run your whole tech stack without the setup pain
3
+ # Flisk: your whole stack, running locally with one command
4
4
 
5
- Go from an empty folder to a running tech stack with one command. Built for agents.
5
+ Ask your AI agent for an app, or type four commands yourself.<br />Flisk sets up the containers, database, routing, and secrets, wires them together, and keeps them in sync as you change things.
6
6
 
7
7
  <img src="https://raw.githubusercontent.com/flisk-sh/.github/main/profile/header-flisk.svg" alt="Flisk: your whole stack, running locally with one command." width="100%">
8
8
 
9
+ [![Flisk Discord](https://img.shields.io/badge/Discord-Join%20Server-5865F2?logo=discord&logoColor=white)](https://discord.gg/Sjhb3tnq3)
10
+ [![npm version](https://img.shields.io/npm/v/@flisk-sh/flisk.svg?style=flat&color=blue)](https://www.npmjs.com/package/@flisk-sh/flisk) [![npm weekly downloads](https://img.shields.io/npm/dw/@flisk-sh/flisk?style=flat&color=blue)](https://www.npmjs.com/package/@flisk-sh/flisk) [![GitHub stars](https://img.shields.io/github/stars/flisk-sh/flisk?style=flat&logo=github)](https://github.com/flisk-sh/flisk/stargazers) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
11
+
12
+ <a href="https://trendshift.io/repositories/266432?utm_source=trendshift-badge&amp;utm_medium=badge&amp;utm_campaign=badge-trendshift-266432" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/trendshift/repositories/266432/weekly?language=Starlark" alt="flisk-sh%2Fflisk | Trendshift" width="250" height="55"/></a>
13
+
14
+ <img src="docs/assets/demo-ai.svg" alt="An AI coding agent builds a small online shop with Flisk and runs it locally" width="900" />
15
+
16
+ <sub>An illustrative agent session. The Flisk commands, and the service list and URLs Flisk prints, come from a real run. Copy the prompt from <a href="#with-your-ai-agent">Try it</a>.</sub>
17
+
18
+ </div>
19
+
20
+ ## Trusted by
21
+
22
+ <table align="center">
23
+ <tr><td align="center" valign="middle"><a href="https://www.linkedin.com/company/lekast/"><img src="docs/assets/trusted-by/lekast.png" alt="Lekast" height="64"></a></td><td align="center" valign="middle"><a href="https://medium.com/@mfin.services"><img src="docs/assets/trusted-by/mfin-services.png" alt="MFin Services" height="64"></a></td><td align="center" valign="middle"><a href="https://www.linkedin.com/company/makeofferio"><img src="docs/assets/trusted-by/makeoffer.png" alt="MakeOffer" height="64"></a></td><td align="center" valign="middle"><a href="https://redmoon.digital/"><img src="docs/assets/trusted-by/redmoon-digital.png" alt="RedMoon.Digital" height="64"></a></td></tr>
24
+ </table>
25
+
26
+ <p align="center"><sub>Teams that run <code>flisk up</code> on their own code, listed with their consent. <a href="docs/project/ADOPTERS.md">See all adopters</a> or <a href="https://github.com/flisk-sh/flisk/issues/new?template=we-use-flisk.yml">add yours</a>.</sub></p>
27
+
28
+ ## Try it
29
+
30
+ ### With your AI agent
31
+
32
+ Install Flisk, then paste a prompt into your coding agent. Claude Code, Codex, Cursor, GitHub Copilot, and any other agent that can run commands will work. Every block below has a copy button.
33
+
34
+ ```bash
35
+ npm install -g @flisk-sh/flisk
36
+ ```
37
+
38
+ **The prompt from the demo:**
39
+
40
+ ```text
41
+ Build me a small online shop with a storefront and an orders API, and run it on my laptop with Flisk.
42
+ ```
43
+
44
+ Your agent creates the project, adds each part, and starts it. If something is missing on your computer, `flisk doctor` tells it what to fix.
45
+
46
+ <details>
47
+ <summary>More prompts to copy</summary>
48
+
49
+ **Add a service to a project you already have**
50
+
51
+ ```text
52
+ Use Flisk to add a backend service called payments-api to my shop stack, then start the stack and give me the URLs.
53
+ ```
54
+
55
+ **Build an AI agent with tools and a database**
56
+
57
+ ```text
58
+ Use Flisk to scaffold an AI agent, an MCP tools server, and a database in one stack called shop, then start it and tell me how to talk to the agent.
59
+ ```
60
+
61
+ **Something is not working**
62
+
63
+ ```text
64
+ Run flisk doctor, explain every problem in plain words, and fix what you can. Then start my stack with flisk up.
65
+ ```
66
+
67
+ **See what is running**
68
+
69
+ ```text
70
+ Use flisk status to tell me which services are running, which are unhealthy, and what URL each one has.
71
+ ```
72
+
73
+ **Stop everything**
74
+
75
+ ```text
76
+ Stop my Flisk stack with flisk down and confirm nothing is left running.
77
+ ```
78
+
79
+ </details>
80
+
81
+ <details>
82
+ <summary>Connect your agent to Flisk as an MCP server</summary>
83
+
84
+ Add this to your agent's MCP settings:
85
+
86
+ ```json
87
+ {
88
+ "mcpServers": {
89
+ "flisk": { "command": "flisk", "args": ["mcp"] }
90
+ }
91
+ }
92
+ ```
93
+
94
+ The agent can then start the stack, check status, restart a service, and read agent sessions through Flisk tools instead of shell commands. See [use Flisk with your AI agent](#use-flisk-with-your-ai-agent).
95
+
96
+ </details>
97
+
98
+ ### In your terminal
99
+
100
+ <p align="center">
101
+ <img src="docs/assets/demo-cli.svg" alt="Four flisk commands create a project, an API, and a website, then start them" width="900" />
102
+ </p>
103
+
104
+ ```bash
105
+ npm install -g @flisk-sh/flisk
106
+ mkdir my-shop && cd my-shop
107
+ flisk project --yes
108
+ flisk resource orders-api --type backend --stack shop --yes
109
+ flisk resource shop-web --type frontend --stack shop --yes
110
+ flisk up shop
111
+ ```
112
+
113
+ You get an orders API and a storefront behind one local gateway, with Postgres and live reload. You need Docker, [Tilt](https://docs.tilt.dev/install.html), Node.js 22.12+, and [Bun](https://bun.sh/) 1.2+; `flisk doctor` checks your machine. Prefer to answer questions instead? `npm init create-microservices my-project` asks what to create. See the [quick start](#quick-start) for every option.
114
+
115
+ <div align="center">
116
+
117
+ <p><strong><a href="#quick-start">Quick start</a> · <a href="#why-flisk-cli">Why Flisk</a> · <a href="#examples">Examples</a> · <a href="#installation">Installation</a> · <a href="#faq">FAQ</a> · <a href="#docs">Documentation</a></strong></p>
118
+
119
+ [Website](https://flisk.sh/) · [Quickstart](https://flisk.sh/docs/quickstart/) · [Examples](https://flisk.sh/docs/examples/) · [Awesome Flisk](https://github.com/flisk-sh/awesome-tdk-framework) · [Demo](https://flisk-sh.github.io/flisk-demo-animation/) · [Report a bug](https://github.com/flisk-sh/flisk/issues)
120
+
121
+ <a id="readme-languages"></a>
122
+
123
+ <p align="center">
124
+
125
+ English | [简体中文](docs/README-zh_cn.md) | [繁體中文](docs/README-zh_tw.md) | [日本語](docs/README-ja.md) | [한국어](docs/README-ko.md) | [Türkçe](docs/README-tr.md) | [Tiếng Việt](docs/README-vi.md) | [ไทย](docs/README-th.md) | [Deutsch](docs/README-de.md) | [Español](docs/README-es.md) | [Français](docs/README-fr.md) | [Українська](docs/README-uk.md) | [Polski](docs/README-pl.md) | [Português (Brasil)](docs/README-pt-BR.md) | [العربية](docs/README-ar.md) | [فارسی](docs/README-fa.md) | [Bahasa Indonesia](docs/README-id.md) | [Italiano](docs/README-it.md) | [Ελληνικά](docs/README-el.md) | [മലയാളം](docs/README-ml.md)
126
+
127
+ </p>
128
+
129
+ <details>
130
+ <summary>Test, scale, and security status</summary>
9
131
 
10
- [![Flisk Discord](https://img.shields.io/badge/Discord-Join%20Server-5865F2?logo=discord&logoColor=white)](https://discord.gg/JG6r33HVB)
11
- [![npm version](https://img.shields.io/npm/v/@flisk-sh/flisk.svg?style=flat&color=blue)](https://www.npmjs.com/package/@flisk-sh/flisk) [![npm weekly downloads](https://img.shields.io/npm/dw/@flisk-sh/flisk?style=flat&color=blue)](https://www.npmjs.com/package/@flisk-sh/flisk) [![unpacked size](https://img.shields.io/npm/unpacked-size/@flisk-sh/flisk)](https://packagephobia.com/result?p=@flisk-sh/flisk) [![install size](https://badgen.net/packagephobia/install/@flisk-sh/flisk)](https://packagephobia.com/result?p=@flisk-sh/flisk) [![GitHub stars](https://img.shields.io/github/stars/flisk-sh/flisk?style=flat&logo=github)](https://github.com/flisk-sh/flisk/stargazers) [![OSS Insight](https://img.shields.io/badge/OSS%20Insight-analytics-blue)](https://ossinsight.io/analyze/flisk-sh/flisk) [![X followers: 1,605](https://img.shields.io/badge/X%20followers-1%2C605-1DA1F2?style=flat&logo=x&logoColor=white)](https://x.com/brookservers)
12
132
  [![Journeys E2E](https://github.com/flisk-sh/flisk/actions/workflows/e2e-journeys.yml/badge.svg)](https://github.com/flisk-sh/flisk/actions/workflows/e2e-journeys.yml) [![ERP fixture scale E2E](https://github.com/flisk-sh/flisk/actions/workflows/e2e-scale-full.yml/badge.svg)](https://github.com/flisk-sh/flisk/actions/workflows/e2e-scale-full.yml) [![Example apps E2E](https://github.com/flisk-sh/flisk/actions/workflows/e2e-real-apps.yml/badge.svg?branch=main)](https://github.com/flisk-sh/flisk/actions/workflows/e2e-real-apps.yml) [![CodeQL](https://github.com/flisk-sh/flisk/actions/workflows/codeql.yml/badge.svg?branch=main)](https://github.com/flisk-sh/flisk/security/code-scanning) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/flisk-sh/flisk/badge)](https://scorecard.dev/viewer/?uri=github.com/flisk-sh/flisk) [![Known Vulnerabilities](https://snyk.io/test/github/flisk-sh/flisk/badge.svg)](https://snyk.io/test/github/flisk-sh/flisk) [![Socket Badge](https://badge.socket.dev/npm/package/@flisk-sh/flisk/latest)](https://socket.dev/npm/package/@flisk-sh/flisk/overview)
13
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
14
133
 
15
134
  [![ERP backends healthy](https://img.shields.io/badge/ERP%20backends%20healthy-100%2F100-brightgreen)](https://github.com/flisk-sh/flisk/actions/runs/39160719471) [![ERP time to all healthy](https://img.shields.io/badge/ERP%20time%20to%20all%20healthy-524s-blue)](https://github.com/flisk-sh/flisk/actions/runs/39160719471) [![ERP frontends answering](https://img.shields.io/badge/ERP%20frontends%20answering-7%2F7-brightgreen)](https://github.com/flisk-sh/flisk/actions/runs/39160719471) [![ERP running containers](https://img.shields.io/badge/ERP%20running%20containers-109-blue)](https://github.com/flisk-sh/flisk/actions/runs/39160719471) [![ERP memory used](https://img.shields.io/badge/ERP%20memory%20used-1736%20MiB-blue)](https://github.com/flisk-sh/flisk/actions/runs/39160719471)
16
135
  [![Test coverage](https://raw.githubusercontent.com/flisk-sh/flisk/main/docs/assets/coverage.svg)](https://github.com/flisk-sh/flisk/blob/main/docs/assets/coverage.svg)
17
136
 
18
137
  <sub>ERP fixture scale run on a clean GitHub-hosted runner (4 vCPU, 15 GB RAM), snapshot from [run 39160719471](https://github.com/flisk-sh/flisk/actions/runs/39160719471). The live status is in the ERP fixture scale E2E badge above.</sub>
19
138
 
139
+ [![unpacked size](https://img.shields.io/npm/unpacked-size/@flisk-sh/flisk)](https://packagephobia.com/result?p=@flisk-sh/flisk) [![install size](https://badgen.net/packagephobia/install/@flisk-sh/flisk)](https://packagephobia.com/result?p=@flisk-sh/flisk) [![OSS Insight](https://img.shields.io/badge/OSS%20Insight-analytics-blue)](https://ossinsight.io/analyze/flisk-sh/flisk) [![X followers: 1,605](https://img.shields.io/badge/X%20followers-1%2C605-1DA1F2?style=flat&logo=x&logoColor=white)](https://x.com/brookservers)
140
+
20
141
  <a href="https://trendshift.io/repositories/266432?utm_source=trendshift-badge&amp;utm_medium=badge&amp;utm_campaign=badge-trendshift-266432" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/trendshift/repositories/266432/daily?language=Starlark" alt="flisk-sh%2Fflisk | Trendshift" width="250" height="55"/></a>
21
- <a href="https://trendshift.io/repositories/266432?utm_source=trendshift-badge&amp;utm_medium=badge&amp;utm_campaign=badge-trendshift-266432" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/trendshift/repositories/266432/weekly?language=Starlark" alt="flisk-sh%2Fflisk | Trendshift" width="250" height="55"/></a>
142
+
22
143
  <p align="center">
23
144
  <a href="https://www.bestpractices.dev/projects/15310">
24
145
  <img src="https://www.bestpractices.dev/assets/openssf_bestpracticesbadge-a908f4124737f3d6b2c5abc82756bd2a435cff474b45615ce469746c31a4288c.svg" alt="OpenSSF Best Practices" height="80" align="middle" style="vertical-align: middle" />
@@ -28,19 +149,7 @@ Go from an empty folder to a running tech stack with one command. Built for agen
28
149
  </a>
29
150
  </p>
30
151
 
31
- <br />
32
-
33
- <a id="readme-languages"></a>
34
-
35
- <p align="center">
36
-
37
- English | [简体中文](docs/README-zh_cn.md) | [繁體中文](docs/README-zh_tw.md) | [日本語](docs/README-ja.md) | [한국어](docs/README-ko.md) | [Türkçe](docs/README-tr.md) | [Tiếng Việt](docs/README-vi.md) | [ไทย](docs/README-th.md) | [Deutsch](docs/README-de.md) | [Español](docs/README-es.md) | [Français](docs/README-fr.md) | [Українська](docs/README-uk.md) | [Polski](docs/README-pl.md) | [Português (Brasil)](docs/README-pt-BR.md) | [العربية](docs/README-ar.md) | [فارسی](docs/README-fa.md) | [Bahasa Indonesia](docs/README-id.md) | [Italiano](docs/README-it.md) | [Ελληνικά](docs/README-el.md) | [മലയാളം](docs/README-ml.md)
38
-
39
- </p>
40
-
41
- <br />
42
-
43
- [Website](https://flisk.sh/) · [Quickstart](https://flisk.sh/docs/quickstart/) · [Examples](https://flisk.sh/docs/examples/) · [Awesome Flisk](https://github.com/flisk-sh/awesome-tdk-framework) · [Demo](https://flisk-sh.github.io/flisk-demo-animation/) · [Report a bug](https://github.com/flisk-sh/flisk/issues)
152
+ </details>
44
153
 
45
154
  </div>
46
155
 
@@ -114,8 +223,9 @@ Fastest way (recommended): open the [Flisk starter](https://github.com/flisk-sh/
114
223
 
115
224
  </details>
116
225
 
117
- ### ⚡ Zero-Config Local Stacks in About 14 Seconds
118
- No vendor lock-in. No tedious plumbing. Run a single command to natively orchestrate **72 different integration tiers** including:
226
+ ### ⚡ A running stack in about 14 seconds
227
+
228
+ On a one-backend quickstart with warm image layers, `flisk up` reaches a healthy API in 12.8 to 13.8 seconds ([timing notes](docs/benchmarks/quickstart-timing.md)). An 8-service stack settles in 32 to 42 seconds warm and about 4.5 minutes on its first cold build ([benchmark](docs/benchmarks/results/tdk-up-warm-start-2026-10-11/summary.md)). No vendor lock-in and no hand-written plumbing. Flisk works with:
119
229
  * **Runtimes & Frameworks:** Bun, Node, Python, Go, Rust, React, Vue, Svelte, Elysia, Fastify, NestJS
120
230
  * **Databases & Tooling:** Prisma, Drizzle, Atlas, Dbmate
121
231
  * **Messaging & Gateway:** NATS, Traefik
@@ -134,11 +244,11 @@ flisk up shop
134
244
  Agents get durable checkpoint volumes that survive `flisk down`, sticky session routing via `x-session-id`, graceful SIGTERM drain during hot reloads, a Docker health check on `/health`, and application-level readiness checks on `/ready`. See the [AI agents guide](docs/agents/ai-agents.md) and [honest comparison with agent frameworks](docs/compare-honest.md#ai-agent-frameworks-and-workflow-engines-libfx-langgraph-mastra-vercel-workflows-temporal).
135
245
 
136
246
 
137
- Flisk CLI — start services on your machine. It is not a deploy and not a Compose file: define each service in `service.json`, then run `flisk up`. No Kubernetes is needed on the machine.
247
+ **What Flisk is:** a local development runtime. Define each service in `service.json` and run `flisk up`. Docker runs the containers, Tilt live-updates them while you code, and Flisk writes the configuration both use. No local Kubernetes is needed.
138
248
 
139
- Stability: 1.x local dev. Write `service.json`; Flisk generates the local runtime files. See [what Flisk writes](docs/generated-files.md) and how to check for drift. Core CLI is MIT and needs no key. Premium is optional.
249
+ **What Flisk is not:** a deploy tool or a Compose file. Production deployment stays with Helm, Argo CD, or Kustomize.
140
250
 
141
- Docker runs the containers. Tilt watches services and live-updates containers while you code. Flisk CLI writes the configuration Tilt uses. Production deployment stays with Helm, Argo CD, or Kustomize.
251
+ Stability: 1.x. The core CLI is MIT and needs no key; Premium is optional. See [what Flisk writes](docs/generated-files.md) and how to check for drift.
142
252
 
143
253
 
144
254
  > [!IMPORTANT]
@@ -147,12 +257,6 @@ Docker runs the containers. Tilt watches services and live-updates containers wh
147
257
  > [official website](https://flisk.sh/). Follow the installation links from these official sources.
148
258
  > A similar repository name or copied README does not establish that a download is official.
149
259
 
150
- <p align="center"><strong><a href="#quick-start">Quick start</a> · <a href="#why-flisk-cli">Why Flisk</a> · <a href="#examples">Examples</a> · <a href="#installation">Installation</a> · <a href="#faq">FAQ</a> · <a href="#docs">Documentation</a></strong></p>
151
-
152
- If Flisk helps you run your local stack, a ⭐ on [this repo](https://github.com/flisk-sh/flisk) helps other developers find it.
153
-
154
- `flisk ui` opens an interactive terminal dashboard for inspecting running services. Move with `↑/↓` or `j/k`, search with `/`, and press `1`–`5` to jump between tabs. See [docs/ui.md](docs/ui.md) for every key binding.
155
-
156
260
  ## Why Flisk CLI?
157
261
 
158
262
  - **One `service.json` per service.** Flisk generates the Dockerfile, Traefik routing, and Tiltfile from it. You do not hand-write a `docker-compose.yml` or `nginx.conf`.
@@ -178,6 +282,22 @@ See the [detailed tool comparison](docs/comparison.md) for architectural tradeof
178
282
 
179
283
  Production deployment stays with your own tools (Helm, Argo CD, or Kustomize).
180
284
 
285
+ ### Everything is wired together, and stays in sync
286
+
287
+ You do not connect services by hand. Flisk derives each connection from the same `service.json` files and regenerates it when they change.
288
+
289
+ | When you... | Flisk updates |
290
+ | --- | --- |
291
+ | Add a service with `flisk resource` | It is discovered automatically and its stack is enabled on the next `flisk up`. It gets an image build, a Compose entry, gateway routes, a health check, and its own `.autogenerated/` files. |
292
+ | Edit a `service.json` (port, `dependsOn`, features) | The Dockerfile, Compose entry, Traefik labels, and nginx config are regenerated on the next `flisk up`. A hand edit to a generated file is caught as drift before anything starts. |
293
+ | Edit your code | Tilt live-updates the running container. No rebuild step. |
294
+ | Add a backend route | Frontends already point at the API through generated `VITE_API_URL`, `env.ts`, and `api-client.ts`, built from the same hostnames the gateway routes. |
295
+ | Add a database or a second backend | `DATABASE_URL` and the other connection settings are injected into each service's environment. No copying of passwords or hostnames. |
296
+ | Run on a project with an older or missing `.env` | Missing secrets such as `JWT_SECRET` are generated without overwriting your values. |
297
+ | Declare `dependsOn` | Services start in health-checked order. |
298
+
299
+ See [how `flisk up` works](docs/how-flisk-up-works.md) for the full startup sequence.
300
+
181
301
  ## What you can do with Flisk
182
302
 
183
303
  | You want to | Flisk does | Command |
@@ -268,33 +388,106 @@ curl http://api.shop.localhost/api/orders/health
268
388
 
269
389
  `flisk up` prints the host ports it chose. It uses port 80 when it is free, so URLs carry no port. Otherwise it picks one from 8080-8180, and the URLs it prints include that port (on Linux and WSL2 a non-root user cannot check port 80, so the range is used there). Use the URL `flisk up` prints, or set `FLISK_HTTP_PORT`. A resource named `orders-api` is served at `/api/orders` (a trailing `-api` is dropped); `flisk up` prints the exact URLs.
270
390
 
271
- <p align="center">
272
- <img src="docs/assets/demo.svg" alt="Flisk scaffolding a backend and a frontend, then listing the stack" width="900" />
273
- <br /><br />
274
- <em>Scaffolding a backend and frontend, then listing the stack.</em>
275
- </p>
391
+ ### What Flisk writes for you
276
392
 
277
- ### What Flisk writes for a frontend
393
+ You write one `service.json` per service. For the two-service shop above, Flisk writes the rest at three levels: the project, the stack, and each service.
278
394
 
279
- You maintain `service.json`; Flisk generates the local runtime files. A frontend such as `services/store/storefront-web` has files like these after generation:
395
+ ```text
396
+ my-shop/
397
+ ├── .env # generated DB_PASSWORD and JWT_SECRET
398
+ ├── .flisk/
399
+ │ ├── project.json # project settings (yours to edit)
400
+ │ └── .flisk-out/ # PROJECT LEVEL
401
+ │ ├── Tiltfile # what Tilt runs
402
+ │ ├── docker-compose.traefik.yml # local gateway, bound to 127.0.0.1
403
+ │ ├── golden-layers.Dockerfile # shared base image layers
404
+ │ ├── TILT_TECH_STACK.star # tech stack settings
405
+ │ ├── TILT_RESOURCE_DEFAULTS.star # service defaults
406
+ │ ├── spec.master # project spec by stack
407
+ │ └── flisk-cli-ext/ # pinned copy of the Flisk engine
408
+ ├── shared-platform-engineering/
409
+ │ └── docker-templates/ # container entrypoint scripts
410
+ └── services/
411
+ ├── platform/database-management/
412
+ │ └── docker-compose.yml # Postgres 16
413
+ └── shop/
414
+ ├── .autogenerated/ # STACK LEVEL
415
+ │ └── docker-compose.app.autogenerated.yml # every service in the stack
416
+ ├── orders-api/
417
+ │ ├── service.json # you write this
418
+ │ └── .autogenerated/ # SERVICE LEVEL: 14 files
419
+ └── shop-web/
420
+ ├── service.json # you write this
421
+ └── .autogenerated/ # SERVICE LEVEL: 18 files
422
+ ```
423
+
424
+ The stack's Compose file is the part you would otherwise write by hand. For these two services it holds the image builds, environment, 33 Traefik routing labels, four networks, health checks, and CPU and memory limits. An excerpt:
425
+
426
+ ```yaml
427
+ orders-api:
428
+ environment:
429
+ - DATABASE_URL=postgresql://my_shop:${DB_PASSWORD}@my_shop_postgres:5432/my_shop_shop?schema=public
430
+ - JWT_SECRET=${JWT_SECRET:?JWT_SECRET is not set. Run `flisk up` ...}
431
+ labels:
432
+ - "traefik.http.routers.orders-api-project.rule=Host(`api.my-shop.localhost`) && PathPrefix(`/api/orders`)"
433
+ - "traefik.http.middlewares.orders-api-strip-prefix-project.stripprefix.prefixes=/api/orders"
434
+ - "traefik.http.services.orders-api.loadbalancer.healthcheck.path=/health"
435
+ healthcheck:
436
+ test: ["CMD", "curl", "-f", "--max-time", "5", "http://localhost:4000/health"]
437
+ ```
438
+
439
+ Secrets come from the project `.env` by default: `flisk project` generates a random database password and JWT secret, and `.env` is added to `.gitignore`. Set `FLISK_SECRET_PROVIDER=infisical` to read secrets from [Infisical](https://infisical.com/) instead ([environment](docs/environment.md)).
440
+
441
+ <details>
442
+ <summary>Every file in each service's <code>.autogenerated/</code> folder</summary>
280
443
 
281
444
  ```text
282
- services/store/storefront-web/
283
- ├── service.json # your service definition
284
- └── .autogenerated/ # Flisk writes these files
285
- ├── nginx.autogenerated.conf # serves the build and routes API requests
286
- ├── Dockerfile.app.autogenerated # local app image
287
- ├── .env.frontend.autogenerated # local frontend environment
288
- ├── vite.config.frontend.autogenerated.ts
289
- ├── tsconfig.autogenerated.json
290
- └── api-client.ts # generated API client
445
+ shop-web/.autogenerated/
446
+ ├── Dockerfile.app.autogenerated # app image
447
+ ├── Dockerfile.app.autogenerated.dockerignore # build context
448
+ ├── nginx.autogenerated.conf # serves the build, routes API requests
449
+ ├── vite.config.frontend.autogenerated.ts # dev server
450
+ ├── vite.config.build.autogenerated.ts # production build
451
+ ├── tsconfig.autogenerated.json # TypeScript, host
452
+ ├── tsconfig.docker.autogenerated.json # TypeScript, container
453
+ ├── .npmrc.autogenerated # package registry, host
454
+ ├── .npmrc.docker.autogenerated # package registry, container
455
+ ├── bunfig.autogenerated.toml # Bun settings, host
456
+ ├── bunfig.docker.autogenerated.toml # Bun settings, container
457
+ ├── .env.frontend.autogenerated # frontend environment
458
+ ├── env.ts # API URL for your imports
459
+ ├── api-client.ts # client for the frontend's API route
460
+ ├── api-index.ts # re-exports the client and URL
461
+ ├── service.yaml # Tilt's projection of service.json
462
+ ├── validation-report.autogenerated.json # preflight validation result
463
+ ├── AGENTS.md # tells coding agents not to edit here
464
+ └── .flisk-contract/ # snapshots for drift checks
291
465
  ```
292
466
 
293
- You do not need to write the nginx config, Dockerfile, or a `docker-compose.yml` for this local stack. `flisk up` uses Docker and Tilt to start it. The [generated-files guide](docs/generated-files.md) lists the other outputs and explains how regeneration and drift checks work.
467
+ ```text
468
+ orders-api/.autogenerated/
469
+ ├── Dockerfile.app.autogenerated # app image
470
+ ├── Dockerfile.app.autogenerated.dockerignore # build context
471
+ ├── vite.config.backend.autogenerated.ts # server build
472
+ ├── prisma.config.autogenerated.ts # database client
473
+ ├── tsconfig.autogenerated.json # TypeScript, host
474
+ ├── tsconfig.docker.autogenerated.json # TypeScript, container
475
+ ├── .npmrc.autogenerated # package registry, host
476
+ ├── .npmrc.docker.autogenerated # package registry, container
477
+ ├── bunfig.autogenerated.toml # Bun settings, host
478
+ ├── bunfig.docker.autogenerated.toml # Bun settings, container
479
+ ├── .env.backend.autogenerated # backend environment
480
+ ├── service.yaml # Tilt's projection of service.json
481
+ ├── validation-report.autogenerated.json # preflight validation result
482
+ ├── AGENTS.md # tells coding agents not to edit here
483
+ └── .flisk-contract/ # snapshots for drift checks
484
+ ```
294
485
 
295
- <p align="center">
296
- <img src="docs/assets/flisk-cli-top-9-uses.jpg" alt="Top 9 places to use Flisk CLI" width="900" />
297
- </p>
486
+ A stack with a database migrator also gets `docker-compose.migrator.autogenerated.yml` in the stack folder, and the migrator gets its own `Dockerfile.migrator.autogenerated`.
487
+
488
+ </details>
489
+
490
+ You never write an nginx config, a Dockerfile, a Compose file, or Traefik labels for this stack. `flisk up` regenerates these files when `service.json` changes and refuses to start if one was edited by hand. Python, Go, and Rust services, and optional features such as Playwright, get their own sets; the [generated-files guide](docs/generated-files.md) lists them and explains the drift checks.
298
491
 
299
492
  If Helm, Compose, or your existing Tilt setup already gives you a working local environment, keep using it. Flisk CLI is for engineers managing several services who want a clear local service contract and one command to start the stack.
300
493
 
@@ -305,7 +498,8 @@ See [how Flisk compares to alternative dev tools](docs/comparison.md), [how Flis
305
498
  Use `flisk ui` to inspect stacks and resources. Arrow keys or `j`/`k` move the
306
499
  selection; `g`/`G` or Home/End jump to the first/last item, and PageUp/PageDown
307
500
  move one visible page. `/` searches; navigation letters remain search text
308
- while searching. The selected row stays visible when the terminal is resized.
501
+ while searching. Press `1`–`5` to jump between tabs. The selected row stays
502
+ visible when the terminal is resized. See [docs/ui.md](docs/ui.md) for every key binding.
309
503
 
310
504
  ## Update Flisk
311
505
 
@@ -359,6 +553,7 @@ Set `FLISK_DEBUG=1` before running `flisk up --verbose` to include Starlark debu
359
553
 
360
554
  ## Docs
361
555
 
556
+ - [Flisk 101: a 13-lab course for beginners](docs/101/README.md)
362
557
  - [CLI command cheat sheet](cli/README.md#cheat-sheet)
363
558
  - [Mega cheat sheet: every command and flag](docs/cheat-sheet.md)
364
559
  - [Documentation index](docs/README.md)
@@ -477,7 +672,65 @@ Then run `flisk doctor` and retry the same task. If the problem persists, [open
477
672
 
478
673
  ## Contributing and license
479
674
 
480
- Contributions are welcome. Start with [CONTRIBUTING.md](.github/CONTRIBUTING.md) and the [contributor guide](docs/contributing/README.md). For the project structure, see the [architecture and repository map](docs/project-overview.md). To review pull requests, see [Review a pull request](docs/contributing/04-review-a-pr.md). Report security issues using [SECURITY.md](.github/SECURITY.md).
675
+ Contributions are welcome. **First step: [say hello on Discord](https://discord.gg/Sjhb3tnq3)**, tell us what you want to work on, and we will point you to a good first task. Then start with [CONTRIBUTING.md](.github/CONTRIBUTING.md) and the [contributor guide](docs/contributing/README.md). For the project structure, see the [architecture and repository map](docs/project-overview.md). To review pull requests, see [Review a pull request](docs/contributing/04-review-a-pr.md). Report security issues using [SECURITY.md](.github/SECURITY.md).
676
+
677
+ ### Contributors
678
+
679
+ Thank you to everyone who has shipped code, docs, and fixes to Flisk since July 2026. Every merged change makes the local stack better for the next developer.
680
+
681
+ <table>
682
+ <tr>
683
+ <td align="center"><a href="https://github.com/kburym"><img src="https://github.com/kburym.png?size=80" width="64" alt="kburym" /><br /><sub><b>kburym</b></sub></a></td>
684
+ <td align="center"><a href="https://github.com/odykyi"><img src="https://github.com/odykyi.png?size=80" width="64" alt="odykyi" /><br /><sub><b>odykyi</b></sub></a></td>
685
+ <td align="center"><a href="https://github.com/sb123sb123"><img src="https://github.com/sb123sb123.png?size=80" width="64" alt="sb123sb123" /><br /><sub><b>sb123sb123</b></sub></a></td>
686
+ <td align="center"><a href="https://github.com/AK-Lmn"><img src="https://github.com/AK-Lmn.png?size=80" width="64" alt="AK-Lmn" /><br /><sub><b>AK-Lmn</b></sub></a></td>
687
+ <td align="center"><a href="https://github.com/yoreva-01"><img src="https://github.com/yoreva-01.png?size=80" width="64" alt="yoreva-01" /><br /><sub><b>yoreva-01</b></sub></a></td>
688
+ <td align="center"><a href="https://github.com/minutechreview"><img src="https://github.com/minutechreview.png?size=80" width="64" alt="minutechreview" /><br /><sub><b>minutechreview</b></sub></a></td>
689
+ </tr>
690
+ <tr>
691
+ <td align="center"><a href="https://github.com/Delfi2007"><img src="https://github.com/Delfi2007.png?size=80" width="64" alt="Delfi2007" /><br /><sub><b>Delfi2007</b></sub></a></td>
692
+ <td align="center"><a href="https://github.com/Ghifariezra"><img src="https://github.com/Ghifariezra.png?size=80" width="64" alt="Ghifariezra" /><br /><sub><b>Ghifariezra</b></sub></a></td>
693
+ <td align="center"><a href="https://github.com/Huang-404-Q"><img src="https://github.com/Huang-404-Q.png?size=80" width="64" alt="Huang-404-Q" /><br /><sub><b>Huang-404-Q</b></sub></a></td>
694
+ <td align="center"><a href="https://github.com/dbdefault"><img src="https://github.com/dbdefault.png?size=80" width="64" alt="dbdefault" /><br /><sub><b>dbdefault</b></sub></a></td>
695
+ <td align="center"><a href="https://github.com/Rohith-Saran"><img src="https://github.com/Rohith-Saran.png?size=80" width="64" alt="Rohith-Saran" /><br /><sub><b>Rohith-Saran</b></sub></a></td>
696
+ <td align="center"><a href="https://github.com/aazminu"><img src="https://github.com/aazminu.png?size=80" width="64" alt="aazminu" /><br /><sub><b>aazminu</b></sub></a></td>
697
+ </tr>
698
+ <tr>
699
+ <td align="center"><a href="https://github.com/xiehuanyi"><img src="https://github.com/xiehuanyi.png?size=80" width="64" alt="xiehuanyi" /><br /><sub><b>xiehuanyi</b></sub></a></td>
700
+ <td align="center"><a href="https://github.com/NimoCao"><img src="https://github.com/NimoCao.png?size=80" width="64" alt="NimoCao" /><br /><sub><b>NimoCao</b></sub></a></td>
701
+ <td align="center"><a href="https://github.com/rahul05ranjan"><img src="https://github.com/rahul05ranjan.png?size=80" width="64" alt="rahul05ranjan" /><br /><sub><b>rahul05ranjan</b></sub></a></td>
702
+ <td align="center"><a href="https://github.com/krishna2707"><img src="https://github.com/krishna2707.png?size=80" width="64" alt="krishna2707" /><br /><sub><b>krishna2707</b></sub></a></td>
703
+ <td align="center"><a href="https://github.com/arxh80"><img src="https://github.com/arxh80.png?size=80" width="64" alt="arxh80" /><br /><sub><b>arxh80</b></sub></a></td>
704
+ <td align="center"><a href="https://github.com/tnalbant"><img src="https://github.com/tnalbant.png?size=80" width="64" alt="tnalbant" /><br /><sub><b>tnalbant</b></sub></a></td>
705
+ </tr>
706
+ <tr>
707
+ <td align="center"><a href="https://github.com/sunny-kavixo"><img src="https://github.com/sunny-kavixo.png?size=80" width="64" alt="sunny-kavixo" /><br /><sub><b>sunny-kavixo</b></sub></a></td>
708
+ <td align="center"><a href="https://github.com/sohammkk"><img src="https://github.com/sohammkk.png?size=80" width="64" alt="sohammkk" /><br /><sub><b>sohammkk</b></sub></a></td>
709
+ <td align="center"><a href="https://github.com/sinhaananya812-star"><img src="https://github.com/sinhaananya812-star.png?size=80" width="64" alt="sinhaananya812-star" /><br /><sub><b>sinhaananya812-star</b></sub></a></td>
710
+ <td align="center"><a href="https://github.com/jay23606"><img src="https://github.com/jay23606.png?size=80" width="64" alt="jay23606" /><br /><sub><b>jay23606</b></sub></a></td>
711
+ <td align="center"><a href="https://github.com/floatyserve"><img src="https://github.com/floatyserve.png?size=80" width="64" alt="floatyserve" /><br /><sub><b>floatyserve</b></sub></a></td>
712
+ <td align="center"><a href="https://github.com/eddyflores100-lang"><img src="https://github.com/eddyflores100-lang.png?size=80" width="64" alt="eddyflores100-lang" /><br /><sub><b>eddyflores100-lang</b></sub></a></td>
713
+ </tr>
714
+ <tr>
715
+ <td align="center"><a href="https://github.com/denisvmedia"><img src="https://github.com/denisvmedia.png?size=80" width="64" alt="denisvmedia" /><br /><sub><b>denisvmedia</b></sub></a></td>
716
+ <td align="center"><a href="https://github.com/amritkang165"><img src="https://github.com/amritkang165.png?size=80" width="64" alt="amritkang165" /><br /><sub><b>amritkang165</b></sub></a></td>
717
+ <td align="center"><a href="https://github.com/airdropia"><img src="https://github.com/airdropia.png?size=80" width="64" alt="airdropia" /><br /><sub><b>airdropia</b></sub></a></td>
718
+ <td align="center"><a href="https://github.com/adity982"><img src="https://github.com/adity982.png?size=80" width="64" alt="adity982" /><br /><sub><b>adity982</b></sub></a></td>
719
+ <td align="center"><a href="https://github.com/YuuGR1337"><img src="https://github.com/YuuGR1337.png?size=80" width="64" alt="YuuGR1337" /><br /><sub><b>YuuGR1337</b></sub></a></td>
720
+ <td align="center"><a href="https://github.com/WilsonSoetomo"><img src="https://github.com/WilsonSoetomo.png?size=80" width="64" alt="WilsonSoetomo" /><br /><sub><b>WilsonSoetomo</b></sub></a></td>
721
+ </tr>
722
+ <tr>
723
+ <td align="center"><a href="https://github.com/Vignesh2662006"><img src="https://github.com/Vignesh2662006.png?size=80" width="64" alt="Vignesh2662006" /><br /><sub><b>Vignesh2662006</b></sub></a></td>
724
+ <td align="center"><a href="https://github.com/Samueldavidddsc"><img src="https://github.com/Samueldavidddsc.png?size=80" width="64" alt="Samueldavidddsc" /><br /><sub><b>Samueldavidddsc</b></sub></a></td>
725
+ <td align="center"><a href="https://github.com/Murphyvon"><img src="https://github.com/Murphyvon.png?size=80" width="64" alt="Murphyvon" /><br /><sub><b>Murphyvon</b></sub></a></td>
726
+ <td align="center"><a href="https://github.com/KeuqS"><img src="https://github.com/KeuqS.png?size=80" width="64" alt="KeuqS" /><br /><sub><b>KeuqS</b></sub></a></td>
727
+ <td align="center"><a href="https://github.com/Golden007-prog"><img src="https://github.com/Golden007-prog.png?size=80" width="64" alt="Golden007-prog" /><br /><sub><b>Golden007-prog</b></sub></a></td>
728
+ <td align="center"><a href="https://github.com/GeoCeff"><img src="https://github.com/GeoCeff.png?size=80" width="64" alt="GeoCeff" /><br /><sub><b>GeoCeff</b></sub></a></td>
729
+ </tr>
730
+ <tr>
731
+ <td align="center"><a href="https://github.com/Enard52"><img src="https://github.com/Enard52.png?size=80" width="64" alt="Enard52" /><br /><sub><b>Enard52</b></sub></a></td>
732
+ </tr>
733
+ </table>
481
734
 
482
735
  Flisk is MIT-licensed; see [LICENSE](LICENSE). The [license boundary](docs/project/GOVERNANCE.md#license-boundary-and-donation-scope) says which code is MIT and which is downloaded with a key.
483
736
 
@@ -651,6 +651,67 @@ export function checkResourceDiscovery() {
651
651
  fix: "Move each under services/<stack>/<name>, or add a matching pattern to discovery.paths in .flisk/project.json and run: flisk config regenerate",
652
652
  };
653
653
  }
654
+ /**
655
+ * `.autogenerated/` is written by `flisk up`, so a resource without it has simply not been generated yet.
656
+ * That is a warning, not a failure: `flisk doctor` is also run before the first `flisk up`.
657
+ */
658
+ /** Regular files under `.autogenerated/`, nested ones included, without the `.flisk-contract` bookkeeping directory. */
659
+ function listGeneratedFiles(root) {
660
+ const files = [];
661
+ const collect = (dir, relativeDir) => {
662
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
663
+ if (relativeDir === "" && entry.name === ".flisk-contract")
664
+ continue;
665
+ const relativeFile = relativeDir === "" ? entry.name : `${relativeDir}/${entry.name}`;
666
+ if (entry.isDirectory())
667
+ collect(join(dir, entry.name), relativeFile);
668
+ else if (entry.isFile())
669
+ files.push(relativeFile);
670
+ }
671
+ };
672
+ collect(root, "");
673
+ return files.sort();
674
+ }
675
+ export function checkGeneratedFiles(strict = false) {
676
+ const projectRoot = findProjectRoot() ?? process.cwd();
677
+ const resources = discoverResourcesFromRoot(projectRoot).filter((resource) => (resource.config?.appType ?? resource.type) !== "library");
678
+ if (resources.length === 0) {
679
+ return {
680
+ name: "Generated Files",
681
+ didPass: true,
682
+ isSkipped: true,
683
+ message: "No resources to check",
684
+ };
685
+ }
686
+ const lines = [];
687
+ const missing = [];
688
+ for (const resource of resources) {
689
+ const label = normalize(relative(projectRoot, resource.path));
690
+ const dir = join(resource.path, AUTOGENERATED_DIR);
691
+ const files = existsSync(dir) ? listGeneratedFiles(dir) : [];
692
+ if (files.length === 0) {
693
+ missing.push(label);
694
+ lines.push(`${label}: no ${AUTOGENERATED_DIR}/ files`);
695
+ }
696
+ else {
697
+ lines.push(`${label}: ${files.join(", ")}`);
698
+ }
699
+ }
700
+ if (missing.length === 0) {
701
+ return {
702
+ name: "Generated Files",
703
+ didPass: true,
704
+ message: `${formatCount(resources.length, "resource")} with generated files:\n ${lines.join("\n ")}`,
705
+ };
706
+ }
707
+ return {
708
+ name: "Generated Files",
709
+ didPass: false,
710
+ isWarning: !strict,
711
+ message: `${missing.length} of ${formatCount(resources.length, "resource")} not generated yet:\n ${lines.join("\n ")}`,
712
+ fix: "Run `flisk up` to generate them (it needs Docker, Compose and Tilt). `flisk config verify` checks the project-level files only.",
713
+ };
714
+ }
654
715
  // The scripts `flisk project` copies into every project. Generated Dockerfiles
655
716
  // may reference others; those are checked by scanning the Dockerfiles below.
656
717
  const REQUIRED_DOCKER_TEMPLATE_FILES = [
@@ -1376,6 +1437,7 @@ export const doctorCommand = new Command("doctor")
1376
1437
  () => checkFliskVersion(),
1377
1438
  checkMasterConfigs,
1378
1439
  checkGeneratedProjectRuntimeAssets,
1440
+ () => checkGeneratedFiles(options.strict),
1379
1441
  checkStarlarkLoadExports,
1380
1442
  checkStartupScripts,
1381
1443
  // A backend without its health route never turns healthy; Traefik 404s it.
@@ -4,7 +4,8 @@ import { statSync } from "node:fs";
4
4
  import { join, resolve } from "node:path";
5
5
  import { Command } from "commander";
6
6
  import { findCliAssetRoot, loadTemplate } from "../generator/template-engine.js";
7
- import { describeLayoutProblems, EXTENSION_DIRS, inspectExtensionLayout, resolveExtensionDir, resolveTiltfile, } from "../utils/runtime-layout.js";
7
+ import { describeLayoutProblems, EXTENSION_DIRS, inspectExtensionLayout, resolveExtensionDir, resolveSharedPlatformDir, resolveTiltfile, } from "../utils/runtime-layout.js";
8
+ const SHARED_PLATFORM_TEMPLATES = "shared-platform-engineering/docker-templates";
8
9
  const REQUIRED_ASSET_PATHS = [
9
10
  { path: "Tiltfile", directory: false },
10
11
  { path: "engine", directory: true },
@@ -12,7 +13,7 @@ const REQUIRED_ASSET_PATHS = [
12
13
  { path: "specs", directory: true },
13
14
  { path: "ext", directory: true },
14
15
  { path: "cli/templates", directory: true },
15
- { path: "shared-platform-engineering/docker-templates", directory: true },
16
+ { path: SHARED_PLATFORM_TEMPLATES, directory: true },
16
17
  ];
17
18
  const EXTENSION_NAMES = new Set(EXTENSION_DIRS);
18
19
  const REQUIRED_TEMPLATES = [
@@ -41,7 +42,9 @@ export const runtimeCommand = new Command("runtime")
41
42
  ? resolveExtensionDir(assetRoot, path)
42
43
  : path === "Tiltfile"
43
44
  ? resolveTiltfile(assetRoot)
44
- : join(assetRoot, path));
45
+ : path === SHARED_PLATFORM_TEMPLATES
46
+ ? join(resolveSharedPlatformDir(assetRoot), "docker-templates")
47
+ : join(assetRoot, path));
45
48
  return directory ? !stats.isDirectory() : !stats.isFile();
46
49
  }
47
50
  catch {
@@ -10,7 +10,7 @@ import { AUTOGENERATED_DIR, DATABASE_MANAGEMENT_FEATURE, DOCKER_COMPOSE_FILE, PA
10
10
  import { writeTextFile } from "../utils/file-helpers.js";
11
11
  import { assertFliskGeneratedPath } from "../utils/generated-paths.js";
12
12
  import { DEFAULT_ALWAYS_ENABLED_INFRA } from "../utils/project-config-defaults.js";
13
- import { describeLayoutProblems, EXTENSION_DIRS, hasExtensionLayout, inspectExtensionLayout, resolveExtensionDir, resolveTiltfile, } from "../utils/runtime-layout.js";
13
+ import { describeLayoutProblems, EXTENSION_DIRS, hasExtensionLayout, inspectExtensionLayout, resolveExtensionDir, resolveSharedPlatformDir, resolveTiltfile, } from "../utils/runtime-layout.js";
14
14
  import { generatedFieldErrorsForFile, validateServiceManifestFile, } from "../utils/service-manifest.js";
15
15
  import { discoverResourcesFromRoot, discoverServiceManifestPaths } from "../utils/services.js";
16
16
  import { isStackFeatureEnabledInStacks } from "../utils/stack-features.js";
@@ -582,10 +582,13 @@ function findSelfContainedEngineRoot() {
582
582
  }
583
583
  return null;
584
584
  }
585
+ function hasDockerTemplates(sourceRoot) {
586
+ return fs.existsSync(path.join(resolveSharedPlatformDir(sourceRoot), "docker-templates"));
587
+ }
585
588
  export function findCliAssetRoot() {
586
589
  let dir = import.meta.dirname || process.cwd();
587
590
  for (let i = 0; i < 8; i++) {
588
- if (fs.existsSync(path.join(dir, "shared-platform-engineering", "docker-templates"))) {
591
+ if (hasDockerTemplates(dir)) {
589
592
  return dir;
590
593
  }
591
594
  const parent = path.dirname(dir);
@@ -598,7 +601,7 @@ export function findCliAssetRoot() {
598
601
  path.join(exeDir, "flisk-cli"),
599
602
  path.join(process.cwd(), "node_modules", "@flisk-sh", "flisk"),
600
603
  ];
601
- return (candidates.find((candidate) => fs.existsSync(path.join(candidate, "shared-platform-engineering", "docker-templates"))) ?? null);
604
+ return candidates.find(hasDockerTemplates) ?? null;
602
605
  }
603
606
  export function ensureProjectRuntimeAssets(projectRoot) {
604
607
  const sourceRoot = findCliAssetRoot();
@@ -609,7 +612,7 @@ export function ensureProjectRuntimeAssets(projectRoot) {
609
612
  return copied;
610
613
  }
611
614
  for (const parts of PROJECT_RUNTIME_ASSET_DIRS) {
612
- const source = path.join(sourceRoot, ...parts);
615
+ const source = path.join(resolveSharedPlatformDir(sourceRoot), ...parts.slice(1));
613
616
  const target = assertFliskGeneratedPath(projectRoot, path.join(...parts));
614
617
  if (!fs.existsSync(source)) {
615
618
  continue;