A comprehensive automation solution for setting up macOS development environments. This dotfiles repository handles everything from Homebrew package installation to SSH/GPG key generation and GitHub integration – all through an interactive bootstrap script.
Repository: github.com/danylomikula/dotfiles
The Problem
Every DevOps engineer knows the pain:
- New laptop arrives – 4-8 hours of manual setup
- Switching between personal/work machines – different configs everywhere
- Team onboarding – "just install these 50 things..."
- Disaster recovery – scrambling to remember every tool and setting
Traditional approaches fall short:
- Manual installation: Error-prone, inconsistent, undocumented
- Basic dotfiles: Only manage config files, not installation
- Homebrew Brewfile: Doesn't handle SSH/GPG keys or directory structures
- Ansible playbooks: Overkill for personal use, slow iteration
The Solution: Intelligent Bootstrap Script
I built a comprehensive dotfiles repository that handles everything through a single bootstrap.sh script with interactive prompts using gum for a beautiful TUI experience.
What It Does
Core Installation:
- Homebrew + analytics disabled
- Nerd Fonts (Hack, Ubuntu Mono, Fira Code, Courier Prime)
- Oh-My-Zsh with plugins (autosuggestions, syntax highlighting, you-should-use)
- Modern CLI tools:
eza,zoxide,fzf,starship,zellij - Python via
pyenvwith latest version auto-installed
Applications:
- Productivity: Zen, Obsidian, Maccy, BetterDisplay, Grammarly
- Communication: Signal, Telegram, Slack, Discord
- Development: VSCode, Alacritty, Fork, Lens
- DevOps/Cloud: AWS CLI, kubectl, helm, terraform, vault, argocd, ansible
- Security: Mullvad VPN, Tailscale, GPG Suite
- Utilities: AldDente, Bartender, AppCleaner, Shottr
Git Configuration:
- Global
.gitconfigwith sane defaults - Separate directories for personal/work repos with automatic context switching
-
includeIfdirectives for email/name per directory - Global
.gitignoresetup - Branch sorting by commit date, auto column UI
SSH Key Generation:
- Ed25519 keys with modern crypto
- Automatic GitHub CLI integration
- Adds key to GitHub via API
- Tests SSH connection to GitHub
GPG Key Generation:
- Ed25519 + Curve25519 keys for signing/encryption
- Configures
pinentry-macfor macOS Keychain integration - Automatic GitHub integration via API
- Sets global signing key in Git
Dotfiles Management:
- GNU Stow for symlink management
- Configs for: zsh, starship, alacritty, zellij, k9s, docker, git, gh
- Alacritty themes auto-cloned (200+ colorschemes)
AI Agents Configuration:
- Configures Codex and Claude for development workflow
- Installs Context7 MCP server for automatic library documentation
- Sets up global Copilot instructions at
~/.config/Code/User/prompts/context7.instructions.md - Enables AI agents to automatically fetch library docs during code generation
- Configured via standalone
configure-ai-agents.shscript
Architecture
Directory Structure
dotfiles/
├── bootstrap.sh # Main installation script
├── configure-git.sh # Standalone Git config tool
├── configure-ai-agents.sh # Standalone AI agents setup
├── generate-gpg-key.sh # Standalone GPG key generator
├── generate-ssh-key.sh # Standalone SSH key generator
├── alacritty/
│ └── .config/alacritty/
│ ├── alacritty.toml
│ └── themes/ # 200+ themes via git submodule
├── docker/.docker/
│ └── config.json
├── git/
│ ├── .gitconfig
│ └── .gitignore_global
├── github-cli/.config/gh/
├── k9s/.config/k9s/
├── starship/.config/
│ └── starship.toml
├── zellij/.config/zellij/
│ └── config.kdl
└── zshrc/
└── .zshrc
Key Design Decisions
1. Interactive Prompts with Gum
Instead of environment variables or config files, I use charmbracelet/gum for beautiful TUI prompts:
gum style --foreground "#00FF00" --bold "Do you want to generate a GPG key?"
CHOICE=$(gum choose "Yes" "No")
This makes the script:
- Self-documenting (you see what's being configured)
- Flexible (skip sections you don't need)
- Beginner-friendly (no prior knowledge required)
2. Conditional Directory Creation
The script offers to create separate Git directories:
~/git/
├── personal/ # Personal projects with personal email
└── work/ # Work projects with work email
Git automatically switches context using includeIf:
[includeIf "gitdir:~/git/personal/**"]
path = ~/git/personal/.gitconfig
[includeIf "gitdir:~/git/work/**"]
path = ~/git/work/.gitconfig
3. Modern Crypto Defaults
- SSH: Ed25519 (fast, secure, small keys)
- GPG: Ed25519 for signing + Curve25519 for encryption
- No RSA 2048/4096 bloat
4. GitHub API Integration
Keys aren't just generated–they're automatically added to GitHub:
# SSH key
gh ssh-key add "$SSH_KEY_PATH.pub" --title "$(hostname)"
# GPG key
gh gpg-key add <(gpg --armor --export "$KEY_ID")
5. Stow for Symlink Management
GNU Stow creates symlinks from dotfiles/ to $HOME:
stow zshrc starship alacritty zellij k9s docker git github-cli
This keeps your actual configs in Git while making them available system-wide.
6. AI Agents with Context7 MCP
The configure-ai-agents.sh script sets up AI development assistants:
- Codex CLI: Command-line AI agent for shell tasks
- Claude Integration: Configured for VS Code with Copilot
- Context7 MCP Server: Provides automatic library documentation via Model Context Protocol
-
Global Instructions: Creates
~/.config/Code/User/prompts/context7.instructions.mdwith rule to always use Context7 for docs
This enables AI agents to automatically fetch up-to-date documentation when generating code, reducing hallucinations and improving accuracy.
Usage
Quick Start (Full Bootstrap)
git clone https://github.com/danylomikula/dotfiles.git ~/dotfiles
cd ~/dotfiles
chmod +x bootstrap.sh
./bootstrap.sh
The script will:
- Install Homebrew and packages (5-10 min)
- Configure Oh-My-Zsh and plugins
- Sync dotfiles via Stow
- Prompt for Git configuration (optional)
- Offer to generate SSH key (optional)
- Offer to generate GPG key (optional)
- Offer to configure AI agents (optional)
Standalone Scripts
Each script can run independently:
# Just configure Git
./configure-git.sh
# Just generate SSH key
./generate-ssh-key.sh
# Just generate GPG key
./generate-gpg-key.sh
# Just configure AI agents
./configure-ai-agents.sh
Customization
Add/Remove Packages:
Edit the brew install lines in bootstrap.sh:
# Add your tools here
brew install --cask your-app-here
Add New Dotfiles:
- Create directory:
mkdir -p newtool/.config/newtool - Add config:
newtool/.config/newtool/config.yaml - Stow it:
stow newtool
Change Alacritty Theme:
# ~/.config/alacritty/alacritty.toml
[general]
import = [
"~/.config/alacritty/themes/themes/tokyo-night.toml"
]
Customize AI Agents:
Edit ~/.config/Code/User/prompts/context7.instructions.md:
---
applyTo: "**"
name: "Global-Context7-Rule"
---
Always use context7 when I need code generation, setup steps, or library docs.
You can add more rules or change the applyTo pattern to scope instructions to specific file types.
Real-World Usage
New Machine Setup
Time to productive workstation: ~15 minutes (mostly package downloads)
# On new Mac
git clone https://github.com/danylomikula/dotfiles.git ~/dotfiles
cd ~/dotfiles
./bootstrap.sh
# Answer prompts:
# - Configure Git? Yes
# - Personal dir? ~/git/personal
# - Work dir? ~/git/work
# - Generate SSH? Yes
# - Generate GPG? Yes
# - Add to GitHub? Yes
# - Configure AI agents? Yes
Result: Fully configured machine with:
- All dev tools installed
- SSH key in GitHub
- GPG signing configured
- Git context switching working
- Terminal customized
- AI agents with Context7 MCP ready
- Ready to
git cloneand start working
Disaster Recovery
Laptop dies or needs rebuild:
# On replacement machine
git clone https://github.com/danylomikula/dotfiles.git ~/dotfiles
cd ~/dotfiles
./bootstrap.sh
Back to 100% productivity in under an hour (including restoring data from backups).
Technical Deep Dive
GPG Key Generation with Batch Mode
I use GPG's batch mode to avoid interactive prompts:
GPG_BATCH_FILE=$(mktemp)
cat > "$GPG_BATCH_FILE" <<EOF
%echo Generating a GPG key
Key-Type: eddsa
Key-Curve: ed25519
Subkey-Type: ecdh
Subkey-Curve: cv25519
Name-Real: ${GPG_OWNER_NAME}
Name-Email: ${GPG_OWNER_EMAIL}
Expire-Date: 0
Passphrase: ${GPG_PASSWORD}
%commit
%echo done
EOF
gpg --batch --gen-key "$GPG_BATCH_FILE"
rm "$GPG_BATCH_FILE"
This creates:
- Primary key: Ed25519 for signing
- Subkey: Curve25519 for encryption
- No expiration: Suitable for long-term code signing
Detecting New GPG Key After Generation
Since we generate the key non-interactively, we need to find the new key ID:
# Capture existing keys before generation
EXISTING_KEYS=$(gpg --list-secret-keys --keyid-format=long \
| awk '/^sec/ {print $2}' | cut -d'/' -f2)
# Generate key...
# Find the new key
NEW_KEYS=$(gpg --list-secret-keys --keyid-format=long \
| awk '/^sec/ {print $2}' | cut -d'/' -f2)
KEY_ID=$(comm -13 <(echo "$EXISTING_KEYS" | sort) \
<(echo "$NEW_KEYS" | sort) | head -n 1)
This uses comm to find the set difference–the new key ID.
GitHub CLI Integration
Adding keys to GitHub via API:
# Authenticate (opens browser for OAuth)
gh auth login
# Add SSH key
gh ssh-key add "$HOME/.ssh/id_ed25519.pub" \
--title "$(hostname)" --type authentication
# Test connection
ssh -T git@github.com
# Add GPG key
gh gpg-key add <(gpg --armor --export "$KEY_ID")
# Configure Git to use it
git config --global user.signingkey "$KEY_ID"
git config --global commit.gpgsign true
git config --global tag.gpgSign true
No manual copying of keys into GitHub UI!
Pinentry Configuration for macOS
macOS Keychain integration requires pinentry-mac:
brew install pinentry-mac
# Configure GPG agent
echo "pinentry-program $(which pinentry-mac)" \
>> ~/.gnupg/gpg-agent.conf
# Restart agent
killall gpg-agent
Now GPG passphrase prompts use macOS Keychain–enter once, cached securely.
AI Agents Configuration Deep Dive
The configure-ai-agents.sh script sets up CLI and desktop AI coding assistants with Context7 MCP integration.
1. Tools Installation:
brew install node codex # Codex CLI
brew install --cask claude-code # Claude desktop app
2. Codex CLI Configuration:
Creates ~/.codex/AGENTS.md with global instructions:
# Global instructions
## context7 instructions
- Always use context7 when I need code generation, setup or configuration
steps, or library/API documentation. This means you should automatically
use the Context7 MCP tools to resolve library id and get library docs
without me having to explicitly ask.
Creates ~/.codex/config.toml with MCP server configuration:
model = "gpt-5.1-codex"
model_reasoning_effort = "high"
[mcp_servers.context7]
command = "npx"
args = ["-y", "@upstash/context7-mcp"]
3. Claude Desktop Configuration:
Creates ~/.claude/CLAUDE.md with Context7 usage instructions:
# Context7 MCP usage
- Always use context7 when I need code generation, setup or configuration
steps, or library/API documentation. This means you should automatically
use the Context7 MCP tools to resolve library id and get library docs
without me having to explicitly ask.
Enables MCP server for Claude:
claude mcp add context7 -- npx -y @upstash/context7-mcp
4. How It Works:
Both agents can now automatically fetch library documentation via Context7 MCP:
# Codex CLI usage
$ codex "Add authentication with Supabase"
[Codex automatically fetches Supabase docs via Context7 MCP]
"Installing supabase-js and configuring auth..."
# Claude Desktop usage
User: "Add authentication with Supabase"
Claude: [fetches Supabase docs via Context7]
"I'll help you set up Supabase authentication..."
This eliminates manual documentation lookups and reduces hallucinations by grounding AI responses in actual library docs.
Conclusion
This dotfiles setup has saved me countless hours across:
- 5+ fresh installs on new machines
- Daily context switching between personal/work
- Team onboarding
Resources
- My dotfiles repository
- Gum - Glamorous shell scripts
- GNU Stow
- Context7 MCP Server
- Model Context Protocol
- Alacritty themes
- GitHub CLI
- Oh My Zsh
Have questions or improvements? Open an issue or PR on the dotfiles repo!
Top comments (0)