by joshukraine
:round_pushpin: My dotfiles for macOS using Neovim, Zsh, and Ghostty + Tmux
# Add to your Claude Code skills
git clone https://github.com/joshukraine/dotfiles![dotfiles screenshot][screenshot]
[!NOTE] This project previously supported [Fish shell][fish] alongside Zsh. Fish support was removed in [PR #135][pr-135] (
f158de9). If you were using the Fish configuration, you can reference that PR to see what changed or recover code for your own setup.
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
The dotfiles assume you are running macOS with (at minimum) the following software pre-installed:
No comments yet. Be the first to share your thoughts!
All of the above and more are installed with my fork of [Laptop][joshuas-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:
▹ [github.com/joshukraine/laptop][joshuas-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:
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][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][zap] describes itself as a "minimal zsh plugin manager that does what you expect."
▹ [zapzsh.com][zap]
[!IMPORTANT] After copying/pasting the install command for Zap, be sure to add the
--keepflag to prevent Zap from replacing you existing.zshrcfile.
Review the included Brewfile and make desired adjustments.
less ~/Brewfile
Install the bundle.
brew bundle install
nvim) and run [:checkhealth][checkhealth]. Resolve errors and warnings. Plugins should install automatically on first launch.*.local files such as ~/.gitconfig.local, ~/.laptop.local.<prefix> + I (https://github.com/tmux-plugins/tpm)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][zap].
Restart your terminal.
One of the best ideas I picked up from using Fish shell is abbreviations over aliases. [zsh-abbr][zsh-abbr] brings this functionality to Zsh.
Abbreviations are managed directly in zsh/.config/zsh-abbr/abbreviations.zsh. You can edit this file directly, or use the abbr add/abbr remove commands in your shell.
The configuration includes intelligent git functions that automatically detect your main branch:
gpum - Push current branch to origin with upstream trackinggrbm - Rebase on main/mastergcom - Checkout main/mastergbrm - Remove branches merged into main/masterThese functions work with both main and master branch names automatically.
[Claude Code][claude-code] is Anthropic's CLI tool for AI-assisted development. This repo includes a full configuration under the claude/ directory, stowed to ~/.claude/.
[!TIP] Claude Code can also run inside Neovim via the [claude-code.nvim][claude-code-nvim] plugin, which is how I use it most of the time during development.
Custom [skills][agent-skills] provide structured workflows for the full development lifecycle:
| Skill | Purpose |
| ----- | ------- |
| /bootstrap-prd | Scaffold PRD-driven development infrastructure into a new project |
| /checkpoint | Quick status update — what's done, in progress, and blocked |
| /commit | Analyze diffs, split into logical commits, Conventional Commits format |
| /create-pr | Create a PR with auto-linked issues and formatted description |
| /debrief | Comprehensive walkthrough of recent work with architecture rationale |
| /plan-phase | Draft implementation plan and create GitHub issues (no code written) |
| /qa-handoff | Prepare a hands-on QA testing guide for a completed PRD phase |
| /resolve-issue | Structured workflow for resolving a GitHub issue end-to-end |
| /review-pr | Read-only PR review with severity-ranked findings |
| /setup-sprint | Create parallel Git worktrees for a batch of labeled issues |
| /sprint-issue | Streamlined variant for small, well-scoped issues |
| /update-deps | Safe dependency updates with testing between each category |
Composable permission presets control what Claude Code is allowed to do in each project. A base preset covers universal operations (git, file editing, Unix tools), and framework overlays add project-specific tooling.
cc-rails # base + Rails overlay
cc-hugo # base + Hugo overlay
cc-js # base + JavaScript/Node overlay
cc-dotfiles # base + dotfiles overlay
cc-sprint # all-inclusive sprint preset
cc-default # base only
cc-clean # remove project settings
cc-perms # show active permission counts
Presets live in claude/.claude/presets/ with a [README][presets-readme] explaining the design.
rm -rf patterns and log all Bash commandssudo, and credential readsZsh abbreviations for quick access (via [zsh-abbr][zsh-abbr]):
| Abbreviation | Expands to |
| ------------ | ---------- |
| cl | claude |
| clr | claude --resume |
| clc | claude --continue |
| clup | claude update |
See zsh/.config/zsh-abbr/abbreviations.zsh for the full set (clsp, clh, clv, clp, clcp, clmcp).
CLAUDE.md — Global development philosophy and coding standards applied across all projectscheatsheet.md — Quick reference for keyboard shortcuts, commands, and context management tipsstarship.toml — Custom [Starship prompt][starship-claude] showing model, context window status, and token cost.mcp.json — [Context7][context7] MCP server for querying up-to-date library documentation[!TIP] TL;DR: Just install [LazyVim][lazyvim]💤
📺 [Zero to IDE with LazyVim][zero-to-ide-lazyvim-video]
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