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:

FLAGDEFAULTWHAT 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.
--host127.0.0.1The 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-browseroffDon't open the hub in a browser after launch — just print the map and exit.

dvt kill:

FLAGDEFAULTWHAT IT DOES
--alloffStop 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.