foundry run
Start Foundry services locally in a unified Services UI. run is a command group with two subcommands — dev and build.
Usage
foundry run [-d|--debug] dev [--filter NAMES] [--migrate-db]
foundry run [-d|--debug] build [--filter NAMES]The -d/--debug flag is on the group and must appear before the subcommand (aliases hoist it automatically).
Subcommands
| Subcommand | Description |
|---|---|
dev | Run the platform in development mode with the Services UI |
build | Run the build command for all services |
Options
| Flag | Applies to | Description |
|---|---|---|
--filter | dev,build | Comma-separated service names to run (dependencies are included automatically) |
--migrate-db, -mdb | dev | Run Liquibase migrations before starting services that have a database block |
--no-tui | dev,build | Plain-text streaming output instead of the full-screen UI. Auto-selected when stdout is not a TTY or FOUNDRY_NO_TUI=1 is set |
--profile NAME | dev,build | Named run profile from the cross-repo foundry.workspace.json (shorthand foundry run dev:NAME). Schema + example: config → Multi-repo workspaces and profiles |
--env NAME | dev | Named environment overlay (environments.NAME run/env/sshTunnels blocks + .foundry/dev.NAME[.local].env); same as FOUNDRY_DEV_ENV |
--debug, -d | group | Show debug output |
Terminal profiles
The UI adapts to the terminal it is drawn in. In the VS Code integrated terminal status uses glyphs (✓ ✗) and arrow hints. Everywhere else (PowerShell, Windows Terminal, macOS Terminal.app, xterm) status is a plain green OK / red ERR and hints are words — glyphs render as boxes in too many fonts. On macOS Terminal.app mouse motion tracking is off (clicks still work) because that terminal spills the motion stream as escape codes over the UI. Overrides: FOUNDRY_TUI_GLYPHS=1|0, FOUNDRY_TUI_MOUSE=1|0|clicks.
What runs, and how run.script is interpreted
Every service declared in the manifest runs (or fails visibly with the reason) — a declared service is never silently skipped, and a declared path that does not exist prints a Note. The launch command comes from the detected runtime (Spring Boot → the Maven wrapper, Vite/Next → the package manager's dev script) unless run.script says otherwise:
- Spring Boot:
run.scriptis the exact command, run verbatim (run.argsappended). - Anything with a
package.json: ifrun.scriptnames a package.json script, it runs through the package manager (npm run <name>); otherwise it is run verbatim from the service directory withnode_modules/.binonPATH— so an nx workspace with nodevscript works with"script": "nx serve enterprise". - No detected runtime, no package.json:
run.scriptis run verbatim; readiness is a TCP probe onrun.portwhen set.
Headless mode and exit codes
In a script, CI job, or pipe, run dev automatically drops the full-screen UI and streams plain, untruncated log lines (--no-tui forces this in a terminal too). When every service ends up failed — an unreachable bastion killing the tunnels, a missing dependency — the process tears everything down and exits with status 1 instead of sitting in the UI, so a wrapping script fails fast. The interactive UI applies the same rule when the whole run fails at startup, printing the full error text after it closes. Ctrl+C (or SIGTERM) is a graceful shutdown: the service process tree and its SSH tunnels are all torn down together — no orphaned mvn/java children.
The Services UI
run dev discovers each enabled service from .foundry/workspace.yml and launches it in a managed runner. Sidecars appear as sub-items nested under their parent service. Service launch behavior — ports, commands, env, health checks — is resolved from the manifest's run block and detected framework conventions, not from a separate runtime file.
Examples
foundry run dev # all enabled services
foundry run dev --filter api,web # just these (plus their deps)
foundry run dev --migrate-db # migrate databases first
foundry run build # build all services