This repository contains my personal dotfiles configuration for macOS, featuring thoroughly tailored setups for NeoVim and Zsh with performance in mind.
| Neovim (Kitty) | Zsh + tmux (Alacritty) |
|---|---|
![]() |
![]() |
$ curl -L dotfiles.creasty.com/provision | bashIt clones this repository to ~/dotfiles, installs Homebrew and Nix, and applies the nix-darwin configuration of flake.nix for the current user, home-manager included.
To apply changes later, provision again:
$ ~/dotfiles/provisionIt skips what's already installed, and pulls master first unless the checkout is on another branch or has changes of its own.
Then it switches to the configuration and verifies the result.
Flakes only see files tracked by git, so git add a new file first.
Files are linked into the home directory by where they are in the repository, with no list to maintain:
| Repository | Home directory |
|---|---|
home/<path> |
~/.<path> (home/aws/config → ~/.aws/config) |
config/<path> |
~/.config/<path> (config/git/config → ~/.config/git/config) |
The Nix modules link the rest: nvim/, the shell files and VS Code's settings.
Links point into the checkout, so edits apply without a rebuild.
Homebrew Bundle installs the App Store apps of nix/modules/appstore.nix with mas, which asks for your password (sudo) to install them.
mas can't sign in to the App Store, so sign in before provisioning.
mas list shows the IDs of installed apps, and mas search <name> those of others.
mas can't install iPhone and iPad apps, such as Kindle's, so get those from the App Store app.
ssh signs in through 1Password's SSH agent, so private keys live in 1Password instead of ~/.ssh.
Keep a host's public key in ~/.ssh/keys and point its IdentityFile at it (in ~/.ssh/config.d/) to pick the key.
Provisioning ends by verifying its result with behavioral tests: shells are started the way terminals start them, and have to find the right runtimes, configs and commands. To verify a machine again:
$ ./verify
$ ./verify --filter java # options go to batsThe tests compare the machine with what the activated configuration lists in /etc/dotfiles/manifest.json.
Set DOTFILES_NOVERIFY=1 to provision without verifying.
bin/: Custom executable scripts and commands (Added to systemPATH)config/*: XDG-compliant configuration files (linked into~/.config)home/*: Home directory dotfiles (linked into~with a leading dot)nvim/: Neovim configurationstests/: End-to-end workflow tests (README)
shell/: Shell environment configurationsbash/*: Bash-specific configurationszsh/*: Zsh-specific configurations
vscode/: VS Code settings and keybindings
docs/: Setup documentation and resourcesflake.nix,nix/modules/: The nix-darwin configuration, a module per topictest/: Behavioral tests of the provisioning
| nvim | zsh | |
|---|---|---|
| Startup time | ~60ms | ~72ms |
| Config size | 2,900 sloc | 700 sloc |
| Original plugins | 10 plugins | 1,100 sloc of bin |
| Third-party plugins | 36 plugins | 2 plugins + 2 hooks |
Original plugins:
- mold.vim
- opfmt
- auto_save.vim
- better_tagfunc.vim
- blockwise_visual_insert.vim
- emacs_cursor.vim
- file.vim
- next_file.vim
- project_dir.vim
- restore_buffer.vim
Third-party plugins (excerpt):
- nvim-lspconfig, for Neovim's built-in LSP client
- blink.cmp
- LuaSnip
- snacks.nvim (its picker)
- nvim-autopairs
- copilot.lua
- conform.nvim, nvim-lint, gitsigns.nvim
- nvim-treesitter
Details
$ hyperfine --warmup 3 --prepare 'sleep 0.1' 'nvim --headless -c quit'
$ cloc --exclude-dir=dein,template nvim
$ rg '^repo\b.+\bcreasty/' nvim/dein/*.toml
$ rg --no-heading '^\[\[plugins' nvim/dein/*.toml | wc -lProfiling:
$ nvim --headless --startuptime /dev/stdout -c quitThird-party plugins/hooks:
Details
$ hyperfine --warmup 3 --prepare 'sleep 0.1' 'zsh -i -c exit'
$ cloc --exclude-dir=plugins,bash --lang-no-ext=zsh shell
$ cloc bin
$ ls shell/zsh/plugins | wc -lProfiling:
$ ZSH_PROF_ENABLED=1 zsh -i -c exitYuki Iwanaga / @creasty


