بنقرة واحدة
devrouter
Work with devrouter for local dev routing (HTTP + TCP/Postgres + dependency-only Docker services)
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Work with devrouter for local dev routing (HTTP + TCP/Postgres + dependency-only Docker services)
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Build the frontend of a GBL platform game - player cockpit with status-switch pattern, admin pages, realtime wiring, and which components to reuse from @gbl-uzh/ui and @uzh-bf/design-system. Use when creating or changing game pages/components in apps/<game>/src.
Scaffold a new GBL platform game app inside this monorepo by copying apps/demo-game - file-by-file copy/rename checklist, prisma setup, local dev environment, and first-run verification. Use when starting a brand-new game.
Keep the GBL platform wiki (docs/) accurate and conformant with the Open Knowledge Format - the repo-specific extension of generic OKF/LLM-wiki practice - when to update it, how to fact-check against code, house conventions, and validation. Use whenever a change touches packages/platform, packages/ui, apps/demo-game behavior, or when doc-code drift is noticed.
Implement the backend of a GBL platform game - the six-module Services contract (Actions, Period, PeriodResult, Segment, SegmentResult, GameFacts), facts types with yup schemas, and seed data. Use when writing or changing game logic in apps/<game>/src/services.
Design a learning game for the GBL platform - check platform fit, map a game idea onto periods/segments/decisions/facts, and produce a build-ready game design. Use BEFORE writing any code for a new game.
Create, run, debug, review, and extend Playwright E2E tests for GBL games (the demo-game suite and specs adapted for new game apps). Use when working in playwright/tests, Playwright config/CI, local devrouter/devcontainer browser validation, multi-player game flows, OIDC mock auth, report/dice/countdown assertions, flaky Playwright failures, or GBL Cypress-to-Playwright coverage planning.
| name | devrouter |
| description | Work with devrouter for local dev routing (HTTP + TCP/Postgres + dependency-only Docker services) |
| user-invocable | false |
Local dev routing via a shared Traefik reverse proxy. Provides stable *.localhost hostnames for HTTP apps and TCP/Postgres multiplexing on shared ports (80, 443, 5432).
.devrouter.yml (single source of truth).~/.config/devrouter (never edit manually)..localhost (lowercase alphanumeric + hyphens only)..devrouter.yml entry schemaversion: 1
devrouter:
version: <semver> # required for devrouter -V / devrouter upgrade
project:
name: <string> # optional
apps:
- name: <string> # unique within repo
kind: app | dependency # optional, default: app
dependencies: # optional
- app: <other-name>
envMap: # optional; maps target env var name -> per-dep source var name
DATABASE_URL: <UPPER_DEP_NAME>_URL
# if kind=app:
host: <name>.localhost
protocol: http | tcp
runtime: host | docker | proxy
# if kind=app and runtime=proxy (protocol http or tcp):
upstream: 127.0.0.1:3000 # already-running port to route to; no lifecycle/deps
# Loopback (127.0.0.1/localhost) -> host.docker.internal (a published host
# port). A non-loopback name is passed verbatim and resolved over devnet —
# so a devcontainer container ON devnet (with a network alias) can be fronted
# by NAME with NO published host port: upstream: <alias>:3000. This is the
# collision-free way to run many apps at once (each its own *.localhost).
# upstream may use the ${WORKSPACE} placeholder (e.g. ${WORKSPACE}-app:3000)
# to target a per-workspace devcontainer alias — substituted with the resolved
# workspace token at runtime. See "Workspace isolation" below. Do NOT put
# ${WORKSPACE} in `host` (rejected); the host is auto-namespaced.
#
# proxy + tcp (front a DB in an externally-managed container, e.g. a
# devcontainer's Postgres on devnet) — no per-DB host port:
# protocol: tcp
# tcpProtocol: postgres # selects shared entrypoint :5432
# upstream: <db-alias>:5432 # devnet alias of the DB container
# Requires `devrouter tls install` (SNI is read from the TLS ClientHello). Connect
# with direct-SSL so the ClientHello carries SNI, e.g.:
# psql "host=db.<app>.localhost port=5432 sslmode=require sslnegotiation=direct ..."
# if kind=app and runtime=host (protocol must be http):
hostRun:
command: <string>
cwd: <string> # relative to repo root, must not escape it
portTimeout: 120 # seconds, optional
strategy:
type: auto
denyPorts: [80, 443, 5432]
allowPortRange: '1024-65535'
# if kind=app and runtime=docker:
docker:
service: <string>
internalPort: <number>
composeFiles: [<string>] # relative to repo root
router: <string> # optional
# if kind=app and protocol=tcp:
tcpProtocol: postgres # required; runtime must be docker OR proxy
# if kind=dependency:
runtime: docker
docker:
service: <string>
composeFiles: [<string>] # relative to repo root
Validation rules:
kind=app: host must end with .localhostkind=app: runtime=host supports protocol=http onlykind=app: runtime=proxy supports protocol=http or protocol=tcp, requires upstream (host:port), and forbids hostRun/docker/dependencies (it only registers a route to an externally-managed upstream). protocol=tcp additionally requires tcpProtocol and TLS (devrouter tls install)kind=app: protocol=tcp requires runtime=docker (devrouter-managed container) or runtime=proxy (externally-managed upstream), plus a supported tcpProtocol (postgres/redis/mariadb/mysql)kind=dependency: must use runtime=docker and does not allow routed fields (host/protocol/tcpProtocol/hostRun/docker.internalPort/docker.router)healthcheck. docker compose up --wait blocks until healthy; without one, wait returns immediately.POSTGRES_USER=prisma, POSTGRES_PASSWORD=prisma, POSTGRES_DB=prisma and create a shadow database. devrouter injects per-dep {PREFIX}_URL / {PREFIX}_SHADOW_URL with these credentials.docker compose down -v).Example healthcheck:
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U prisma -d prisma']
interval: 5s
timeout: 3s
retries: 20
When a host app depends on a TCP Docker service, devrouter app run and devrouter app exec inject per-dep deterministic vars (where {PREFIX} = dep.name.toUpperCase().replace(/-/g, "_")):
| Variable | Value |
|---|---|
{PREFIX}_HOST | localhost |
{PREFIX}_PORT | random mapped port |
{PREFIX}_URL | protocol-specific URL (postgres, redis, mysql/mariadb) |
{PREFIX}_SHADOW_URL | postgres://prisma:prisma@localhost:<port>/shadow (postgres only) |
Host apps also receive PORT (random free port), HOSTNAME=0.0.0.0, HOST=0.0.0.0.
Config-level envMap on dependency references aliases per-dep vars to app-expected names (for example DATABASE_URL: DB_URL maps the per-dep DB_URL to DATABASE_URL).
Run several worktrees of one repo in parallel without host/route collisions. A workspace token spans the DevPod id, devrouter routes, ${WORKSPACE} proxy upstreams, and devcontainer aliases.
DEVROUTER_WORKSPACE may repeat the identity but cannot rename it. Ambiguous identities fail closed. The primary checkout remains non-namespaced.web.localhost → web.<ws>.localhost), ${WORKSPACE} in upstream is substituted with the token, and the docker router key is suffixed per workspace. The runtime config is computed in memory only — the committed .devrouter.yml is never rewritten.web.<ws>.localhost) are not covered by the *.localhost wildcard; devrouter auto-extends the mkcert cert SANs for active hosts when TLS is enabled.${localEnv:DEVCONTAINER_COMPOSE_OVERLAY:docker-compose.default.yml}; custom repositories may keep another default overlay. Selecting .devcontainer/docker-compose.devrouter.yml for linked worktrees must pass WORKSPACE and DEVROUTER_WORKSPACE across the combined base/overlay config and bind-mount ${DEVROUTER_GIT_COMMON_DIR} to the same absolute app-container path. The app exposes ${WORKSPACE}-app; the proxy uses upstream: ${WORKSPACE}-app:<port>.workspace up creates and starts a worktree; workspace ensure . starts/reconciles an existing linked worktree; workspace ls reports owner/Git/DevPod/route state; workspace stop stops DevPod/routes but keeps checkout, record, and data; full workspace down deletes runtime/routes and removes only a clean, unlocked worktree, then its record; down --keep-worktree keeps checkout and record. Dirty or locked full down fails before side effects.present, missing, locked, or conflict. workspace gc is a dry-run report; --yes deletes only exact ledger-owned missing/prunable resources and their records. GC never removes Git worktrees, branches, or prune state. Git has no worktree-removal hook..devrouter.yml folder without .git.secretManager.command in .devrouter.yml (include trailing --). devrouter wraps commands and re-injects dep env vars after the SM boundary.secretManager.defaultEnv: optional fallback environment for {env} template in command string.{env} template placeholder: secretManager.command: "infisical run --env {env} --" resolved at runtime. --env <env> CLI flag overrides defaultEnv.secretManager:
command: infisical run --env {env} --
defaultEnv: dev
envMap on dependency references to alias per-dep vars to app-expected names:
dependencies:
- app: db
envMap:
DATABASE_URL: DB_URL
DIRECT_URL: DB_URL
SHADOW_DATABASE_URL: DB_SHADOW_URL
infisical run or doppler run in sh -lc unless shell expansion is strictly required.devrouter app exec <app> --yes -- infisical run --projectId <id> --env=<env> -- pnpm payload migratedevrouter app exec <app> --yes -- printenv DB_URL DB_HOST DB_PORT DB_SHADOW_URLdevrouter app exec <app> --yes -- doppler run -- pnpm payload migratePROD_DATABASE_URL) and map intentionally via envMap.devrouter app exec --shell -- "<single command string>" only when shell expansion is required.envMap fails fast when source var is missing so migrations do not run with partial mapping..devrouter.yml metadata devrouter.version aligned with the currently applied devrouter release.devrouter -V (shows installed CLI version, local repo version, and next upgrade target).devrouter upgrade to list available upgrade targets and devrouter upgrade <version> to print that target's Agent Adaptation Prompt from upgrade-prompts/<version>.md.devrouter repo agents (or devrouter init --write-agents --write-skill).devrouter doctor --repo ., devrouter app ls --repo ., one representative devrouter app exec flow, and devrouter ls.devrouter init [--write-agents] [--write-skill]: print AI onboarding prompt (non-mutating by default)devrouter -V [--repo .]: show installed CLI version, local repo version, and next upgrade targetdevrouter upgrade [version] [--repo .]: list upgrade targets or print target Agent Adaptation Promptdevrouter setup --yes [--repo .] [--json]: first-run machine setup plus structured diagnosticsdevrouter up / devrouter down: start/stop shared Traefik routerdevrouter status: router/container/network/TLS healthdevrouter doctor [--repo .]: deep diagnostics (global + repo)devrouter ls: list active HTTP + TCP routesdevrouter open <name>: open HTTP route or print TCP connection hint (matches app name, then service/container/host identities)devrouter logs [-f]: Traefik access logsdevrouter tls install: install mkcert certs, enable HTTPS + TCP/SNIdevrouter repo init: create .devrouter.ymldevrouter repo inspect [--json]: inspect package, scripts, compose services, env names, devcontainer, devrouter config, and agent guidance for onboardingdevrouter repo devcontainer write --dry-run --json: plan conservative Node/pnpm/Postgres devcontainer/devrouter scaffold files without writingdevrouter repo devcontainer write --yes: write managed Node/pnpm/Postgres devcontainer/devrouter scaffold files when no custom-file conflicts existdevrouter repo devcontainer verify --json: emit read-only onboarding evidence for PRsdevrouter repo devcontainer verify --live --yes --json: register proxy routes and probe HTTP routes after the devcontainer is runningdevrouter repo agents: write devrouter section in AGENTS.md + install this skilldevrouter app add: add/update app entry in .devrouter.ymldevrouter app ls: list app entriesdevrouter app run <name> [--env <env>] [--workspace <slug>]: run app with dependency lifecycle (--env overrides SM defaultEnv; --workspace overrides the per-workspace token)devrouter app exec <name> [--shell] [--env <env>] [--workspace <slug>] -- <cmd>: one-shot command with resolved dep envdevrouter app rm <name> [--keep-config]: remove app entry (--keep-config frees only the live route/hostname, leaves .devrouter.yml untouched)devrouter workspace up <branch> [--path <dir>] [--no-devpod] [--open]: create a worktree and start/prove it unless create-only mode is requesteddevrouter workspace ensure [path] [--open]: start/reconcile and prove an existing linked worktree environmentdevrouter workspace ls [--json]: list ownership, Git, DevPod, route, path, and branch evidencedevrouter workspace stop <workspace|branch>: stop DevPod and routes; preserve checkout, owner record, and datadevrouter workspace down <workspace|branch> [--keep-worktree]: delete runtime/routes and optionally remove the clean worktree and recorddevrouter workspace gc [--json] [--yes]: report missing owners by default; apply exact eligible cleanup with --yesFor devcontainer onboarding:
devrouter setup --repo . --yes --jsondevrouter doctor --repo . --jsondevrouter repo inspect --repo . --jsondevrouter repo devcontainer write --repo . --dry-run --jsondevrouter repo devcontainer write --repo . --yesdevrouter repo devcontainer verify --repo . --jsondevrouter workspace ensure . (use devpod up . for a primary checkout)devrouter repo devcontainer verify --repo . --live --yes --jsonFor host/docker runtime apps only:
devrouter setup --repo . --yesdevrouter doctor --repo .devrouter app ls --repo .devrouter app run <host-app> --repo . --yesdevrouter lscurl -I https://<host>.localhostdevrouter open <name> for the connection hint.devrouter app run auto-starts Docker dependencies and waits for health. Host app runs stop auto-started docker deps on exit; docker app runs leave target services running until explicit cleanup.kind=dependency entries do not create routes and cannot be direct targets for devrouter app run, devrouter app exec, or devrouter open.kind=dependency services start as declared in compose (no Traefik label wiring, no random port publishing, no injected env vars).:5432 requires TLS/SNI (devrouter tls install). Standard app clients should use the injected random port instead.devrouter app exec follows the same dep lifecycle for one-shot commands and preserves argv semantics by default (shell: false).devrouter app exec --shell is explicit and requires exactly one command string after --.printenv DB_URL DB_HOST DB_PORT) before migrate/seed.