Skip to content


How can I quickly check for problems with chezmoi on my machine?


$ chezmoi doctor

Anything ok is fine, anything warning is only a problem if you want to use the related feature, and anything error indicates a definite problem.

A specific command is not behaving as I expect. How can I debug it?

The --verbose flag makes chezmoi to print extra information about what it is doing.

The --debug flag makes chezmoi print very detailed step by step information.

The output of chezmoi diff is broken and does not contain color. What could be wrong?

By default, chezmoi's diff output includes ANSI color escape sequences (e.g. ESC[37m) and is piped into your pager (by default less). chezmoi assumes that your pager passes through the ANSI color escape sequences, as configured on many systems, but not all. If your pager does not pass through ANSI color escape sequences then you will see monochrome diff output with uninterpreted ANSI color escape sequences.

This can typically by fixed by setting the environment variable

$ export LESS=-R

which instructs less to display "raw" control characters via the -R / --RAW-CONTROL-CHARS option.

You can also set the pager configuration variable in your config file, for example:

pager = "less -R"

If you have set a different pager (via the pager configuration variable or PAGER environment variable) then you must ensure that it passes through raw control characters. Alternatively, you can use the --color=false option to chezmoi to disable colors or the --no-pager option to chezmoi to disable the pager.

Why do I get a blank buffer or empty file when running chezmoi edit?

In this case, chezmoi edit typically prints a warning like:

chezmoi: warning: $EDITOR $TMPDIR/$FILENAME: returned in less than 1s

chezmoi edit performs a bit of magic to improve the experience of editing files in the source state by invoking your editor with filenames in a temporary directory that look like filenames in your home directory. What's happening here is that your editor command is exiting immediately, so chezmoi thinks you've finished editing and so removes the temporary directory, but actually your editor command has forked a edit process in the background, and that edit process opens a now non-existent file.

To fix this you have to configure your editor command to remain in the foreground until you have finished editing the file, so chezmoi knows when to remove the temporary directory.

Pass the -f flag, e.g. by setting the edit.flags configuration variable to ["-f"], or by setting the EDITOR environment variable to include the -f flag, e.g. export EDITOR="vim -f".

Pass the --wait flag, e.g. by setting the edit.flags configuration variable to ["--wait"] or by setting the EDITOR environment variable to include the --wait flag, e.g. export EDITOR="code --wait".

The "bit of magic" that chezmoi edit performs includes:

  • chezmoi edit makes the filename opened by your editor more closely match the target filename, which can help your editor choose the correct syntax highlighting. For example, if you run chezmoi edit ~/.zshrc, your editor is be opened with $TMPDIR/.zshrc but you'll actually be editing ~/.local/share/chezmoi/dot_zshrc. Under the hood, chezmoi creates a hardlink in a temporary directory to the file in your source directory, so even though your editor thinks it's editing .zshrc, it is really editing dot_zshrc in your source directory.

  • If the source file is encrypted then chezmoi edit transparently decrypts and re-encrypts the file for you. Specifically, chezmoi decrypts the file into a private temporary directory and open your editor with the decrypted file, and re-encrypts the file when you exit your editor.

  • If the source file is a template, then chezmoi edit preserves the .tmpl extension.

chezmoi makes ~/.ssh/config group writeable. How do I stop this?

By default, chezmoi uses your system's umask when creating files. On most systems the default umask is 022 but some systems use 002, which means that files and directories are group writeable by default.

You can override this for chezmoi by setting the umask configuration variable in your configuration file, for example:

umask = 0o022


This will apply to all files and directories that chezmoi manages and will ensure that none of them are group writeable. It is not currently possible to control group write permissions for individual files or directories. Please open an issue on GitHub if you need this.

chezmoi reports chezmoi: user: lookup userid NNNNN: input/output error

This is likely because the chezmoi binary you are using was statically compiled with musl and the machine you are running on uses LDAP or NIS.

The immediate fix is to use a package built for your distribution (e.g a .deb or .rpm) which is linked against glibc and includes LDAP/NIS support instead of the statically-compiled binary.

If the problem still persists, then please open an issue on GitHub.

chezmoi reports chezmoi: timeout or chezmoi: timeout obtaining persistent state lock

chezmoi will report this when it is unable to lock its persistent state (~/.config/chezmoi/chezmoistate.boltdb), typically because another instance of chezmoi is currently running and holding the lock.

This can happen, for example, if you have a run_ script that invokes chezmoi, or are running chezmoi in another window.

Under the hood, chezmoi uses bbolt which permits multiple simultaneous readers, but only one writer (with no readers).

Commands that take a write lock include add, apply, edit, forget, import, init, state, unmanage, and update. Commands that take a read lock include diff, status, and verify.

chezmoi reports chezmoi: fork/exec /tmp/XXXXXXXXXX.XX: exec format error when executing a template script

This error occurs when you have a newline before the #! in your script. Suppress the newline by including a - before the closing }} on the first line.

For example, if your template script begins with

{{ if eq .chezmoi.os "linux" }}

change this to

{{ if eq .chezmoi.os "linux" -}}

chezmoi reports chezmoi: fork/exec /tmp/XXXXXXXXXX.XX: permission denied when executing a script

This error occurs when your temporary directory is mounted with the noexec option.

As chezmoi scripts can be templates, encrypted, or both, chezmoi needs to write the final script's contents to a file so that it can be executed by the operating system. By default, chezmoi will use $TMPDIR for this.

You can change the temporary directory into which chezmoi writes and executes scripts with the scriptTempDir configuration variable. For example, to use a subdirectory of your home directory you can use:

scriptTempDir = "~/tmp"

chezmoi reports chezmoi: mkdir xxxxx: no such file or directory when trying to manage file or directory

This error occurs when you try to add directory/file to be managed via chezmoi but the same directory is only listed in .chezmoiexternal.$FORMAT.

A workaround can be applied in a such case via manually creating import directory in chezmoi source directory (typically ~/.local/share/chezmoi) and create .keep file.

For example, if .chezmoiexternal.toml has the configuration:

    type = "git-repo"
    url = ""
    refreshPeriod = "168h"
        args = ["--ff-only"]

Now chezmoi add ~/.config/direnv/direnvrc will raise the error:

chezmoi: mkdir /home/<user>/.local/share/chezmoi/dot_config/direnv: no such file or directory

But the workaround can be applied:

$ chezmoi cd
$ mkdir -p dot_config/
$ touch dot_config/.keep

Now once that done chezmoi add ~/.config/direnv/direnvrc should work. For reference see this issue

chezmoi reports read /dev/stdin: permission denied or write /dev/stdout: permission denied when I redirect standard input or standard output

This error occurs when you installed chezmoi with snap and is caused by a long-standing bug in snap.

This is not a bug in chezmoi and there is nothing that chezmoi can do about this. However, there are two workarounds:

Firstly, you can use alternatives to shell redirection. For standard input:

$ chezmoi $COMMAND <$FILENAME       # fails
$ cat $FILENAME | chezmoi $COMMAND  # succeeds

For standard output:

$ chezmoi $COMMAND >$FILENAME                  # fails
$ chezmoi $COMMAND -o $FILENAME                # succeeds
$ chezmoi $COMMAND --output=$FILENAME          # succeeds
$ chezmoi $COMMAND | tee $FILENAME >/dev/null  # succeeds

Secondly, you can install chezmoi with any of the many supported install methods instead of snap.

chezmoi reports fork/exec ...: no such file or directory when running scripts on Nix or Termux

You are likely using a hardcoded script interpreter in the shebang line of your scripts, e.g.


/bin/bash does not exist on Nix or Termux. You must update the shebang line to point to the actual bash interpreter. The easiest way to do this is make the script a template and use the lookPath template function, for example:

#!{{ lookPath "bash" }}

Alternatively, you can use the actual path to bash on your system, for example:

#!/usr/bin/env bash