Skip to content

moinsen-dev/devhub

Repository files navigation

DevHub

Multi-project development environment manager - Start, stop, and monitor all your local development services from one place.

License: MIT Rust Release Docs

The Problem

Working on multiple projects means juggling multiple terminals:

# Project A
cd ~/work/project-a && npm run dev        # Terminal 1
cd ~/work/project-a && cargo run          # Terminal 2

# Project B
cd ~/work/project-b && docker compose up  # Terminal 3
cd ~/work/project-b && npm start          # Terminal 4

# Which ports? Which commands? Where's that README again?

The Solution

devhub start project-a    # Starts all services
devhub start project-b    # Starts all services
devhub status             # See everything at a glance

# Or open http://devhub.localhost for the dashboard

Features

  • One command to rule them all - devhub start launches your entire stack
  • Bulk discovery - Scan directories and register 100+ projects at once
  • Monorepo support - Auto-detects multi-service projects (frontend + backend + packages)
  • Environment file loading - Automatic .env and .env.local support with variable interpolation
  • Web dashboard - Visual status, start/stop buttons, log viewer, real-time updates
  • Fuzzy search - Find projects fast with devhub search
  • Favorites & Recent - Star projects, track recently used
  • Batch operations - devhub start --all or --favorites
  • Auto-discovery - Detects Rust, Node, Python, Go, Docker, Flutter projects
  • Port conflict detection - Know before you crash with devhub ports --resolve
  • PM2 integration - Node.js services managed properly
  • Docker Compose support - First-class container orchestration
  • Health checks - Wait for services to be truly ready
  • Reverse proxy integration - Pretty URLs like http://myproject.localhost
  • Shell completions - Tab completion for bash, zsh, and fish
  • Developer shortcuts - devhub code, devhub open, devhub path
  • Zero lock-in - Simple TOML config, works with any stack

Quick Start

1. Install DevHub

# Homebrew (macOS)
brew tap moinsen-dev/tap
brew install devhub

# Or download pre-built binary
curl -sL https://github.com/moinsen-dev/devhub/releases/latest/download/devhub-aarch64-apple-darwin.tar.gz | tar xz
sudo mv devhub /usr/local/bin/

# Or from source
git clone https://github.com/moinsen-dev/devhub.git && cd devhub
cargo build --release && cp target/release/devhub ~/.local/bin/

2. Discover Your Projects

# Scan your project directories
devhub scan --dry-run ~/work

# Found 50 projects? Register them all!
devhub scan --auto-register ~/work

3. Install Shell Completions

# Zsh (most common on macOS)
devhub completions zsh > ~/.zfunc/_devhub

# Bash
devhub completions bash > ~/.local/share/bash-completion/completions/devhub

# Fish
devhub completions fish > ~/.config/fish/completions/devhub.fish

4. Start Working

# Start a project
devhub start my-project

# Check status
devhub status

# Quick navigation
cd $(devhub path my-project)  # Jump to project directory
devhub code my-project        # Open in VS Code
devhub open my-project        # Open in browser

# Check for port conflicts
devhub ports --check

5. Launch the Dashboard (Optional)

# Start the daemon as a background service
devhub daemon start

# Or if installed via Homebrew
brew services start devhub

# Start the UI
cd devhub-ui && npm install && npm run dev

# Open http://localhost:5173

CLI Reference

Project Management

devhub init                    # Create devhub.toml in current directory
devhub discover                # Auto-detect and generate devhub.toml
devhub discover --dry-run      # Preview discovery without writing files
devhub register [path]         # Register project with DevHub
devhub unregister <name>       # Remove project from registry
devhub list                    # List all registered projects

Bulk Operations

devhub scan [paths...]         # Scan directories for projects
devhub scan --dry-run          # Preview what would be discovered
devhub scan --auto-register    # Discover and register in one step
devhub scan --depth 3          # Scan deeper into subdirectories

Service Control

devhub start [project]         # Start project services
devhub start --all             # Start ALL registered projects
devhub start --favorites       # Start all favorite projects
devhub stop [project]          # Stop project services
devhub restart [project]       # Restart project services
devhub status                  # Show status of all projects
devhub logs <project> [-f]     # Stream logs (with follow mode)

Discovery & Search

devhub search <query>          # Fuzzy search for projects
devhub recent                  # Show recently used projects
devhub fav add <project>       # Add to favorites
devhub fav list                # List favorites
devhub fav toggle <project>    # Toggle favorite status

Port Management

devhub ports                   # Show all port allocations
devhub ports --check           # Detect port conflicts
devhub ports --resolve         # Suggest fixes for conflicts

Developer Shortcuts

devhub open <project>          # Open project in browser
devhub open <project> -s api   # Open specific service
devhub code <project>          # Open project in VS Code
devhub path <project>          # Print project path (for cd integration)

Environment & Utilities

devhub env <project>           # Show resolved environment variables
devhub env <project> -s api    # Show env for specific service
devhub env <project> -f export # Output in shell export format
devhub completions <shell>     # Generate shell completions (bash/zsh/fish)

Daemon Management

devhub daemon                  # Run daemon in foreground (default)
devhub daemon start            # Start daemon as background service
devhub daemon stop             # Stop running daemon
devhub daemon restart          # Restart daemon
devhub daemon status           # Show daemon status and version
devhub daemon --port 9876      # Run on custom port

Configuration

Each project gets a devhub.toml file:

[project]
name = "my-app"
description = "My awesome application"
tags = ["rust", "web"]
env_files = [".env", ".env.local"]  # Environment files to load

[[services]]
name = "api"
type = "rust-binary"
command = "cargo run --release"
port = 8080
health_check = "/health"
subdomain = "api"           # http://api.my-app.localhost
env_file = "api/.env"       # Service-specific env file

[[services]]
name = "frontend"
type = "node"
command = "npm run dev"
cwd = "frontend"            # Relative working directory
port = 3000
main = true                 # http://my-app.localhost (no subdomain)
depends_on = ["api"]        # Start order

[environment]
RUST_LOG = "info"
DATABASE_URL = "postgres://localhost/myapp"

Environment Loading Priority

Environment variables are loaded in this order (later sources override earlier):

  1. System environment variables
  2. Project root .env file
  3. Project root .env.local file
  4. Files listed in env_files
  5. [environment] section in manifest
  6. Service-specific env_file
  7. Service cwd/.env file
  8. Service cwd/.env.local file
  9. Service env = {} section
  10. DevHub service URL injection (see below)

Variable interpolation is supported: DATABASE_URL=$DB_HOST:$DB_PORT/mydb

Service URL Environment Variables

DevHub automatically injects environment variables for service-to-service communication. This solves the common problem of hardcoding localhost:PORT in your .env files.

Auto-Injected Variables

For every service in your project, DevHub injects:

Variable Example Description
DEVHUB_<SERVICE>_URL http://api.myapp.localhost External URL via Caddy reverse proxy
DEVHUB_<SERVICE>_INTERNAL_URL http://myapp-api:8080 Internal URL for container-to-container
DEVHUB_<SERVICE>_PORT 8080 Service port

Example for a project with api and frontend services:

DEVHUB_API_URL=http://api.myapp.localhost
DEVHUB_API_INTERNAL_URL=http://myapp-api:8080
DEVHUB_API_PORT=8080
DEVHUB_FRONTEND_URL=http://myapp.localhost
DEVHUB_FRONTEND_INTERNAL_URL=http://myapp-frontend:3000
DEVHUB_FRONTEND_PORT=3000

Service Reference Syntax

You can reference other services in your devhub.toml using the ${service.property} syntax:

[[services]]
name = "frontend"
type = "node"
command = "npm run dev"
port = 3000
main = true

[services.env]
# These get auto-expanded by DevHub:
NEXT_PUBLIC_API_URL = "${api.url}"           # → http://api.myapp.localhost
INTERNAL_API_URL = "${api.internal}"         # → http://myapp-api:8080
API_PORT = "${api.port}"                     # → 8080

Available properties:

  • ${service.url} - External URL (via Caddy, for browser/client-side)
  • ${service.internal} - Internal URL (for container-to-container communication)
  • ${service.port} - Service port number

Use Case: Next.js + Python Backend

[project]
name = "demo-app"
mode = "container"

[[services]]
name = "backend"
type = "python"
command = "uvicorn main:app --host 0.0.0.0 --port 8081"
port = 8081
subdomain = "api"

[[services]]
name = "frontend"
type = "node"
command = "npm run dev"
port = 3000
main = true

[services.env]
# Client-side API calls go through Caddy
NEXT_PUBLIC_API_URL = "${backend.url}"

Your frontend automatically gets NEXT_PUBLIC_API_URL=http://api.demo-app.localhost - no more hardcoded localhost:8081!

Service Types

Type Detection Default Command
rust-binary Cargo.toml with [[bin]] cargo run
node package.json npm run dev (uses PM2 if available)
python pyproject.toml uvicorn or python -m
go go.mod go run .
docker-compose docker-compose.yml docker compose up -d
shell Any Custom command

Dashboard

The web dashboard provides:

  • Project cards with running status indicators
  • One-click start/stop/restart buttons
  • Log viewer with auto-refresh and syntax highlighting
  • Service-level controls (start/stop individual services on hover)
  • Real-time auto-refresh (5-second polling)
  • Search and filter by name or status
  • Service metrics (X/Y services running)
  • Open in Terminal / VS Code buttons

Access:

  • http://devhub.localhost (with Caddy proxy)
  • http://localhost:5173 (development mode)

Reverse Proxy Setup

DevHub auto-generates Caddy configurations for pretty .localhost URLs.

Quick Setup

cd proxy
docker compose up -d

This gives you:

  • http://projectname.localhost - Your main service
  • http://api.projectname.localhost - API services
  • http://devhub.localhost - Dashboard

Custom Proxy Location

mkdir -p ~/.devhub
cat > ~/.devhub/config.toml << EOF
caddy_sites_dir = "/path/to/your/proxy/sites.d"
caddy_reload_command = "docker exec caddy-proxy caddy reload --config /etc/caddy/Caddyfile"
EOF

Project Structure

devhub/
├── src/                  # Rust CLI + daemon
│   ├── main.rs           # CLI entry (clap)
│   ├── api.rs            # REST API (axum)
│   ├── process.rs        # Service management (PM2, Docker, native)
│   ├── discovery.rs      # Auto-detection (6 project types)
│   ├── manifest.rs       # TOML parsing
│   ├── registry.rs       # Project registry (+ favorites, recent)
│   ├── ports.rs          # Port allocation & conflict detection
│   ├── caddy.rs          # Proxy config generation
│   └── config.rs         # Global settings
├── devhub-ui/            # SvelteKit dashboard (Svelte 5)
├── proxy/                # Caddy reverse proxy setup
└── Cargo.toml            # Rust dependencies

Troubleshooting

Port shows as "not running" but service is up

DevHub checks both IPv4 and IPv6. If issues persist:

lsof -i :3000

PM2 not being used

PM2 must be installed globally:

npm install -g pm2

Service won't start

# Check logs
devhub logs my-project my-service

# Or directly
cat ~/Library/Application\ Support/com.moinsen.devhub/logs/my-project/my-service.err.log

Caddy not reloading

docker exec caddy-proxy caddy reload --config /etc/caddy/Caddyfile
docker logs caddy-proxy

Installation

Homebrew (macOS)

brew tap moinsen-dev/tap
brew install devhub

# Start as background service (optional)
brew services start devhub

Pre-built Binaries

Download from GitHub Releases:

# macOS Apple Silicon
curl -sL https://github.com/moinsen-dev/devhub/releases/latest/download/devhub-aarch64-apple-darwin.tar.gz | tar xz
sudo mv devhub /usr/local/bin/

# macOS Intel
curl -sL https://github.com/moinsen-dev/devhub/releases/latest/download/devhub-x86_64-apple-darwin.tar.gz | tar xz
sudo mv devhub /usr/local/bin/

# Linux x64
curl -sL https://github.com/moinsen-dev/devhub/releases/latest/download/devhub-x86_64-unknown-linux-gnu.tar.gz | tar xz
sudo mv devhub /usr/local/bin/

# Linux ARM64
curl -sL https://github.com/moinsen-dev/devhub/releases/latest/download/devhub-aarch64-unknown-linux-gnu.tar.gz | tar xz
sudo mv devhub /usr/local/bin/

From Source

git clone https://github.com/moinsen-dev/devhub.git
cd devhub
cargo build --release
cp target/release/devhub ~/.local/bin/

Cargo (crates.io) - Coming Soon

cargo install devhub

Contributing

Contributions welcome! See CONTRIBUTING.md for guidelines.

License

MIT License - see LICENSE for details.


Acknowledgments

  • Caddy - The reverse proxy that makes this possible
  • axum - Excellent Rust web framework
  • clap - CLI argument parsing with completions
  • PM2 - Node.js process management
  • SvelteKit - Clean, fast UI framework

"Stop remembering. Start building."