Personal configuration files using the mirror home directory pattern. This repository mirrors your home directory structure, making setup simple and intuitive.
dotfiles/
├── .gitignore # Excludes machine-specific/transient files
├── .gitconfig # → ~/.gitconfig (git user identity)
├── README.md # This file
├── .config/ # → ~/.config/
│ ├── gh/ # GitHub CLI configuration
│ │ ├── config.yml # Global preferences and aliases
│ │ └── hosts.yml # GitHub username and host config
│ ├── git/
│ │ └── ignore # Global gitignore patterns
│ ├── iterm2/ # iTerm2 preferences
│ │ └── com.googlecode.iterm2.plist
│ └── nvim/ # Neovim configuration
│ ├── init.lua # Main config file
│ ├── lazy-lock.json # Plugin lockfile
│ └── lua/
│ ├── vim-options.lua
│ └── plugins/ # Plugin configurations
├── .tmux.conf # → ~/.tmux.conf
├── .tmux/ # → ~/.tmux/
│ └── plugins/
│ └── tpm/ # Tmux Plugin Manager (submodule)
├── .zshrc # → ~/.zshrc (main zsh config)
└── .zsh/ # → ~/.zsh/ (modular zsh configs)
├── env.zsh # Environment variables
├── path.zsh # PATH modifications
├── aliases.zsh # Shell aliases
├── functions.zsh # Custom functions
├── fzf.zsh # fzf configuration and key bindings
└── sensitive.zsh.example # Template for ~/.zsh_sensitive
Note: Sensitive data goes in ~/.zsh_sensitive (home root, not tracked)
Mapping: The directory structure mirrors your home directory exactly.
dotfiles/.config/git/→~/.config/git/dotfiles/.gitconfig→~/.gitconfigdotfiles/.tmux.conf→~/.tmux.confdotfiles/.tmux/→~/.tmux/dotfiles/.zshrc→~/.zshrcdotfiles/.zsh/→~/.zsh/
GNU Stow automatically creates symlinks based on directory structure.
# Install stow (if needed)
brew install stow # macOS
# or: apt install stow # Linux
# Clone and setup
git clone <your-repo-url> ~/Development/dotfiles
cd ~/Development/dotfiles
# Create all symlinks automatically
stow -t ~ .What stow does:
- Creates
~/.config→~/Development/dotfiles/.config - Handles all nested files and directories automatically
If you prefer manual control or don't want to use stow:
# Clone repository
git clone <your-repo-url> ~/Development/dotfiles
# Create symlinks
ln -s ~/Development/dotfiles/.config ~/.config
# Or symlink individual files/directories as needed# Check symlinks
ls -la ~ | grep '\->'
# Should show:
# .config -> /Users/you/Development/dotfiles/.configVersioned (Portable):
- Main configuration file (
.tmux.conf) - TPM (Tmux Plugin Manager) - included as git submodule
- Custom prefix key:
Ctrl-Space(instead of defaultCtrl-b) - Vi-style pane navigation (
h/j/k/l) - Mouse support enabled
- Catppuccin Mocha theme with status modules
- Plugin declarations
Auto-Downloaded (Not Versioned):
- Plugins managed by TPM (catppuccin, tmux-sensible, vim-tmux-navigator)
- Installed to
~/.tmux/plugins/on first use
1. Clone with submodules:
git clone --recurse-submodules <repo-url> ~/Development/dotfiles
# TPM is automatically included!2. Create symlinks:
cd ~/Development/dotfiles
stow -t ~ .
# Or manually:
ln -s ~/Development/dotfiles/.tmux.conf ~/.tmux.conf
ln -s ~/Development/dotfiles/.tmux ~/.tmux3. Start tmux:
tmux4. Install plugins:
Press Ctrl-Space + I (that's capital I) inside tmux. TPM will automatically download:
- Catppuccin theme (v2.1.3)
- tmux-sensible (sensible defaults)
- vim-tmux-navigator (seamless vim/tmux navigation)
5. Verify setup:
- Status bar should show Catppuccin Mocha theme
- Try
Ctrl-Space + h/j/k/lto navigate between panes - Mouse clicks should work for pane selection
Important: This config uses Ctrl-Space as the prefix key (not the default Ctrl-b).
| Keybinding | Action |
|---|---|
Ctrl-Space |
Prefix key (all commands start with this) |
Ctrl-Space + r |
Reload tmux configuration |
Ctrl-Space + h/j/k/l |
Navigate panes (left/down/up/right) |
Ctrl-Space + c |
Create new window |
Ctrl-Space + I |
Install/update plugins (capital I) |
TPM not found:
# Check if submodules were initialized
ls ~/.tmux/plugins/tpm/
# If missing, initialize submodules:
cd ~/Development/dotfiles
git submodule update --init --recursivePlugins not installing:
# Ensure TPM is present, then inside tmux:
# Press: Ctrl-Space + I (capital I)
# If that doesn't work, source the config manually:
tmux source ~/.tmux.conf
# Then press: Ctrl-Space + ITheme not loading:
# Kill tmux server and restart
tmux kill-server
tmux
# Press: Ctrl-Space + I (to reinstall plugins)Wrong prefix key:
If you're pressing Ctrl-b and nothing happens, remember this config uses Ctrl-Space.
Versioned (Portable):
.gitconfig- User identity (name and email).config/git/ignore- Global gitignore patterns
What's included:
- User name and email configuration
- Global gitignore patterns
Setup on new machine: The symlinks created by stow or manual linking will automatically configure git with your identity and global ignores.
Verify setup:
git config --global user.name
git config --global user.emailNote: If you need machine-specific git config, you can create ~/.gitconfig.local and include it in your main .gitconfig:
[include]
path = ~/.gitconfig.localVersioned (Portable):
init.lua- Main configuration with lazy.nvim bootstraplua/vim-options.lua- Core vim settings (tabs, navigation, line numbers)lua/plugins/*.lua- Plugin configurationslazy-lock.json- Plugin version lockfile.luarc.json- Lua language server configuration
Plugin Manager:
- lazy.nvim - Modern plugin manager with lazy loading
- Automatically bootstraps itself on first run (no manual installation needed)
- Plugins are declared in
lua/plugins/*.luafiles
Included Plugins:
- catppuccin - Catppuccin color scheme
- nvim-lspconfig - LSP configurations
- nvim-cmp - Autocompletion
- telescope - Fuzzy finder
- treesitter - Syntax highlighting and parsing
- neo-tree - File explorer
- copilot - GitHub Copilot integration (via vim-plug/pack)
- lualine - Status line
- none-ls - Formatting and linting
- nvim-java - Java language support
- vim-test - Test runner integration
Auto-Downloaded (Not Versioned):
- Plugin data stored in
~/.local/share/nvim/lazy/ - Native vim packages in
.config/nvim/pack/(like Copilot) - Both are gitignored and auto-installed on first run
Setup on new machine:
- Create symlink:
ln -s ~/Development/dotfiles/.config/nvim ~/.config/nvim- Open Neovim:
nvim-
Plugins auto-install: Lazy.nvim will automatically bootstrap and install all plugins on first run. Just wait for the installation to complete.
-
Verify setup:
- Catppuccin colorscheme should be active
- LSP should work for your languages
:Lazycommand opens the plugin manager UI
Key Bindings:
<Space>- Leader key<Ctrl-h/j/k/l>- Navigate between vim panes<Space>ff- Telescope find files<Space>fg- Telescope live grep<Leader>gf- Format current file with LSP/null-ls
Optional Dependencies:
These tools enhance the Neovim experience but aren't required:
-
stylua - Lua code formatter (for none-ls)
# macOS brew install stylua # Or via cargo cargo install stylua
-
Language servers - Install LSPs for your languages (handled by nvim-lspconfig)
-
GitHub Copilot - Requires GitHub Copilot subscription and separate setup
Note: Neovim will show warnings if optional tools are missing but will function normally otherwise.
Versioned (Portable):
config.yml- Global preferences (git protocol, editor, aliases)hosts.yml- GitHub hostname and username configuration
What's included:
- Git protocol preference:
https - Prompt settings
- Alias:
co→pr checkout - GitHub username
Not versioned (Secure):
- OAuth tokens are stored in system keychain (not in config files)
- Auth state is machine-specific
Setup on new machine:
- Create symlink:
ln -s ~/Development/dotfiles/.config/gh ~/.config/gh- Authenticate:
gh auth loginFollow the prompts to authenticate. Your preferences from the config will be used, but you'll need to auth separately on each machine.
- Verify setup:
gh auth status
gh config listCustomization:
Edit .config/gh/config.yml to add your own aliases or change preferences. Changes sync via git to all machines.
Modular structure for maintainability:
The Zsh configuration is split into logical modules for easy management:
.zshrc # Main config, sources all modules
.zsh/
├── env.zsh # Environment variables (ANDROID_HOME, etc.)
├── path.zsh # PATH modifications
├── aliases.zsh # Command aliases
├── functions.zsh # Custom shell functions
└── sensitive.zsh.example # Template for ~/.zsh_sensitive
~/.zsh_sensitive # Your actual secrets (NOT in repo, not symlinked)
Versioned (Portable):
.zshrc- Main configuration file.zsh/env.zsh- Environment variables (Android, Java, etc.).zsh/path.zsh- PATH modifications.zsh/aliases.zsh- Shell aliases (git shortcuts, vim → nvim).zsh/functions.zsh- Custom functions (blog post helpers)
Not versioned (Sensitive):
~/.zsh_sensitive- Machine-specific secrets (OAuth tokens, API keys)- Location:
~/.zsh_sensitive(in HOME root, NOT in.zsh/directory) - Not symlinked: Created directly in home directory, never tracked by git
- Location:
.zsh_history- Command history.zsh_sessions/- Session state
What's included:
- Oh My Zsh integration with robbyrussell theme
- ASDF version manager initialization
- Git aliases:
gs(status),gc(commit),gp(push), etc. - Android/Java development environment setup
- Blog functions:
postandblistfor cuento-blog management - Modular loading: Each module can be enabled/disabled independently
Setup on new machine:
- Create symlinks:
ln -s ~/Development/dotfiles/.zshrc ~/.zshrc
ln -s ~/Development/dotfiles/.zsh ~/.zsh- Create sensitive file (in HOME, not in repo):
# Copy template to HOME directory (NOT in .zsh/)
cp ~/.zsh/sensitive.zsh.example ~/.zsh_sensitive
# Edit and add your actual tokens
vim ~/.zsh_sensitive- Add your tokens:
# Inside ~/.zsh_sensitive (in home root, not versioned)
export CLAUDE_CODE_OAUTH_TOKEN="your-actual-token-here"
export API_KEY="your-key-here"
# etc.Important: ~/.zsh_sensitive is created in your HOME directory root, NOT inside the .zsh/ directory. This keeps it outside the repo and prevents accidental commits.
- Reload shell:
source ~/.zshrc
# Or use the alias: srcVerify setup:
echo $CLAUDE_CODE_OAUTH_TOKEN # Should show your token
gs # Should run git status
vim # Should open neovimAdding new configuration:
- Aliases: Edit
.zsh/aliases.zsh - Functions: Edit
.zsh/functions.zsh - Environment vars: Edit
.zsh/env.zsh - PATH changes: Edit
.zsh/path.zsh - Secrets: Edit
~/.zsh_sensitive(in home root, not versioned)
Dependencies:
- Oh My Zsh: Install from ohmyz.sh
- zsh-syntax-highlighting: Install via Oh My Zsh or homebrew
- ASDF: Version manager for multiple languages
What's included:
iTerm2 preferences including color schemes, fonts, key bindings, profiles, and window settings.
Versioned (Portable):
com.googlecode.iterm2.plist- Complete iTerm2 preferences
Setup on new machine:
-
Clone dotfiles (if not already done)
-
Configure iTerm2 to load from dotfiles:
# Tell iTerm2 where to find preferences
defaults write com.googlecode.iterm2 PrefsCustomFolder -string "~/Development/dotfiles/.config/iterm2"
defaults write com.googlecode.iterm2 LoadPrefsFromCustomFolder -bool true- Restart iTerm2:
Close and reopen iTerm2 for settings to take effect.
- Verify settings loaded:
Open iTerm2 → Preferences → General → Preferences
Should show: "Load preferences from a custom folder or URL"
Path: ~/Development/dotfiles/.config/iterm2
Making changes:
Any preference changes in iTerm2 will automatically save to the dotfiles folder. Commit and push to sync across machines:
cd ~/Development/dotfiles
git add .config/iterm2/
git commit -m "Update iTerm2 preferences"
git pushNote: Changes require iTerm2 to be restarted to take effect on other machines after pulling updates.
What's included:
Command-line fuzzy finder with shell integration, custom key bindings, and helper functions.
Versioned (Portable):
.zsh/fzf.zsh- Complete fzf configuration including:- Shell integration (key bindings and completions)
- Custom color scheme and layout
- File/directory preview with syntax highlighting
- Git integration functions
- Process management helpers
Setup on new machine:
- Install fzf and dependencies:
brew install fzf bat fd tree- Reload shell:
source ~/.zshrc
# or open a new terminalKey bindings:
- Ctrl+R: Search command history with preview
- Ctrl+T: Search files with syntax-highlighted preview
- Alt+C: Search directories with tree preview
- Ctrl+/: Toggle preview window
- Ctrl+U/D: Scroll preview half-page up/down
Custom functions:
fgb(fzf-git-branch): Checkout git branch with commit previewfgc(fzf-git-commit-show): Browse and view git commitsfkill(fzf-kill): Kill processes interactively
Dependencies:
- fzf: Core fuzzy finder
- bat: Syntax-highlighted file previews (optional but recommended)
- fd: Fast file searching (optional, fallback to
find) - tree: Directory tree previews (optional, fallback to basic listing)
Usage examples:
# Search files and open in editor
vim $(fzf)
# Search and checkout git branch
fgb
# Browse git commit history
fgc
# Kill a process interactively
fkillThe mirror pattern makes adding configs simple:
For XDG-compliant tools (nvim, alacritty, etc.):
cd ~/Development/dotfiles
mkdir -p .config/nvim
# Add your nvim config files
git add .config/nvim
git commit -m "Add nvim configuration"For traditional dotfiles (tmux, bash, etc.):
cd ~/Development/dotfiles
cp ~/.tmux.conf .tmux.conf
git add .tmux.conf
git commit -m "Add tmux configuration"The pattern: Mirror the actual location in your home directory.
| Tool | Home Location | Dotfiles Location |
|---|---|---|
| Git | ~/.gitconfig |
.gitconfig |
| Git (global ignore) | ~/.config/git/ |
.config/git/ |
| Neovim | ~/.config/nvim/ |
.config/nvim/ |
| iTerm2 | ~/.config/iterm2/ |
.config/iterm2/ |
| tmux | ~/.tmux.conf + ~/.tmux/ |
.tmux.conf + .tmux/ |
| Zsh | ~/.zshrc + ~/.zsh/ |
.zshrc + .zsh/ |
| Alacritty | ~/.config/alacritty/ |
.config/alacritty/ |
# 1. Clone repository with submodules
git clone --recurse-submodules <your-repo-url> ~/Development/dotfiles
# This includes TPM (Tmux Plugin Manager) automatically!
# 2. Install dependencies (if needed)
# - GNU Stow (optional)
# - Other tools (nvim, tmux, etc.)
# 3. Create symlinks
cd ~/Development/dotfiles
stow -t ~ .
# Or manually:
ln -s ~/Development/dotfiles/.config ~/.config
ln -s ~/Development/dotfiles/.tmux.conf ~/.tmux.conf
ln -s ~/Development/dotfiles/.tmux ~/.tmux
# 4. Install tmux plugins (if using tmux)
tmux
# Press: Ctrl-Space + I (to install plugins)Changes sync instantly since configs are symlinked:
cd ~/Development/dotfiles
git pull
git submodule update --remote --merge # Update submodules (TPM)
# Changes are immediately available in ~/.config, etc.cd ~/Development/dotfiles
# Edit files directly (changes reflect immediately)
vim .gitconfig
vim .config/nvim/init.lua
# Stage and commit
git add .gitconfig
git commit -m "Update git configuration"
git pushcd ~/Development/dotfiles
# Check status
git status
# Stage changes
git add .gitconfig
# Commit
git commit -m "Update git configuration"
# Push to remote
git push
# Pull updates
git pullcd ~/Development/dotfiles
# Add remote
git remote add origin <your-remote-url>
# Push
git push -u origin main# Stow specific directory only
stow -t ~ -d ~/Development/dotfiles .config
# Unstow (remove symlinks)
stow -D -t ~ .
# Restow (useful after adding new files)
stow -R -t ~ .
# Dry run (see what would happen)
stow -n -v -t ~ .✓ Automatic symlinking of entire directory trees
✓ Easy to add/remove configs
✓ Handles nested directories perfectly
✓ Clean uninstall with stow -D
✓ No custom scripts needed
Check if symlink exists:
ls -la ~/.config
# Should show: .config -> /Users/you/Development/dotfiles/.configFix broken symlink:
rm ~/.config
ln -s ~/Development/dotfiles/.config ~/.configError: "existing target is not owned by stow"
# Backup existing file
mv ~/.config ~/.config.backup
# Retry stow
stow -t ~ .Problem: Files appear in git status that should be ignored.
Solution: Ensure .gitignore is committed and patterns are correct:
git check-ignore -v <file-path>
# Shows which gitignore rule matches (or doesn't)✓ Self-Documenting: Directory structure shows exactly where files go
✓ Simple Setup: One stow command or a few symlinks
✓ Cross-Machine Sync: Keep configs consistent everywhere
✓ Version Control: Track changes, roll back mistakes
✓ Safe: Machine-specific files automatically excluded
✓ Extensible: Easy to add new tool configs
✓ Standard Pattern: Widely used in dotfiles community
- Command history and session data are excluded from version control
- Machine-specific settings stay local via
.gitignore - Consider using a private repository for sensitive configs
- API keys should never be in these files (Claude doesn't store them here anyway)
- Location:
~/Development/dotfiles - Symlink Strategy: Mirror home directory structure
- Primary Configs: Git, Neovim, Tmux, Zsh
- Ready For: nvim, tmux, zsh, and more (
.config/, root-level dotfiles) - Version: 1.0.0
-
Add Git Remote (if you haven't):
cd ~/Development/dotfiles git remote add origin <your-remote-url> git push -u origin main
-
Add More Configs:
- Copy your nvim config to
.config/nvim/ - Copy your tmux config to
.tmux.conf - Commit and push
- Copy your nvim config to
-
Setup Other Machines:
- Clone and stow on your other computers
- Same configs everywhere, instantly
Repository: ~/Development/dotfiles
Pattern: Mirror home directory structure
Symlink Method: GNU Stow or manual ln -s