Personal dotfiles for Linux, managed with Nix + home-manager. One repo, one command, and any Linux machine ends up configured the same way.
Windows hosts (e.g. the wezterm side of a WSL setup) are still handled by the PowerShell installer - see Windows.
Running the switch builds:
- Nix user packages (ripgrep, fd, fzf, jq, lazygit, Neovim, tmux, git, ranger)
- Tools installed outside Nix so they track upstream releases instead of nixpkgs: the coding agents claude-code / codex / opencode / pi via their native installers, no-mistakes, treehouse, gh-axi, their agent skills, their herdr integrations, and herdr as the prebuilt binary from its GitHub releases
- Neovim's toolchain deps from Nix (gcc, make, nodejs, unzip) so treesitter, telescope, and Mason's language servers have what they need. LSP servers and formatters themselves are still managed by Mason inside Neovim - see Neovim
- Shell (zsh, aliases, autosuggestions, syntax highlighting, starship prompt)
- Editor (Neovim config, based on kickstart.nvim, under
home/.config/nvim) - Terminal (WezTerm config)
- tmux (config + the agent-status daemon scripts)
- Agent config (
home/AGENTS.md, symlinked to Claude, Codex, and opencode) - Nerd Fonts (JetBrains Mono, Hack)
- Distro-agnostic. This is standalone home-manager, not NixOS and not
nix-darwin. It runs on any Linux distribution (Ubuntu, Fedora, Arch, Debian,
WSL, ...) without touching the system package manager. Nothing here calls
apt/dnf/pacman. - Stable by default.
flake.nixpins nixpkgs and home-manager to the current stable NixOS release (nixos-26.05/release-26.05). To upgrade, bump both branch numbers together and run./install.sh. - Edit-in-place. The real config files live under
home/.home.nixusesmkOutOfStoreSymlinkto point~/.config/nvim,~/.config/wezterm,~/.config/tmux,~/.config/herdr, and~/.tmux.confstraight at this repo, so editing a file here edits your live config with no rebuild. You only run./install.shwhen you change something that isn't a symlinked file, like a package list or a shell setting. - One idempotent script. There is a single
install.sh. Run it to set a machine up, and run it again any time to apply changes. Every step is guarded (nix install, repo symlink, TPM clone, login shell) so re-running is a no-op where nothing changed - the same command works on a fresh box and on day 200.
From a bare clone:
git clone https://github.com/knowttl/dotfiles.git
cd dotfilesBefore the first run, open the config and change the values in Make it yours (username and home path at minimum). Then, now and every time after:
./install.sh(There's also a rebuild shell alias that runs the same script.)
Run ./install.sh --update to update all flake inputs.
After a successful update, the installer asks whether to commit and push the
resulting flake.lock change.
The default is no, and automatic publishing is skipped when flake.lock had
pre-existing changes or the installer is running non-interactively.
On a fresh machine install.sh, in order:
- Installs Determinate Nix if missing (distro-agnostic installer).
- Symlinks this repo to
~/.dotfiles(themkOutOfStoreSymlinkpaths inhome.nixresolve through here, so it must exist before the build). - Clones TPM (tmux plugin manager) into
~/.tmux/plugins/tpmif missing. - Runs
home-manager switch(from the flake on first run, via the installed CLI after that). - Best-effort sets the nix
zshas your login shell (/etc/shells+chsh) if it isn't already. Skipped gracefully if it can't; the manual command is printed.
On later runs the guarded steps are skipped and it just re-applies the config. Open a new terminal after the first run so zsh and the new PATH take effect.
Once Nix is installed you can check the config builds without touching your system:
nix flake check
nix build --impure .#homeConfigurations.default.activationPackage --dry-run- Username and home path are taken from
$USER/$HOMEat switch time (home.nixreads them viabuiltins.getEnv, which is whyinstall.shpasses--impure). Nothing to edit for a different user or host. - Git identity in
home.nix(knowttl/knowttl42@gmail.com). - Agent policy
home/AGENTS.mdstarted as the template author's personal instructions and is symlinked to Claude / Codex / opencode. Edit it to your own preferences. - CPU architecture
systeminflake.nix-x86_64-linuxby default; useaarch64-linuxon ARM.
claude-code, codex, and opencode are fast-moving and unfree
(allowUnfree = true is set in flake.nix). If a future stable release is
missing one of these attributes, the build fails on exactly that line - just
remove it from home.packages in home.nix, or pull only that tool from an
nixpkgs-unstable overlay while keeping everything else on stable.
The Neovim config is based on kickstart.nvim and keeps Mason to manage LSP servers and formatters (pyright, lua_ls, clangd, stylua, ...) from inside the editor. Nix's job is only to provide the tools those depend on, so Mason and the plugins have a working environment:
gcc+gnumake- treesitter compiles parsers on first launch; fzf-native builds withmakenodejs- runtime for node-based servers Mason installs (e.g. pyright)unzip- Mason unpacks some release archives with itripgrep+fd- telescope live-grep and file finding
Manage language servers with :Mason inside Neovim as usual. Note Mason
installs dynamically-linked prebuilt binaries, so it works on glibc distros
(Ubuntu, Fedora, Arch, ...) but not on NixOS - there you'd switch those servers
to Nix packages instead.
For a WSL setup, wezterm runs on the Windows host and reads its config from the Windows home directory. That side is installed with PowerShell:
.\install.ps1It symlinks the shared home/.config/wezterm/wezterm.lua (and the background
image and herdr config) into the Windows home dir, and skips Linux-only files
like .tmux.conf. Windows may require Developer Mode or an elevated shell for
symlinks; the installer falls back to hard links otherwise.
- The first time you launch
nvim, it bootstraps lazy.nvim by cloning plugins from GitHub. That needs network access once; after that it's offline. - After bootstrap, start tmux and press
prefix + Ito install the tmux plugins declared in.tmux.confvia TPM. - Do not commit secrets or machine-specific credentials to this repository.