Dotfiles
Personal configuration files managed with GNU Stow.
⚠️ Important Notes
Git Configuration
- Default email: Set to personal email
- Work projects: Manually configure work email per repository:
cd ~/Code/work-project git config user.email "work@example.com"
Breaking Changes from Previous Configs
- Default branch: Uses
main(notmaster) - Pull strategy: Uses
rebaseby default for cleaner history - Email: Defaults to personal email (override per project as needed)
- New aliases: Added
co,br,ci,stfor common git commands
Cross-Platform Compatibility
This repo is organized around a shared Zsh setup plus OS-specific overlays:
- Shared shell base:
shell/.zshrcloadsshell/.config/zsh/common.zsh - OS overlays:
shell/.config/zsh/macos.zshandshell/.config/zsh/linux.zsh - Local overrides: Copy
shell/.config/zsh/local.zsh.exampleto~/.config/zsh/local.zshfor machine-specific settings and secrets
When using on Linux systems that have existing git configs:
- Backup existing config:
cp ~/.gitconfig ~/.gitconfig.backup - Check for conflicts: Compare settings before stowing
- Merge manually if needed: Combine useful settings from both configs
OMArchy/Hyprland Integration
The Hyprland configuration is designed for OMArchy systems:
- Keybindings: Custom app launchers (Super+A for ChatGPT, Super+B for Brave)
- Theme integration: Sources OMArchy theme system
- Hardware: Configured for modern displays with proper scaling
- Input: Natural touchpad scrolling and fingerprint authentication
Note: Hyprland configs only apply to OMArchy/Linux systems with Hyprland installed.
Machine-Specific Linux Fixes
scripts/install-lid-wakeup-fix.sh: Installs a small systemd service that disables ACPI lid wakeup on boot for laptops that immediately wake from suspend with the lid open.- This is intentionally managed as an install script plus service template instead of a stowed
~/.configfile, because it writes to/etc/systemd/system/and is machine-specific.
Structure
dotfiles/
├── config/ # Modern config files (~/.config/)
│ └── .config/
│ ├── hypr/ # Hyprland window manager (OMArchy)
│ ├── nvim/ # Neovim configuration (LazyVim + GitHub Copilot)
│ ├── waybar/ # Waybar status bar (OMArchy) with VPN module
│ └── zed/ # Zed editor settings and keymaps
├── ghostty/ # Ghostty terminal configuration
│ └── config # Terminal settings, colors, fonts
├── git/ # Git configuration
│ ├── .gitconfig
│ └── .gitignore_global
├── homebrew/ # Homebrew package management
│ └── Brewfile # List of installed packages
├── logseq/ # Logseq knowledge management
│ ├── config/
│ │ ├── config.edn # Global shortcuts and settings
│ │ └── plugins.edn # Installed plugins list
│ ├── settings/
│ │ ├── logseq-everforest-theme.json
│ │ └── logseq-journals-calendar.json
│ └── preferences.json # UI preferences and themes
├── shell/ # Shell configuration
│ ├── .bash_functions/
│ │ └── image-tools.bash # Bash image utilities
│ ├── .zsh_functions/
│ │ └── image-tools.zsh
│ ├── .bashrc # Enhanced bash config (Arch Linux/OMArchy)
│ ├── .bash_profile # Bash profile (sources .bashrc)
│ ├── .config/zsh/ # Shared + OS-specific Zsh config layers
│ ├── .env.local
│ └── .zshrc # Cross-platform Zsh entrypoint
├── ssh/ # SSH client configuration
│ └── .ssh/
│ └── config
├── vim/ # Vim configuration
│ └── .vimrc
├── vscode/ # VS Code configuration
│ └── Library/Application Support/Code/User/
│ ├── settings.json
│ └── keybindings.json
└── vscode-insiders/ # VS Code Insiders configuration
└── Library/Application Support/Code - Insiders/User/
├── settings.json
└── keybindings.json
Prerequisites
Install Stow
macOS (Homebrew):
brew install stowArch Linux:
sudo pacman -S stowInstallation
Fresh Machine Setup
-
Install prerequisites:
# Install Homebrew (if not already installed) /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" # Install Stow brew install stow
-
Clone the repository:
git clone <your-repo-url> ~/dotfiles cd ~/dotfiles
-
Install packages from Brewfile:
brew bundle install --file=homebrew/Brewfile
On Linux, install the shell dependencies you want manually (
zsh,fnm,zoxide,fastfetch, etc.) or with your distro package manager. -
Stow packages individually:
stow git # Git configuration stow shell # Cross-platform Zsh, Bash, profile, functions stow vim # Vim configuration stow config # Neovim, Zed, and Hyprland configuration stow ghostty # Ghostty terminal configuration stow ssh # SSH client config stow vscode # VS Code settings and keybindings stow vscode-insiders # VS Code Insiders settings stow logseq # Logseq configuration stow homebrew # Homebrew Brewfile
-
Or stow all packages at once:
stow */
Existing Machine (Update)
If you already have some configs and want to adopt them:
-
Pull latest changes:
cd ~/dotfiles git pull
-
Stow with adopt flag to take over existing files:
stow --adopt packagename # For specific package # or stow --adopt */ # For all packages
Usage
Zsh Layout
~/.zshrcdetects the OS and loads shared config first~/.config/zsh/common.zshholds portable aliases, tool init, and function loading~/.config/zsh/macos.zshholds Homebrew and macOS-specific behavior~/.config/zsh/linux.zshholds Linux clipboard and path behavior~/.config/zsh/local.zshis optional and stays machine-specific
Raspberry Pi Pi-hole Rebuild
After flashing a fresh Bookworm card, enabling SSH, and installing Pi-hole, you can restore the saved Pi-hole config with:
./scripts/pi-pihole-restore.shThe script expects the backup set at ~/Downloads/pi-pre-upgrade-backups/20260310-150325 by default and can target a different host or backup directory with --host and --backup-dir.
Adding New Configurations
-
Create a new package directory:
mkdir ~/dotfiles/newpackage -
Move your dotfiles to the package:
mv ~/.someconfig ~/dotfiles/newpackage/
-
Stow the new package:
cd ~/dotfiles stow newpackage
Updating Configurations
Simply edit the files in your dotfiles directory. Changes are immediately reflected since they're symlinked.
Adding New Files to Existing Packages
- Add the file to the appropriate package directory
- Re-stow if necessary:
stow -R packagename # Restow to pick up new files
Maintenance
Backup Before Major Changes
# Create a backup branch before major updates
git checkout -b backup-$(date +%Y%m%d)
git checkout mainKeep Dependencies Updated
- Update Oh My Zsh:
omz update - Update Neovim plugins:
:Lazy syncin nvim - Update Homebrew packages:
brew upgrade - Regenerate Brewfile:
brew bundle dump --force --file=homebrew/Brewfile
Sync Across Machines
# On machine A (after making changes)
git add .
git commit -m "Update configurations"
git push
# On machine B
git pull
stow -R */ # Restow all packagesTroubleshooting
Before First-Time Setup: Backup Existing Configs
Always backup existing configurations before stowing for the first time:
# Create backup directory
mkdir -p ~/config-backup/$(date +%Y%m%d)
# Backup common config files
cp ~/.gitconfig ~/config-backup/$(date +%Y%m%d)/ 2>/dev/null || true
cp ~/.zshrc ~/config-backup/$(date +%Y%m%d)/ 2>/dev/null || true
cp ~/.vimrc ~/config-backup/$(date +%Y%m%d)/ 2>/dev/null || true
cp -r ~/.config/nvim ~/config-backup/$(date +%Y%m%d)/ 2>/dev/null || true
cp -r ~/.config/zed ~/config-backup/$(date +%Y%m%d)/ 2>/dev/null || true
cp -r ~/.config/hypr ~/config-backup/$(date +%Y%m%d)/ 2>/dev/null || true
cp ~/Library/Application\ Support/Code/User/settings.json ~/config-backup/$(date +%Y%m%d)/vscode-settings.json 2>/dev/null || true
cp -r ~/.logseq/config ~/config-backup/$(date +%Y%m%d)/ 2>/dev/null || true
cp ~/.logseq/preferences.json ~/config-backup/$(date +%Y%m%d)/ 2>/dev/null || true
echo "Backup created in ~/config-backup/$(date +%Y%m%d)/"Stow Conflicts
When stow reports "cannot stow over existing target", you have three options:
Method 1: Manual backup and removal (Recommended - Safest)
# Backup the conflicting file first
cp ~/.conflicting-file ~/.conflicting-file.backup
# Remove the conflicting file
rm ~/.conflicting-file
# Then stow normally
stow packagename
# If issues occur, restore from backup:
# cp ~/.conflicting-file.backup ~/.conflicting-fileMethod 2: Using -R flag (Only for already-stowed packages)
# This only works if the package was previously stowed successfully
# -R (restow) removes existing symlinks, then recreates them
stow -R packagename
# Note: -R will FAIL if there are actual file conflicts
# It only removes symlinks it previously createdMethod 3: Using --adopt flag (Advanced - Modifies your dotfiles repo)
# CAUTION: This modifies your dotfiles repo!
stow --adopt packagename--adopt:
- Takes existing files from your system and overwrites files in your dotfiles repo
- Your carefully crafted configurations will be replaced with current system files
- Always run
git diffafter using--adoptto see what changed - Only commit if you actually want to keep the system versions over your dotfiles versions
- This is useful when setting up dotfiles on a machine with existing configs you prefer
Safe workflow with --adopt:
# 1. Create a backup branch first
git checkout -b backup-before-adopt-$(date +%Y%m%d)
git checkout main
# 2. Try adopt
stow --adopt packagename
# 3. MANDATORY: Review what changed
git diff
# 4. Decision point:
# Keep adopted changes: git add . && git commit -m "Adopt system configs"
# Revert adopted changes: git checkout -- .Restoring from Backup
If something goes wrong after stowing:
# Unstow the problematic package
stow -D packagename
# Restore from backup
cp ~/config-backup/YYYYMMDD/.configfile ~/.configfile
# Fix issues, then try stowing againOther Common Issues
Broken Symlinks:
# Find broken symlinks
find ~ -maxdepth 1 -type l ! -exec test -e {} \; -print
# Remove broken symlinks
find ~ -maxdepth 1 -type l ! -exec test -e {} \; -deleteVerify Stow Status:
# Check what's currently stowed
ls -la ~ | grep dotfiles
# Check specific config directories
ls -la ~/.config/ | grep dotfilesComplete Reset (Nuclear option):
# Unstow everything
cd ~/dotfiles
stow -D */
# Restore all from backup
cp -r ~/config-backup/YYYYMMDD/* ~/
# Start fresh with stowingSecurity Notes
- SSH keys and sensitive data are excluded via
.gitignore - Only configuration files are tracked, not secrets
- Review
.env.localfor sensitive environment variables
Package Overview
| Package | Contains | Purpose |
|---|---|---|
git |
.gitconfig, .gitignore_global | Git settings and global ignores |
shell |
.bashrc, .bash_profile, .zshrc, .env.local, functions | Shell configuration (bash for Arch/OMArchy, zsh for macOS) |
vim |
.vimrc | Traditional Vim settings |
config |
.config/nvim/, .config/zed/, .config/hypr/, .config/waybar/ | Modern app configurations (Neovim includes GitHub Copilot) |
ghostty |
config | Terminal emulator settings and themes |
ssh |
.ssh/config | SSH client settings (no keys) |
vscode |
settings.json, keybindings.json | VS Code configuration |
vscode-insiders |
settings.json, keybindings.json | VS Code Insiders configuration |
logseq |
config.edn, plugins.edn, preferences.json | Logseq knowledge management settings and plugins |
homebrew |
Brewfile | Homebrew package list for easy setup |
Dependencies
- Zsh plugins: zsh-syntax-highlighting
- Neovim: LazyVim distribution
- Tools: fnm, zoxide, fastfetch, podman
- macOS specific: Uses Keychain for SSH keys