Tutorials
Tutorial: Create a Machine Profile
Machine profiles tell chezmoi how to render templates differently on each host — display scale, keyboard layout, performance preset, available features.
When to Use a Profile
- You have more than one host (laptop + desktop, work + personal)
- Your hardware differs materially (HiDPI laptop vs 1080p external, ARM vs x86)
- Certain features only apply to specific setups (Niri on Wayland, AeroSpace on macOS)
Step 1: Choose or Create a Preset
Presets live in .chezmoidata/hardware.toml:
[hardware.macbook-t2]
display_scale = 2.0
kbd_layout = "qwerty"
modifier_mode = "left-cmd-control"
perf_profile = "laptop"
wm = "aerospace"
[hardware.macbook-t2.features]
retina = true
touchid = true
[hardware.surface-pro]
display_scale = 1.5
kbd_layout = "colemak-dh"
modifier_mode = "standard"
perf_profile = "laptop"
wm = "niri"
[hardware.surface-pro.features]
touch = true
pen = true
If an existing preset fits: use its name. Otherwise, add a new one.
Step 2: Select the Preset for This Host
Edit ~/.config/chezmoi/chezmoi.toml:
[data]
machine = "surface-pro" # choose from .chezmoidata/hardware.toml
theme = "monterey-dark"
default_shell = "fish"
terminal_font_family = "JetBrainsMono Nerd Font"
terminal_font_size = 11 # larger for HiDPI, smaller for dense screens
chezmoi.toml is not in the repository — each host has its own. Generated by chezmoi init on first install.
Step 3: Reference the Preset in Templates
Inside any .tmpl file:
# Ghostty config — uses machine-specific font size
font-family = "{{ .terminal_font_family }}"
font-size =
# DPI-aware settings
window-decoration = false
window-decoration = true
# Feature-gated config
mouse-scroll-multiplier = 3
After editing the template, run chezmoi apply or dot apply.
Step 4: Add a New Preset
Suppose you have a new mini PC. Add to .chezmoidata/hardware.toml:
[hardware.my-nuc]
display_scale = 1.0 # external 1440p
kbd_layout = "qwerty"
modifier_mode = "standard"
perf_profile = "desktop"
wm = "gnome"
[hardware.my-nuc.features]
multi-monitor = true
gaming = true
Then on that host:
# ~/.config/chezmoi/chezmoi.toml
[data]
machine = "my-nuc"
Apply:
Templates automatically pick up the new preset data.
Step 5: Per-Preset Feature Flags
Feature flags in .chezmoidata.toml can be gated by preset:
# .chezmoidata.toml — defaults for all hosts
[features]
dms = false
linux_desktop = false
waybar = false
Override per-preset in .chezmoidata/hardware.toml:
[hardware.surface-pro.features]
touch = true
pen = true
dms = true # override feature default
waybar = true
In templates:
# ... waybar-specific config ...
Example: Font Size by Preset
A single Ghostty config that renders correctly on every host:
# dot_config/ghostty/config.tmpl
theme =
font-family = "{{ .terminal_font_family }}"
# DPI-aware font sizing
font-size = 12 # Retina MacBook
font-size = 11 # Surface Pro
font-size = 14 # External 1440p/4K
On the MacBook: 12pt. On the Surface: 11pt. On the NUC: 14pt. One template.
Example: Platform × Preset
Combine .chezmoi.os with the preset:
# macOS + AeroSpace specifics
# Linux + Niri specifics
Listing Known Presets
# macbook-t2
# surface-pro
# geekom-a9
# my-nuc
Changing Presets on an Existing Host
If you reassign a host to a different preset:
# Edit ~/.config/chezmoi/chezmoi.toml
# machine = "my-nuc" (was "surface-pro")
Chezmoi re-renders every template with the new preset data. No reboot needed.
Troubleshooting
"Machine preset 'foo' not found"
The machine value in ~/.config/chezmoi/chezmoi.toml doesn't match any key under [hardware.*] in .chezmoidata/hardware.toml. Check spelling.
Templates Silently Use Defaults
Make sure you're using {{- $hw := index .hardware .machine }} at the top of templates. If machine is empty, index returns nil — reference with {{- with $hw }}...{{- end }} guards.
Feature Flag Not Taking Effect
Verify the merge order:
Per-preset features must override global defaults. If the output doesn't reflect that, check template syntax.
Summary
Profiles let one source tree produce correctly-configured output on every host you own. The machinery:
.chezmoidata/hardware.tomldefines presets (declarative)~/.config/chezmoi/chezmoi.tomlselects a preset per host (per-host override).tmplfiles read.hardware+.machine(template-time)