Overmind for Development
Overmind is a tmux-based process manager. Key advantage over Foreman: daemon
mode, individual process restart, and interactive debugging via overmind connect.
Requires tmux (installed automatically by brew install overmind on macOS).
Setup Checklist
Procfile.devat project root — one service per line (name: command)bin/dev— bash wrapper with subcommands (start, stop, restart, status, logs, help).overmind.env— socket path + recommended settingstmp/.keep— tracked by git;.gitignorehas/tmp/*+!/tmp/.keep
.overmind.env — Recommended Settings
OVERMIND_SOCKET=tmp/overmind.sock
OVERMIND_NO_PORT=1
OVERMIND_CAN_DIE=css
| Setting | Why |
|---|---|
OVERMIND_SOCKET=tmp/overmind.sock | Keeps project root clean, avoids macOS 104-char socket path limit |
OVERMIND_NO_PORT=1 | Prevents Overmind from injecting PORT=5000/5100/5200 which shadows explicit port vars in Procfile |
OVERMIND_CAN_DIE=css | Tailwind watcher crash doesn't tear down the whole stack |
Optional: OVERMIND_AUTO_RESTART=css to auto-restart watchers on crash.
Key Design Decisions
- Daemon by default for engine/library projects —
bin/devdaemonizes so agents and developers can keep working.-fflag for foreground when debugging. For app projects, foreground by default may be better (crashes are immediately visible). - Explicit
-s "$SOCKET"on every overmind command — don't rely on.overmind.envalone. The socket flag works regardless of CWD, which matters for scripts thatcdinto subdirectories. - Socket in
tmp/— keeps project root clean (Rails convention). - Stale socket handling —
bin/devcleans up stale sockets before starting (prevents "already running" errors).bin/dev stopfalls back to removing the socket ifovermind quitfails.
bin/dev Commands
| Command | What it does |
|---|---|
bin/dev | Start daemonized (default) |
bin/dev -f | Start in foreground |
bin/dev stop | Stop running instance |
bin/dev restart web | Restart a specific service |
bin/dev status | Show process statuses and URLs |
bin/dev logs | Tail all logs |
bin/dev logs web | Tail logs from a specific service |
bin/dev -- -l web,css | Pass flags directly to overmind |
Procfile Patterns
# Standard Rails
web: bin/rails server -p ${PORT:-3000}
css: bin/rails tailwindcss:watch
# With explicit port vars (use with OVERMIND_NO_PORT=1)
web: cd lookbook && bin/rails server -p ${LOOKBOOK_PORT:-4001}
docs: cd docs && bin/bridgetown start -P ${DOCS_PORT:-4000}
# With workers
worker: bundle exec sidekiq
Agent Workflow
- Check status:
bin/dev status 2>/dev/null && echo "running" || echo "not running" - Start daemonized:
bin/dev(never foreground — blocks terminal) - After lib/ changes:
bin/dev restart web(app/ changes autoload) - Read logs:
bin/dev logs web(single process) orbin/dev logs(all) - Leave running at session end — user runs
bin/dev stopwhen done.
Useful Overmind Flags
| Flag | Purpose |
|---|---|
-D | Daemonize |
-f FILE | Specify Procfile path |
-s SOCKET | Specify socket path |
-r PROCESS | Auto-restart on crash (-r all for everything) |
-l PROCESS | Only start specific processes (-l web,css) |
-N | Disable automatic PORT assignment (same as OVERMIND_NO_PORT=1) |
Common Pitfalls
- Stale sockets — after crash/reboot,
overmind startsays "already running". Fix:rm tmp/overmind.sock(or letbin/devhandle it). - Port shadows — without
OVERMIND_NO_PORT=1, Overmind injects PORT=5000/5100/5200 per process, overriding explicit port vars. - Socket path length — macOS limits Unix socket paths to 104 chars.
tmp/overmind.sock(relative) avoids this. Never use$TMPDIR. - Nested tmux — if inside tmux,
overmind connectnests sessions. Detach withCtrl-b Ctrl-b d(double prefix).
