Skills dev-serve
Start and manage tmux-backed dev servers exposed through Caddy at wildcard subdomains.
install
source · Clone the upstream repo
git clone https://github.com/openclaw/skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/openclaw/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/brennerspear/dev-serve" ~/.claude/skills/clawdbot-skills-dev-serve && rm -rf "$T"
manifest:
skills/brennerspear/dev-serve/SKILL.mdsource content
dev-serve — One-Command Dev Server Hosting
Start a dev server in a tmux session and expose it via Caddy at
<project>.YOUR_DOMAIN. One command up, one command down.
Setup
-
Install the script:
cp scripts/dev-serve.sh ~/.local/bin/dev-serve chmod +x ~/.local/bin/dev-serve -
Set your domain (one of):
- Export
in your shell profileDEV_SERVE_DOMAIN - Or edit the
variable in the scriptDOMAIN
- Export
-
Requirements:
- Caddy running with wildcard DNS + TLS (see caddy skill)
,tmux
,jqcurl- Caddy admin API on
localhost:2019
CLI
dev-serve up <repo-path> [port] # Start dev server + add Caddy route dev-serve down <name> # Stop dev server + remove Caddy route dev-serve ls # List active dev servers dev-serve restart <name> # Restart dev server (keep Caddy route)
How It Works
- Derives subdomain from the repo folder name (
→~/projects/myapp
)myapp.YOUR_DOMAIN - Detects the dev command from
package.json
(supports vite, next, nuxt, sveltekit)scripts.dev - Auto-patches Vite
if a vite config file existsallowedHosts - Starts the dev server in a tmux session named
withdev-<name>--host 0.0.0.0 --port <port> - Adds a Caddy route + dashboard link to the Caddyfile
- Reloads Caddy via admin API (no sudo, no restart)
- Verifies end-to-end: waits for the dev server to listen, then polls HTTPS until 2xx/3xx (up to 90s)
Examples
# Start with auto-assigned port (starts at 5200, skips used ports) dev-serve up ~/projects/myapp # → https://myapp.YOUR_DOMAIN # Explicit port dev-serve up ~/projects/myapp 5200 # Override dev command DEV_CMD="bun dev" dev-serve up ~/projects/myapp 5300 # Stop and clean up dev-serve down myapp # List what's running dev-serve ls
Configuration
| Variable | Default | Description |
|---|---|---|
| (must be set) | Your wildcard domain (e.g. ) |
| | Where state JSON is stored |
| | Path to your Caddyfile |
| | Caddy admin API address |
| (auto-detected) | Override the dev server command |
Port Convention
- Permanent services: 3100 range (managed in Caddyfile directly)
- Dev servers: 5200+ (managed by dev-serve, auto-assigned)
Vite allowedHosts
allowedHostsVite blocks requests from unrecognized hostnames.
dev-serve up automatically patches vite.config.ts (or .js/.mts/.mjs) to add the subdomain. If auto-patching fails, it prints the manual fix.
Architecture
Browser (Tailscale / LAN / etc.) → DNS: *.YOUR_DOMAIN → your server IP → Caddy (HTTPS with auto certs) → reverse_proxy localhost:<port> → Dev server (in tmux session)
Companion Skills
- caddy — Required. Sets up the Caddy reverse proxy with wildcard TLS.
Troubleshooting
Dev server not starting:
tmux attach -t dev-<name> # see what happened
Cert not provisioning (curl exit 35): Wait 30-60s for DNS-01 challenge. Check
tail -20 /var/log/caddy-error.log.
Caddy reload failed:
caddy reload --config ~/.config/caddy/Caddyfile --address localhost:2019
403 from Vite: The subdomain wasn't added to
allowedHosts. Add it manually to your vite.config.ts:
server: { allowedHosts: ['myapp.YOUR_DOMAIN'] }