Skip to content

ml3m/dev

 
 

Repository files navigation

πŸš€ Comprehensive macOS Development Environment Setup

"20 minute script using bash" - A simple, powerful development environment setup that replaces complex configuration management with straightforward bash scripts.

This repository provides a modular, extensible development environment setup specifically adapted for macOS. It uses your personal dotfiles and Homebrew to create a complete development workspace in minutes.

οΏ½οΏ½οΏ½ Table of Contents

🎯 Philosophy & Goals

The Problem This Solves

  • Complex Setup Tools: No more Ansible, Chef, or overcomplicated configuration management
  • One-Size-Fits-All: Generic setups that don't respect your personal workflow
  • Platform Incompatibility: Linux-focused setups that don't work well on macOS
  • Opaque Processes: Black-box installers where you don't know what's happening

Our Approach

  • Simple Bash Scripts: Each component is a readable, modifiable bash script
  • Modular Design: Install only what you need, when you need it
  • Your Dotfiles: Uses YOUR configurations, not someone else's
  • Transparent Process: Every action is visible and customizable
  • macOS Native: Homebrew-based, respects macOS conventions

πŸ”§ How The System Works

The Core Concept

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   ./run         │───▢│   runs/*        │───▢│  Your System    β”‚
β”‚  (Orchestrator) β”‚    β”‚  (Components)   β”‚    β”‚  (Configured)   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  1. ./run is the main orchestrator that discovers and executes component scripts
  2. runs/* directory contains individual setup scripts for different tools
  3. Your dotfiles are integrated seamlessly through the dotfiles component
  4. Everything is installed via Homebrew for consistency and macOS compatibility

The Magic of Modularity

Each script in runs/ is:

  • Self-contained: Can be run independently
  • Idempotent: Safe to run multiple times
  • Conditional: Only installs if not already present
  • Focused: Does one thing well

πŸ“ Repository Structure

dev/
β”œβ”€β”€ README.md              # This comprehensive guide
β”œβ”€β”€ SETUP.md              # Quick start instructions
β”œβ”€β”€ main.go               # Web server for remote setup
β”œβ”€β”€ go.mod/go.sum         # Go dependencies
β”œβ”€β”€ Dockerfile            # Container setup
β”œβ”€β”€ fly.toml              # Deployment configuration
β”œβ”€β”€ run                   # 🎯 Main orchestrator script
β”œβ”€β”€ init                  # Project initialization
β”œβ”€β”€ resources/
β”‚   β”œβ”€β”€ setup             # Web-served setup script
β”‚   └── luarocks          # Lua package manager
β”œβ”€β”€ runs/                 # πŸš€ Component scripts directory
β”‚   β”œβ”€β”€ dotfiles          # Your personal dotfiles setup
β”‚   β”œβ”€β”€ dev               # Core development tools
β”‚   β”œβ”€β”€ neovim            # Neovim editor setup
β”‚   β”œβ”€β”€ tmux              # Terminal multiplexer
β”‚   β”œβ”€β”€ zsh               # Shell configuration
β”‚   β”œβ”€β”€ docker            # Container platform
β”‚   β”œβ”€β”€ node              # JavaScript runtime
β”‚   β”œβ”€β”€ libs              # Development libraries
β”‚   β”œβ”€β”€ i3                # Window management (yabai/skhd)
β”‚   β”œβ”€β”€ rofi              # Application launcher (Raycast)
β”‚   β”œβ”€β”€ rust              # Rust toolchain
β”‚   β”œβ”€β”€ eleven-tools      # Additional utilities
β”‚   β”œβ”€β”€ emoji             # Emoji support
β”‚   β”œβ”€β”€ gdb               # Debugger setup
β”‚   β”œβ”€β”€ ghostty           # Terminal emulator
β”‚   β”œβ”€β”€ keyboard          # Keyboard configuration
β”‚   β”œβ”€β”€ odin              # Odin programming language
β”‚   β”œβ”€β”€ opencode          # VS Code setup
β”‚   β”œβ”€β”€ php               # PHP development
β”‚   └── zed               # Zed editor
β”œβ”€β”€ tmux-sessionizer/     # Project session management
└── env/                  # Legacy environment files (unused)

πŸš€ Getting Started

Prerequisites

  • macOS (this setup is macOS-specific)
  • Internet connection for downloading packages
  • Your dotfiles repository ready

Step 1: Prepare Your Dotfiles

Ensure your dotfiles are properly structured:

~/.dotfilesmacos/
β”œβ”€β”€ scripts/bin/setup     # Main setup script
β”œβ”€β”€ zsh/                  # Zsh configuration
β”œβ”€β”€ tmux/                 # Tmux configuration
β”œβ”€β”€ nvim/                 # Neovim configuration
β”œβ”€β”€ git/                  # Git configuration
└── ...                   # Other tool configurations

Clone your dotfiles if not already done:

git clone https://github.com/YOUR_USERNAME/dotfiles.git ~/.dotfilesmacos

Step 2: Get This Repository

git clone https://github.com/YOUR_USERNAME/dev ~/personal/dev
cd ~/personal/dev

Step 3: Run the Setup

# Set the environment variable (required)
export DEV_ENV="$(pwd)"

# Run everything
./run

# Or run specific components
./run dotfiles neovim tmux

# Or see what would happen
./run --dry

Alternative: Web-based Setup

Start the web server:

go run main.go

Then from any terminal:

curl -sSL http://localhost:8080 | bash

πŸ› οΈ Available Components

Core Development Tools

dotfiles - Your Personal Configuration

./run dotfiles
  • Executes your ~/.dotfilesmacos/scripts/bin/setup
  • Stows your configurations using your existing system
  • Installs your custom scripts to ~/.local/bin
  • This is where YOUR personality comes into the setup

dev - Essential Development Tools

./run dev

Installs:

  • go - Go programming language
  • node & npm - JavaScript runtime and package manager
  • fzf - Fuzzy finder for terminal
  • btop - System monitor
  • bat - Better cat with syntax highlighting
  • tree - Directory structure visualization
  • ripgrep - Fast text search
  • tldr - Simplified man pages
  • stylua - Lua code formatter
  • ffmpeg - Media processing
  • ghostty - Modern terminal emulator
  • raycast - Application launcher
  • font-jetbrains-mono-nerd-font - Developer font

neovim - Text Editor Setup

./run neovim

Installs:

  • neovim - Modern Vim fork
  • lua - Lua scripting language
  • luarocks - Lua package manager
  • Creates ~/personal/projects directory for your code

tmux - Terminal Multiplexer

./run tmux

Installs:

  • tmux - Terminal multiplexer
  • tpm - Tmux Plugin Manager
  • Sets up plugin directory at ~/.tmux/plugins/tpm

zsh - Shell Configuration

./run zsh

Installs:

  • zsh shell (if not present)
  • Changes default shell to zsh
  • Installs Oh My Zsh framework
  • Note: Your dotfiles will override with your zsh configuration

Platform & Language Tools

docker - Container Platform

./run docker

Installs:

  • Docker Desktop (GUI option)
  • docker-compose
  • Alternative: Uncomment Colima lines for CLI-only Docker

node - JavaScript Development

./run node

Installs:

  • Node.js and npm
  • Sets up npm prefix to ~/.local/npm
  • Installs n (Node version manager)
  • Installs latest LTS Node
  • Deno runtime

rust - Rust Development

./run rust

Installs:

  • Rust toolchain via rustup
  • Common Rust development tools

macOS-Specific Tools

i3 - Window Management

./run i3

Installs:

  • yabai - Tiling window manager for macOS
  • skhd - Simple hotkey daemon
  • Note: Replaces Linux i3 with macOS equivalents

rofi - Application Launcher

./run rofi

Installs:

  • raycast - Modern application launcher for macOS
  • Note: Replaces Linux rofi with macOS equivalent

Supporting Tools

libs - Development Libraries

./run libs

Installs:

  • Core development libraries
  • Python 3.13
  • Git, ripgrep, jq, tldr
  • Raycast for screenshots

ghostty - Terminal Emulator

./run ghostty

Installs:

  • Ghostty terminal emulator
  • Modern, fast terminal alternative

βš™οΈ The Run System Explained

Understanding the ./run Script

The ./run script is the heart of the system. Here's how it works:

#!/usr/bin/env bash
script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"

# Environment variable check
if [ -z "$DEV_ENV" ]; then
    echo "env var DEV_ENV needs to be present"
    exit 1
fi

# Command line argument parsing
grep=""
dry_run="0"

while [[ $# -gt 0 ]]; do
    if [[ "$1" == "--dry" ]]; then
        dry_run="1"
    else
        grep="$1"
    fi
    shift
done

# Find all executable scripts in runs/
runs_dir=`find $script_dir/runs -mindepth 1 -maxdepth 1 -executable`

# Execute matching scripts
for s in $runs_dir; do
    if basename $s | grep -vq "$grep"; then
        # Skip if doesn't match filter
        continue
    fi
    
    # Execute the script
    if [[ $dry_run == "0" ]]; then
        $s
    fi
done

Key Features Explained

1. Environment Variable Requirement

export DEV_ENV="$(pwd)"

Why? This ensures scripts know where the repository is located and prevents accidental execution.

2. Filtering System

./run neovim         # Only run neovim-related scripts
./run docker node    # Run docker and node scripts
./run               # Run all scripts

How it works: Uses grep to match script names containing your filter terms.

3. Dry Run Mode

./run --dry
./run --dry neovim

Purpose: See what would be executed without actually running anything.

4. Script Discovery

The system automatically finds all executable files in runs/ directory:

find $script_dir/runs -mindepth 1 -maxdepth 1 -executable

Creating Your Own Run Scripts

Basic Template

#!/usr/bin/env bash

# Check if tool is already installed
if ! command -v my-tool &> /dev/null; then
    echo "Installing my-tool..."
    brew install my-tool
else
    echo "my-tool already installed"
fi

# Additional configuration
echo "Configuring my-tool..."
# Your configuration here

Best Practices

  1. Make it executable: chmod +x runs/my-script
  2. Check before installing: Use command -v or brew list
  3. Provide feedback: Echo what's happening
  4. Handle errors: Exit gracefully on failures
  5. Be idempotent: Safe to run multiple times

Advanced Example

#!/usr/bin/env bash

# runs/python-dev
echo "Setting up Python development environment..."

# Install Python via Homebrew
if ! brew list python@3.13 &> /dev/null; then
    echo "Installing Python 3.13..."
    brew install python@3.13
fi

# Install pipenv for dependency management
if ! command -v pipenv &> /dev/null; then
    echo "Installing pipenv..."
    brew install pipenv
fi

# Install common development packages
echo "Installing Python development packages..."
pip3 install --user black flake8 mypy pytest

# Create virtual environment directory
mkdir -p "$HOME/python-envs"

echo "Python development setup complete!"
echo "Create new projects with: pipenv install"

πŸ”— Dotfiles Integration

How Your Dotfiles Are Used

The dotfiles run script acts as a bridge between this setup system and your personal configuration:

#!/usr/bin/env bash
# runs/dotfiles

# Ensure stow is installed
if ! command -v stow &> /dev/null; then
    brew install stow
fi

# Navigate to your dotfiles and run setup
if [[ -d "$HOME/.dotfilesmacos" ]]; then
    cd "$HOME/.dotfilesmacos"
    
    # Use your existing setup script
    if [[ -f "scripts/bin/setup" ]]; then
        ./scripts/bin/setup
    else
        # Fallback: manual stowing
        for dir in zsh tmux nvim git alacritty kitty ghostty bat bpytop lsd wm zen; do
            if [[ -d "$dir" ]]; then
                stow -v "$dir"
            fi
        done
    fi
fi

Your Dotfiles Structure Integration

Your existing dotfiles structure is respected:

~/.dotfilesmacos/
β”œβ”€β”€ scripts/bin/setup          # ← Called automatically
β”œβ”€β”€ zsh/.zshrc                 # ← Stowed to ~/.zshrc
β”œβ”€β”€ tmux/.tmux.conf           # ← Stowed to ~/.tmux.conf
β”œβ”€β”€ nvim/.config/nvim/        # ← Stowed to ~/.config/nvim/
β”œβ”€β”€ git/.gitconfig            # ← Stowed to ~/.gitconfig
└── scripts/bin/              # ← Copied to ~/.local/bin/

Customizing Dotfiles Integration

If your dotfiles have a different structure, modify runs/dotfiles:

#!/usr/bin/env bash
# Custom dotfiles integration

DOTFILES_DIR="$HOME/.config/dotfiles"  # Your custom location

if [[ -d "$DOTFILES_DIR" ]]; then
    cd "$DOTFILES_DIR"
    
    # Your custom setup command
    make install
    
    # Or custom stowing
    stow --target="$HOME" zsh tmux vim
fi

πŸŽ›οΈ Customization Guide

Adding New Tools

1. Create a New Run Script

touch runs/my-new-tool
chmod +x runs/my-new-tool

2. Write the Installation Logic

#!/usr/bin/env bash
# runs/my-new-tool

echo "Setting up my-new-tool..."

# Install via Homebrew
if ! brew list my-new-tool &> /dev/null; then
    brew install my-new-tool
fi

# Configuration
mkdir -p "$HOME/.config/my-new-tool"
cat > "$HOME/.config/my-new-tool/config.yaml" << EOF
setting1: value1
setting2: value2
EOF

echo "my-new-tool setup complete!"

3. Test Your Script

export DEV_ENV="$(pwd)"
./run --dry my-new-tool  # Test without executing
./run my-new-tool        # Actually run it

Modifying Existing Scripts

Example: Customizing the dev Script

# Edit runs/dev
vim runs/dev

# Add your favorite tools
brew install your-favorite-tool
brew install another-tool

# Remove tools you don't want
# (just comment out or delete the lines)

Creating Tool Groups

You can create scripts that install related tools:

#!/usr/bin/env bash
# runs/web-dev

echo "Setting up web development tools..."

# Frontend tools
brew install node npm yarn
npm install -g create-react-app vue-cli @angular/cli

# CSS tools  
npm install -g sass postcss-cli

# Build tools
npm install -g webpack webpack-cli parcel

echo "Web development setup complete!"

Environment-Specific Configurations

Create different configurations for different contexts:

#!/usr/bin/env bash
# runs/work-setup

echo "Setting up work-specific tools..."

# Work-specific applications
brew install --cask slack microsoft-teams zoom

# Work development tools
brew install awscli terraform

# Company-specific configurations
git config --global user.email "work@company.com"

echo "Work setup complete!"

πŸ“š Advanced Usage

Conditional Execution

Run different setups based on conditions:

# Only run if on work laptop
if [[ $(hostname) == *"work"* ]]; then
    export DEV_ENV="$(pwd)"
    ./run work-setup
fi

# Only run if home directory exists
if [[ -d "$HOME/personal" ]]; then
    export DEV_ENV="$(pwd)"
    ./run personal-setup
fi

Integration with Other Systems

Git Hooks Integration

# .git/hooks/post-merge
#!/bin/bash
cd "$(git rev-parse --show-toplevel)"
export DEV_ENV="$(pwd)"
./run dotfiles  # Re-sync dotfiles after pulling changes

Automated Scheduling

# Add to crontab for weekly updates
0 9 * * 1 cd ~/personal/dev && export DEV_ENV="$(pwd)" && ./run --dry

Debugging Scripts

Enable Verbose Mode

# Add to any run script for debugging
set -x  # Show commands as they execute
set -e  # Exit on any error

Log Output

# Capture logs
export DEV_ENV="$(pwd)"
./run 2>&1 | tee setup.log

Performance Optimization

Parallel Execution

For independent tools, you can run them in parallel:

# Custom run script with parallel execution
export DEV_ENV="$(pwd)"
./run node &
./run rust &
./run docker &
wait  # Wait for all background jobs to complete

Caching Downloads

Some tools can cache downloads for faster re-runs:

# In your run script
CACHE_DIR="$HOME/.cache/dev-setup"
mkdir -p "$CACHE_DIR"

if [[ ! -f "$CACHE_DIR/my-tool.tar.gz" ]]; then
    curl -o "$CACHE_DIR/my-tool.tar.gz" "https://example.com/my-tool.tar.gz"
fi

πŸ› Troubleshooting

Common Issues

1. Permission Errors

# Error: Permission denied
# Solution: Ensure scripts are executable
chmod +x runs/*

2. DEV_ENV Not Set

# Error: env var DEV_ENV needs to be present
# Solution: Export the variable
export DEV_ENV="$(pwd)"

3. Homebrew Not Found

# Error: brew: command not found
# Solution: Install Homebrew first
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

4. Dotfiles Not Found

# Error: Dotfiles not found at $HOME/.dotfilesmacos
# Solution: Clone your dotfiles
git clone https://github.com/YOUR_USERNAME/dotfiles.git ~/.dotfilesmacos

Debugging Techniques

1. Dry Run Everything

export DEV_ENV="$(pwd)"
./run --dry

2. Run Individual Components

export DEV_ENV="$(pwd)"
./run dotfiles  # Test just dotfiles

3. Check Script Execution

# Add debugging to any script
#!/usr/bin/env bash
set -x  # Show all commands
echo "Starting script: $(basename "$0")"
# ... rest of script
echo "Script completed: $(basename "$0")"

4. Verify Tool Installation

# Check if tools were installed correctly
brew list
which nvim tmux git node

Recovery Procedures

1. Reset Dotfiles

cd ~/.dotfilesmacos
stow -D zsh tmux nvim  # Unstow configurations
stow zsh tmux nvim     # Re-stow configurations

2. Clean Homebrew

brew cleanup
brew doctor

3. Start Fresh

# Remove all Homebrew packages (nuclear option)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh)"
# Then re-run setup

🀝 Contributing

Adding Components

When contributing new components to this repository:

  1. Follow Naming Convention: Use lowercase, descriptive names
  2. Make It Executable: chmod +x runs/your-component
  3. Test Thoroughly: Test on clean macOS installation
  4. Document: Add clear comments explaining what it does
  5. Be Idempotent: Safe to run multiple times

Example Contribution

#!/usr/bin/env bash
# runs/data-science
# Sets up Python data science environment with Jupyter, pandas, etc.

echo "Setting up data science environment..."

# Install Python data science tools
if ! brew list jupyter &> /dev/null; then
    brew install jupyter
fi

# Install via pip
pip3 install --user pandas numpy matplotlib seaborn scikit-learn

# Create data projects directory
mkdir -p "$HOME/data-projects"

# Create sample Jupyter config
jupyter --generate-config

echo "Data science environment ready!"
echo "Start Jupyter with: jupyter notebook"

Testing New Components

# Test your new component
export DEV_ENV="$(pwd)"
./run --dry your-new-component  # Dry run first
./run your-new-component        # Then real run

πŸŽ‰

About

???

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Lua 91.4%
  • q 5.2%
  • Shell 2.7%
  • Makefile 0.7%
  • Go 0.0%
  • Dockerfile 0.0%