A YAML-based tmux session manager that creates development environments from configuration files.
Pre-built binaries available for all platforms:
- 📦 Download from Releases - Windows, macOS, Linux (recommended)
- 🔨 Build from source - See installation section below
- YAML configuration for tmux sessions
- Multi-shell support (bash, zsh, fish)
- Pre-hooks for setup commands
- Working directory management per session/window/pane
- Multiple windows and panes with custom layouts
- Colored pane labels for easy visual identification
- Real-time log streaming from selected windows and panes
- Go to Releases
- Download the appropriate binary for your system:
- Windows:
dolly_Windows_x86_64.zip - macOS Intel:
dolly_Darwin_x86_64.tar.gz - macOS Apple Silicon:
dolly_Darwin_arm64.tar.gz - Linux x86_64:
dolly_Linux_x86_64.tar.gz - Linux ARM64:
dolly_Linux_arm64.tar.gz
- Windows:
- Extract and place in your PATH
git clone https://github.com/suhailgupta03/dolly.git
cd dolly
make installOr build manually:
make build
sudo cp dolly /usr/local/bin/-
Copy the sample configuration:
cp sample-config.yml my-project.yml
-
Edit your configuration:
session_name: "my-dev-setup" terminal: "zsh" working_directory: "/path/to/your/project" windows: - name: "development" panes: - command: "npm run dev" split: "none" pre_hooks: - "nvm use"
-
Launch your session:
dolly my-project.yml
-
Terminate your session:
dolly -terminate my-project.yml # or use the shortcut: dolly -t my-project.yml
session_name: "my-session" # Required: Session name
working_directory: "/path/to/project" # Optional: Default directory
terminal: "zsh" # Optional: Shell (bash/zsh/fish)
auto_color: true # Optional: Enable automatic window coloring (default: true)
show_pane_labels: true # Optional: Show pane labels (default: true)
default_label_color: "blue" # Optional: Default color for pane labels (default: blue)
# Optional: Log streaming configuration
log_stream:
enabled: true # Enable log streaming
windows: ["*"] # Windows to stream from ("*" for all)
panes: ["*"] # Panes to stream from ("*" for all)
grep: ["ERROR", "WARNING"] # Filter for specific keywords (optional)
windows:
- name: "frontend" # Window name
color: "green" # Optional: Window tab color
panes:
- id: "dev-server" # Optional: Pane identifier (used for labels)
command: "npm run dev" # Command to execute
split: "none" # Split type: none/horizontal/vertical
working_directory: "./web" # Optional: Pane-specific directory
show_label: true # Optional: Override global label setting
label_color: "brightblue" # Optional: Custom color for this pane label
pre_hooks: # Optional: Commands run before main command
- "nvm use 18"
- "export NODE_ENV=development"Dolly supports automatic and manual color coding for window tabs to improve visual organization:
Automatic Coloring (default):
- When
auto_color: true(default), windows without explicit colors are automatically assigned colors - To disable auto-coloring:
auto_color: false
Manual Coloring:
- Set explicit colors using the
colorfield in window configuration - Explicit colors override automatic assignment
- Supports multiple color formats:
- Basic colors:
red,green,blue,yellow,cyan,magenta,white,black - Bright colors:
brightred,brightgreen,brightblue,brightyellow,brightcyan,brightmagenta,brightwhite
- Basic colors:
Example Configuration:
auto_color: true # Enable automatic window coloring (default)
show_pane_labels: true # Enable pane labels (default)
default_label_color: "blue" # Default label color
windows:
- name: "development"
# No color specified - gets "green" (first window in palette)
panes:
- id: "server" # This ID becomes the pane label
command: "npm run dev"
- name: "testing"
color: "brightred" # Explicit color overrides auto-assignment
panes:
- id: "tests" # Label: "tests" with blue background
command: "npm test"
- name: "monitoring"
# No color specified - gets "red" (third window in palette)
panes:
- id: "logs" # Label: "logs" with blue background
command: "tail -f app.log"Dolly supports colored pane labels to help identify panes visually. Labels appear at the top border of each pane with a colored background.
Features:
- Labels are extracted from pane IDs for easy identification
- Configurable background colors for better visual organization
- Can be enabled/disabled globally or per-pane
- Uses high-contrast white text on colored backgrounds
Global Label Configuration:
show_pane_labels: true # Enable pane labels (default: true)
default_label_color: "green" # Default background color (default: blue)Per-Pane Label Configuration:
windows:
- name: "development"
panes:
- id: "dev-server" # This becomes the label text
command: "npm start"
show_label: true # Override global setting (optional)
label_color: "brightblue" # Custom color for this pane (optional)
- id: "tests"
command: "npm test"
label_color: "yellow" # Different color for test paneSupported Colors:
- Basic:
red,green,blue,yellow,cyan,magenta,white,black - Bright:
brightred,brightgreen,brightblue,brightyellow,brightcyan,brightmagenta,brightwhite
Visual Result: Each pane displays its ID in a colored label at the top:
[blue bg] dev-server [end] [yellow bg] tests [end]
┌─────────────────┐ ┌─────────────────┐
│ │ │ │
│ Server output │ │ Test results │
│ │ │ │
└─────────────────┘ └─────────────────┘
Dolly supports different ways to split panes:
Horizontal Split (horizontal or h):
┌─────────────────┐
│ Pane 1 │
├─────────────────┤
│ Pane 2 │
├─────────────────┤
│ Pane 3 │
└─────────────────┘
Panes are stacked top to bottom
Vertical Split (vertical or v):
┌─────┬─────┬─────┐
│ │ │ │
│Pane1│Pane2│Pane3│
│ │ │ │
└─────┴─────┴─────┘
Panes are arranged side by side
| Option | Description | Default |
|---|---|---|
session_name |
Name of the tmux session | Required |
working_directory |
Default working directory | Current directory |
terminal |
Shell to use (bash/zsh/fish) | bash |
auto_color |
Enable automatic window coloring | true |
show_pane_labels |
Show colored pane labels | true |
default_label_color |
Default background color for pane labels | blue |
windows[].name |
Window name | Required |
windows[].color |
Window tab color | auto-assigned if auto_color: true |
windows[].panes[].id |
Unique identifier for the pane (used for labels) | auto-generated |
windows[].panes[].command |
Command to execute | "" |
windows[].panes[].split |
Split type: none, horizontal, vertical |
none |
windows[].panes[].split_from |
ID of pane to split from | previous pane |
windows[].panes[].working_directory |
Pane working directory | Inherits from session |
windows[].panes[].pre_hooks |
Commands to run before main command | [] |
windows[].panes[].show_label |
Override global pane label setting | Inherits from global |
windows[].panes[].label_color |
Background color for this pane's label | Inherits from default |
log_stream.enabled |
Enable real-time log streaming | false |
log_stream.windows |
Windows to stream from (names or "*" for all) | [] |
log_stream.panes |
Panes to stream from (IDs or "*" for all) | [] |
log_stream.grep |
Keywords to filter log messages (case-insensitive) | [] |
Split Behavior:
- First pane in each window must use
split: "none" - Subsequent panes can specify exactly which pane to split from using
split_from - Pane IDs can be explicitly set or auto-generated (
pane1,pane2, etc.) - Split directions:
horizontal: Creates top/bottom arrangement (stacked)vertical: Creates side-by-side arrangement
Advanced Layout Control:
windows:
- name: "complex-layout"
panes:
- id: "main"
command: "echo 'Main pane'"
split: "none"
- id: "right"
command: "echo 'Right side'"
split: "vertical"
split_from: "main" # Split vertically from main
- id: "bottom-left"
command: "echo 'Bottom left'"
split: "horizontal"
split_from: "main" # Split horizontally from main
- id: "bottom-right"
command: "echo 'Bottom right'"
split: "horizontal"
split_from: "right" # Split horizontally from rightResult layout:
┌─────────┬─────────┐
│ main │ right │
├─────────┼─────────┤
│bottom- │bottom- │
│left │right │
└─────────┴─────────┘
Backward Compatibility:
- Configurations without
split_fromwork as before (split from previous pane) - Configurations without
idget auto-generated IDs
Dolly supports real-time log streaming that captures output from selected windows and panes into a dedicated streaming window. When enabled, the streaming window becomes the first window (window 0) and continuously displays timestamped output from the specified sources.
session_name: "my-project"
log_stream:
enabled: true
windows: ["*"] # Stream from all windows
panes: ["*"] # Stream from all panesStream from specific windows:
log_stream:
enabled: true
windows: ["frontend", "backend"] # Only these windows
panes: ["*"] # All panes within selected windowsStream from specific panes:
log_stream:
enabled: true
windows: ["*"] # All windows
panes: ["server", "tests"] # Only these pane IDsCombine window and pane filtering:
log_stream:
enabled: true
windows: ["development"] # Only from development window
panes: ["main-app", "logger"] # Only these specific panesFilter by keywords (grep):
log_stream:
enabled: true
windows: ["*"] # All windows
panes: ["*"] # All panes
grep: ["ERROR", "WARNING", "FAIL"] # Only show lines containing these keywords- Streaming Window: When log streaming is enabled, Dolly creates a "logs" window as the first window (window 0)
- Real-time Capture: The streaming window continuously monitors the specified panes using
tmux capture-pane - Timestamped Output: Each log entry is prefixed with the pane ID and timestamp
- Incremental Updates: Only new output since the last check is displayed
- Keyword Filtering: Optional grep functionality to filter log messages by keywords (case-insensitive)
- Non-intrusive: Original panes continue to work normally while being monitored
=== Log Streaming Started for Session: my-project ===
Streaming from 3 panes
==================================
[%123] 14:30:15:
[SERVER] Starting development server on port 3000
[SERVER] Webpack compilation completed
[%124] 14:30:16:
[TESTS] Running test suite...
[TESTS] ✓ All tests passed
[%125] 14:30:17:
[DB] Database connection established
dolly [options] <config.yml>
Options:
-terminate, -t Terminate the tmux session
-help, -h Show help information
Examples:
dolly my-project.yml # Create session
dolly -t my-project.yml # Terminate session
dolly -h # Show helpmake help # Show all available commands
make build # Build the dolly binary
make install # Install to system PATH
make test # Run test suite
make run-sample # Run with sample configuration
make clean # Clean build artifactsmake test # Run all tests
./test_runner # Run tests manually- Go 1.21 or higher
- tmux installed on your system
git clone https://github.com/suhailgupta03/dolly.git
cd dolly
make build
make testDolly uses GoReleaser for automated cross-platform builds and releases:
Automated Process:
- Build: Triggers on every push/PR to validate builds
- Release: Creates GitHub releases with binaries on git tag push
- Testing: Separate workflow runs tests and integration tests
- Artifacts: Generates SHA256 checksums and release notes
Manual Build with GoReleaser:
# Install GoReleaser (macOS)
brew install goreleaser
# Build snapshot (all platforms)
goreleaser build --snapshot --clean
# Release (requires git tag)
goreleaser release --cleanCreating Releases:
- Git tag:
git tag v1.0.0 && git push origin v1.0.0 - Manual: GitHub Actions → Release workflow → Enter version → Run
Manual Cross-Platform Build:
# Use GoReleaser config or manual build
make build # Uses existing MakefileMIT License - see the LICENSE file for details.