Skip to main content

Templates Overview

chezmoi executes templates using Go’s text/template package. Templates allow you to create dynamic configuration files that adapt to different machines, operating systems, and environments.

Basic Concepts

Templates are files with a .tmpl suffix in the source state. chezmoi processes these files and outputs the result to the destination.

Example

~/.local/share/chezmoi/dot_gitconfig.tmpl
[user]
    name = {{ .name }}
    email = {{ .email }}
{{ if eq .chezmoi.os "darwin" }}
[credential]
    helper = osxkeychain
{{ end }}

Template Execution

The result of template execution is treated differently depending on the target type:

For Files

  • If the result is an empty string, the file is removed
  • Otherwise, the target file contents are the result
  • Leading and trailing whitespace are stripped from the result
  • If the result is an empty string, the symlink is removed
  • Otherwise, the target symlink target is the result

Template Options

chezmoi executes templates using text/template’s missingkey=error option by default, which means that misspelled or missing keys will raise an error. This can be overridden by setting options in the configuration file:
~/.config/chezmoi/chezmoi.toml
[template]
    options = ["missingkey=zero"]
Available options:
  • missingkey=default - Use the default behavior
  • missingkey=error - Return an error on missing keys (default)
  • missingkey=zero - Use the zero value for missing keys
  • missingkey=invalid - Print <no value> for missing keys
For a full list of template options, see Template.Option.

Template Syntax

Basic Substitution

{{ .variable }}          # Output a variable
{{ .chezmoi.os }}        # Access nested values
{{ .email | quote }}     # Use functions

Comments

{{/* This is a comment */}}
{{- /* Comments can trim whitespace */ -}}

Whitespace Control

{{- .value }}    # Trim whitespace before
{{ .value -}}    # Trim whitespace after
{{- .value -}}   # Trim both sides

Conditionals

{{ if .condition }}
    # Rendered if condition is true
{{ end }}

{{ if .condition }}
    # True branch
{{ else }}
    # False branch
{{ end }}

{{ if .condition1 }}
    # Branch 1
{{ else if .condition2 }}
    # Branch 2
{{ else }}
    # Default branch
{{ end }}

Loops

{{ range .items }}
    Item: {{ . }}
{{ end }}

{{ range $index, $value := .items }}
    {{ $index }}: {{ $value }}
{{ end }}

{{ range $key, $value := .dict }}
    {{ $key }} = {{ $value }}
{{ end }}

Variables

{{ $var := .value }}
{{ $var }}

{{ $name := "John" }}
{{ $email := .email }}

Comparison Operators

{{ if eq .chezmoi.os "darwin" }}Mac{{ end }}
{{ if ne .value "test" }}Not test{{ end }}
{{ if lt .count 10 }}Less than 10{{ end }}
{{ if le .count 10 }}10 or less{{ end }}
{{ if gt .count 5 }}Greater than 5{{ end }}
{{ if ge .count 5 }}5 or more{{ end }}

Boolean Operators

{{ if and .condition1 .condition2 }}Both true{{ end }}
{{ if or .condition1 .condition2 }}At least one true{{ end }}
{{ if not .condition }}Negated{{ end }}

Template Functions

chezmoi provides all standard text/template functions, all Sprig functions, and many additional functions. See Template Functions for a complete list.

Common Functions

{{ .value | quote }}                    # Quote a string
{{ .value | upper }}                    # Convert to uppercase
{{ .value | lower }}                    # Convert to lowercase
{{ .dict | toYaml }}                    # Convert to YAML
{{ .dict | toJson }}                    # Convert to JSON
{{ include "file.txt" }}                # Include file contents
{{ includeTemplate "template.tmpl" . }} # Include and execute template

Template Variables

chezmoi provides automatically-populated variables accessible via .chezmoi:
{{ .chezmoi.os }}           # Operating system (linux, darwin, etc.)
{{ .chezmoi.arch }}         # Architecture (amd64, arm64, etc.)
{{ .chezmoi.hostname }}     # Hostname
{{ .chezmoi.username }}     # Username
{{ .chezmoi.homeDir }}      # Home directory
{{ .chezmoi.sourceDir }}    # Source directory
{{ .chezmoi.config }}       # Configuration data
See Template Variables for a complete list.

Template Directives

File-specific template options can be set using directives:
chezmoi:template:$KEY=$VALUE

Custom Delimiters

script.sh.tmpl
#!/bin/bash
# chezmoi:template:left-delimiter="# [[" right-delimiter="]]"

# [[ .variable ]]

Line Endings

{{/* chezmoi:template:line-endings=crlf */}}

Encoding

{{/* chezmoi:template:encoding=utf-16-le */}}
See Template Directives for all available directives.

Practical Examples

OS-Specific Configuration

dot_bashrc.tmpl
# Common configuration
export EDITOR=vim

{{ if eq .chezmoi.os "darwin" }}
# macOS-specific
export PATH="/usr/local/bin:$PATH"
alias ls="ls -G"
{{ else if eq .chezmoi.os "linux" }}
# Linux-specific
export PATH="/usr/bin:$PATH"
alias ls="ls --color=auto"
{{ end }}

Machine-Specific Configuration

dot_config_app_config.toml.tmpl
{{ if eq .chezmoi.hostname "workstation" }}
theme = "dark"
font_size = 14
{{ else }}
theme = "light" 
font_size = 12
{{ end }}

Using Custom Data

.chezmoidata.yaml
packages:
  - vim
  - git
  - tmux
run_once_install-packages.sh.tmpl
#!/bin/bash
{{ range .packages }}
apt-get install -y {{ . }}
{{ end }}

Using Secrets

dot_config_app_credentials.ini.tmpl
[api]
key = {{ onepassword "API Key" }}
secret = {{ onepassword "API Secret" }}

[database]
password = {{ bitwarden "item-id" }}

Error Handling

Templates will stop execution if an error occurs:
# This will error if .missing doesn't exist (with default missingkey=error)
{{ .missing }}

# Use default to provide a fallback
{{ .missing | default "default-value" }}

# Check if a key exists
{{ if hasKey . "missing" }}
    {{ .missing }}
{{ else }}
    default-value
{{ end }}

Testing Templates

Use chezmoi execute-template to test template expressions:
# Test a simple expression
chezmoi execute-template '{{ .chezmoi.os }}'

# Test with file
echo '{{ .chezmoi.hostname }}' | chezmoi execute-template

# Test complex template
chezmoi execute-template < template.tmpl

Performance Tips

  1. Cache expensive operations: Store results in variables
  2. Avoid repeated function calls: Call once and store
  3. Use includes wisely: Don’t include large files multiple times
  4. Minimize external calls: Group output calls when possible
{{/* GOOD: Call once */}}
{{ $os := .chezmoi.os }}
{{ if eq $os "darwin" }}...{{ end }}
{{ if eq $os "linux" }}...{{ end }}

{{/* BAD: Multiple calls */}}
{{ if eq .chezmoi.os "darwin" }}...{{ end }}
{{ if eq .chezmoi.os "linux" }}...{{ end }}

Build docs developers (and LLMs) love