@tdk-landscape/tdk-cli-core 1.3.79 → 1.3.81

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,14 @@ Notable changes to the `tdk` CLI. Versions match [npm](https://www.npmjs.com/pac
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 1.3.80 (2026-09-30)
8
+
9
+ - Add `tdk doctor --json` with schema-versioned readiness, checks, and structured errors; diagnostics remain on stderr.
10
+ - Stabilize doctor exits: 0 ready, 1 blocking findings, 2 invalid arguments/internal check failures. Invalid `--ping-timeout` now exits 2 instead of 1 and rejects fractional/unit-suffixed values.
11
+ - Add versioned `--json` envelopes to `tdk status`, `tdk resources`, and `tdk networks`; existing `networks --json` array consumers can migrate with `--json-legacy` through CLI 1.4.x. The compatibility flag is scheduled for removal in 1.5.0.
12
+ - Add `tdk config verify --json` with drift summaries and unified diffs for missing or stale master outputs; verification remains read-only, and structured command/internal failures use exits 1/2.
13
+
14
+
7
15
  ## 1.3.77 (2026-09-30)
8
16
 
9
17
  - `tdk up` no longer leaves `nats` (and any other service in `services/platform/messaging/docker-compose.yml`, e.g. a local mail catcher) disabled in Tilt. The pre-alpha default always goes through a focus-filter path that only re-enabled `init-networks`/`postgres`/`traefik`/`golden-layers-build`, so a resource with the `nats` feature retried its broker connection forever until you ran `tilt enable nats` by hand. Fixes #155.
package/README.md CHANGED
@@ -1,27 +1,8 @@
1
- <div align="center">
2
-
3
1
  # TDK — Tilt Development Kit
4
2
 
5
- TDK is a local development kit. It scaffolds services and runs a stack on your
6
- laptop with Docker and Tilt (hot reload, health, Traefik, Postgres).
7
-
8
- It is not a Kubernetes packager. It does not replace Helm, Argo CD,
9
- Kustomize, or your production charts.
10
-
11
- Use TDK when local bring-up of many services is painful and you do not want a
12
- cluster on the laptop.
13
-
14
- Skip TDK if `helm install` (or your existing compose/Tilt/Skaffold) already
15
- gives you a working local or shared-dev environment.
16
-
17
- ## Status
3
+ TDK runs many services on your laptop with Docker + Tilt. Helm still deploys the cluster.
18
4
 
19
- Supported: macOS, Linux, Windows via WSL2 Ubuntu.
20
- Native Windows: CLI inspect only; `tdk up` unsupported.
21
- WSL2 smoke: local script only (no GitHub WSL runner).
22
- Stability: 1.x — generated files are a contract; verify in CI.
23
- Check your machine: `tdk doctor`
24
- Known limits: [docs/compare-honest.md](docs/compare-honest.md)
5
+ [Website](https://tdk-landscape.github.io/tdk-website/) · [Quickstart](https://tdk-landscape.github.io/tdk-website/docs/quickstart/) · [Examples](https://tdk-landscape.github.io/tdk-website/docs/examples/) · [Awesome TDK](https://github.com/tdk-landscape/awesome-tdk-framework) · [Demo](https://tdk-landscape.github.io/tdk-demo-animation/) · [Report a bug](https://github.com/tdk-landscape/tdk-cli-core/issues)
25
6
 
26
7
  [![npm version](https://img.shields.io/npm/v/@tdk-landscape/tdk-cli-core.svg?style=flat&color=blue)](https://www.npmjs.com/package/@tdk-landscape/tdk-cli-core)
27
8
  [![CI](https://github.com/tdk-landscape/tdk-cli-core/actions/workflows/ci.yml/badge.svg)](https://github.com/tdk-landscape/tdk-cli-core/actions/workflows/ci.yml)
@@ -32,216 +13,68 @@ Known limits: [docs/compare-honest.md](docs/compare-honest.md)
32
13
  [![Socket Badge](https://badge.socket.dev/npm/package/@tdk-landscape/tdk-cli-core/latest)](https://socket.dev/npm/package/@tdk-landscape/tdk-cli-core/overview)
33
14
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
34
15
 
35
- [Website](https://tdk-landscape.github.io/tdk-website) · [Quickstart](https://tdk-landscape.github.io/tdk-website/docs/quickstart/) · [Examples](https://tdk-landscape.github.io/tdk-website/docs/examples/) · [Demo](https://tdk-landscape.github.io/tdk-demo-animation/) · [Report a bug](https://github.com/tdk-landscape/tdk-cli-core/issues/new/choose)
36
-
37
- </div>
38
-
39
- ## When not to use TDK
40
-
41
- - Production or shared-cluster deploy is Helm/Argo/Kustomize — keep it.
42
- - Your local or namespace-per-dev environment already works.
43
- - You will not adopt `service.json` and generated files.
44
-
45
- ## TDK is for you if
46
-
47
- - You have many services and want `tdk up <one stack>` on Docker.
48
- - You do not want kind or minikube as your daily path.
49
- - You want to generate services, run `tdk config verify`, and use Traefik `*.localhost` routes.
50
-
51
- Start with the [bundled product example](examples/tdk-example/README.md); its write path is covered by [example-e2e](.github/workflows/example-e2e.yml).
52
-
53
- ```bash
54
- npm install -g @tdk-landscape/tdk-cli-core
55
- npx @tdk-landscape/tdk-cli-core
56
- mkdir shop && cd shop # tdk writes files into the current directory
57
- tdk project --yes # set up the project
58
- tdk resource orders-api --type backend --stack shop # scaffold a service
59
- tdk up shop # run it with hot reload
60
- ```
61
-
62
- ![tdk scaffolding a backend and a frontend, then listing the stack](docs/demo.svg)
63
-
64
- Want to inspect a stack before starting containers? `tdk up shop --dry-run` shows the services and local URLs without Docker or Tilt installed.
65
-
66
- ![npm downloads, last month](docs/npm-downloads.svg)
67
-
68
- **Requirements:** Docker (Desktop, OrbStack or Colima; Engine 25+, Compose 2.20+), [Tilt](https://docs.tilt.dev/install.html), [Bun](https://bun.sh) for the generated services, and Node.js 22.12+ for npm installs. Ports 80, 443 and 5432 must be free (a local Postgres is the usual conflict). macOS and Linux releases are available. Windows native is unsupported. WSL2 Ubuntu is supported. See docs/wsl2.md. Run `tdk doctor` to check your setup.
69
-
70
- This is the core monorepo for TDK: the `tdk` CLI, the Starlark-based Tilt orchestration engine that powers it, and the discovery system that turns a directory of services into a running local landscape.
71
-
72
- ## Why TDK?
73
-
74
- | | docker-compose | Local Kubernetes (kind, minikube) | Plain Tilt | **TDK** |
75
- |---|---|---|---|---|
76
- | Scaffold a new service in one command | ❌ | ❌ | ❌ | ✅ `tdk resource` |
77
- | Hot reload on file change | ⚠️ `compose watch` config | ⚠️ extra tooling | ✅ | ✅ |
78
- | Health-checked startup order | ✅ `depends_on: condition: service_healthy` | ✅ | ⚠️ write it yourself | ✅ |
79
- | Proxy, Postgres, monitoring included | ❌ | ❌ | ❌ | ✅ |
80
- | Needs a cluster | No | Yes | Optional | **No** |
81
- | Start only one stack of a large system | ⚠️ profiles | ⚠️ | ⚠️ | ✅ `tdk up <stack>` |
82
-
83
- TDK is not a replacement for Tilt: it generates the Tiltfile, Dockerfiles and compose files and then runs Tilt. If you already have a hand-written Tiltfile or compose setup you're happy with, TDK mostly saves you the boilerplate for the next service.
84
-
85
- ## Fixture bench: 100 generated services on one laptop
86
-
87
- Measured with [`scripts/benchmark/container-scale.ts`](scripts/benchmark/README.md) against the 100-service [`tdk-erp-system` fixture bench](https://github.com/tdk-landscape/tdk-erp-system), a scale fixture of generated `/health` services rather than an ERP product, on a 16 GB machine (Docker VM: 7.75 GiB). Raw results are in [`benchmarks/results/`](benchmarks/results).
88
-
89
- | Services | All healthy after | Total memory | Avg memory / service | Crashes / OOM kills |
90
- |---:|---:|---:|---:|---:|
91
- | 10 | 8 s | 161 MiB | 16 MiB | 0 / 0 |
92
- | 50 | 24 s | 829 MiB | 17 MiB | 0 / 0 |
93
- | 100 | 112 s | 1.6 GiB | 17 MiB | 0 / 0 |
94
-
95
- What this does and doesn't measure:
96
-
97
- - The ERP services are small generated Bun HTTP services (about 20 lines each) answering `/health`. Real services with real dependencies use more memory; the point is that TDK's per-service overhead (runtime image, healthchecks, proxy routing) stays small.
98
- - Images were already built, so build time isn't included. The clean-machine run below includes it.
99
- - The script starts the service containers with the settings `tdk up` generates (512 MiB / 0.5 CPU limits, healthchecks), without Tilt running. The memory column counts only the service containers, not Postgres or Traefik.
100
- - Numbers vary between runs (a later run reached 100 healthy in 74 s). Run it yourself with `bun scripts/benchmark/container-scale.ts`.
101
-
102
- ### Cold boot on a clean machine (CI)
103
-
104
- The table above is a warm start. Two workflows install the published CLI on a fresh GitHub-hosted Ubuntu runner and run `tdk up` from nothing, building every image:
105
-
106
- - [**Quickstart E2E**](.github/workflows/quickstart-e2e.yml): the commands from the top of this README, one scaffolded backend, until it answers `/health` through Traefik. About 4 minutes. Runs after each release and daily.
107
- - [**ERP fixture scale E2E**](.github/workflows/erp-scale-e2e.yml): the 100-service generated-health fixture bench. [Run 36395860088](https://github.com/tdk-landscape/tdk-cli-core/actions/runs/36395860088) (CLI 1.3.72, 4 vCPU / 15 GB): **100 / 100 backends healthy through Traefik after 472 s**, 111 containers, 1.8 GiB used by all containers. Runs weekly.
108
-
109
- Both are Linux/Ubuntu CI fixtures: generated services answering `/health`, not a real business app. A green run means TDK can generate, build, route and health-check a landscape of that size on a clean Ubuntu runner. Windows now has a separate smoke workflow for CLI startup and unit tests, but it does not boot a full landscape on Windows. These CI runs also don't cover Apple Silicon or an existing repo you bring yourself.
16
+ ## Installation
110
17
 
111
- ## What is TDK?
112
-
113
- TDK organizes microservices using a **Project → Stack → Resource** hierarchy, then uses Tilt to build, run, and hot-reload them locally:
114
-
115
- ```
116
- Project (1 per repo)
117
- ├── TILT_RESOURCE_DEFAULTS.star # Ports, health checks, memory
118
- ├── TILT_TECH_STACK.star # Bun, Vite, Prisma, NATS
119
- │
120
- └── Stacks (deployment groups)
121
- ├── api-stack
122
- │ ├── api-backend # Resource
123
- │ └── web-frontend # Resource
124
- │
125
- └── worker-stack
126
- ├── worker-backend
127
- └── web-frontend
128
- ```
129
-
130
- `.tdk/project.json` also groups stacks into phases (`pre_alpha`, `alpha`, `beta`, `out_of_scope`) so a large system can be brought up in stages. `tdk up` runs stacks from the first three and adds any new stack to `pre_alpha`.
131
-
132
- Running `tdk resource` scaffolds a service (Dockerfile, TypeScript config, starter code, tests); `tdk up` hands the whole landscape to Tilt for orchestration, live-reload, and health checking — sized to fit dozens of services on a single laptop.
133
-
134
- ## Install
18
+ Install the CLI from npm (requires Node.js 22.12+) or use the prebuilt binary (no Node.js or Bun required):
135
19
 
136
20
  ```bash
137
21
  npm install -g @tdk-landscape/tdk-cli-core
138
- # or
139
- bun install -g @tdk-landscape/tdk-cli-core
140
- ```
141
-
142
- Or install the prebuilt binary (no Node or Bun needed; verified against the release checksums):
143
-
144
- ```bash
22
+ # or install the prebuilt binary
145
23
  curl -fsSL https://tdk-landscape.github.io/install.sh | sh
146
24
  ```
147
25
 
148
- Premium features don't need a different install: set `TDK_LICENSE_KEY` and any of these installs unlocks them. See [docs/FEATURES.md](docs/FEATURES.md).
149
-
150
26
  ## Quick start
151
27
 
152
28
  ```bash
153
29
  mkdir shop && cd shop
154
- tdk project --yes # writes .tdk/project.json and generated configs
155
- tdk resource orders-api --type backend --stack shop # asks you to confirm, then scaffolds services/shop/orders-api
156
- tdk resource storefront --type frontend --stack shop
157
- tdk up shop # starts Tilt; UI at http://localhost:10350
158
- tdk networks # lists the *.localhost URLs Traefik routes
159
- tdk down # stops everything
30
+ tdk project --yes
31
+ tdk resource orders-api --type backend --stack shop --yes
32
+ tdk up shop
33
+ tdk networks
160
34
  ```
161
35
 
162
- See the [CLI reference](cli/README.md) for the full command set (`stack`, `resources`, `doctor`, `ui`, and more).
163
-
164
- ## Repository layout
165
-
166
- This is a monorepo — most day-to-day CLI work happens under `cli/`, while `engine/` and `discovery/` implement the Tilt-side orchestration that the CLI drives.
167
-
168
- | Path | What it is |
169
- |------|------------|
170
- | [`cli/`](cli) | The `tdk` CLI source (TypeScript/Bun) — commands, UI, templates. See [cli/README.md](cli/README.md). |
171
- | [`engine/`](engine) | The Starlark Tilt framework: topology modules for Docker, networking, database virtualization, secrets, observability. See [engine/README.md](engine/README.md). |
172
- | [`discovery/`](discovery) | Manifest-driven service discovery — scans `service.json` files and builds the resource/dependency graph consumed by the engine. |
173
- | [`ext/`](ext) | Tilt extension (`ext://tdk-cli`) plus IDE/UI enhancement components. |
174
- | [`scripts/`](scripts) | Release, benchmarking, and dev-environment scripts (git hooks, pre-commit, idle-footprint measurement). |
175
- | [`benchmarks/`](benchmarks) | Container/landscape scale benchmarks. |
176
- | [`docs/`](docs) | Reference docs, including [FEATURES.md](docs/FEATURES.md) for project- and resource-level feature flags. |
177
- | [`Tiltfile`](Tiltfile) | Entry point that wires the engine into `tilt up`. |
178
- | [`install.sh`](install.sh) | Legacy installer URL; hands off to the official installer at `tdk-landscape.github.io/install.sh`. |
179
-
180
- ## Features
181
-
182
- TDK ships a set of always-on infrastructure services (Traefik proxy, PostgreSQL) plus opt-in features — monitoring, ELK, Debezium CDC, a local npm registry, and more. Enable/disable them per-project via `.tdk/project.json`, or per-resource via each service's `service.json`. Full reference: [docs/FEATURES.md](docs/FEATURES.md).
183
-
184
- ## Free and paid features
185
-
186
- The CLI, engine and everything in this repository are MIT-licensed and work without an account or key. A few extras are paid and need a `TDK_LICENSE_KEY`: on-demand start/stop of idle services (Sablier), a local npm registry (Verdaccio), DDD scaffolding, Playwright config, C4 diagrams, synthetic monitoring, and a few generators (see `KNOWN_RESOURCES` in [extension-fetch.ts](cli/src/generator/extension-fetch.ts)). In this repo those are disabled stubs; with a key set, the CLI downloads the real implementations. [docs/FEATURES.md](docs/FEATURES.md) marks which features are which. To get a key, use the [request form on the website](https://tdk-landscape.github.io/tdk-website/#waitlist) or open a [Premium license request](https://github.com/tdk-landscape/tdk-cli-core/issues/new?template=premium_license.yml).
36
+ `tdk up shop --dry-run` previews selected local services and URLs before starting containers. The default starter is Bun/TypeScript; TDK's core role is running local containers through Docker + Tilt, not providing a Node.js application framework. See the [one-backend example](examples/one-backend/README.md).
187
37
 
188
- ## Network access and telemetry
38
+ ![TDK scaffolding a backend and a frontend, then listing the stack](docs/demo.svg)
189
39
 
190
- TDK has no telemetry or analytics. The CLI only goes online when you ask it to:
40
+ *Scaffolding a backend and frontend, then listing the stack.*
191
41
 
192
- - `tdk upgrade` checks the latest release on GitHub.
193
- - With `TDK_LICENSE_KEY` set, `tdk project` and `tdk up` download the paid bundle from `tdk-extension-dist.oranguman.workers.dev` and re-check the key every 12 hours. Without a key, nothing is sent.
194
- - Docker and Tilt pull images and packages as they normally would.
195
- - Tilt, which TDK runs, has its own anonymous usage analytics. Turn them off with `tilt analytics opt out`.
196
-
197
- ## FAQ
198
-
199
- **Why not just docker compose?** For a handful of services, compose is fine. TDK generates the compose files for you. It adds hot reload through Tilt, one-command scaffolding with matching Dockerfiles, and a stack-level `tdk up` for large systems where starting everything is too slow.
200
-
201
- **How is this different from Skaffold, Garden, DevSpace or Tilt itself?** Skaffold, Garden and DevSpace are built around Kubernetes, and plain Tilt leaves the Tiltfile to you. TDK runs on plain Docker with no cluster, and generates both the services and the Tilt config from a `service.json` per service.
202
-
203
- See the [honest comparison](docs/compare-honest.md) for tradeoffs and cases where TDK may not fit.
204
-
205
- **Do I need 100 microservices?** No. Two services work the same way. The 100-service fixture bench is a stress test to show the overhead stays flat; it is not an ERP product example.
206
-
207
- **Is TDK affiliated with Tilt or Docker?** No. TDK is an independent project built on top of [Tilt](https://tilt.dev), which is maintained by Docker, Inc.
208
-
209
- ## Development
42
+ ## Why TDK?
210
43
 
211
- ```bash
212
- make help # list all make targets
213
- make test # run the full test suite
214
- make test-fast # fast unit tests, no external deps
215
- make pre-commit-run # run pre-commit hooks on all files
216
- ```
44
+ | | Compose | Local Kubernetes (kind, minikube) | Plain Tilt | **TDK** |
45
+ |---|---|---|---|---|
46
+ | Scaffold a service in one command | ❌ | ❌ | ❌ | ✅ `tdk resource` |
47
+ | Hot reload on file change | ⚠️ `compose watch` config | ⚠️ extra tooling | ✅ | ✅ |
48
+ | Health-checked startup order | ✅ | ✅ | ⚠️ configure it yourself | ✅ |
49
+ | Needs a cluster | No | Yes | Optional | **No** |
217
50
 
218
- `npm run typecheck` / `npm run lint` / `npm run test` delegate to the `cli/` workspace. If you're contributing, start with the [step-by-step contributor guide](docs/contributing/README.md) for subsystem-specific instructions.
51
+ 100 generated health-check services reached healthy in 112 s, using about 1.6 GiB in service-container memory on a 16 GB machine. [Details and caveats](docs/scale-bench.md).
219
52
 
220
- ## Environment check
53
+ ## When not to use TDK
221
54
 
222
- ### Cold npx / first run
55
+ - Your existing Compose or Tilt workflow already gives you a working local environment.
56
+ - You do not want `service.json` manifests and generated local configuration.
223
57
 
224
- ```bash
225
- npx @tdk-landscape/tdk-cli-core
226
- npx @tdk-landscape/tdk-cli-core doctor
227
- ```
58
+ ## Docs
228
59
 
229
- Ranked first failures: Node 22.12+, Docker Engine 25+, Compose 2.20.2+, Tilt 0.25+, Bun 1.2+, and ports 80/443/5432.
230
- Install Bun 1.2+ as a machine prerequisite. `tdk project` generates the stack configuration; Prisma and NATS are project-specific, and NATS is required only when the feature is enabled.
60
+ - [Documentation index](docs/README.md)
61
+ - [Working alongside Helm](docs/with-helm.md)
62
+ - [Configuration and editor schemas](docs/configuration.md)
63
+ - [Runnable one-backend example](examples/one-backend/README.md)
64
+ - [Full multi-service example](examples/tdk-example/README.md)
65
+ - [Features and license limits](docs/FEATURES.md)
66
+ - [Honest comparison and known limits](docs/compare-honest.md)
67
+ - [Architecture and repository map](docs/project-overview.md)
68
+ - [Scale fixture measurements and caveats](docs/scale-bench.md)
231
69
 
232
- ```bash
233
- tdk doctor
234
- ```
70
+ ## Requirements and support
235
71
 
236
- Checks Docker, Compose and Tilt. Inside a project it also checks the generated configs, `.env`, service scripts and that the ingress ports are free, before you run `tdk up`. It also catches wiring mistakes: a resource without `package.json`, a `params` URL that uses the wrong port for another service, a frontend calling a backend on `localhost:<port>`, the `nats` feature without a broker to start, duplicate Tilt processes, and Docker running out of network address space.
72
+ For the local runtime, install Docker (Desktop, OrbStack, or Colima; Engine 25+, Compose 2.20+) and [Tilt](https://docs.tilt.dev/install.html). Bun 1.2+ is used by the default generated services. TDK selects host ports from bounded fallback ranges for HTTP, HTTPS, and Postgres; set `TDK_HTTP_PORT`, `TDK_HTTPS_PORT`, or `TDK_POSTGRES_PORT` to override them. TDK supports macOS, Linux, and Windows through WSL2 Ubuntu; native Windows supports CLI inspection only. Run `tdk doctor` to check local readiness. See [WSL2 setup](docs/wsl2.md).
237
73
 
238
- ## Community
74
+ **Ecosystem map:** examples, articles, related tools, and notes live in [awesome-tdk-framework](https://github.com/tdk-landscape/awesome-tdk-framework). Star this repo (`tdk-cli-core`) if the CLI is what you run; use the awesome list to browse the rest.
239
75
 
240
- - **Questions and ideas:** [open an issue](https://github.com/tdk-landscape/tdk-cli-core/issues/new/choose).
241
- - **Contributing:** see [CONTRIBUTING.md](CONTRIBUTING.md) and the [step-by-step guide](docs/contributing/README.md). Issues labeled [`good first issue`](https://github.com/tdk-landscape/tdk-cli-core/labels/good%20first%20issue) are a good place to start.
242
- - **Security:** see [SECURITY.md](SECURITY.md). Please don't report vulnerabilities in public issues.
243
- - **Examples:** bundled [TDK product example](examples/tdk-example), [ERP fixture bench (100 generated services)](https://github.com/tdk-landscape/tdk-erp-system), [SaaS starter](https://github.com/tdk-landscape/tdk-saas-starter), [restaurant](https://github.com/tdk-landscape/tdk-restaurant-example), [ecommerce (Vue + Hono)](https://github.com/tdk-landscape/tdk-ecommerce-example).
76
+ ## Contributing and license
244
77
 
245
- ## License
78
+ Contributions are welcome. Start with [CONTRIBUTING.md](CONTRIBUTING.md) and the [contributor guide](docs/contributing/README.md). Report security issues using [SECURITY.md](SECURITY.md).
246
79
 
247
- [MIT](LICENSE) © [TDK Landscape](https://github.com/tdk-landscape)
80
+ TDK is MIT-licensed; see [LICENSE](LICENSE).
package/cli/dist/cli.js CHANGED
@@ -13,6 +13,7 @@ import { projectCommand } from "./commands/project.js";
13
13
  import { projectsCommand } from "./commands/projects.js";
14
14
  import { resourceCommand } from "./commands/resource.js";
15
15
  import { resourcesCommand } from "./commands/resources.js";
16
+ import { runtimeCommand } from "./commands/runtime.js";
16
17
  import { stackCommand } from "./commands/stack.js";
17
18
  import { stacksCommand } from "./commands/stacks.js";
18
19
  import { statusCommand } from "./commands/status.js";
@@ -46,6 +47,7 @@ program.addCommand(ejectCommand);
46
47
  program.addCommand(statusCommand);
47
48
  program.addCommand(stackCommand);
48
49
  program.addCommand(resourceCommand);
50
+ program.addCommand(runtimeCommand);
49
51
  program.addCommand(projectCommand);
50
52
  program.addCommand(configCommand);
51
53
  program.addCommand(uiCommand);
@@ -11,10 +11,14 @@ _tdk_completions() {
11
11
  prev="\${COMP_WORDS[COMP_CWORD-1]}"
12
12
 
13
13
  # Main commands
14
- local commands="project projects stack stacks resource resources up down status ui doctor version completion help upgrade"
14
+ local commands="project projects stack stacks resource resources up down status ui doctor runtime version completion help upgrade"
15
15
 
16
16
  # Options for specific commands
17
17
  case "\${prev}" in
18
+ runtime)
19
+ COMPREPLY=( $(compgen -W "--check-assets --json" -- \${cur}) )
20
+ return 0
21
+ ;;
18
22
  tdk)
19
23
  COMPREPLY=( $(compgen -W "\${commands}" -- \${cur}) )
20
24
  return 0
@@ -108,6 +112,11 @@ _tdk() {
108
112
  _arguments
109
113
  '--fix[Attempt to fix issues]'
110
114
  ;;
115
+ runtime)
116
+ _arguments
117
+ '--check-assets[Check bundled engine and template assets]'
118
+ '--json[Print the check result as JSON]'
119
+ ;;
111
120
  upgrade)
112
121
  _arguments
113
122
  '--force[Force upgrade even if on latest]'
@@ -129,6 +138,7 @@ _tdk_commands() {
129
138
  'status:Show resource status'
130
139
  'ui:Open interactive UI'
131
140
  'doctor:Check environment'
141
+ 'runtime:Inspect packaged runtime assets'
132
142
  'version:Show version'
133
143
  'upgrade:Upgrade TDK CLI'
134
144
  'completion:Generate shell completions'
@@ -173,6 +183,7 @@ complete -c tdk -n '__fish_use_subcommand' -a 'down' -d 'Stop all services'
173
183
  complete -c tdk -n '__fish_use_subcommand' -a 'status' -d 'Show resource status'
174
184
  complete -c tdk -n '__fish_use_subcommand' -a 'ui' -d 'Open interactive UI'
175
185
  complete -c tdk -n '__fish_use_subcommand' -a 'doctor' -d 'Check environment'
186
+ complete -c tdk -n '__fish_use_subcommand' -a 'runtime' -d 'Inspect packaged runtime assets'
176
187
  complete -c tdk -n '__fish_use_subcommand' -a 'version' -d 'Show version'
177
188
  complete -c tdk -n '__fish_use_subcommand' -a 'upgrade' -d 'Upgrade TDK CLI'
178
189
  complete -c tdk -n '__fish_use_subcommand' -a 'completion' -d 'Generate shell completions'
@@ -208,6 +219,8 @@ complete -c tdk -n '__fish_seen_subcommand_from up' -a '(tdk resources 2>/dev/nu
208
219
 
209
220
  # doctor command options
210
221
  complete -c tdk -n '__fish_seen_subcommand_from doctor' -l fix -d 'Attempt to fix issues'
222
+ complete -c tdk -n '__fish_seen_subcommand_from runtime' -l check-assets -d 'Check bundled engine and template assets'
223
+ complete -c tdk -n '__fish_seen_subcommand_from runtime' -l json -d 'Print the check result as JSON'
211
224
 
212
225
  # upgrade command options
213
226
  complete -c tdk -n '__fish_seen_subcommand_from upgrade' -l force -d 'Force upgrade even if on latest'
@@ -215,7 +228,7 @@ complete -c tdk -n '__fish_seen_subcommand_from upgrade' -l dry-run -d 'Show wha
215
228
  `;
216
229
  const POWERSHELL_COMPLETION = `Register-ArgumentCompleter -Native -CommandName tdk -ScriptBlock {
217
230
  param($wordToComplete)
218
- $cmds = @('up','down','doctor','project','resource','stacks','status','networks','upgrade','version','ui','config')
231
+ $cmds = @('up','down','doctor','project','resource','stacks','status','networks','upgrade','runtime','version','ui','config')
219
232
  $cmds | Where-Object { $_ -like "$wordToComplete*" }
220
233
  }`;
221
234
  const POWERSHELL_START = "# TDK-CLI-COMPLETION-START";
@@ -8,8 +8,10 @@ import { generateMasterConfigs, readProjectConfig, TemplateEngine, verifyMasterC
8
8
  import { isMasterConfigFileName } from "../types/index.js";
9
9
  import { assertValid } from "../utils/command-helpers.js";
10
10
  import { MASTER_CONFIG_FILES } from "../utils/constants.js";
11
- import { requireProjectRoot, runCommand } from "../utils/errors.js";
11
+ import { errorFactories, requireProjectRoot, runCommand } from "../utils/errors.js";
12
12
  import { writeJsonFile } from "../utils/file-helpers.js";
13
+ import { createMachineEnvelope, writeMachineError } from "../utils/machine-output.js";
14
+ import { findProjectRoot } from "../utils/paths.js";
13
15
  import { SERVICE_MANIFEST_SCHEMA_VERSION, validateServiceManifest, } from "../utils/service-manifest.js";
14
16
  import { discoverServiceManifestPaths } from "../utils/services.js";
15
17
  import { validateOptionalInfraService } from "../utils/validation.js";
@@ -173,11 +175,25 @@ export const configCommand = new Command("config")
173
175
  }))
174
176
  .addCommand(new Command("verify")
175
177
  .description("Verify that generated files match .tdk/project.json")
176
- .action(async () => {
177
- await runCommand(async () => {
178
- const projectRoot = requireProjectRoot();
179
- console.log(chalk.blue("🔍 Verifying configuration...\n"));
178
+ .option("--json", "Emit a machine-readable verification report")
179
+ .action(async (options) => {
180
+ const action = async () => {
181
+ const projectRoot = options.json ? findProjectRoot() : requireProjectRoot();
182
+ if (!projectRoot)
183
+ throw errorFactories.notInProject();
180
184
  const result = verifyMasterConfigs(projectRoot);
185
+ if (options.json) {
186
+ console.log(JSON.stringify(createMachineEnvelope({
187
+ valid: result.valid,
188
+ errors: result.errors,
189
+ warnings: result.warnings,
190
+ diffs: result.diffs,
191
+ })));
192
+ if (!result.valid)
193
+ process.exit(1);
194
+ return;
195
+ }
196
+ console.log(chalk.blue("🔍 Verifying configuration...\n"));
181
197
  for (const warning of result.warnings) {
182
198
  console.warn(chalk.yellow(`⚠️ ${warning}`));
183
199
  }
@@ -190,10 +206,22 @@ export const configCommand = new Command("config")
190
206
  for (const error of result.errors) {
191
207
  console.log(chalk.gray(` - ${error}`));
192
208
  }
209
+ for (const { diff } of result.diffs)
210
+ console.log(chalk.gray(`\n${diff}`));
193
211
  console.log(chalk.gray("\nRun `tdk config regenerate` to fix."));
194
212
  process.exit(1);
195
213
  }
196
- });
214
+ };
215
+ if (options.json) {
216
+ try {
217
+ await action();
218
+ }
219
+ catch (error) {
220
+ writeMachineError(error);
221
+ }
222
+ return;
223
+ }
224
+ await runCommand(action);
197
225
  }))
198
226
  .addCommand(new Command("edit").description("Open .tdk/project.json in your $EDITOR").action(async () => {
199
227
  await runCommand(async () => {