@adamhancock/devctl
v1.0.1
Published
Development environment manager for multi-worktree projects with Caddy, database isolation, and port management
Maintainers
Readme
devctl
A powerful development environment manager for multi-worktree projects. Simplifies the management of development environments by automatically handling:
- Caddy reverse proxy routes for subdomain-based worktrees
- Database isolation with automatic PostgreSQL database creation per worktree
- Port allocation using deterministic hashing to avoid conflicts
- Environment file management with automatic .env updates
- MCP integration for Claude Code and Spotlight
Features
- 🌐 Automatic Caddy route setup with subdomain or root domain support
- 🗄️ PostgreSQL database creation from templates
- 🔢 Deterministic port allocation based on worktree path
- 📝 Automatic .env file updates across all packages
- 🔄 Database backup and restore functionality
- 🔍 Spotlight integration for debugging
- 🤖 MCP (Model Context Protocol) configuration
- 🏥 Built-in health checks and diagnostics
Installation
Local Development
# Install dependencies
pnpm install
# Build the package
pnpm build
# Link globally for local testing
npm linkFrom npm (once published)
npm install -g devctl
# or
pnpm add -g devctlQuick Start
- Initialize configuration in your project:
cd /path/to/your/project
devctl init my-projectEdit
.devctlrc.jsonto match your project structureSetup a worktree:
cd /path/to/your/worktree
devctl setupConfiguration
Create a .devctlrc.json file in your project root. You can use devctl init [project-name] to generate a starter config.
Example Configuration
{
"projectName": "my-project",
"baseDomain": "dev.local",
"databasePrefix": "myproject",
"caddyApi": "http://localhost:2019",
"portRanges": {
"api": {
"start": 3000,
"count": 1000
},
"web": {
"start": 5000,
"count": 1000
},
"spotlight": {
"start": 7000,
"count": 1000
}
},
"envFiles": {
"api": "packages/api/.env",
"web": "packages/web/.env",
"spotlight": "packages/spotlight/.env",
"e2e": "packages/e2e/.env"
},
"database": {
"host": "localhost",
"port": 5432,
"user": "postgres",
"password": "",
"templateDb": "myproject_dev"
},
"features": {
"database": true,
"spotlight": true,
"queuePrefix": true
},
"integrations": {
"mcp": true,
"spotlight": true
}
}Configuration Options
Core Settings
projectName(required): Your project name, used in various identifiersbaseDomain(required): Base domain for routing (e.g.,dev.local)databasePrefix(required): Prefix for database namescaddyApi: URL for Caddy Admin API (default:http://localhost:2019)
Port Ranges
Define port ranges for each service. Ports are deterministically allocated based on worktree path:
"portRanges": {
"api": { "start": 3000, "count": 1000 },
"web": { "start": 5000, "count": 1000 },
"spotlight": { "start": 7000, "count": 1000 }
}Environment Files
Specify paths to .env files relative to project root:
"envFiles": {
"api": "packages/api/.env",
"web": "packages/web/.env",
"spotlight": "packages/spotlight/.env",
"e2e": "packages/e2e/.env"
}Database Configuration
"database": {
"host": "localhost",
"port": 5432,
"user": "postgres",
"password": "",
"templateDb": "myproject_dev"
}templateDb: Template database to clone for new worktrees
Features
Enable or disable features:
"features": {
"database": true, // PostgreSQL database per worktree
"spotlight": true, // Spotlight debugging integration
"queuePrefix": true // BullMQ queue prefix per worktree
}Integrations
"integrations": {
"mcp": true, // MCP configuration updates
"spotlight": true // Spotlight MCP server
}Commands
devctl setup [name]
Setup a worktree with ports, database, and Caddy routes.
# Use current branch name
devctl setup
# Use custom subdomain
devctl setup my-feature
# Use root domain instead of subdomain
devctl setup --root-domain
# Use custom config file
devctl setup -c /path/to/.devctlrc.jsonWhat it does:
- Generates unique ports based on worktree path
- Creates a PostgreSQL database from template (if enabled)
- Updates .env files with ports and database URL
- Configures Caddy reverse proxy routes
- Updates .mcp.json for Claude Code integration
- Runs database migrations
devctl list / devctl ls
List all active Caddy routes with their ports and worktree paths.
devctl listdevctl remove <subdomain> / devctl rm <subdomain>
Remove a Caddy route for a specific subdomain.
devctl remove my-featuredevctl ports <subdomain>
Get port information for a specific subdomain.
devctl ports my-featuredevctl init [project-name]
Create a .devctlrc.json configuration file in the current directory.
devctl init my-project
# Overwrite existing config
devctl init my-project --forceDatabase Commands
devctl dump [database-name]
Dump a database to SQL file.
# Dump current worktree's database
devctl dump
# Dump specific database
devctl dump myproject_feature_branch
# Specify output file
devctl dump -o /path/to/backup.sqldevctl restore <dump-file> [database-name]
Restore a database from SQL dump file.
# Restore to current worktree's database
devctl restore backup.sql
# Restore to specific database
devctl restore backup.sql myproject_feature_branchdevctl list-dumps
List available database dump files.
devctl list-dumpsdevctl doctor
Check environment and dependencies.
devctl doctorChecks:
- Configuration file
- Git repository status
- Caddy availability
- PostgreSQL tools
Workflow Example
Setting up a new feature branch
# Create a new worktree
git worktree add ../my-feature feature/my-feature
cd ../my-feature
# Setup development environment
devctl setup
# Start your services
pnpm devYour feature branch is now accessible at https://my-feature.dev.local with:
- Isolated PostgreSQL database
- Unique ports that don't conflict
- Caddy routing configured
- All .env files updated
Working with databases
# Dump your main database for use in feature branches
cd /path/to/main-worktree
devctl dump
# In your feature worktree, restore from main
cd /path/to/feature-worktree
devctl restore myproject_main-2024-01-15T10-30-00.sqlCleaning up
# Remove Caddy route when done
devctl remove my-feature
# Remove worktree
git worktree remove ../my-feature
# Optionally drop the database
dropdb myproject_my_featureRequirements
- Node.js: v18 or higher
- Caddy: v2 with Admin API enabled
- PostgreSQL: For database features (optional)
- Git: For worktree detection
Caddy Setup
Your Caddyfile should enable the Admin API:
{
admin localhost:2019
}Or run Caddy with API enabled:
caddy run --config CaddyfilePostgreSQL Setup
For database features, ensure PostgreSQL is installed:
# macOS
brew install postgresql
# Or use Docker
docker run -d \
--name postgres \
-e POSTGRES_PASSWORD=postgres \
-p 5432:5432 \
pgvector/pgvector:pg16How It Works
Port Allocation
Ports are deterministically generated using MD5 hashing of the worktree path:
- Hash the worktree absolute path
- Convert first 4 hex characters to offset
- Add offset to configured port range start
- Check availability and try next offset if occupied
This ensures:
- Same worktree always gets same ports (if available)
- Different worktrees get different ports
- No manual port management needed
Database Isolation
Each worktree gets its own PostgreSQL database:
- Creates database name:
{prefix}_{sanitized_branch_name} - Clones from template database using
CREATE DATABASE ... TEMPLATE - Runs migrations automatically
- Updates all .env files with new DATABASE_URL
Caddy Routing
Automatically configures reverse proxy routes:
https://feature-branch.dev.local/api/* → localhost:3042 (API)
https://feature-branch.dev.local/* → localhost:5042 (Web)
https://feature-branch.dev.local/_spotlight → localhost:7042 (Spotlight)Routes include custom headers with worktree metadata for debugging.
Troubleshooting
Caddy is not running
# Check if Caddy is running
curl http://localhost:2019/config/
# Start Caddy
caddy run --config CaddyfilePostgreSQL tools not found
# macOS - Install PostgreSQL
brew install postgresql
# Or use the bundled tools from Postgres.app
export PATH="/Applications/Postgres.app/Contents/Versions/latest/bin:$PATH"Port conflicts
If ports are already in use, devctl will try up to 100 different offsets. If all fail:
- Check what's using the ports:
lsof -i :PORT - Adjust your port ranges in
.devctlrc.json - Kill conflicting processes
Database connection errors
# Check PostgreSQL is running
psql -U postgres -h localhost -d postgres
# Verify template database exists
psql -U postgres -h localhost -d postgres -c "\l"Routes not working
# Check Caddy configuration
curl http://localhost:2019/config/apps/http/servers/srv0/routes | jq
# List all routes
devctl list
# Run diagnostics
devctl doctorDevelopment
# Install dependencies
pnpm install
# Build TypeScript
pnpm build
# Watch mode for development
pnpm build --watch
# Link for local testing
npm link
# Test in a project
cd /path/to/test/project
devctl setupLicense
MIT
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
