DVT SERVE
dvt servestarts your project's whole app suite — the hub, the data catalog, Chat with Martin, profiling, the scheduler, the explorer, dashboards, the api-portal and the executions monitor — on one port, then opens the hub in your browser and hands your terminal back. The suite runs detached in the background and stays up until you say dvt kill.
START IT
No flags needed. From inside your project:
$ dvt serve ✅ DVT suite · 'analytics' · http://localhost:46100 http://localhost:46100/ hub + Settings http://localhost:46100/catalog catalog http://localhost:46100/portal api-portal http://localhost:46100/chat Chat with Martin http://localhost:46100/profiling profiling http://localhost:46100/scheduler scheduler http://localhost:46100/explorer explorer http://localhost:46100/dashboards dashboards http://localhost:46100/executions executions monitor Always up until `dvt kill`. Apps with no artifacts serve their empty state and pick up compiles on refresh.
That map is the whole idea: one origin, and every app is a path on it — /chat, /explorer, /dashboards — instead of a scatter of ports to remember. The hub at /is the front door: it lists every app and carries Settings. You don't need to have compiled anything first — an app with no artifacts yet serves its empty state and picks up your next compile on refresh.
IN PLAIN DBT
The only thing you can serve is dbt docs serve — a static docs site, in the foreground, tied to your terminal, gone when you close it, on whatever port you remembered to pass. In DVT one command brings up nine apps on one pinned port, in the background, and they stay up until you stop them on purpose.
A DAY WITH IT
The intended rhythm is: run dvt serveonce in the morning and forget it. It's safe to run again — if your project's suite is already up, dvt serve notices, reuses it, and just reprints the map and reopens the hub:
$ dvt serve ▶ suite for 'analytics' already serving on :46100 ✅ DVT suite · 'analytics' · http://localhost:46100 ...
Meanwhile you keep working in the same terminal — dvt run, dvt build, edits — and the apps notice: the suite watches the project and the open pages pick up fresh state. The scheduler lives inside the suite too, which is exactly why the suite is built to be always-up: as long as it runs, your schedules fire.
THE PORT COMES FROM DVT_PROJECT.YML — AND NOWHERE ELSE
The suite's port is the suite_port key in dvt_project.yml — the only place it is defined. No environment variable, no --port flag, no dynamic allocation. If the key is missing, DVT falls back to the scaffold default (46100) and dvt config-checkup flags the project as unhealthy until the key is restored — the silent fallback must never be the only record of where your project serves.
And if something already holds your port, dvt serve refuses — a hard error that names the holder:
$ dvt serve ❌ port 46100 is this project's suite_port (dvt_project.yml), but it is held by the suite for project 'marketing' (pid 4821) — free it, or change suite_port in dvt_project.yml. DVT never evicts or hops (your API URLs never move), and it never picks a port for you.
That refusal is a promise, not a limitation. The api-portal serves real API endpoints, and dashboards get bookmarked — if DVT quietly hopped to a free port, every consumer of those URLs would break in silence. So the port never moves: you either free it or change the pin yourself. Running several projects side by side? Give each its own suite_port — one suite per project, each on its own pin.
DETACHED — YOUR TERMINAL IS NOT THE OFF SWITCH
dvt serveis a launcher, not a server. It spawns the suite as its own detached process (you'll see it as dvt suite in ps), waits up to ten seconds for the port to answer, prints the map, and exits. Close the terminal, and the suite keeps serving.
The suite's log lives inside the project, at .dvt/web_apps/suite/suite.log. If the suite doesn't come up, the launcher says so and points you there:
$ dvt serve ❌ suite did not come up on :46100 — see /home/dana/analytics/.dvt/web_apps/suite/suite.log
One broken app never takes the suite down. If a single app fails to mount, the rest serve normally and that app's paths answer 503 with this app failed to start — check the suite log.
STOPPING — DVT KILL
dvt killis the off switch, and it's project-scoped: run it in a project and it stops thatproject's suite, nobody else's.
$ dvt kill ⛔ Stopped suite on port 46100 (pid 4821)
dvt kill --allis the machine-wide sweep — it stops every project's suite. Either way, kill touches servers only: a dvt run in flight is never signaled (Ctrl+C in its own terminal owns stopping runs). Stale leftovers are cleared as it goes, and if there was nothing to stop it says so plainly: No hosted apps registered for 'analytics'.
IN PLAIN DBT
Stopping a background server means archaeology: lsof -i :8080, find the pid, kill it, hope it was the right one. DVT keeps a registry of what it started, so dvt killstops exactly your project's suite by name — and never touches a running transformation.
IF YOU'RE LOOKING FOR PER-APP SERVE FLAGS
Earlier DVT versions served apps individually with dvt serve -s <app>. That's gone by design — one way to serve, one way to kill — and both commands say so instead of dumping usage:
$ dvt serve -s catalog 'dvt serve -s' is gone — the suite serves every app on one port: dvt serve (apps are paths: /catalog, /portal, /chat, ...). $ dvt kill -s catalog 'dvt kill -s' is gone — the suite is one server: dvt kill stops this project's suite, dvt kill --all stops every project's.
REFERENCE — EVERY FLAG
dvt serve:
| FLAG | DEFAULT | WHAT IT DOES |
|---|---|---|
| --project-dir | . | The project whose suite to launch. The port pin, the watcher, the log and the registry entry are all scoped to this project. |
| --profiles-dir | (profiles.yml's usual home) | Read connections from a non-default profiles.yml location; passed through to every app in the suite. |
| --host | 127.0.0.1 | The address the suite binds. The default is loopback-only; the suite answers local hostnames only (a DNS-rebinding guard), and a deliberate non-loopback bind admits its own name. |
| --no-browser | off | Don't open the hub in a browser after launch — just print the map and exit. |
dvt kill:
| FLAG | DEFAULT | WHAT IT DOES |
|---|---|---|
| --all | off | Stop every project's suite on this machine, not just this project's. Servers only — running dvt work is never signaled. |
| --project-dir | . | Which project's suite to stop when you're not standing inside it. |