A comprehensive dotfiles setup for a modern development environment featuring Neovim, Fish shell, and Tmux with plugin management and LSP support.
- Neovim: Fully configured with LSP, autocompletion, Git integration, and modern plugins (managed by lazy.nvim)
- Fish Shell: Lightweight
simple.fishprompt, cross-machine history sync, aliases, and productivity functions - Tmux: Custom keybindings, mouse support, and a modular status bar with toggleable gadgets
- Cross-platform: Supports macOS, Linux (Arch, Debian/Ubuntu, Alpine, Fedora/RHEL, Gentoo), and FreeBSD
- Config Sets: Pick and choose which groups of config get deployed via an interactive
make pickydialog - Automated Setup: One-command installation via Makefile
makeThe setup will automatically detect your operating system and install all necessary packages and configurations.
To re-sync just the config file symlinks (without reinstalling packages or plugins):
make refreshTo interactively choose which config sets get deployed, then run the full install using that selection:
make pickyconfig/
sets/
basic/ # The default config set (today's dotfiles)
description # One-line blurb shown by `make picky`
manifest # Declares what gets deployed and where
vim/init.lua # Neovim configuration
fish/config.fish # Fish entrypoint (greeting + $EDITOR)
fish/aliases.fish # Shell aliases (deployed to conf.d/)
fish/functions.fish # Shell functions (deployed to conf.d/)
fish/envvars.fish # Environment variables (copied, per-machine)
tmux/tmux.conf # Tmux configuration
tmux/scripts/status.sh # Modular status bar renderer
tmux/scripts/status.conf # Status gadget list (copied, per-machine)
tmux/scripts/bluetooth-menu.sh # Bluetooth popup menu
kde/ # KDE Plasma keyboard repeat settings
description
manifest
os # "Linux" — hidden from `make picky` elsewhere
apply.sh
macos/ # macOS keyboard repeat settings
description
manifest
os # "Darwin" — hidden from `make picky` elsewhere
apply.sh
# further sets live alongside these, following the same layout
install-scripts/ # Numbered setup scripts run by the Makefile
lib/sets.sh # Shared helpers for discovering/enabling sets
pick-sets.sh # `make picky` — the dialog checklist
scripts/ # Misc helper scripts (e.g. Gentoo kernel upgrade)
tests/ # Dockerfiles used by CI to test installs per distro
Config files are grouped into sets under config/sets/<name>/:
basic— everything this repo has always deployed (Neovim, Fish, Tmux)kde— sets the KDE Plasma keyboard repeat rate to 50/s with a 250ms delay (viakwriteconfig5/6onkcminputrc)macos— sets the macOS keyboard repeat rate as fast as possible with the shortest delay (viadefaults write)
Each set is independent and additive — enabling kde or macos doesn't
disturb basic. kde and macos each declare an os file restricting
them to their platform, so make picky only offers kde on Linux and
macos on macOS in the first place; if one somehow ends up enabled on the
wrong OS anyway (e.g. a shared sets.conf), it's skipped with a warning
at deploy time instead of failing.
Run make picky to get an interactive checklist (space to toggle, enter to
confirm) of every set found under config/sets/. Confirming saves your
selection to ~/.config/dotfiles/sets.conf and immediately kicks off the
full install (packages, plugins, config deployment, last touches) using it
— the same steps make full-install runs. Cancelling (Esc) leaves your
existing selection untouched and stops there, without installing anything.
The saved selection is remembered by future make refresh / make full-install runs too, so you only need to pick once per machine. If
you've never run make picky, everything defaults to just basic,
matching this repo's historical behavior.
- Create
config/sets/<name>/. - Add a
manifestfile listing what to deploy, one entry per line:link some/file ~/.config/some/file copy some/per-machine ~/.config/some/per-machine link-glob scripts/*.sh ~/.local/bin/ run apply.shlinksymlinks (so edits at the destination flow back into the repo)copycopies only if the destination doesn't already exist (for per-machine files you don't want overwritten on re-runs)link-globsymlinks every file matching a glob into a destination directoryrunexecutes a script instead of deploying a file — for settings that aren't dotfiles, like the KDE/macOS keyboard repeat rate. It should exit 0 even when it can't apply anything (wrong OS/DE), so other enabled sets still get deployed; seeconfig/sets/kde/apply.shfor an example- Paths are relative to the set's own directory; destinations may use
~
- Optionally add a one-line
descriptionfile — shown next to the set's name in themake pickychecklist. - Optionally add an
osfile if the set only makes sense on certain platforms — oneuname -svalue per line (e.g.Darwin,Linux). Sets with anosfile are hidden frommake pickyon any other OS; sets without one are offered everywhere. Seeconfig/sets/macos/os/config/sets/kde/osfor examples.
The basic set is deployed by default; see Config Sets & make picky above for how to add or select other sets.
- Deployed to:
~/.config/nvim/init.lua(symlinked) - Purpose: Complete Neovim setup with modern IDE-like features
- Features:
- Plugin management with lazy.nvim (bootstraps itself on first launch)
- LSP support via Mason for Bash, Docker, Go, JSON, YAML, Python, and Lua
- Autocompletion with nvim-cmp
- File explorer (nvim-tree), fuzzy finding (fzf + Telescope), and diagnostics
- Git integration with fugitive and gitsigns
- Syntax highlighting with Treesitter
- Custom keybindings and the carbonfox colorscheme (nightfox.nvim)
- Deployed to:
~/.config/fish/config.fish(symlinked) - Purpose: Minimal Fish entrypoint
- Features:
- Silences the welcome greeting
- Sets
$EDITORtonvim
- Deployed to:
~/.config/fish/conf.d/aliases.fish(symlinked) - Purpose: Command aliases loaded automatically by Fish
- Features:
- OS-specific package manager aliases (
get,search) - Tooling aliases:
vim→ nvim,cat→ bat,ls→ eza,lg→ lazygit - Kubernetes shortcuts (
k,kp,kc) - Gentoo and PipeWire volume helpers
- OS-specific package manager aliases (
- Deployed to:
~/.config/fish/conf.d/functions.fish(symlinked) - Purpose: Custom shell functions
- Features:
- Bash-like
!!history expansion cheatlookup against cht.shgitissuehelper to branch off a freshmaster
- Bash-like
- Deployed to:
~/.config/fish/conf.d/envvars.fish(copied, not symlinked) - Purpose: Per-machine environment variable definitions
- Note: Only copied if it doesn't already exist, so local customizations are preserved
- Deployed to:
~/.tmux.conf(symlinked) - Purpose: Tmux terminal multiplexer configuration
- Features:
- Custom prefix key (Ctrl+A)
- Alt-based keybindings for panes, windows, and resizing
- Mouse support enabled
- Truecolor passthrough
- Modular status bar driven by
status.sh - Bluetooth popup menu bound to
prefix + b - Plugin management with TPM (tpm, tmux-better-mouse-mode)
- Deployed to:
~/.tmux/scripts/(.shsymlinked,status.confcopied) - Purpose: Render the status bar and power the Bluetooth menu
- Features:
status.sh: renders gadgets (WLAN, Bluetooth, battery, CPU, memory, temperature, disk) cross-platform (macOS + Linux)status.conf: lists the enabled gadgets and their order — comment out a line to disable a gadget (copied per-machine so local edits stick)bluetooth-menu.sh: interactive Bluetooth device menu
The Makefile's full-install target runs 7 sequential scripts for a complete setup:
Installs essential packages based on your OS:
- Common packages: tmux, neovim, git, fish, curl, bat, go, eza, ripgrep, lazygit
- macOS: Uses Homebrew (installs it first if missing)
- Arch Linux: Uses pacman, installs the yay AUR helper, and installs
cronie(cron daemon) for the hourly pacman sync job set up in07-last-touches.sh - Debian/Ubuntu: Uses apt (
go→golang, skips lazygit) - Alpine: Uses apk
- Fedora/RHEL/CentOS: Uses dnf (skips curl and lazygit)
- FreeBSD: Uses pkg
- Gentoo: Uses emerge (
git→dev-vcs/git)
Deploys each enabled config set (basic by default, or whatever was chosen
via make picky) by walking its manifest:
- Creates any destination directories on the fly
- Symlinks most files into place, so edits to the live config flow straight back to the repo
- Copies (rather than symlinks) per-machine files like
envvars.fishandstatus.conf, and only if they don't already exist
Installs Fisher, the Fish shell plugin manager
Installs Fish plugins:
- simple.fish: a minimal, fast prompt
- history-sync.fish: keeps shell history in sync across sessions/machines
Sets up Tmux plugin management:
- Installs TPM (Tmux Plugin Manager) if missing
- Installs/updates configured plugins (tmux-better-mouse-mode)
With lazy.nvim no manual bootstrapping is required — plugins and LSP servers install automatically the first time Neovim launches. This script is kept as a placeholder for future setup steps.
Completes the setup:
- Adds Fish to
/etc/shells - Changes the default shell to Fish
- Creates
~/binfor personal scripts - On Gentoo, installs the appropriate kernel-upgrade helper (OpenRC or systemd)
- On Arch, enables the cron daemon and installs an hourly
sudo pacman -Syycron job for the current user; if that user isn't root, grants them passwordless sudo (/etc/sudoers.d/99-<user>-nopasswd) so the unattended job can actually run
If you prefer manual installation or want to customize the process:
- Install packages manually: Check
install-scripts/01-install-packages.shfor your OS - Copy config files:
# Neovim mkdir -p ~/.config/nvim ln -sf "$PWD/config/sets/basic/vim/init.lua" ~/.config/nvim/init.lua # Fish mkdir -p ~/.config/fish/conf.d ln -sf "$PWD/config/sets/basic/fish/config.fish" ~/.config/fish/config.fish ln -sf "$PWD/config/sets/basic/fish/aliases.fish" ~/.config/fish/conf.d/aliases.fish ln -sf "$PWD/config/sets/basic/fish/functions.fish" ~/.config/fish/conf.d/functions.fish cp "$PWD/config/sets/basic/fish/envvars.fish" ~/.config/fish/conf.d/ # Tmux ln -sf "$PWD/config/sets/basic/tmux/tmux.conf" ~/.tmux.conf mkdir -p ~/.tmux/scripts ln -sf "$PWD"/config/sets/basic/tmux/scripts/*.sh ~/.tmux/scripts/ cp "$PWD/config/sets/basic/tmux/scripts/status.conf" ~/.tmux/scripts/
- Run individual scripts: Execute scripts in
install-scripts/directory in order
- Internet connection for downloading packages and plugins
- Sudo access for package installation
- Git for cloning repositories
After installation:
- Restart your terminal or run
exec fishto start using Fish shell - Start tmux with
tmuxto use the enhanced terminal multiplexer - Open Neovim with
nvimto verify plugin installation - Customize: Edit config files to suit your preferences
All configuration files are designed to be easily customizable:
- Add Fish aliases: Edit
config/sets/basic/fish/aliases.fish - Add Fish functions: Edit
config/sets/basic/fish/functions.fish - Modify Neovim plugins: Edit
config/sets/basic/vim/init.lua - Change Tmux keybindings: Edit
config/sets/basic/tmux/tmux.conf - Toggle status bar gadgets: Edit
~/.tmux/scripts/status.conf - Add environment variables: Edit
~/.config/fish/conf.d/envvars.fish
- Permission errors: Ensure you have sudo access
- Package not found: Check if your OS is supported in the install scripts
- Plugin installation fails: Run individual scripts manually to identify issues
- Shell not changed: Log out and back in, or restart your terminal
This repository includes automated testing via GitHub Actions to ensure the dotfiles installation works correctly across multiple Linux distributions.
When you submit a pull request, the following automated checks run:
-
Multi-distro Testing: The installation is tested on:
- Alpine Linux
- Arch Linux
- Fedora
- Ubuntu
- macOS
-
Docker-based Testing: Each Linux distribution test runs in a containerized environment using Docker Buildx with QEMU for cross-platform compatibility
-
Native Testing: macOS has no equivalent official container image, so it runs the full install directly on a hosted
macos-latestrunner instead -
Build Verification: The GitHub Action (
pr-test.yml) verifies that the dotfiles can be successfully built on each supported platform, and that the install actually landed (symlinks in place, fish functions loaded) — not just that the install command exited 0
The PR testing workflow:
- Triggers on pull requests to
masterormainbranches - Uses a matrix strategy to test against multiple Linux distributions, plus a separate macOS job
- Sets up QEMU and Docker Buildx for multi-platform Linux testing
- Builds the dotfiles installation in each distribution's container, and runs the full install natively on macOS
This ensures that changes don't break compatibility with any supported operating system before they're merged.
Please don't contribute.