Search docs

Search the Beamd documentation

Wrap a dev server

beamd run starts your dev server, waits for it to listen, exposes it, and tears everything down on exit — one command.

beamd open exposes a port you've already started. beamd run does the whole thing: it picks a free port, starts your dev server on it, waits for it to listen, opens the tunnel, and tears everything down — tunnel and process tree — when you exit.

beamd run -- npm run dev        # name from .beamd / --from / port
beamd run api -- npm run dev     # explicit name

Everything after -- is your command, run as-is.

What it injects

run makes any framework reachable through the tunnel without you editing config:

  • $PORT — set to the port it picked, so your server listens where Beamd expects.
  • $BEAMD_URL — the public URL, for OAuth callbacks, webhooks, and absolute links that need to point at the tunnel.
  • Allowed-host env — so dev servers that reject unknown hosts (Vite, Next) accept the tunnel domain instead of throwing "Blocked request."
  • --port / --host args — added for frameworks that ignore $PORT (Vite, Astro, Angular, …).
  • node_modules/.bin on PATH — so project-local binaries resolve.

Naming and routing

run resolves the edge, scope, and name exactly like open — accounts, the project .beamd, and --as / --from all apply. So a committed .beamd with from: branch gives every branch its own preview URL with zero flags:

beamd run -- npm run dev
# on branch feat/login → https://feat-login.beam.example.com

Teardown

run is foreground and tied to your shell: Ctrl-C stops the dev server and closes the tunnel, and it cleans up the whole child process tree — no orphaned node processes, no dangling tunnel. For long-lived background tunnels managed by an agent instead, use beamd open -d.