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

SubcommandDescription
devRun the platform in development mode with the Services UI
buildRun the build command for all services

Options

FlagApplies toDescription
--filterdev,buildComma-separated service names to run (dependencies are included automatically)
--migrate-db, -mdbdevRun Liquibase migrations before starting services that have a database block
--no-tuidev,buildPlain-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 NAMEdev,buildNamed run profile from the cross-repo foundry.workspace.json (shorthand foundry run dev:NAME). Schema + example: config → Multi-repo workspaces and profiles
--env NAMEdevNamed environment overlay (environments.NAME run/env/sshTunnels blocks + .foundry/dev.NAME[.local].env); same as FOUNDRY_DEV_ENV
--debug, -dgroupShow 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.script is the exact command, run verbatim (run.args appended).
  • Anything with a package.json: if run.script names a package.json script, it runs through the package manager (npm run <name>); otherwise it is run verbatim from the service directory with node_modules/.bin on PATH — so an nx workspace with no dev script works with "script": "nx serve enterprise".
  • No detected runtime, no package.json: run.script is run verbatim; readiness is a TCP probe on run.port when 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