This thing is 100% vibe coded with Claude Code.
Local development environment orchestrator for monorepos. Spin up fully configured preview environments with real HTTPS URLs from a single command.
veld start frontend:local --name my-feature
# => https://frontend.my-feature.myproject.localhost
# => https://backend.my-feature.myproject.localhostNo port numbers. No manual wiring. Just clean, stable, human-readable URLs.
- No port numbers — work with stable HTTPS URLs instead of
localhost:3847 - Dependency graph — resolves node dependencies, parallelizes startup, reverse-order teardown
- TLS by default — Caddy's internal CA handles TLS termination, auto-trusted during setup
- Health checks — readiness probes (two-phase: TCP port + HTTP/command) gate startup; liveness probes detect failures after startup (e.g., dropped SSH tunnels)
- Automatic recovery — when liveness probes detect failure, the environment is automatically restarted (configurable failure threshold and max recovery attempts)
- Multiple variants — same node, different behaviors (local server, Docker, remote URL)
- Named runs — multiple environments coexist; re-running by name is idempotent
- Setup / teardown — project-level lifecycle steps that gate startup (check Docker, create networks) and clean up after stop
- Presets — named shortcuts for common selections (
fullstack,ui-only) - Variable interpolation —
${veld.port},${nodes.backend.url}, git branch, etc. - Structured output — all commands support
--jsonfor scripting and CI - Browser dashboard — management UI at
https://veld.localhostwith service health, logs, search, stop/restart - Client-side logs — captures browser
console.log/warn/error, exceptions, and promise rejections; view withveld logs --source client - Internal logs — liveness probe outcomes (with stderr), recovery decisions, health state transitions; view with
veld logs --source internal
Download the latest release for your platform:
curl -fsSL https://veld.oss.life.li/get | bashThis detects your OS and architecture, downloads the latest release, and installs:
veldto~/.local/bin/veld-helperandveld-daemonto~/.local/lib/veld/
No sudo required. Ensure ~/.local/bin is on your PATH.
Setup is optional — commands auto-bootstrap on first use with HTTPS on port 18443. For the full experience with clean URLs (no port numbers), run the one-time privileged setup:
veld setup privilegedThis registers system services and binds ports 80/443, so your URLs are just
https://frontend.my-feature.myproject.localhost — no :18443 suffix. Requires
sudo once; you won't be asked again.
Alternatively, veld setup unprivileged does a no-sudo setup with HTTPS on port 18443.
Both modes support the full feature set with one difference: unprivileged mode uses port 18443 in URLs and only supports .localhost domains (RFC 6761). Custom apex domains (e.g. {service}.mycompany.dev) require veld setup privileged since they need /etc/hosts or dnsmasq management.
To install a specific version: VELD_VERSION=1.0.0 curl -fsSL https://veld.oss.life.li/get | bash
git clone https://github.com/prosperity-solutions/veld.git
cd veld
cargo build --release
# Binaries: target/release/veld, target/release/veld-helper, target/release/veld-daemon- Create a
veld.jsonin your project root:
{
"$schema": "https://veld.oss.life.li/schema/v2/veld.schema.json",
"schemaVersion": "2",
"name": "myproject",
"url_template": "{service}.{run}.{project}.localhost",
"nodes": {
"backend": {
"default_variant": "local",
"variants": {
"local": {
"type": "start_server",
"command": "npm run dev -- --port ${veld.port}",
"probes": { "readiness": { "type": "http", "path": "/health", "timeout_seconds": 30 } }
}
}
},
"frontend": {
"default_variant": "local",
"variants": {
"local": {
"type": "start_server",
"command": "npm run dev -- --port ${veld.port}",
"probes": { "readiness": { "type": "http", "path": "/", "timeout_seconds": 30 } },
"depends_on": { "backend": "local" },
"env": { "NEXT_PUBLIC_API_URL": "${nodes.backend.url}" }
}
}
}
}
}- Start the environment:
veld start frontend:local --name devVeld resolves the dependency graph (backend first, then frontend), allocates ports, starts processes, runs health checks, configures Caddy routes, and gives you HTTPS URLs.
- Check status:
veld status --name dev
veld urls --name dev- Stop:
veld stop --name dev| Command | Description |
|---|---|
veld start [NODE:VARIANT...] --name <n> |
Start an environment |
veld stop [--name <n>] [--all] |
Stop a running environment |
veld restart [--name <n>] |
Restart an environment |
veld status [--name <n>] [--json] |
Show run status |
veld urls [--name <n>] [--json] |
Show URLs for a run |
veld logs [--name <n>] [--node <n>] [--lines <n>] [-f] [--since <d>] [--source <s>] [-s <term>] [-C <n>] |
View logs (-f follow, -s search, -C context lines) |
veld graph [NODE:VARIANT...] |
Print dependency graph |
veld nodes |
List all nodes and variants |
veld presets |
List presets |
veld runs |
List all runs |
veld feedback listen [--name <n>] [--after <seq>] |
Listen for feedback events (agent-facing) |
veld feedback answer --thread <id> "<msg>" |
Reply to a feedback thread |
veld feedback ask "<msg>" |
Ask the reviewer a question |
veld feedback threads [--name <n>] |
List feedback threads |
veld ui |
Open the management dashboard in the browser |
veld gc |
Clean up stale state and logs |
veld setup [unprivileged|privileged] |
One-time system setup |
veld init |
Create a new veld.json |
start_server— long-running process. Veld allocates a port (${veld.port}), starts the process, and runs health checks.command— runs a command to completion. Can emit outputs by writingkey=valuelines to$VELD_OUTPUT_FILE(preferred) or viaVELD_OUTPUT key=valueon stdout (legacy, discouraged). Optionalskip_ifcommand for idempotency.
Project-level lifecycle steps that run outside the dependency graph. Setup steps run sequentially before any node starts; teardown steps run after all nodes stop.
{
"setup": [
{ "name": "docker", "command": "docker info", "failureMessage": "Docker must be running" },
{ "name": "veld-network", "command": "docker network create ${veld.name}-net 2>/dev/null || true" }
],
"teardown": [
{ "name": "veld-network", "command": "docker network rm ${veld.name}-net 2>/dev/null || true" }
]
}Setup steps that fail (non-zero exit) abort startup with the failureMessage if provided. Teardown is best-effort — failures are logged but don't block stop. Commands support shell env vars and project-level Veld variables: ${veld.name}, ${veld.project}, ${veld.root}, ${veld.run}.
{ "type": "http", "path": "/health", "expect_status": 200, "timeout_seconds": 30 }
{ "type": "port", "timeout_seconds": 10 }
{ "type": "command", "command": "curl -sf http://localhost:${veld.port}/ready" }| Variable | Description |
|---|---|
{service} |
Node name |
{run} |
Run name |
{project} |
Project name from veld.json |
{branch} |
Current git branch (slugified) |
{worktree} |
Worktree directory name (slugified) |
{username} |
OS username |
{hostname} |
Machine hostname |
Fallback operator: {branch ?? run} uses the first non-empty value.
Veld automatically captures browser console.log, console.warn, console.error, unhandled exceptions, and promise rejections from start_server nodes. Configure which levels to capture with client_log_levels at the project, node, or variant level (most specific wins):
"client_log_levels": ["log", "warn", "error"]Valid levels: "log", "warn", "error", "info", "debug". Default: ["log", "warn", "error"]. Unhandled exceptions are always captured regardless of this setting.
View client logs with veld logs --source client or filter by source in the management UI.
Control which Veld capabilities are injected into start_server nodes' HTML responses with features at the project, node, or variant level (most specific wins):
"features": {
"feedback_overlay": false,
"client_logs": true
}Available features: feedback_overlay (toolbar/comments UI), client_logs (browser log collector), inject (auto-inject bootstrap scripts). All default to true.
Declare env at the project, node, or variant level. Variables cascade: variant > node > project (per-key merge, most specific wins). Values support ${...} variable substitution.
{
"env": { "FEATURE_FLAG": "1" },
"nodes": {
"api": {
"env": { "LOG_LEVEL": "debug" },
"variants": {
"local": {
"env": { "PORT": "${veld.port}" }
}
}
}
}
}Commands, env values, and output templates support ${veld.port}, ${veld.url}, ${veld.run}, ${veld.root}, ${nodes.backend.url}, ${nodes.backend.port}, etc.
For start_server nodes, individual URL location pieces are also available (mirrors the Web URL API):
| Variable | Example | Description |
|---|---|---|
${veld.url.hostname} |
app.my-run.proj.localhost |
DNS name only |
${veld.url.host} |
app.my-run.proj.localhost:19443 |
hostname:port (omits port if 443) |
${veld.url.origin} |
https://app.my-run.proj.localhost:19443 |
scheme + host (same as ${veld.url}) |
${veld.url.scheme} |
https |
Protocol scheme |
${veld.url.port} |
19443 |
HTTPS port (note: ${veld.port} is the backend bind port) |
These are also available as cross-node references: ${nodes.backend.url.hostname}, ${nodes.backend.url.host}, etc.
Ports and URLs for all start_server nodes are pre-computed before execution, so ${nodes.X.url} works everywhere — even across nodes with no dependency relationship. Frontend can reference backend's URL and backend can reference frontend's URL without a cycle.
Three binaries work together:
veld— CLI. Parses commands, orchestrates environments, displays output.veld-helper— manages DNS entries and Caddy routes via a minimal Unix socket API. Runs as either a system daemon (privileged, for clean URLs on ports 80/443) or a user process (unprivileged, on port 18443).veld-daemon— user-space daemon. Monitors health, runs garbage collection, broadcasts state updates.
Caddy handles HTTPS termination and reverse proxying. Its internal CA is trusted in the system keychain during setup so browsers accept certificates without warnings.
Veld includes a browser-based dashboard at https://veld.localhost (or https://veld.localhost:18443 in unprivileged mode). It shows all environments with:
- Services tab — nodes with health status indicators, URLs with copy/open, variant, PID
- Logs tab — terminal viewer with search + highlighting, context lines (grep -C), auto-scroll, node filter, source filter (server/client/all)
- Stop/Restart — control environments directly from the browser
Open it with veld ui or visit the URL directly.
If you use Hammerspoon, Veld ships a menu bar widget that shows running environments at a glance.
veld setup hammerspoonThis installs the Veld.spoon into ~/.hammerspoon/Spoons/ and offers to patch your init.lua to load it automatically. No sudo required. The menu includes an "Open Management UI" item for quick access to the browser dashboard.
Check extension status with veld doctor.
- macOS (arm64/x64) or Linux (x64/arm64)
- Optional: sudo access for
veld setup privileged(clean URLs without port numbers, custom apex domains)
Veld ships skills for AI coding agents (Claude Code, Cursor, Codex, Windsurf, and 40+ more). Install them so your agent knows how to configure, use, and collaborate through Veld:
npx skills add prosperity-solutions/veldThis installs the veld skill — a single skill covering CLI usage, veld.json configuration, and the bidirectional feedback workflow. It loads live project state (nodes, presets, active runs, current config) at invocation time so your agent can act immediately without discovery steps.
We only accept agentic contributions — see CONTRIBUTING.md for details.