Run Dev Servers in Parallel
Two branches, two dev servers, one machine. uxd allocates a port block per
workspace; your job is to hand those ports to your app.
Single port
Most apps need one. Interpolate {port} into [env]:
[env]
PORT = "{port}"
[commands.dev]
run = "pnpm dev"
Now every workspace gets its own PORT:
uxd my-project feat/login run dev # PORT=3053
uxd my-project feat/search run dev # PORT=3011
$UXD_PORT is exported to every child process whether or not your config
references it. [env] is how you map it onto the variable name your app
actually reads.Several ports per workspace
An app that needs a web port, an API port, and a database port asks for a block:
ports = 3
[env]
PORT = "{port}"
API_PORT = "{port+1}"
DB_PORT = "{port+2}"
VITE_API_URL = "http://localhost:{port+1}"
ports accepts 1–10. {port+N} is valid for N < ports; asking for
{port+3} with ports = 3 is a config error, caught by uxd config validate.
The same values reach child processes as $UXD_PORT, $UXD_PORT_1,
$UXD_PORT_2.
Pinning the window
By default uxd derives a per-project base port. Pin it when you want
predictable ranges across a team, or to keep two projects out of each other's
way:
base_port = 5700
ports = 2
Allocation starts at a deterministic candidate derived from the workspace slug
within a 100-stride window above base_port, and only scans upward if that
block is claimed or already listening. So a given branch keeps the same port
across sessions — bookmarks and OAuth callback URLs keep working.
Overriding for one run
uxd my-project 42 run dev --port 6000
--port changes the environment for that invocation only. Nothing is
persisted, and the workspace keeps its allocated block.
Checking what a workspace holds
uxd my-project list
SLUG KIND BRANCH STATUS PORT AGE LAST USED
feat-login branch feat/login clean 3053 0m 0m
Or for one workspace, with --json if you are scripting:
uxd my-project feat/login info --json
Seeing the computed environment
Not sure what your app will receive? Ask, without running anything:
uxd my-project feat/login run dev --dry-run
--dry-run prints the environment as export lines followed by the
shell-quoted command:
export UXD_PATH=~/dev/uxd/my-project/trees/feat-login
export UXD_REPO_PATH=~/dev/uxd/my-project/repo
export UXD_DATA_DIR=~/dev/uxd/my-project/trees/.data/feat-login
export UXD_PROJECT=my-project
export UXD_REF=feat/login
export UXD_BRANCH=feat/login
export UXD_SLUG=feat-login
export UXD_PORT=3053
export PORT=3053
bash -c 'pnpm dev "$@"' uxd