Naming & project config
How Beamd picks a tunnel's subdomain — the port default, --as and --from, the one-label rule, and a committed .beamd file.
A tunnel's public name is a single subdomain label on your edge's base domain:
api → https://api.beam.example.com. Beamd gives you three ways to set it,
and a project file so you rarely set it by hand.
The subdomain label
By default the label is the port number — beamd open 3000 →
https://3000.beam.example.com. That's fine for a quick look, but real apps
want a stable name.
--as and --from
Set the label explicitly, or derive it from your project:
beamd open 3001 --as api # literal label → api.<base>
beamd open 3001 --from repo # derive it → <repo-name>.<base>--from sources:
| Source | Label becomes |
|---|---|
port (default) | the port number |
dir | the current folder name |
repo | the git repository name |
branch | the current git branch |
worktree | <branch>-<repo> in a linked git worktree on a non-default branch, else the repo name |
--as (a literal) wins if you pass both. A good default for branch-based
previews is --from branch; set it once as a naming default.
The one-label rule
The wildcard certificate is exactly one DNS label deep — *.<base> (flat)
or *.<slug>.<base> (namespaced). So a tunnel name must be a single RFC 1123
label: lowercase letters, digits, and hyphens. Encode structure with hyphens,
not dots:
- ✅
api,web-api,proj-ab12-web - ❌
a.b— nested labels don't get a cert and won't resolve
This matters most for multi-app and worktree workflows: name a worktree's API
and web as proj-ab12-api and proj-ab12-web, not api.proj-ab12.
Hosted vs self-host. The hosted service folds your org into the label as a
hyphen suffix — api-acme.beamd.run — so every tunnel stays under one
*.beamd.run certificate. A self-hosted edge instead namespaces with a dotted
slug (api.turing.beam.example.com), backed by a per-slug
*.turing.beam.example.com cert. Either way, the name you choose is still a
single label.
Project config (.beamd)
Commit a .beamd at the repo root so the right edge, scope, and name come from
context — open and run then need zero flags:
# .beamd
server: acme.com # which edge (account)
scope: acme # which org (hosted; omit for a self-hosted edge)
from: repo # how to name the tunnel (or `name: <literal>`)Beamd walks up from the current directory to find it. A gitignored
.beamd.local overrides it for your machine — the .env / .env.local
pattern. A .beamd references an edge and scope, never a token, so it's
safe to commit. (More on server / scope in Accounts & scopes.)
Precedence
The label resolves in this order — first match wins:
1. --as <literal> # this command
2. --from <source> # this command
3. .beamd name: / from: # this repo (committed)
4. your naming default # ~/.beamd/config, e.g. { from: branch }
5. the port number # fallback