- Shell 41.8%
- Go Template 32.5%
- Lua 25.2%
- Dockerfile 0.5%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .chezmoiscripts | ||
| .claude | ||
| .github/workflows | ||
| bench | ||
| dev/raycast-scripts | ||
| dot_claude | ||
| private_dot_config | ||
| private_dot_gnupg | ||
| private_Library/Scripts | ||
| scripts | ||
| .chezmoi.toml.tmpl | ||
| .chezmoiexternal.toml.tmpl | ||
| .chezmoiignore | ||
| .chezmoiremove | ||
| .dockerignore | ||
| .editorconfig | ||
| .gitattributes | ||
| .gitignore | ||
| CLAUDE.md | ||
| docker-test.sh | ||
| Dockerfile | ||
| dot_gitconfig.tmpl | ||
| dot_inputrc | ||
| dot_lesskey | ||
| dot_zshenv.tmpl | ||
| dot_zshrc.tmpl | ||
| install.sh | ||
| README.md | ||
| renovate.json | ||
| run_once_before_purge-orphaned-repo-meta.sh | ||
| 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 shell.
Features
- 🦓 Zsh configuration with cross-platform support
- 🍎 macOS-specific optimizations (Homebrew, Ghostty, etc.)
- 🐧 Linux compatibility
- 🛠️ Useful shell functions and utilities
- 📦 Template-based configuration for different environments
- 🔧 mise for language runtimes (Node.js always; Go, Java, Python opt-in per machine; bun self-managed)
- 🌊 mise aqua backend for the modern CLI suite (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 all mise-managed tools (runtimes + CLI suite) for a fast, minimal bootstrap
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:
- Zsh - Interactive shell with plugins and abbreviations
- 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:
- Node.js — always installed via mise (the dotfiles tooling depends on it)
- Bun — installed by its official installer and self-updated via
bun upgrade(deliberately not pinned in mise) - Go, Java (Temurin), Python/Miniconda — opt-in per machine, chosen at
chezmoi init(default off, so VMs/CI stay lean). See Per-machine language runtimes.
Usage
Common Commands
chezmoi diff- See what changes would be madechezmoi apply- Apply the configurationchezmoi add ~/.config/zsh/functions/foo.zsh- Add a new filechezmoi edit ~/.zshrc- Edit a managed filechezmoi update- Pull latest changes and apply
Zsh Functions
This configuration includes several useful Zsh functions:
mkcd <dir>- Create a directory and cd into itbackup <file>- Create a timestamped backup of a fileextract <archive>- Extract various archive formatsupdate- Update mise tools, system packages (brew/apt/dnf/pacman) and bun, then restart the shellports- 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
- 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 Findershowdesktop/hidedesktop- Toggle desktop iconsafk- Start the screensaver (lock away from keyboard)cleanup- 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
- hunk - Diff viewer/pager
- npm package
hunkdiff; run ashunk
- npm package
- gh - GitHub CLI
- Manage PRs, issues from terminal
- cf - Cloudflare CLI
- Manage DNS, zones, Workers deploys 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
- worktrunk - Git worktree manager
- Create/switch worktrees fast; launched via
wt(and thewscabbreviation)
- Create/switch worktrees fast; launched via
- biome - JS/TS formatter and linter
- Single fast toolchain for formatting and linting
- uv - Fast Python package/project manager
- Neovim - Hyperextensible modal editor; resolved as
$EDITOR- Launched via
nvim(also aliased tovim); personal config lives in~/.config/nvim
- Launched via
- helix - Modal editor with LSP built in
- Launched via
hx; kept as a fallback editor
- Launched via
- ktlint - Kotlin linter/formatter (macOS only)
- md-tui - Markdown viewer (TUI)
- Render and browse markdown in the terminal; launched via
mdt
- Render and browse markdown in the terminal; launched via
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:
- Node.js (LTS) — always installed (via mise)
- Go — opt-in per machine
- Java (Eclipse Temurin LTS) — opt-in per machine
- Python (via Miniconda) — opt-in per machine
(Bun is installed separately by its official installer and self-updates via
bun upgrade — it is not managed by mise.)
Per-machine language runtimes
node is always installed via mise because the dotfiles tooling depends on it;
bun is installed by its own official installer and self-updates via bun upgrade (not mise-managed). The heavier, project-specific runtimes — Go,
Java, Python/Miniconda — are off by default and opted into per machine:
- Choosing at setup:
chezmoi initprompts "Install Go/Java/Python on this machine?" (default no). In CI or any non-interactive bootstrap the prompts are skipped and nothing extra is installed, so VMs stay lean. - Changing later: re-run
chezmoi init --prompt(or edit~/.config/chezmoi/chezmoi.toml), thenchezmoi apply. mise picks up the new selection from the managed~/.config/mise/conf.d/runtimes.toml. - Version pins for these runtimes live in
private_dot_config/mise/conf.d/runtimes.toml.tmpland are still bumped by Renovate. - Removing a runtime: turn it off and apply; mise leaves the old install in
place. Every
chezmoi applyprints the current selection and flags any runtime that's installed but no longer selected, with themise uninstall/mise prunecommand to reclaim the disk. Nothing is deleted automatically. - Ad-hoc, machine-only tools that shouldn't be tracked in this repo go in
the unmanaged
~/.config/mise/conf.d/local.toml.
CLI Tools via the mise aqua backend:
- Modern CLI replacements: bat, fd, eza, ripgrep, zoxide, duf, dust
- Development tools: fzf, starship, atuin, delta, lazygit, gh, jq, just, gum, direnv, uv
- Editor: neovim (
nvim), tree-sitter CLI (builds nvim-treesitter parsers) - Kubernetes tools: kubectl, kubectx, kubens
- AWS tools: granted (
assume) - Fuzzy finder TUI: television (
tv, via a mise plugin)
Tools outside the aqua registry (btop, httpie, broot, tldr, pinentry, helix,
md-tui, worktrunk, biome, and macOS-only eza/ktlint) are installed by
.chezmoiscripts/run_onchange_after_05-install-tools.sh.tmpl.
The exact tool list and versions 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 dot_zshrc.tmpl
# Preview changes
chezmoi diff
# Apply changes locally
chezmoi apply
# Commit and push
git add -A
git commit -m "Update zsh config"
git push
Or use the included dotfiles 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/zsh/config.local.zsh for machine-specific configuration that won't be managed by chezmoi.
Zsh
Zsh is the login shell (the provisioning script recommends it on fresh machines; chsh -s $(which zsh) to switch an existing one). It comprises:
~/.zshenv— PATH/environment for all shells (the non-interactive half).~/.zshrc— interactive config: vi mode, completions, abbreviations, tool inits (mise, zoxide, fzf, atuin, starship, direnv, broot), aliases, and the MOTD/greeting.~/.config/zsh/functions/*.zsh— one function per file (mkcd,extract,fcd,fgit,crpr,tools, …).~/.config/zsh/conf.d/*.zsh— fzf options, macOS extras, greeting, and MOTD.~/.config/zsh/completions/— completion functions generated at apply time (currently_rgfor ripgrep; mise/aqua binaries don't ship completion files the way brew does). Onfpath, autoloaded by compinit — zero startup cost.
The prompt (starship) and history (atuin) round out the setup.
Plugins (autosuggestions, syntax highlighting) are fetched by chezmoi into ~/.config/zsh/plugins (see .chezmoiexternal.toml) — there is no separate plugin manager. Both are deferred: sourced at the first idle moment after the prompt is drawn rather than at rc time, keeping ~13% off time-to-first-prompt while staying behaviourally identical within a frame of an interactive prompt. Abbreviations (git shortcuts, wsc, cca) are a small built-in ZLE widget (ZABBR in .zshrc), not a plugin — typing one at command position then space/enter expands it inline to the full command.
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
The chezmoi source directory lives at ~/.local/share/chezmoi (run chezmoi cd
to jump there; ~/dev/dotfiles is only the mount path used by docker-test.sh).
chezmoi source/
├── .chezmoi.toml.tmpl # Per-machine data (prompts, .isWork, etc.)
├── .chezmoiignore # Files present in the repo but not deployed
├── .chezmoiremove # Files chezmoi deletes from $HOME on apply
├── .chezmoiexternal.toml.tmpl # Externally-fetched files (zsh plugins)
├── .chezmoiscripts/ # Ordered run_once / run_onchange install scripts
├── dot_zshenv.tmpl # Zsh env for all shells (PATH, etc.)
├── dot_zshrc.tmpl # Main Zsh interactive config
├── dot_gitconfig.tmpl # Git config (delta, etc.)
├── dot_inputrc / dot_lesskey # readline / less key bindings
├── dot_claude/ # Claude Code config (agents, commands, hooks, statusline)
├── private_dot_config/
│ ├── zsh/ # functions/, conf.d/
│ ├── mise/ # mise config (tool + runtime source of truth)
│ ├── ghostty/ helix/ lazygit/ # per-tool configs
│ ├── starship.toml.tmpl # shared prompt
│ └── herdr/ worktrunk/ # herdr (multiplexer) and worktrunk configs
├── private_dot_gnupg/ # gpg-agent config
├── install.sh test.sh docker-test.sh setup-aliases.sh
├── Dockerfile renovate.json
└── README.md CLAUDE.md SCRIPTS.md # docs (not deployed)
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
zsh
./test.sh # Run the test suite
Manual Docker Commands
# Build the test image
docker build -f Dockerfile -t dotfiles-test .
# Run container with mounted dotfiles
docker run -it --rm -v "$(pwd):/home/testuser/dev/dotfiles:ro" dotfiles-test
./docker-test.sh(and./docker-test.sh --ci) wrap these commands; there is noDockerfile.testor docker-compose file.
Test Script
The test.sh script verifies all tools are installed correctly:
- Checks all CLI tools are available
- Verifies Zsh 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 24.04 and macOS 26 (GitHub-hosted runners)
- Full tool installation verification (
install.sh+test.sh) - Docker-based testing is available locally via
./docker-test.sh
Running in CI Mode
install.sh takes no CLI flags; CI behaviour is driven by environment variables.
# Non-interactive install (skips prompts and the login-shell step)
CI=true ./install.sh
# Non-interactive and skip language runtimes
CI=true QUICK_INSTALL=true ./install.sh
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
Only relevant if you opted Python in for this machine (see Per-machine language runtimes). Miniconda requires ToS acceptance; this is a known issue and the install continues 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"
Zsh doesn't start with correct configuration
# Re-apply dotfiles
chezmoi apply -v
There is no plugin manager to set up: fzf key bindings come from conf.d/fzf.zsh
(and fzf --zsh in ~/.zshrc), and every CLI tool is provided by mise. If a tool
is missing, ensure mise is active (eval "$(mise activate bash)") and re-run
chezmoi apply -v.
Tools not found after installation
# Activate mise in current shell
eval "$(mise activate bash)"
# Or start a new Zsh shell
zsh
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 + conf.d/runtimes.toml.tmpl)
- Node.js version (core, in
config.toml.tmpl) - Go, Java, and Python/Miniconda versions (opt-in runtimes, in
conf.d/runtimes.toml.tmpl)
(Bun is self-managed via bun upgrade, so Renovate does not track it.)
2. GitHub Actions (.github/workflows/*.yml)
- Action versions (e.g.,
actions/checkout) - GitHub-hosted runner versions
3. Pinned binaries in the install-tools script (.chezmoiscripts/run_onchange_after_05-install-tools.sh.tmpl)
- btop (system monitor)
- tealdeer / tldr (man-page examples)
- broot (tree navigation)
- md-tui (markdown viewer)
These are the only tools with hardcoded version pins; everything else tracks
latest (or a pinned version) via the mise config above. install.sh itself is a
flagless bootstrap and contains no version pins.
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 is always installed (pinned in private_dot_config/mise/config.toml.tmpl). Go, Java (Eclipse Temurin LTS), and Python (miniconda3) are opt-in per machine (pinned in private_dot_config/mise/conf.d/runtimes.toml.tmpl); see Per-machine language runtimes. Both files are the source of truth and are bumped automatically by Renovate. Bun is installed by its official installer and self-updates via bun upgrade (not mise-managed).
License
MIT