This repo is designed to manage dotfiles with GNU Stow.
Stow allows you to easily manage collections of symlinks, which is perfect for dotfiles.
This repo stores multiple configurations, each for a particular program or collections of tightly integrated programs (such as hyprland, hyprlock, hypridle and hyprpaper, which are all included in the hyprland configuration).
The configurations are stored in separate directories in the root of the repo. You "install" a configuration by running stow <config dir name> from within the repo, which will create symlinks for all files in the specified directory in the target directory. Each configuration's directory is structured to mirror a home directory with the expectation that your own home directory is the target.
Note that Stow's default target is actually the parent directory of the current working directory, so it's easiest to clone this repo directly into your home directory. Otherwise you'll need to include the --target $HOME flag in your stow commands to specify your home directory as the target. Your choice :)
-
Install GNU Stow
-
Clone this repo to your home directory
-
Install configurations with
stow <configuration directory name>. For example:stow neovim # Symlinks everything in 'neovim' directory stow git # Symlinks everything in the 'git' directory
You can install multiple packages at once:
stow neovim zsh git alacritty # Symlinks everything in the 'neovim', 'zsh', 'git' and 'alacritty' directories
A modern configuration of Neovim, requiring at least 0.12.x as it uses the new built-in vim.pack package manager.
It uses Mason for installing LSPs, unless NEOVIM_USE_MASON is set to false, in which case Mason will not be configured or used at all. In that case, you'll need to manually install any tools you wish to use.
It also supports an HTTP proxy URL to be set via the NEOVIM_HTTP_PROXY environment variable. This allows the same config to be used on corporate machines that require an HTTP proxy for any web fetch requests, such as for fetching schemas for YAML LS and JSON LS.
A separate LazyVim distribution install at ~/.config/lazyvim/. This was what I was using while I learnt Neovim, before writing my own config from scratch.
Customisations from the OOTB LazyVim experience include:
- Replaces the large LAZYVIM ASCII header with "Welcome"
- Dashboard shows root/CWD, git status, git log, and Neovim/LazyVim versions
- Sets conceal level to zero — this was extremely annoying when writing Markdown
- Explorer shows hidden files with normal font colour; git-ignored files appear greyed out
- Files picker shows hidden files but not git-ignored files
<leader>l*keymaps for Lazy, LazyHealth, config, and extras- Opens the Snacks dashboard when the last buffer is deleted
- Git blame in ghost text on the current line
- Sidekick for AI-assisted programming (via LazyVim extra)
- Language extras: Go, PHP, Python, TypeScript, Terraform, Docker, JSON, TOML, Tailwind, and more
- Disables inlay hints by default
This can be launched with NVIM_APPNAME=lazyvim nvim, or lazyvim if the ZSH config from this repo is being used.
Managing multiple installations of Neovim can be messy if not done properly. If things get messy you can clear all installed plugins and their cache like so:
rm -r ~/.local/share/nvim
rm -r ~/.local/state/nvim
rm -r ~/.cache/nvimAlacritty expects the Fira Code Nerd Font to be installed and available.
NOTE: This will be different on MacOS
- Download the Fira Code Nerd Font
https://github.com/ryanoasis/nerd-fonts/releases/download/v3.4.0/FiraCode.zip
- Create a fonts directory (if it doesn't exist):
# For system-wide
sudo mkdir -p /usr/local/share/fonts/nerd-fonts/FiraCode
# For your user only
mkdir -p ~/.local/share/fonts/FiraCode-
Copy or move the font files (e.g., .ttf or .otf) into that directory.
-
Grant correct permissions if system-wide:
sudo chown -R root: /usr/local/share/fonts/nerd-fonts/FiraCode
sudo chmod 644 /usr/local/share/fonts/nerd-fonts/FiraCode/*- Rebuild the font cache
fc-cache -fv- Verify the font is installed
fc-list | grep -i "FiraCode"To make ZSH your default shell, run the following. Note that if you use sudo, it will change the default shell for the root user instead of your user.
chsh -s $(which zsh)ZSH expects that the following plugins are cloned to ~/.zsh/*.
git clone https://github.com/zsh-users/zsh-autosuggestions.git ~/.zsh/zsh-autosuggestions
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ~/.zsh/zsh-syntax-highlighting
git clone https://github.com/zsh-users/zsh-history-substring-search.git ~/.zsh/zsh-history-substring-searchIt also sources ~/.zsh/extra.zsh for host-specific additional config, aliases, functions, etc. Example snippets I put in extra.zsh on some machines:
Start SSH agent:
if [ -z "$SSH_AUTH_SOCK" ]; then
# Check for a currently running instance of the agent
RUNNING_AGENT="`ps -ax | grep 'ssh-agent -s' | grep -v grep | wc -l | tr -d '[:space:]'`"
if [ "$RUNNING_AGENT" = "0" ]; then
# Launch a new instance of the agent
ssh-agent -s &> $HOME/.ssh/ssh-agent
fi
eval `cat $HOME/.ssh/ssh-agent`
fiSet keyboard brightness on the Lenovo laptop:
brightnessctl --device='platform::kbd_backlight' set 1Similar to how ZSH sources ~/.zsh/extra.zsh (which is not committed) for host-specific config, the Git config points to a ~/.gitconfig.local file for any additional host-specific or sensitive Git config you'd like to apply, such as GPG config. Create this file to use it as it's not committed.
The global config sets EDITOR=vim, uses main as the default branch, rebases on pull, and includes a global gitignore for editor and OS junk files.
- Requires
GITHUB_PERSONAL_ACCESS_TOKENfor the GitHub MCP server - Shared config lives in
~/.config/opencode/opencode.jsonc(stowed). For host-specific extras, create~/.config/opencode/local.jsonc(not committed)- ZSH sets
OPENCODE_CONFIGto that path so OpenCode deep-merges it on top of the shared config. Verify withopencode debug config.
- ZSH sets
For machine-specific config variations, create a local config overlay file at .config/opencode/local.jsonc. ZSHRC sets and env var (OPENCODE_CONFIG) that points to this location so OpenCode knows to deep-merge any config found here into the base config.
An example local config overlay file:
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"external_directory": {
"$HOME/work/**": "allow"
}
},
"mcp": {
"atlassian": {
"enabled": true
},
"context7": {
"enabled": true,
"headers": {
"CONTEXT7_API_KEY": "{env:CONTEXT7_API_KEY}"
}
}
}
}Final config can be verified with opencode debug config.
# Disable the hold key for accented alternatives
defaults write -g ApplePressAndHoldEnabled -bool false