- Shell 73.2%
- Go Template 26.3%
- Dockerfile 0.5%
- README: zsh is the default shell with fish as the mirrored alternative (was the reverse); Ghostty not iTerm2; add Java to the runtime list; strip hardcoded runtime versions (already drifted - Go said 1.26.1 vs 1.26.4 pinned) in favour of pointing at the mise config as source of truth - SCRIPTS: install.sh takes no CLI options (it is a minimal chezmoi bootstrap; behaviour is driven by CI/QUICK_INSTALL env vars), and setup-aliases.sh is called by docker-test.sh, not install.sh |
||
|---|---|---|
| .chezmoiscripts | ||
| .claude | ||
| .github/workflows | ||
| dot_claude | ||
| private_dot_config | ||
| private_dot_gnupg | ||
| .chezmoi.toml.tmpl | ||
| .chezmoiexternal.toml.tmpl | ||
| .chezmoiignore | ||
| .chezmoiremove | ||
| .dockerignore | ||
| .editorconfig | ||
| .gitattributes | ||
| .gitignore | ||
| .tool-versions | ||
| CLAUDE.md | ||
| docker-test.sh | ||
| Dockerfile | ||
| dot_gitconfig.tmpl | ||
| dot_inputrc | ||
| dot_lesskey | ||
| dot_tmux.conf | ||
| dot_zshenv.tmpl | ||
| dot_zshrc.tmpl | ||
| install.sh | ||
| README.md | ||
| renovate.json | ||
| SCRIPTS.md | ||
| setup-aliases.sh | ||
| test-chezmoi-data.yaml | ||
| test.sh | ||
Cross-Platform Dotfiles with Chezmoi
This repository contains my personal dotfiles managed by chezmoi, supporting both Linux and macOS. Zsh is the default shell, with a parallel Fish configuration kept feature-for-feature in sync.
Features
- 🦓 Zsh configuration (the default shell) with cross-platform support
- 🐟 Fish configuration that mirrors the Zsh setup feature-for-feature
- 🍎 macOS-specific optimizations (Homebrew, Ghostty, etc.)
- 🐧 Linux compatibility
- 🛠️ Useful shell functions and utilities (ported 1:1 across both shells)
- 📦 Template-based configuration for different environments
- 🔧 mise for language runtimes (Node.js, Python, Go, Bun, Java)
- 🌊 mise aqua backend for 22 modern CLI tools (bat, fd, eza, kubectl, gh, etc.)
- 🔍 Modern CLI tools: Complete suite of replacements for traditional Unix tools
- ⭐ Starship cross-shell prompt with git integration
- 📜 Atuin for enhanced shell history (better search, statistics, deduplication)
- 🧹 Automatic cleanup of old tool installations
Prerequisites
- Git
- curl or wget
- sudo access (for package installation)
Installation
Quick Install (Recommended)
# One-liner installation
curl -fsLS https://raw.githubusercontent.com/ryanlewis/dotfiles/main/install.sh | bash
Or if you prefer using wget:
wget -qO- https://raw.githubusercontent.com/ryanlewis/dotfiles/main/install.sh | bash
Alternative: Using Chezmoi Directly
If you already have chezmoi installed:
chezmoi init --apply ryanlewis/dotfiles
Environment Variables
Control installation behavior with these environment variables:
# Skip language runtimes (Node.js, Python, Go)
QUICK_INSTALL=true curl -fsLS https://raw.githubusercontent.com/ryanlewis/dotfiles/main/install.sh | bash
# Provide git config to avoid prompts
CHEZMOI_USER_NAME="Your Name" CHEZMOI_USER_EMAIL="you@example.com" \
curl -fsLS https://raw.githubusercontent.com/ryanlewis/dotfiles/main/install.sh | bash
What Gets Installed
The installation process automatically sets up:
- Fish shell - Modern, user-friendly shell
- chezmoi - Dotfiles manager
- mise - Universal version manager
- Modern CLI tools:
eza- Betterlsbat- Bettercatwith syntax highlightingripgrep- Bettergrepfd- Betterfindfzf- Fuzzy finderzoxide- Smartercdstarship- Cross-shell promptbtop- Bettertopduf- Betterdfdust- Betterdugum- Pretty shell scriptskubectl- Kubernetes CLIkubectx- K8s context switcherkubens- K8s namespace switcher- And more...
- Language runtimes (optional):
- Node.js (via mise)
- Python/Miniconda (via mise)
- Go (via mise)
- Bun (via mise)
Usage
Common Commands
chezmoi diff- See what changes would be madechezmoi apply- Apply the configurationchezmoi add ~/.config/fish/newfile.fish- Add a new filechezmoi edit ~/.config/fish/config.fish- Edit a managed filechezmoi update- Pull latest changes and apply
Fish Functions
This configuration includes several useful Fish functions:
mkcd <dir>- Create a directory and cd into itbackup <file>- Create a timestamped backup of a fileextract <archive>- Extract various archive formatsupdate- Update system packages (brew/apt/dnf/pacman)ports- Show listening portsmyip- Display local and public IP addressesyank- Copy text to clipboard via OSC 52 (works over SSH)mise-setup- Show configured mise tools and install hintsmise-install-latest- Install latest stable versions of all toolsmise-update- Update mise and all plugins
Clipboard Function: yank
The yank function enables clipboard access from anywhere, even over SSH:
# Copy command output
git diff | yank
cat ~/.ssh/id_rsa.pub | yank
echo "some text" | yank
# Works over SSH - copies to your local clipboard!
ssh server "cat /var/log/nginx/error.log | yank"
Why use yank?
- Works over SSH without X11 forwarding
- Works in tmux/screen sessions
- Universal solution across different terminals (iTerm2, Terminal.app, Alacritty, Windows Terminal, etc.)
- No need for platform-specific tools (pbcopy/xclip)
FZF-Powered Functions
fcd- Fuzzy change directory with previewfopen- Fuzzy find and open file in editorfkill- Fuzzy find and kill processesfgrep <term>- Fuzzy grep with file previewfgit <cmd>- Interactive git operations:fgit add- Stage files interactivelyfgit checkout- Checkout branches with previewfgit log- Browse git log with commit previewfgit diff- View file diffs interactively
macOS-Specific Features
When running on macOS, additional features are enabled:
- Homebrew integration
- GNU coreutils in PATH (if installed)
- macOS-specific aliases:
flushdns- Flush DNS cacheql <file>- Quick Look previewshowfiles/hidefiles- Toggle hidden files in Findercleanup- Remove .DS_Store files
Modern CLI Tools
This configuration includes a comprehensive suite of modern CLI tools:
File & Directory Tools
- eza - Modern
lsreplacement- Icons, colors, git integration, tree view
- Aliased to replace all
lsvariants
- fd - Better
find- Simple syntax, respects .gitignore
- Default file finder for fzf
- ripgrep - Better
grep- Extremely fast, respects .gitignore
- Powers the
fgrepfunction
- bat - Better
cat- Syntax highlighting, line numbers
- File previews in fzf
- zoxide - Smarter
cd- Learns your most used directories
- Jump with partial names
System Monitoring
- btop - Better
top/htop- Beautiful terminal UI
- Aliased to replace
topandhtop
- duf - Better
df- User-friendly disk usage display
- dust - Better
du- Intuitive disk usage analyzer
Development Tools
- lazygit - Terminal UI for git
- Interactive staging, branching, merging
- Launch with
lg
- delta - Better git diffs
- Syntax highlighting, side-by-side view
- Auto-configured in gitconfig
- gh - GitHub CLI
- Manage PRs, issues from terminal
- httpie - Better
curl- Human-friendly HTTP client
httpsalias for HTTPS requests
- jq - JSON processor
- Query and manipulate JSON data
- just - Modern
make- Simpler command runner
Shell Enhancements
- fzf - Fuzzy finder
- Ctrl+R (history), Ctrl+T (files), Alt+C (directories)
- Powers many custom functions
- starship - Cross-shell prompt
- Fast, customizable, git-aware
- Pre-configured with icons
- atuin - Better shell history
- Advanced fuzzy search, statistics, intelligent deduplication
- direnv - Directory environments
- Auto-load .envrc files
- broot - Better
tree- Navigate directories efficiently
- tldr - Simplified man pages
- Quick command examples
Container & Kubernetes Tools
- kubectl - Kubernetes CLI
- Manage Kubernetes clusters
- kubectx - Context switcher
- Quickly switch between Kubernetes contexts
- kubens - Namespace switcher
- Quickly switch between Kubernetes namespaces
Version Management with mise
This configuration includes mise for managing:
Language Runtimes (5 tools):
- Node.js (LTS)
- Python (via Miniconda)
- Go
- Bun
- Java (Eclipse Temurin LTS)
CLI Tools via aqua backend (22 tools):
- Modern CLI replacements: bat, fd, eza, ripgrep, zoxide, duf, dust
- Development tools: fzf, starship, atuin, delta, lazygit, gh, jq, just, gum, direnv, uv
- Kubernetes tools: kubectl, kubectx, kubens
- AWS tools: granted
Versions above track
private_dot_config/mise/config.toml.tmpl, which is the source of truth.
All tools are automatically installed via ~/.config/mise/config.toml when you run:
# Install all configured tools (languages + CLI tools)
mise install
# Or install latest stable versions
mise-install-latest
Note: Old installations (Homebrew, apt packages, binaries) are automatically cleaned up after mise aqua setup.
Development
Making Changes to Dotfiles
After installation, your dotfiles are managed by chezmoi. To make changes:
# Go to chezmoi's source directory
chezmoi cd
# Edit files directly
vim .config/fish/config.fish.tmpl
# Preview changes
chezmoi diff
# Apply changes locally
chezmoi apply
# Commit and push
git add -A
git commit -m "Update fish config"
git push
Or use the included dotfiles Fish function:
dotfiles edit # Go to source directory
dotfiles diff # Preview changes
dotfiles apply # Apply locally
dotfiles push # Commit and push all changes
dotfiles pull # Pull latest from GitHub
Updating from GitHub
On any machine with your dotfiles installed:
chezmoi update # Pull latest changes and apply them
Customization
Local Configuration
Create ~/.config/fish/config.local.fish (Fish) or ~/.config/zsh/config.local.zsh (Zsh) for machine-specific configuration that won't be managed by chezmoi.
Zsh (the default shell)
Zsh is the default login shell (the provisioning script recommends it on fresh machines; chsh -s $(which zsh) to switch an existing one). A parallel Fish configuration is kept feature-for-feature in sync for when an interactive-first shell is preferred. The Zsh side comprises:
~/.zshenv— PATH/environment for all shells (the non-interactive half ofconfig.fish).~/.zshrc— interactive config: vi mode, completions, abbreviations, tool inits (mise, zoxide, fzf, atuin, starship, direnv, broot), aliases, and the same MOTD/greeting.~/.config/zsh/functions/*.zsh— a 1:1 port of every Fish function (mkcd,extract,fcd,fgit,ca,crpr,tools, …).~/.config/zsh/conf.d/*.zsh— fzf options, macOS extras, greeting, and MOTD.
The prompt (starship), history (atuin), and the modern-CLI aliases are shared, so both shells behave identically.
Plugins that Fish ships built-in (autosuggestions, syntax highlighting) plus zsh-abbr are fetched by chezmoi into ~/.config/zsh/plugins (see .chezmoiexternal.toml) — there is no separate plugin manager.
Try it without switching: just run zsh. To make it your login shell when ready: chsh -s "$(command -v zsh)".
Templates
This repository uses chezmoi templates to handle OS-specific differences. Key template variables:
{{ .chezmoi.os }}- "darwin" or "linux"{{ .chezmoi.arch }}- System architecture{{ .brewPrefix }}- Homebrew prefix path{{ .packageManager }}- System package manager
Directory Structure
~/dev/dotfiles/
├── .chezmoi.toml.tmpl # Chezmoi configuration template
├── .chezmoiignore # Files to ignore by OS
├── .chezmoiexternal.toml.tmpl # Externally-fetched files (zsh plugins)
├── dot_zshenv.tmpl # Zsh env for all shells (PATH, etc.)
├── dot_zshrc.tmpl # Main Zsh interactive config
├── private_dot_config/
│ ├── private_fish/
│ │ ├── config.fish.tmpl # Main Fish config
│ │ ├── functions/ # Fish functions
│ │ └── conf.d/ # Fish conf.d files
│ └── zsh/
│ ├── functions/ # Zsh functions (1:1 port of Fish)
│ └── conf.d/ # Zsh conf.d files (fzf, macos, greeting, motd)
└── README.md # This file
Testing with Docker
You can test the dotfiles installation in a clean Docker environment:
Quick Test
# Run the interactive test script
./docker-test.sh
# Inside the container:
cd /home/testuser/dev/dotfiles
./install.sh
fish
./test.sh # Run the test suite
Manual Docker Commands
# Build the test image
docker build -f Dockerfile.test -t dotfiles-test .
# Run container with mounted dotfiles
docker run -it --rm -v "$(pwd):/home/testuser/dev/dotfiles:ro" dotfiles-test
# Or use docker-compose
docker-compose up -d dotfiles-test
docker exec -it dotfiles-test fish
Test Script
The test.sh script verifies all tools are installed correctly:
- Checks all CLI tools are available
- Verifies Fish functions exist
- Confirms configurations are in place
- Tests mise tools
CI/CD
This repository includes automated testing via GitHub Actions:
Continuous Integration
- Tests on Ubuntu 22.04 and 24.04
- Tests on macOS 13 and 14
- Docker-based testing
- Full tool installation verification
Running in CI Mode
# Install with CI mode (non-interactive)
./install.sh --ci
# Or just skip confirmations
./install.sh --no-confirm
Environment variables for CI:
CI=true- Automatically detected by GitHub ActionsCHEZMOI_USER_NAME- Name for git configCHEZMOI_USER_EMAIL- Email for git config
Troubleshooting
Installation Issues
Python/Miniconda fails with "Terms of Service" error
This is a known issue with Miniconda requiring ToS acceptance. The script will continue without Python. To fix:
# Accept Conda ToS manually
~/.local/share/mise/installs/python/miniconda3-latest/bin/conda init
~/.local/share/mise/installs/python/miniconda3-latest/bin/conda config --set auto_activate_base false
Script fails with "command not found"
Ensure ~/.local/bin is in your PATH:
export PATH="$HOME/.local/bin:$PATH"
Fish doesn't start with correct configuration
# Re-apply dotfiles
chezmoi apply -v
# Install Fisher plugins manually
fish -c "curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source && fisher install jorgebucaran/fisher"
fish -c "fisher install PatrickF1/fzf.fish"
Tools not found after installation
# Activate mise in current shell
eval "$(mise activate bash)"
# Or start a new Fish shell
fish
Automated Dependency Updates with Renovate Bot
This repository uses Renovate Bot to automatically keep dependencies up-to-date. Renovate creates pull requests when new versions are available.
What Renovate Updates
1. mise Tool Versions (private_dot_config/mise/config.toml.tmpl)
- Node.js versions
- Go versions
- Bun versions
- Python/Miniconda versions
2. GitHub Actions (.github/workflows/*.yml)
- Action versions (e.g.,
actions/checkout) - GitHub-hosted runner versions
3. Binary Tools in install.sh
- mise version manager
- fzf (fuzzy finder)
- delta (git diff viewer)
- atuin (shell history)
- just (command runner)
- kubectx/kubens (Kubernetes tools)
- duf (disk usage)
- dust (du alternative)
How It Works
- Automated Runs: Renovate app runs automatically on its schedule
- Pull Requests: Creates PRs for each dependency update with conventional commits
- Auto-merge: Minor and patch updates are auto-merged if tests pass
- Major Updates: Require manual review and approval
Configuration
- Main config:
renovate.json - Managed by: GitHub Renovate App (no additional setup needed)
For Contributors
If you fork this repo, you'll need to:
- Install the Renovate GitHub App on your fork
- Renovate will automatically detect the configuration and start creating PRs
Contributing
Feel free to fork and customize for your own use!
Tool Versions
Last updated: June 2026
The authoritative version list is private_dot_config/mise/config.toml.tmpl; Renovate keeps it current. CLI tools track latest, so only the pinned language runtimes are listed here.
Core Tools
- chezmoi: latest from official installer
- mise: latest
Programming Languages (pinned via mise)
Node.js, Python (miniconda3), Go, Bun, and Java (Eclipse Temurin LTS) — exact pinned versions live in private_dot_config/mise/config.toml.tmpl, the source of truth, and are bumped automatically by Renovate.
License
MIT