zdev
v0.2.8
Published
Multi-agent worktree development environment for cloud dev with preview URLs
Maintainers
Readme
🐂 zdev
Multi-agent worktree development environment for Vite/TanStack projects.
Built for Clawdbot users who want to run multiple AI coding agents on different features simultaneously.
Supports:
- Vite / TanStack Start frontends
- Convex backend (optional — auto-detected)
- Monorepos with
web/,apps/web/, etc.
Features
- Worktree Management — Isolated git worktrees per feature
- Port Allocation — Automatic port assignment, no conflicts
- Preview URLs — Public HTTPS URLs via Traefik (optional)
- Config Auto-Copy —
.env.localand other files copied automatically - Vite Support — Auto-patches
allowedHostsfor external access - Convex Integration — Auto-detected; runs
convex devif present - Monorepo Support — Auto-detects
web/,frontend/,apps/web/, etc.
Installation
# Run directly
bunx zdev
# Or install globally
bun add -g zdevUsing with AI Agents
Claude Code / Clawdbot
Add the zdev skill to teach your agent the workflow:
npx add-skill 5hanth/zdev-skillThen prompt your agent:
Use zdev to create a new project called my-app and start a feature branch for authentication.Manual Setup
If your agent doesn't support skills, copy the SKILL.md contents into your agent's context or system prompt.
Prerequisites
Required
- Bun —
curl -fsSL https://bun.sh/install | bash - Git repository with Vite-based frontend
Optional
- Convex — auto-detected if
convex/directory exists
Optional (for public preview URLs)
- Traefik reverse proxy with file provider
- DNS wildcard record (
*.dev.yourdomain.com)
See Traefik Setup below.
Quick Start
New Project
# Create a new TanStack Start project
zdev create my-app
# Or with Convex backend
zdev create my-app --convex
# Flat structure (no monorepo)
zdev create my-app --convex --flatExisting Project
# 1. Initialize your project
cd your-project
zdev init
# 2. (Convex only) Setup Convex once if not already done
cd web # or wherever package.json is
bunx convex dev # select project, then Ctrl+C
# 3. Start a feature
zdev start my-feature -p /path/to/project
# 4. Work on it
cd ~/.zdev/worktrees/project-my-feature
# 5. Stop when done
zdev stop my-feature -p /path/to/projectCommands
zdev create <name>
Create a new TanStack Start project from scratch.
zdev create my-app # Basic TanStack Start
zdev create my-app --convex # With Convex backend
zdev create my-app --flat # Flat structure (no monorepo)By default creates a monorepo with web/ subdirectory. Use --flat for single-package structure.
zdev init [path]
Initialize zdev for an existing project. Creates seed data from current Convex state.
zdev init # Current directory
zdev init ./my-project # Specific path
zdev init -s # Also create seed snapshotzdev start <feature>
Start working on a feature. Creates worktree, installs deps, starts servers.
zdev start auth -p ./my-project
zdev start auth -p ./my-project --local # Skip public URL
zdev start auth -p ./my-project --port 3000 # Specific port
zdev start auth -p ./my-project --seed # Import seed data
zdev start auth --base-branch origin/develop # Different basezdev stop <feature>
Stop servers for a feature.
zdev stop auth -p ./my-project
zdev stop auth --keep # Keep worktree, just stop serverszdev list
List all active features and their status.
zdev list
zdev list --jsonzdev clean <feature>
Remove a feature worktree completely (use after PR merged).
zdev clean auth -p ./my-project
zdev clean auth --force # Force even if git failszdev seed export/import
Manage database seed data.
zdev seed export # Export current Convex state
zdev seed import # Import into current worktreezdev config
View and manage configuration.
zdev config --list
zdev config --set devDomain=dev.example.com
zdev config --set traefikConfigDir=/etc/traefik/dynamic
zdev config --add .env.production
zdev config --remove .env.productionSetup Script
zdev uses .zdev/setup.sh in your project to run setup commands when creating worktrees.
Default (generated by zdev create):
#!/bin/bash
# .zdev/setup.sh - Runs after worktree creation
set -e
bun installCustomize it:
#!/bin/bash
set -e
# Use a different package manager
pnpm install
# Generate Prisma client
bunx prisma generate
# Copy secrets from parent
cp ../.env.local .This file is committed to git, so all team members use the same setup.
Configuration
Config stored at ~/.zdev/config.json:
| Key | Default | Description |
|-----|---------|-------------|
| devDomain | (empty) | Domain for preview URLs (e.g., dev.example.com) |
| dockerHostIp | 172.17.0.1 | How Traefik (in Docker) reaches host services |
| traefikConfigDir | /infra/traefik/dynamic | Directory where Traefik watches for route configs (see below) |
| copyPatterns | .env.local, etc. | Files to auto-copy to worktrees |
Traefik Setup for Preview URLs
What's a "dynamic config directory"?
Traefik can be configured to watch a folder for
.ymlfiles. Each file defines a route (e.g., "requests toauth.dev.example.comgo to port 5173"). When you add/remove files, Traefik automatically updates its routing — no restart needed.zdev uses this to create/remove routes on-the-fly as you start/stop features.
To get public HTTPS URLs for each feature:
1. DNS Wildcard
Add a wildcard A record pointing to your server:
*.dev.example.com → your-server-ip2. Traefik with File Provider
Configure Traefik to watch a dynamic config directory:
# traefik.yml
providers:
file:
directory: /etc/traefik/dynamic # zdev writes route files here
watch: true
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
certificatesResolvers:
letsencrypt:
acme:
email: [email protected]
storage: /etc/traefik/acme.json
httpChallenge:
entryPoint: web3. Configure zdev
zdev config --set devDomain=dev.example.com
zdev config --set traefikConfigDir=/etc/traefik/dynamic
zdev config --set dockerHostIp=172.17.0.1 # or host.docker.internal on MacHow It Works
When you run zdev start my-feature, it creates a file like /etc/traefik/dynamic/project-my-feature.yml:
http:
routers:
project-my-feature:
rule: "Host(`project-my-feature.dev.example.com`)"
service: project-my-feature
entryPoints:
- websecure
tls:
certResolver: letsencrypt
services:
project-my-feature:
loadBalancer:
servers:
- url: "http://172.17.0.1:5173" # Host port from Docker's perspectiveTraefik watches the directory and automatically picks up the new route.
Multi-Agent Workflow
- Agent A works on auth:
zdev start auth -p ./project - Agent B works on billing:
zdev start billing -p ./project - Each gets isolated worktree + ports + preview URL
- No conflicts, parallel development
Directory Structure
~/.zdev/
├── config.json # Global config
├── worktrees/ # All worktrees live here
│ ├── project-auth/
│ └── project-billing/
└── seeds/ # Seed data snapshots
└── project.zip