@devrouter/cli 0.0.22 → 0.0.24

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Roland Schlaefli
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -27,13 +27,12 @@ This is the only supported per-repo config for app routing/runtime definitions.
27
27
 
28
28
  Both are configured the same way (`.devrouter.yml`) and can be mixed in one repo.
29
29
 
30
- ### 1. Front a devcontainer / existing process `runtime: proxy` (preferred)
30
+ ### 1. Front a devcontainer / existing process: `runtime: proxy` (preferred)
31
31
 
32
- The recommended setup going forward. A **devcontainer** (DevPod, VS Code Dev
33
- Containers, `@devcontainers/cli`, Codespaces) owns the *environment* — toolchain,
34
- databases, auth mocks, the app process, seeding and publishes the app on a local
35
- port. devrouter is a thin **routing layer**: it puts a stable `*.localhost` HTTPS
36
- host (shared `:443`, mkcert TLS) in front of that port and does nothing else.
32
+ The recommended setup is devcontainer first. The devcontainer owns the toolchain,
33
+ databases, auth mocks, app process, and seed data. devrouter owns only the local
34
+ routes. In the best case the container joins `devnet` and exposes stable network
35
+ aliases, so the app and database need no published host ports.
37
36
 
38
37
  ```yaml
39
38
  apps:
@@ -41,18 +40,20 @@ apps:
41
40
  host: myapp.localhost
42
41
  protocol: http
43
42
  runtime: proxy
44
- upstream: 127.0.0.1:3000 # the port your devcontainer publishes
43
+ upstream: myapp-app:3000 # devnet alias inside the devcontainer compose
45
44
  ```
46
45
 
47
46
  ```bash
48
- dev up && dev tls install # one-time
49
- dev app run app # registers the route; the container owns start/stop
47
+ devrouter setup --yes
48
+ devpod up .
49
+ devrouter repo devcontainer verify --live --yes --json
50
50
  ```
51
51
 
52
52
  Why prefer it: the environment is reproducible and runs anywhere the devcontainer
53
- spec runs (including remote/cloud via DevPod), devrouter never duplicates the
54
- DB/lifecycle/env work, and the two layers can't fight. See
55
- [`docs/DEVCONTAINER.md`](./docs/DEVCONTAINER.md) for the end-to-end walkthrough.
53
+ spec runs, while devrouter gives it stable local HTTPS and database hostnames.
54
+ Agents can add the scaffold with `devrouter repo inspect`, `devrouter repo devcontainer write`,
55
+ and `devrouter repo devcontainer verify`, then include the JSON evidence in a PR. See
56
+ [`docs/DEVCONTAINER.md`](./docs/DEVCONTAINER.md) for the full reference.
56
57
 
57
58
  ### 2. devrouter runs everything — `runtime: host` / `runtime: docker`
58
59
 
@@ -62,27 +63,38 @@ vars. Use it when you are not (yet) on a devcontainer. Fully supported.
62
63
 
63
64
  ## Core commands
64
65
 
65
- - `dev init [--repo <path>] [--entries-json <json>] [--json] [--write-agents] [--write-skill] [--with-linear]`
66
- - `dev -V [--repo <path>]` (installed CLI version, local repo version, next upgrade target)
67
- - `dev upgrade [version] [--repo <path>]`
68
- - `dev up`
69
- - `dev down`
70
- - `dev status [--repo <path>] [--json]`
71
- - `dev doctor|verify [--repo <path>] [--json]`
72
- - `dev ls [--json]`
73
- - `dev open <name>` (matches app name, then service/container/host)
74
- - `dev tls install`
75
- - `dev repo init [--repo <path>]`
76
- - `dev repo agents [--repo <path>] [--with-linear]`
77
- - `dev app add ...` (`--kind app|dependency`, default `app`)
78
- - `dev app ls [--repo <path>] [--json]`
79
- - `dev app run <name> [--repo <path>] [--yes] [--workspace <slug>]`
80
- - `dev app exec <name> [--repo <path>] [--yes] [--shell] [--env-map TARGET=SOURCE] [--workspace <slug>] -- <command>`
81
- - `dev app rm <name> [--repo <path>]`
82
- - `dev logs [-f]`
83
- - `dev workspace up <branch> [--path <dir>] [--no-devpod] [--open] [--repo <path>]`
84
- - `dev workspace ls [--repo <path>] [--json]`
85
- - `dev workspace down <workspace|branch> [--keep-worktree] [--keep-devpod] [--repo <path>]`
66
+ - `devrouter init [--repo <path>] [--entries-json <json>] [--json] [--write-agents] [--write-skill] [--with-linear]`
67
+ - `devrouter -V [--repo <path>]` (installed CLI version, local repo version, next upgrade target)
68
+ - `devrouter upgrade [version] [--repo <path>]`
69
+ - `devrouter setup --yes [--repo <path>] [--json]`
70
+ - `devrouter up`
71
+ - `devrouter down`
72
+ - `devrouter status [--repo <path>] [--json]`
73
+ - `devrouter doctor|verify [--repo <path>] [--json]`
74
+ - `devrouter ls [--json]`
75
+ - `devrouter open <name>` (matches app name, then service/container/host)
76
+ - `devrouter tls install`
77
+ - `devrouter repo init [--repo <path>]`
78
+ - `devrouter repo inspect [--repo <path>] [--json]`
79
+ - `devrouter repo devcontainer write [--repo <path>] [--dry-run] [--yes] [--json]`
80
+ - `devrouter repo devcontainer verify [--repo <path>] [--live] [--yes] [--json]`
81
+ - `devrouter repo agents [--repo <path>] [--with-linear]`
82
+ - `devrouter app add ...` (`--kind app|dependency`, default `app`)
83
+ - `devrouter app ls [--repo <path>] [--json]`
84
+ - `devrouter app run <name> [--repo <path>] [--yes] [--workspace <slug>]`
85
+ - `devrouter app exec <name> [--repo <path>] [--yes] [--shell] [--env <env>] [--workspace <slug>] -- <command>`
86
+ - `devrouter app rm <name> [--repo <path>]`
87
+ - `devrouter logs [-f]`
88
+ - `devrouter workspace up <branch> [--path <dir>] [--no-devpod] [--open] [--repo <path>]`
89
+ - `devrouter workspace ls [--repo <path>] [--json]`
90
+ - `devrouter workspace down <workspace|branch> [--keep-worktree] [--keep-devpod] [--repo <path>]`
91
+
92
+ The current `devrouter repo devcontainer write` scaffold is intentionally narrow:
93
+ Node + pnpm + Postgres. Other package managers stop with a JSON diagnostic
94
+ instead of writing files that would need manual repair.
95
+ Use `devrouter repo devcontainer verify --json` for read-only PR evidence; add
96
+ `--live --yes` only after the devcontainer is running and route probes should
97
+ mutate local route state.
86
98
 
87
99
  ## Workspace isolation (parallel worktrees)
88
100
 
@@ -108,24 +120,29 @@ A **workspace token** lets several git worktrees of the same repo run side-by-si
108
120
 
109
121
  ```bash
110
122
  # Bring up a feature branch as an isolated workspace
111
- dev workspace up feat/my-feature
123
+ devrouter workspace up feat/my-feature
112
124
 
113
125
  # List git worktrees with workspace tokens and route counts
114
- dev workspace ls
126
+ devrouter workspace ls
115
127
 
116
128
  # Tear down a workspace (stop devpod, remove worktree, free routes)
117
- dev workspace down feat/my-feature
129
+ devrouter workspace down feat/my-feature
118
130
  ```
119
131
 
120
132
  **devcontainer integration:** the devcontainer compose service exposes a devnet network alias `${WORKSPACE}-app` (defaulting to the project name in `devcontainer.env`); the proxy app uses `upstream: ${WORKSPACE}-app:<port>`. Workspace `feat-a` → alias `feat-a-app`, host `app.feat-a.localhost`.
121
133
 
122
134
  **Try it:** [`examples/workspace/`](examples/workspace/) is a runnable showcase — `./run.sh` brings up one app in two parallel worktrees (`wsdemo.localhost` and `wsdemo.feat-a.localhost`) served at once, then `./run.sh down` tears it down.
123
135
 
124
- **GC:** `dev doctor` check `routes.orphaned-workspace-routes` reclaims proxy routes whose worktree directory was removed without `dev workspace down`. Only orphaned workspace routes are reclaimed; primary-checkout routes are never touched.
136
+ **DevPod example:** [`examples/devcontainer/`](examples/devcontainer/) is the
137
+ agent-native devcontainer path end to end — `./run.sh` brings up a DevPod
138
+ workspace, registers app/Postgres proxy routes, runs static/live verification,
139
+ and prints the proof. `./run.sh down` tears it down.
140
+
141
+ **Orphan detection:** `devrouter doctor` check `routes.orphaned-workspace-routes` reports proxy routes whose worktree directory was removed without `devrouter workspace down`. It does not mutate route state.
125
142
 
126
143
  ## Upgrade metadata and prompts
127
144
 
128
- `dev upgrade` and `dev -V` read local upgrade metadata from `.devrouter.yml` in the target repo (`devrouter.version`):
145
+ `devrouter upgrade` and `devrouter -V` read local upgrade metadata from `.devrouter.yml` in the target repo (`devrouter.version`):
129
146
 
130
147
  ```yaml
131
148
  version: 1
@@ -136,18 +153,18 @@ apps: []
136
153
 
137
154
  Quick checks:
138
155
 
139
- - `dev -V` shows installed CLI version, local repo version, and next available upgrade target.
140
- - `dev upgrade` lists all upgrade targets newer than the local repo version and marks the next one.
141
- - `dev upgrade <version>` prints that target release's Agent Adaptation Prompt and then shows if a further version is available.
156
+ - `devrouter -V` shows installed CLI version, local repo version, and next available upgrade target.
157
+ - `devrouter upgrade` lists all upgrade targets newer than the local repo version and marks the next one.
158
+ - `devrouter upgrade <version>` prints that target release's Agent Adaptation Prompt and then shows if a further version is available.
142
159
  - Upgrade prompts are sourced from `upgrade-prompts/<version>.md`.
143
- - `dev repo init` initializes `devrouter.version` to the installed CLI version.
160
+ - `devrouter repo init` initializes `devrouter.version` to the installed CLI version.
144
161
 
145
162
  ## AI-native onboarding prompt
146
163
 
147
164
  Generate a ready-to-copy onboarding prompt for an AI agent:
148
165
 
149
166
  ```bash
150
- dev init --repo /absolute/path/to/repo
167
+ devrouter init --repo /absolute/path/to/repo
151
168
  ```
152
169
 
153
170
  By default, this command is non-mutating (it prints prompt text only).
@@ -155,47 +172,48 @@ By default, this command is non-mutating (it prints prompt text only).
155
172
  Optional: embed target app entries as JSON:
156
173
 
157
174
  ```bash
158
- dev init --repo /absolute/path/to/repo --entries-json '[{"name":"web","host":"web.localhost","protocol":"http","runtime":"host"}]'
175
+ devrouter init --repo /absolute/path/to/repo --entries-json '[{"name":"web","host":"web.localhost","protocol":"http","runtime":"host"}]'
159
176
  ```
160
177
 
161
178
  JSON mode for machine consumption:
162
179
 
163
180
  ```bash
164
- dev init --repo /absolute/path/to/repo --json
181
+ devrouter init --repo /absolute/path/to/repo --json
165
182
  ```
166
183
 
167
184
  Optional repo artifact writes are explicit:
168
185
 
169
186
  ```bash
170
- dev init --repo /absolute/path/to/repo --write-agents --write-skill
187
+ devrouter init --repo /absolute/path/to/repo --write-agents --write-skill
171
188
  ```
172
189
 
173
190
  Optional: also bootstrap Linear workflow skill/templates and AGENTS section:
174
191
 
175
192
  ```bash
176
- dev init --repo /absolute/path/to/repo --with-linear --write-agents --write-skill
193
+ devrouter init --repo /absolute/path/to/repo --with-linear --write-agents --write-skill
177
194
  ```
178
195
 
179
196
  When `--with-linear` is combined with AGENTS writes, devrouter captures minimal Linear mapping (workspace, team, project). In non-interactive mode it writes placeholders and prints a warning so values can be filled in later.
180
197
 
181
198
  ## Health diagnostics
182
199
 
183
- Run deep checks for global router state and repo configuration:
200
+ Run check-only diagnostics for global router state, machine prerequisites, route state, and repo configuration:
184
201
 
185
202
  ```bash
186
- dev doctor --repo /absolute/path/to/repo
203
+ devrouter doctor --repo /absolute/path/to/repo
187
204
  ```
188
205
 
189
206
  Machine-friendly output:
190
207
 
191
208
  ```bash
192
- dev doctor --repo /absolute/path/to/repo --json
209
+ devrouter doctor --repo /absolute/path/to/repo --json
193
210
  ```
194
211
 
195
- `dev status` now includes readiness hints and next-step commands.
196
- For host apps that depend on postgres, `dev doctor` also checks host command wrapper precedence and warns with `repo.host-command-env-precedence` when `DATABASE_URI`/`DATABASE_URL` is assigned before a `run --` wrapper boundary.
197
- When TLS is enabled, `dev doctor` also checks TLS host coverage and warns with `repo.tls-host-coverage` if configured `.localhost` hosts are not covered by the current cert SANs.
198
- `dev doctor` also reclaims orphaned workspace proxy routes (`routes.orphaned-workspace-routes`) whose worktree directory was removed without `dev workspace down`.
212
+ `devrouter status` now includes readiness hints and next-step commands.
213
+ For host apps that depend on postgres, `devrouter doctor` also checks host command wrapper precedence and warns with `repo.host-command-env-precedence` when `DATABASE_URI`/`DATABASE_URL` is assigned before a `run --` wrapper boundary.
214
+ When TLS is enabled, `devrouter doctor` also checks TLS host coverage and warns with `repo.tls-host-coverage` if configured `.localhost` hosts are not covered by the current cert SANs.
215
+ When `.devcontainer/` exists, `devrouter doctor` checks devnet aliases, published host ports, and proxy upstream alias matches.
216
+ `devrouter doctor` reports stale host routes and orphaned workspace proxy routes without mutating route state.
199
217
 
200
218
  ## `.devrouter.yml` example
201
219
 
@@ -254,61 +272,69 @@ apps:
254
272
  Notes:
255
273
 
256
274
  - `kind` defaults to routed app behavior. Use `kind: dependency` for non-routed Docker dependencies.
257
- - `runtime: proxy` registers an HTTP route to an externally-managed `upstream` (`host:port`) and does nothing else — use it to put a stable `*.localhost` HTTPS host in front of a devcontainer or any process you start yourself. Loopback upstreams (`localhost`/`127.0.0.1`/`0.0.0.0`) are rewritten to `host.docker.internal` so Traefik (in Docker) can reach the host. The route persists until `dev app rm`.
258
- - TCP mode currently supports PostgreSQL first (`tcpProtocol: postgres`).
259
- - Multi-DB hostname routing on shared `:5432` requires TLS/SNI.
260
- - Plaintext Postgres is not supported for multiplexed hostname routing.
275
+ - `runtime: proxy` registers an HTTP route to an externally-managed `upstream` (`host:port`) and does nothing else — use it to put a stable `*.localhost` HTTPS host in front of a devcontainer or any process you start yourself. Loopback upstreams (`localhost`/`127.0.0.1`/`0.0.0.0`) are rewritten to `host.docker.internal` so Traefik (in Docker) can reach the host. The route persists until `devrouter app rm`.
276
+ - TCP routing supports `tcpProtocol: postgres`, `redis`, `mariadb`, and `mysql` on shared protocol ports with TLS/SNI.
277
+ - Plaintext TCP is not supported for multiplexed hostname routing.
261
278
  - Multi-segment `.localhost` hosts are supported (for example `elearning.klicker.localhost`).
262
279
 
263
280
  ## Runtime behavior
264
281
 
265
- `dev app run <name>`:
282
+ `devrouter app run <name>`:
266
283
 
267
284
  - reads `.devrouter.yml`
268
285
  - prompts to start declared dependencies (or use `--yes`)
269
286
  - starts docker target services for `runtime: docker` apps, plus declared docker dependencies
270
- - for `runtime: proxy` apps: registers the route to `upstream` and returns immediately (no process started, no dependencies); re-running is an idempotent upsert and the route persists until `dev app rm`
287
+ - for `runtime: proxy` apps: registers the route to `upstream` and returns immediately (no process started, no dependencies); re-running is an idempotent upsert and the route persists until `devrouter app rm`
271
288
  - fails fast if host-runtime dependencies are configured (start those manually)
272
289
  - waits for Docker dependencies to become healthy (`--wait`) before proceeding
273
- - automatically stops Docker dependencies when a host app exits; docker app services remain running until explicit cleanup (`docker compose down`, `dev down`, or equivalent)
290
+ - automatically stops Docker dependencies when a host app exits; docker app services remain running until explicit cleanup (`docker compose down`, `devrouter down`, or equivalent)
274
291
  - prints recent dependency logs (last 20 lines) after deps start
275
- - `kind=dependency` apps are dependency-only: they do not create routes and cannot be direct targets for `dev app run`, `dev app exec`, or `dev open`
292
+ - `kind=dependency` apps are dependency-only: they do not create routes and cannot be direct targets for `devrouter app run`, `devrouter app exec`, or `devrouter open`
276
293
  - `kind=dependency` services start as declared in compose (no Traefik labels, no random published ports, no injected env vars)
277
- - for TCP deps of host apps: publishes a random host port and injects `<NAME>_HOST`/`<NAME>_PORT` env vars into the host process; for postgres deps also injects `DATABASE_URL` and `SHADOW_DATABASE_URL` (fixed credentials `prisma:prisma`, databases `prisma`/`shadow`)
278
- - for one-shot commands, `dev app exec` starts declared docker deps as needed and only stops deps it started in that invocation (already-running deps stay running)
279
- - if `dev app exec` cannot determine pre-existing running services, it leaves selected deps running to avoid stopping non-owned services
280
- - when TLS is enabled, `dev app run` / `dev app exec` auto-refresh cert SAN coverage for configured repo hosts before startup (fails fast with `Run: dev tls install` guidance if refresh fails)
281
- - for one-shot commands, `dev app exec` preserves argv semantics by default (`shell: false`) to avoid nested quoting issues
282
- - `dev app exec --shell` is explicit and requires one command string after `--`
283
- - `dev app exec --env-map TARGET=SOURCE` (repeatable) maps aliases after dependency env resolution (for example `DATABASE_URI=DATABASE_URL`)
294
+ - for TCP deps of host apps: publishes a random host port and injects per-dependency `<NAME>_HOST`/`<NAME>_PORT`/`<NAME>_URL` env vars into the host process; for postgres deps also injects `<NAME>_SHADOW_URL` (fixed credentials `prisma:prisma`, databases `prisma`/`shadow`)
295
+ - for one-shot commands, `devrouter app exec` starts declared docker deps as needed and only stops deps it started in that invocation (already-running deps stay running)
296
+ - if `devrouter app exec` cannot determine pre-existing running services, it leaves selected deps running to avoid stopping non-owned services
297
+ - when TLS is enabled, `devrouter app run` / `devrouter app exec` auto-refresh cert SAN coverage for configured repo hosts before startup (fails fast with `Run: devrouter tls install` guidance if refresh fails)
298
+ - for one-shot commands, `devrouter app exec` preserves argv semantics by default (`shell: false`) to avoid nested quoting issues
299
+ - `devrouter app exec --shell` is explicit and requires one command string after `--`
300
+ - config-level `envMap` on dependency references maps aliases after dependency env resolution (for example `DATABASE_URL: DB_URL`)
284
301
  - starts host app command for host runtime apps
285
302
  - generates docker overlay in `~/.config/devrouter/cache/...` for docker runtime apps
286
303
 
287
304
  Secret manager interop (Infisical/Doppler):
288
305
 
289
- - dependency env injection from devrouter includes `<NAME>_HOST`, `<NAME>_PORT`, `DATABASE_URL`, and `SHADOW_DATABASE_URL`
306
+ - dependency env injection from devrouter includes `<NAME>_HOST`, `<NAME>_PORT`, `<NAME>_URL`, and postgres-only `<NAME>_SHADOW_URL`
290
307
  - do not assume secret-manager precedence when DB vars overlap; validate effective env before migrate/seed
291
308
  - avoid pre-wrapper DB assignments such as `DATABASE_URI=... <wrapper> run -- ...`; wrapper-managed env may override those values
292
- - safe host-run override pattern when wrapper also defines `DATABASE_URI`: `infisical run --projectId <id> --env=<env> -- env DATABASE_URI=${DATABASE_URL:?missing DATABASE_URL} pnpm dev`
293
- - non-Prisma mapping example: `dev app exec web --yes --env-map DATABASE_URI=DATABASE_URL -- infisical run --projectId <id> --env=<env> -- pnpm payload migrate`
294
- - env probe example: `dev app exec web --yes --env-map DATABASE_URI=DATABASE_URL -- printenv DATABASE_URL DATABASE_URI DB_HOST DB_PORT SHADOW_DATABASE_URL`
295
- - run `dev doctor --repo <path>` to surface risky wrapper precedence (`repo.host-command-env-precedence`) before migrations or app startup
296
-
297
- `dev ls` output includes both configured app identity (`APP`) and runtime service identity (`SERVICE`).
309
+ - map app-specific names in `.devrouter.yml`:
310
+ ```yaml
311
+ dependencies:
312
+ - app: db
313
+ envMap:
314
+ DATABASE_URL: DB_URL
315
+ DIRECT_URL: DB_URL
316
+ SHADOW_DATABASE_URL: DB_SHADOW_URL
317
+ ```
318
+ - safe host-run override pattern when wrapper also defines `DATABASE_URI`: `infisical run --projectId <id> --env=<env> -- env DATABASE_URI=${DB_URL:?missing DB_URL} pnpm dev`
319
+ - non-Prisma mapping example: `devrouter app exec web --yes -- infisical run --projectId <id> --env=<env> -- pnpm payload migrate`
320
+ - env probe example: `devrouter app exec web --yes -- printenv DB_URL DATABASE_URL DB_HOST DB_PORT DB_SHADOW_URL SHADOW_DATABASE_URL`
321
+ - run `devrouter doctor --repo <path>` to surface risky wrapper precedence (`repo.host-command-env-precedence`) before migrations or app startup
322
+
323
+ `devrouter ls` output includes both configured app identity (`APP`) and runtime service identity (`SERVICE`).
298
324
 
299
325
  ## First onboarding quick path
300
326
 
301
327
  In a repo that has a host app and a Docker Postgres service:
302
328
 
303
329
  ```bash
304
- dev repo init
305
- dev app add --name web --host web.localhost --protocol http --runtime host --command "pnpm dev" --cwd .
306
- dev app add --name db --host db.localhost --protocol tcp --runtime docker --tcp-protocol postgres --service db --port 5432 --compose-file docker-compose.yml
307
- dev app add --name redis --kind dependency --service redis --compose-file docker-compose.yml
308
- dev app add --name web --host web.localhost --protocol http --runtime host --command "pnpm dev" --cwd . --depends-on db --depends-on redis
309
- dev tls install
310
- dev app run web --yes
311
- dev ls
330
+ devrouter repo init
331
+ devrouter app add --name web --host web.localhost --protocol http --runtime host --command "pnpm dev" --cwd .
332
+ devrouter app add --name db --host db.localhost --protocol tcp --runtime docker --tcp-protocol postgres --service db --port 5432 --compose-file docker-compose.yml
333
+ devrouter app add --name redis --kind dependency --service redis --compose-file docker-compose.yml
334
+ devrouter app add --name web --host web.localhost --protocol http --runtime host --command "pnpm dev" --cwd . --depends-on db --depends-on redis
335
+ devrouter tls install
336
+ devrouter app run web --yes
337
+ devrouter ls
312
338
  ```
313
339
 
314
340
  Expected endpoints:
@@ -316,11 +342,11 @@ Expected endpoints:
316
342
  - `https://web.localhost`
317
343
  - `postgres://db.localhost:5432 (tls required)`
318
344
 
319
- ## Demo workspace (in this repo)
345
+ ## Routing example (without devcontainers)
320
346
 
321
- A complete sample repository is included at:
347
+ A complete no-devcontainer sample repository is included at:
322
348
 
323
- - [`./demo`](./demo)
349
+ - [`./examples/routing`](./examples/routing)
324
350
 
325
351
  It contains:
326
352
 
@@ -329,24 +355,33 @@ It contains:
329
355
  - Postgres in Docker (`db`)
330
356
  - ready-to-use `.devrouter.yml`
331
357
 
332
- Run the end-to-end smoke demo:
358
+ Run the bundled routing smoke:
359
+
360
+ ```bash
361
+ pnpm routing:smoke
362
+ ```
363
+
364
+ Run the live DevPod/devcontainer smoke when Docker, DevPod, and mkcert are
365
+ available:
333
366
 
334
367
  ```bash
335
- pnpm demo:smoke
368
+ pnpm devcontainer:smoke
369
+ pnpm devcontainer:smoke down
336
370
  ```
337
371
 
338
372
  See details:
339
373
 
340
- - [`./demo/README.md`](./demo/README.md)
374
+ - [`./examples/routing/README.md`](./examples/routing/README.md)
375
+ - [`./examples/devcontainer/README.md`](./examples/devcontainer/README.md)
341
376
 
342
377
  ## AI agent discoverability
343
378
 
344
- `dev repo agents` writes a devrouter section into the repo's `AGENTS.md` and installs a skill file at `.agents/skills/devrouter/SKILL.md`. The skill content is embedded in the CLI bundle so it stays in sync across repos.
379
+ `devrouter repo agents` writes a devrouter section into the repo's `AGENTS.md` and installs a skill file at `.agents/skills/devrouter/SKILL.md`. The skill content is embedded in the CLI bundle so it stays in sync across repos.
345
380
 
346
381
  If you also want Linear workflow assets and repository mapping metadata, run:
347
382
 
348
383
  ```bash
349
- dev repo agents --with-linear
384
+ devrouter repo agents --with-linear
350
385
  ```
351
386
 
352
387
  This additionally installs:
@@ -380,8 +415,8 @@ Required Linear execution hygiene:
380
415
 
381
416
  - Host-runtime dependencies are not auto-started; only Docker dependencies are auto-started.
382
417
  - `kind=dependency` apps are not direct run/exec/open targets (must be started via a routed app dependency graph).
383
- - TCP routing currently supports PostgreSQL only (`tcpProtocol: postgres`).
384
- - Shared `:5432` hostname multiplexing requires TLS/SNI (`sslmode=require` or stronger).
418
+ - TCP routing supports `tcpProtocol: postgres`, `redis`, `mariadb`, and `mysql`.
419
+ - Shared TCP hostname multiplexing requires TLS/SNI (`sslmode=require` or protocol-equivalent client SNI).
385
420
 
386
421
  ## Router state
387
422
 
@@ -400,6 +435,6 @@ Global managed artifacts remain under:
400
435
  - Setup and bootstrapping: [`docs/GETTING_STARTED.md`](./docs/GETTING_STARTED.md)
401
436
  - Onboarding repositories and AI prompt: [`docs/REPO_ONBOARDING.md`](./docs/REPO_ONBOARDING.md)
402
437
  - Agent contributor guide: [`AGENTS.md`](./AGENTS.md)
403
- - Demo workspace: [`./demo/README.md`](./demo/README.md)
438
+ - Routing example: [`./examples/routing/README.md`](./examples/routing/README.md)
404
439
  - Roadmap: [`docs/PLAN.md`](./docs/PLAN.md)
405
440
  - Release and adaptation history: [`CHANGELOG.md`](./CHANGELOG.md) and [`upgrade-prompts/`](./upgrade-prompts/)