- Neovim editor configured with LazyVim💤
- Starship prompt
- Shell support for both Zsh and Fish with 95% functional parity via shared configuration
- Flexible, terminal-based dev environment with ghostty 👻 + Tmux!
- Fast, idempotent setup with GNU Stow
- New Mac bootstrap based on thoughtbot’s Laptop
- Support for both Apple Silicon and Intel Macs
- AI-assisted development with Claude Code (optional)
- Quick Setup
- Comprehensive Setup Documentation
- Prerequisites
- New Mac Bootstrap
- Zsh or Fish?
- Shared Configuration Framework
- Claude Code Integration (Optional)
- Functions and Abbreviations
- Markdown Linting
- About Neovim Distributions
- My Favorite Programming Fonts
- Nerd Fonts and Icons
- A Note about Vim performance and Ruby files
- Identifying Sources of Slow Startup Times (Zsh)
- Awesome Neovim Dotfiles, Distros, and Starters
- Some of my favorite dotfile repos
- Helpful web resources on dotfiles, et al.
- License
For first-time users: See the complete setup documentation for detailed guidance.
Make sure macOS is up to date and you have installed the required software.
Clone this repo.
git clone https://github.com/joshukraine/dotfiles.git ~/dotfiles
Read the setup script and check available options.
less ~/dotfiles/setup.sh
~/dotfiles/setup.sh --help
Preview what the setup script will do (dry-run mode).
~/dotfiles/setup.sh --dry-run
Run the setup script.
~/dotfiles/setup.sh
For detailed guidance on installation, customization, and troubleshooting:
Guide | Purpose |
---|---|
Setup Overview | Choose the right guide for your situation |
Installation Guide | Complete step-by-step setup walkthrough |
Usage Examples | Command examples and practical scenarios |
Troubleshooting | Solutions for common setup issues |
Customization | Personalizing your dotfiles setup |
Migration Guide | Moving from other dotfiles or manual configs |
The dotfiles assume you are running macOS with (at minimum) the following software pre-installed:
- Git
- Homebrew (including coreutils)
- asdf
- Ruby
- Node.js
- Zsh and/or Fish
- Neovim
- Starship
yq
(for regenerating abbreviations from shared YAML source)
All of the above and more are installed with my fork of Laptop.
This is what I would do if I bought a new Mac computer today. The steps below assume you have already completed the basics:
- Log in to iCloud
- Check for software updates
- Install Xcode Command Line Tools
▹ github.com/joshukraine/laptop
Download the mac
script:
curl --remote-name https://raw.githubusercontent.com/joshukraine/laptop/main/mac
Download .local.laptop
for additional customizations:
curl --remote-name https://raw.githubusercontent.com/joshukraine/dotfiles/master/laptop/.laptop.local
Review both scripts before proceeding:
less mac
less .laptop.local
Execute the mac
script:
sh mac 2>&1 | tee ~/laptop.log
I’ve made the following changes to my fork of Laptop:
- Install asdf via git instead of Homebrew
- Comment out Heroku-related code
- Comment out unused Homebrew taps and formulae
It is worth noting that the Laptop script (mac
) is idempotent and can be safely run multiple times to ensure a consistent baseline configuration.
The dotfiles setup.sh
script uses GNU Stow to symlink all the config files to your $HOME
directory. If you already have an identically-named file/directory in $HOME
(e.g. ~/.zshrc
leftover from installing Laptop), this will cause a conflict, and Stow will (rightly) abort with an error.
The setup script will try to detect and backup these files ahead of Stow, but it’s still a good idea to check your $HOME
directory as well as $HOME/.config
and $HOME/.local/bin
.
Clone
git clone https://github.com/joshukraine/dotfiles.git ~/dotfiles
Read and preview
less ~/dotfiles/setup.sh
~/dotfiles/setup.sh --help
~/dotfiles/setup.sh --dry-run # Preview changes without applying them
Setup
~/dotfiles/setup.sh
If you do encounter Stow conflicts, resolve these and run setup again. The script is idempotent, so you can run it multiple times safely.
Zap describes itself as a “minimal zsh plugin manager that does what you expect.”
Important
After copying/pasting the install command for Zap, be sure to add the --keep
flag to prevent Zap from replacing you existing .zshrc
file.
Review the included Brewfile
and make desired adjustments.
less ~/Brewfile
Install the bundle.
brew bundle install
- Launch LazyVim (
nvim
) and run:checkhealth
. Resolve errors and warnings. Plugins should install automatically on first launch. - Add personal data as needed to
*.local
files such as~/.gitconfig.local
,~/.laptop.local
,~/dotfiles/local/config.fish.local
. - (Optional) Set up 1Password CLI for managing secrets.
- (Optional) Set up 1Password SSH key management.
- If using Fish, customize your setup by running the
fish_config
command. - Install Tmux plugins with
<prefix> + I
(https://github.com/tmux-plugins/tpm)
Having used both Zsh and Fish for several years, I’ve decided to keep my configs for both. One thing I particularly love about Fish is the concept of abbreviations over aliases. Happily, there is now zsh-abbr which brings this functionality to Zsh.
My Zsh and Fish configs have 95% functional parity via shared configuration:
- Same prompt (Starship)
- Identical abbreviations (250+) generated from single YAML source
- Shared environment variables
- Smart git functions with automatic branch detection
Zsh Setup Instructions
Zsh is now the default shell on macOS. However, it's helpful to add an entry enabling the Homebrew version of Zsh (`/opt/homebrew/bin/zsh` on Apple Silicon, `/usr/local/bin/zsh` on Intel) instead of the default (`/bin/zsh`) version.Ensure that you have Zsh from Homebrew. (which zsh
) If not:
brew install zsh
Add Zsh (Homebrew version) to /etc/shells
:
# Apple Silicon Macs:
echo /opt/homebrew/bin/zsh | sudo tee -a /etc/shells
# Intel Macs:
echo /usr/local/bin/zsh | sudo tee -a /etc/shells
# Or use this universal command:
echo $(which zsh) | sudo tee -a /etc/shells
Set it as your default shell:
chsh -s $(which zsh)
Install Zap. (Required for functional parity with Fish)
Restart your terminal.
Fish Setup Instructions
Install Fish from Homebrew: brew install fish
Add Fish to /etc/shells
:
# Apple Silicon Macs:
echo /opt/homebrew/bin/fish | sudo tee -a /etc/shells
# Intel Macs:
echo /usr/local/bin/fish | sudo tee -a /etc/shells
# Or use this universal command:
echo $(which fish) | sudo tee -a /etc/shells
Set it as your default shell:
chsh -s $(which fish)
Restart your terminal. This will create the ~/.config
and ~/.local
directories if they don’t already exist.
The dotfiles use a unified configuration system that eliminates duplication between Fish and Zsh shells:
shared/abbreviations.yaml
- Single source of truth for all 250+ abbreviationsshared/environment.sh
andshared/environment.fish
- Common environment variablesshared/generate-all-abbr.sh
- Unified script to regenerate abbreviations for all shellsshared/generate-fish-abbr.sh
andshared/generate-zsh-abbr.sh
- Individual shell-specific generation scripts
-
Edit
~/dotfiles/shared/abbreviations.yaml
-
Regenerate all abbreviations (from any directory):
reload-abbr # Available as a shell function - works from anywhere!
-
Reload your shell configuration:
- Fish:
exec fish
or open a new terminal - Zsh:
src
or open a new terminal
- Fish:
Alternative methods
Manual script execution:
cd ~/dotfiles/shared
./generate-all-abbr.sh # Updates both Fish and Zsh abbreviation files
Individual shell regeneration:
cd ~/dotfiles/shared
./generate-fish-abbr.sh # Updates fish/.config/fish/abbreviations.fish
./generate-zsh-abbr.sh # Updates zsh/.config/zsh-abbr/abbreviations.zsh
Important
Never edit the generated abbreviation files directly - changes will be overwritten!
The shared configuration includes intelligent git functions that automatically detect your main branch:
gpum
- Pull from upstream main/mastergrbm
- Rebase on main/mastergcom
- Checkout main/mastergbrm
- Remove branches merged into main/master
These functions work with both main
and master
branch names automatically.
This project includes comprehensive Claude Code integration for AI-assisted development workflows. Using Claude Code is completely optional - all dotfiles functionality works independently.
- Global CLAUDE.md - Project context and coding standards for AI assistance
- Custom slash commands - User-level commands for common development tasks
- Workflow automation - GitHub issue fixes, PR creation, code reviews, and more
Command | Description |
---|---|
/commit |
Create commits with clipboard workflow (no attribution) |
/commit-auto |
Create commits with full automation (includes attribution) |
/commit-msg |
Generate commit messages from staged changes |
/context-bridge |
Create session continuity documents for Claude Code |
/create-pr |
Generate comprehensive pull requests with smart issue linking |
/resolve-issue |
Systematic GitHub issue resolution workflow |
/review-pr |
Thorough pull request reviews with configurable depth |
/setup-scratch |
Initialize temporary workspace for development notes |
/new-project |
Comprehensive project setup (use after Claude Code's /init ) |
/update-deps |
Safe dependency updates with testing |
/save-knowledge |
Capture session insights into structured knowledge base |
/process-inbox |
Process web content into organized knowledge base entries |
/help |
Display available commands with usage examples |
- Install Claude Code: Follow the official quickstart guide
- Explore commands: Run
/help
in any terminal to see available commands - Learn more: Check the
claude/
directory for detailed command documentation
- Issue-to-PR workflows with automatic linking and proper GitHub integration
- Commit message standards following Conventional Commits format
- Scratchpad management for organized development notes and planning
- Cross-project consistency via global configuration and reusable commands
The Claude Code setup enhances but doesn't replace the core dotfiles functionality. Whether you use AI assistance or not, you'll have a fully functional development environment.
This repository includes comprehensive documentation for all shell functions and abbreviations to improve maintainability and user experience.
All 35+ shell functions are thoroughly documented with standardized inline comments and external reference guides:
- Function Overview - Complete index of all functions with descriptions and categories
- Git Functions - Smart git operations with automatic branch detection
- Development Tools - Development utilities, navigation shortcuts, and command wrappers
- Tmux Functions - Terminal multiplexer session management and workflows
- System Functions - System utilities, process management, and command enhancements
All 289 shell abbreviations are documented with usage examples and descriptions:
- Complete Abbreviations Reference - Comprehensive guide to all abbreviations across categories
- UNIX commands with enhanced options
- Git workflow shortcuts
- Development tool shortcuts
- Homebrew package management
- Docker, Rails, Node.js, and more
- Standardized Format: All functions include usage, arguments, examples, and return values
- Cross-Shell Consistency: Identical documentation quality in both Fish and Zsh
- Practical Examples: Real-world usage scenarios and workflow integration
- Cross-References: Links between related functions and abbreviations
Function Documentation: Manually maintained with standardized inline comments and reference guides.
Abbreviation Documentation: Fully automated! Generated from shared/abbreviations.yaml
:
# Regenerate everything (abbreviations + documentation)
reload-abbr
# Or manually from the dotfiles directory
~/dotfiles/shared/generate-all-abbr.sh
# Individual generators (for development)
~/dotfiles/shared/generate-fish-abbr.sh # Fish abbreviations only
~/dotfiles/shared/generate-zsh-abbr.sh # Zsh abbreviations only
~/dotfiles/shared/generate-abbreviations-doc.sh # Documentation only
What gets regenerated automatically:
fish/.config/fish/abbreviations.fish
(288 abbreviations)zsh/.config/zsh-abbr/abbreviations.zsh
(289 abbreviations)docs/abbreviations.md
(complete reference documentation)
After regeneration: Reload your shell (exec fish
or src
) to use new abbreviations.
This repository includes a complete markdownlint setup for consistent markdown formatting across all projects.
- Fallback Configuration Discovery: Automatically finds markdown config in multiple locations:
~/dotfiles/markdown/.markdownlint-cli2.yaml
(primary)PWD/markdown/.markdownlint-cli2.yaml
(project-specific)PWD/.markdownlint-cli2.yaml
(project root)- Falls back to legacy
.markdownlint.yaml
files for compatibility
- Global Wrapper Script:
markdown-validate
command available system-wide - Shell Abbreviations: Quick access via
mdl
/mdv
commands - Editor Integration: Works seamlessly with Neovim/LazyVim
- Auto-fix Coordination: Prettier → markdownlint-cli2 tool chain
# Install markdownlint-cli2 (if not already installed)
brew bundle install
# Lint files using abbreviations
mdl # Lint *.md files in current directory
mdlf # Auto-fix *.md files in current directory
mdla # Lint **/*.md files recursively
mdlaf # Fix **/*.md files recursively
# Global validation with dotfiles config
mdv # Detailed validation (markdown-validate)
mdvf # Validation with auto-fix
mdvq # Quick fix with minimal output
Markdown validation is integrated into the main validation workflow. For manual validation:
# Validate markdown files
./scripts/validate-config.sh --validator markdown --fix
# Use the global wrapper from any directory
markdown-validate --fix
- Dotfiles config: Edit
~/dotfiles/markdown/.markdownlint-cli2.yaml
- Project-specific: Create
markdown/.markdownlint-cli2.yaml
or.markdownlint-cli2.yaml
in project - Add abbreviations: Edit
~/dotfiles/shared/abbreviations.yaml
and runreload-abbr
- Global access: Use
markdown-validate
wrapper from any directory
Tip
TL;DR: Just install LazyVim💤
Back in the day if you wanted to use Vim (and later Neovim) you had to code a ton of configuration on your own. With Vim we got Vimscript 🤢, but then came Neovim which brought us Lua 🤩. I went from ye olde crunchy .vimrc
to the more adventurous init.vim
to the blessed path of init.lua
. 😇
Meanwhile, there were the VS Code boys across the fence, bragging about their fancy icons, shiny tabs, and the oh-so-cool LSP. I confess, I even tried VS Code for a bit. That didn't last long. 😬
But Neovim has caught up. And wow have they. caught. up. Not only do we have native LSP support in Neovim (have had for a while now — v0.5), but we are solidly in the era of pre-baked Neovim distributions that are really challenging the notion of Vim/Neovim as austere, command-line editors. (I will say that I think we owe a lot to VS Code for raising the bar here. But I'm still glad I'm with Neovim. 😉)
If you want a quick primer on Neovim distros, check out the YouTube video below. I started with LunarVim (my first entry into distro-land) and now I'm with LazyVim and the Folke gang. Bottom line: you can still config Neovim from scratch if you want to, but you can get a HUGE head-start by just grabbing a distro and tweaking it to your needs.
📺 I tried Neovim Distributions so you don't have to
Boy, when I reminisce about the days of writing PHP for Internet Explorer in BBEdit...
Over the years, I’ve branched out to explore a variety of mono-spaced fonts, both free and premium. Here is a list of my favorites.
Included in my Brewfile
and installed by default via Homebrew Cask Fonts
- Cascadia Code
- Fira Code
- Hack
- JetBrains Mono
- Monaspace Argon
- Monaspace Neon
- Symbols Nerd Font Mono (for icons only)
You have to give people money if you want these. 🤑
I first discovered ligatures through Fira Code, which IMHO is probably the king of programming fonts. After using Fira Code, it’s hard to go back to a sans-ligature typeface. Therefore all the fonts I’ve included in my fave’s list do include ligatures, although some have more than others.
Note
Operator Mono does not include ligatures but can be easily patched to add them.
Back in the day, I started using the VimDevicons plugin so I could have fancy file-type icons in Vim. (Remember NERDTree?) In order for this to work, one had to install patched “Nerd-font” versions of whatever programming font one wanted to use. For example:
# Original font
$ brew install --cask font-fira-code
# Patched variant
$ brew install --cask font-fira-code-nerd-font
Patching fonts with icons still works fine of course, and is, I think, pretty widely used. However, during my exploration of kitty, I discovered that there is a different (better?) approach to icon fonts. It turns out, you don't need a patched version of your chosen mono-spaced font. You can get most if not all the icons you need and use them alongside any font by just installing the Symbols Nerd Font Mono
font.
Leveraging this approach depends on your terminal. In iTerm2, for example, you need to check “Use a different font for non-ASCII text” in the Preferences panel. Then select Symbols Nerd Font Mono
font under “Non-ASCII font”. (see screenshot below)
kitty does things a little differently. If you install a patched font, it will mostly work. Mostly. But the “kitty way” can be broken down in three steps:
- Install a normal, un-patched mono-spaced font, such as
Cascadia Code
- Install a dedicated icon font, such as
Symbols Nerd Font Mono
- Create a set of Unicode symbol maps1 to tell kitty which font to use for which icons (symbols)
More work up front, maybe, but less guesswork in the long-term once you understand what's going on. And if you're using my dotfiles, you have it easy. All the fonts you need are installed in Brewfile
, and I have a set of Unicode symbol maps ready to go. 😎
Note
To learn more about Nerd fonts in terminals, as well as Unicode symbol maps and all the rest, be sure to check out Effective Nerd Fonts in Multiple Terminals by Elijah Manor
If you want to check whether icons and ligatures are working properly, try running the included nerd-font-smoke-test.sh
script from the root of the dotfiles
folder like so:
bash nerd-font-smoke-test.sh
If your terminal is configured correctly, the output of the test should look like this:
Again, thank you, Elijah Manor!
Once upon a time, I almost left Vim due to some crippling performance issues. These issues were particularly painful when editing Ruby files. I documented what I learned here:
▹ What I’ve learned about slow performance in Vim
The .zshrc
script can be profiled by touching the file ~/.zshrc.profiler
and starting a new login shell. To see the top 20 lines that are taking the most time use the zshrc_profiler_view
. zshrc_profiler
parameters are number of lines to show (20) and path to profiler log file ($TMPDIR/zshrc_profiler.${PID}log
).
- https://github.com/LazyVim/lazyvim
- https://github.com/LunarVim/LunarVim
- https://github.com/NvChad/NvChad
- https://github.com/LunarVim/Launch.nvim
- https://github.com/folke/dot
- https://github.com/nvim-lua/kickstart.nvim
- https://github.com/ThePrimeagen/init.lua
- https://github.com/elijahmanor/dotfiles
- https://github.com/cpow/cpow-dotfiles
- https://github.com/josean-dev/dev-environment-files
- https://github.com/glepnir/nvim
- https://github.com/numToStr/dotfiles
- https://github.com/jdhao/nvim-config
- https://github.com/brainfucksec/neovim-lua
- https://github.com/disrupted/dotfiles
- https://github.com/topics/neovim-dotfiles
- https://github.com/topics/neovim-config
- Pro Vim (https://github.com/Integralist/ProVim)
- Trevor Brown (https://github.com/Stratus3D/dotfiles)
- Chris Toomey (https://github.com/christoomey/dotfiles)
- thoughtbot (https://github.com/thoughtbot/dotfiles)
- Lars Kappert (https://github.com/webpro/dotfiles)
- Ryan Bates (https://github.com/ryanb/dotfiles)
- Ben Orenstein (https://github.com/r00k/dotfiles)
- Joshua Clayton (https://github.com/joshuaclayton/dotfiles)
- Drew Neil (https://github.com/nelstrom/dotfiles)
- Kevin Suttle (https://github.com/kevinSuttle/OSXDefaults)
- Carlos Becker (https://github.com/caarlos0/dotfiles)
- Zach Holman (https://github.com/holman/dotfiles/)
- Mathias Bynens (https://github.com/mathiasbynens/dotfiles/)
- Paul Irish (https://github.com/paulirish/dotfiles)
- http://dotfiles.github.io/
- https://medium.com/@webprolific/getting-started-with-dotfiles-43c3602fd789
- http://code.tutsplus.com/tutorials/setting-up-a-mac-dev-machine-from-zero-to-hero-with-dotfiles--net-35449
- https://github.com/webpro/awesome-dotfiles
- http://blog.smalleycreative.com/tutorials/using-git-and-github-to-manage-your-dotfiles/
- http://carlosbecker.com/posts/first-steps-with-mac-os-x-as-a-developer/
- https://mattstauffer.co/blog/setting-up-a-new-os-x-development-machine-part-1-core-files-and-custom-shell
Copyright © 2014–2025 Joshua Steele. MIT License