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 nameEverything 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/--hostargs — added for frameworks that ignore$PORT(Vite, Astro, Angular, …).node_modules/.binon 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.comTeardown
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.