Skip to content

Customization Guide

How to personalize your dotfiles without modifying synced files.


Overview

This setup supports machine-specific customization through local override files. These files:

  • Are sourced by the main config files
  • Are not tracked in git (listed in .gitignore)
  • Allow per-machine customization without merge conflicts

Deployment Modes

This repository supports different deployment scenarios based on your environment.

Full System Setup

Use case: Personal workstations, development machines

What's included: - All dotfiles (shell configs, git hooks, editor settings) - System package installation via run_once scripts - CLI tool installation via mise (Node, Python, Rust, etc.) - Shell plugin installation (Antidote, tmux plugins)

How to deploy: Use scripts/bootstrap or mise run install


Dotfiles Only

Use case: Servers, containers, shared systems, read-only environments

What's included: - All dotfiles (shell configs, git hooks, editor settings) - No system package installation - No mise tool installation (assumes tools already present)

What's excluded: - run_once_before_01-install-packages.sh.tmpl (system packages) - provision/ directory (Windows/platform provisioning) - mise-tasks/ (automation scripts) - tests/ and .github/ (development files)

How to deploy:

chezmoi init --apply jerdaw/dotfiles --exclude "run_once_*"

Sparse checkout (minimal clone):

git clone --filter=blob:none --sparse https://github.com/jerdaw/dotfiles ~/.local/share/chezmoi
cd ~/.local/share/chezmoi
git sparse-checkout set 'dot_*' '.chezmoi*'
chezmoi apply --exclude "run_once_*"


Customizing Deployment

Skip specific files:

chezmoi apply --exclude "**/nvim/**"  # Skip Neovim config

Dry run (preview changes):

chezmoi apply --dry-run --verbose

Interactive mode (approve each change):

chezmoi apply --interactive


Local Override Files

Shell Configuration

Override File Sourced By Purpose
~/.zshrc.local ~/.zshrc Machine-specific shell config
~/.bashrc.local ~/.bashrc Machine-specific Bash config
~/.secrets ~/.zshrc and ~/.bashrc API keys, tokens, private env vars

Example: ~/.zshrc.local

# Work laptop specific
export WORK_PROJECT_DIR="$HOME/work/projects"
alias vpn='sudo openconnect vpn.company.com'

# Use a different node version here
eval "$(mise activate zsh)"
mise use node@18

Secrets Management

The ~/.secrets file stores API keys, tokens, and private environment variables.

Option A: Manual Setup (unencrypted, gitignored):

cp ~/repos/dotfiles/dot_secrets.example ~/.secrets
nvim ~/.secrets

Option B: Encrypted Secrets (recommended, safe to commit):

mise run setup-secrets
This script: 1. Generates an age key at ~/.config/chezmoi/key.txt. 2. Re-runs chezmoi init, which automatically detects the key and enables encryption in your configuration. 3. Encrypts ~/.secrets to encrypted_dot_secrets.age.

How it works: - Sourced automatically by ~/.zshrc on shell startup. - If using encryption: decrypted by chezmoi during apply. - Template Logic: Encryption settings are managed in .chezmoi.toml.tmpl. If key.txt exists, encryption is ON; if missing, it's OFF.

Caution

Never commit ~/.secrets to version control. The file is already in .gitignore, but always double-check before committing.


Git Configuration

Git supports includes for local configuration:

~/.gitconfig (already configured)

[include]
    path = ~/.gitconfig.local

Global Gitignore

This setup uses a global gitignore file at ~/.gitignore_global to hide "system junk" (like .DS_Store, __pycache__, or editor swap files) from all your repositories automatically.

  • Synced file: dot_gitignore_global
  • Local overrides: Add to a project .gitignore or create ~/.gitignore_local.

To add your own global ignores that you don't want synced, you can create a ~/.gitignore_local and add it to your ~/.gitconfig.local:

[core]
    excludesfile = ~/.gitignore_local


~/.gitconfig.local (create this)

# Work machine identity
[user]
    email = yourname@company.com
    signingkey = ABC123...

# Company-specific settings
[url "git@github.company.com:"]
    insteadOf = https://github.company.com/

Theme Customization

Powerlevel10k

Run the configuration wizard:

p10k configure

This updates ~/.p10k.zsh. To keep the same theme across machines, this file is synced. For machine-specific tweaks, edit ~/.zshrc.local:

# Override p10k settings
typeset -g POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(
  dir vcs newline prompt_char
)

Bat Theme

Set in mise.toml:

[env]
BAT_THEME = "Dracula"

View available themes:

bat --list-themes

Override in ~/.zshrc.local for a different machine:

export BAT_THEME="Solarized (light)"

Tinty (Theme Manager)

Tinty manages themes across shell, fzf, bat, tmux, and more.

Select a Theme:

tinty apply base16-dracula

List Available Themes:

tinty list

Customize Configuration: Edit ~/.config/tinted-theming/tinty/config.toml to change which tools are themed or default schemes.

FZF Colors

FZF colors are set via $FZF_DEFAULT_OPTS. Override in mise.toml:

[env]
FZF_DEFAULT_OPTS = "--color=light"

Adding Personal Tools

Create ~/.config/mise/config.local.toml:

[tools]
go = "latest"
rust = "stable"

Then add to ~/.zshrc.local:

eval "$(mise activate zsh)"

Option 2: Modify mise.toml (for tools you want on all machines)

Edit the synced mise.toml:

[tools]
# ... existing tools ...
"github:some/newtool" = "latest"

Then update docs: 1. Add entry to docs/TOOLS.md 2. Add to README tools table 3. Update CHANGELOG.md


Disabling Features

Disable Smart Wrappers

If you want ps/df/du to always use standard commands, add to ~/.zshrc.local:

# Restore original commands
unfunction ps df du top htop 2>/dev/null

Disable Specific Aliases

# In ~/.zshrc.local
unalias rm  # Remove the safety alias

Disable Vi Mode

# In ~/.zshrc.local
bindkey -e  # Use emacs mode instead

Directory-Specific Configuration

Use direnv for per-project environment variables:

cd ~/projects/myproject
echo 'export DATABASE_URL="postgres://..."' > .envrc
direnv allow

Now DATABASE_URL is set only when you're in that directory.


WSL-Specific Customization

The dotfiles automatically detect WSL and enable appropriate aliases. For more advanced control, WSL uses two primary configuration files:

.wslconfig (Global Settings)

Configures the WSL 2 virtual machine itself (RAM, CPUs, network, timeouts). Located on the Windows host at %UserProfile%\.wslconfig.

  • Keep-Alive: This setup sets vmIdleTimeout=-1 in dot_config/wsl/wslconfig.example to prevent WSL from shutting down automatically.
  • Provisioning: The mise-tasks/setup/provision/windows/install.ps1 script automatically copies this to your user profile if it doesn't exist.

wsl.conf (Per-Distro Settings)

Configures settings for the specific Linux distribution (systemd, automounts, interop). Located at /etc/wsl.conf inside Linux.

  • Systemd: Enabled by default in this setup for better service support.
  • Interop: Allows launching Windows apps and sharing the Windows $PATH.

Windows Packages

The list of Windows packages installed by mise-tasks/setup/provision/windows/install.ps1 is defined in mise-tasks/setup/provision/windows/packages.toml. This file serves as the manifest for standardized Windows environments.

Customizing in ~/.zshrc.local

You can still use shell-level overrides:

# ~/.zshrc.local
if grep -q "Microsoft" /proc/version 2>/dev/null; then
    # WSL-specific settings
    export BROWSER="wslview"
    alias pbcopy="clip.exe"
    alias pbpaste="powershell.exe -command 'Get-Clipboard'"
fi

Multiple Machine Strategies

Strategy 1: Single Branch, Local Overrides

Best for similar machines. Use local override files for differences.

Strategy 2: Git Branches per Machine Type

# main branch - common config
# work branch - work-specific changes
# server branch - headless server config

git checkout work
git merge main  # Pull in updates

Strategy 3: Conditional Logic in Main Config

# In .zshrc
case "$(hostname)" in
    work-*) source ~/.config/work-config.zsh ;;
    home-*) source ~/.config/home-config.zsh ;;
esac

Testing Customizations

After making changes:

  1. Reload shell: source ~/.zshrc or reload
  2. Check health: mise run doctor
  3. Verify tools: Test aliases and commands work as expected