Skip to main content

Have chezmoi create a directory, but ignore its contents

For directories like ~/src where you want the directory created but not its contents managed:
1

Create the directory in source state

mkdir -p $(chezmoi source-path)/src
chezmoi will create this directory when you run chezmoi apply.
2

Add a .keep file

touch $(chezmoi source-path)/src/.keep
This ensures git tracks the directory while chezmoi ignores the .keep file.
chezmoi automatically creates .keep files when you add an empty directory with chezmoi add.

Ensure that a target is removed

Create a .chezmoiremove file in the source directory with patterns of files to remove:
# Remove old config files
.oldconfig
*.backup

# Machine-specific removals
{{- if eq .chezmoi.hostname "work-laptop" }}
.personal-scripts
{{- end }}
Always preview with --dry-run first. .chezmoiremove is a template, so you can remove different files on different machines. Negative matches (prefixed with !) and targets in .chezmoiignore will never be removed.

Manage part, but not all, of a file

chezmoi provides two approaches for managing partial file contents:
A modify_ script receives the current file content on stdin and outputs the modified content:
#!/bin/sh
# Replace 'old' with 'new' in the file
sed 's/old/new/g'
If the file doesn’t exist, stdin will be empty and the script must write a complete file to stdout.

Manage a file’s permissions, but not its contents

Use the create_ attribute to manage permissions without changing file contents:
Create an empty file with the desired attributes:
# Ensures ~/.kube/config has 0600 permissions
touch $(chezmoi source-path)/dot_kube/private_config
chezmoi will apply permission changes from private_, executable_, and readonly_ attributes without modifying contents.
This approach creates the file if it doesn’t exist.

Handle configuration files which are externally modified

Some programs modify their own config files. To track these changes, use symlinks:
1

Copy config to source directory

cp ~/.config/Code/User/settings.json $(chezmoi source-path)
2

Tell chezmoi to ignore this file

echo settings.json >> $(chezmoi source-path)/.chezmoiignore
3

Create a symlink to the source file

mkdir -p $(chezmoi source-path)/private_dot_config/private_Code/User
echo -n "{{ .chezmoi.sourceDir }}/settings.json" > $(chezmoi source-path)/private_dot_config/private_Code/User/symlink_settings.json.tmpl
The private_ prefix is used because ~/.config and ~/.config/Code are private by default.
4

Apply the changes

chezmoi apply -v
Now when the program modifies its config, it modifies the file in your source state.

Populate ~/.ssh/authorized_keys with your public SSH keys from GitHub

chezmoi can retrieve public SSH keys from GitHub:
~/.local/share/chezmoi/dot_ssh/authorized_keys.tmpl
{{ range gitHubKeys "$GITHUB_USERNAME" -}}
{{   .Key }}
{{ end -}}
This will populate ~/.ssh/authorized_keys with all public keys from your GitHub account.
You can use similar template functions for other services like gitLabKeys and gitHubLatestRelease.

Build docs developers (and LLMs) love