Skip to content


Understand chezmoi's files and directories

chezmoi generates your dotfiles for your local machine. It combines two main sources of data:

The source directory, ~/.local/share/chezmoi, is common to all your machines, and is a clone of your dotfiles repo. Each file that chezmoi manages has a corresponding file in the source directory.

The config file, typically ~/.config/chezmoi/chezmoi.toml (although you can use JSON or YAML if you prefer), is specific to the local machine.

Files whose contents are the same on all of your machines are copied verbatim from the source directory. Files which vary from machine to machine are executed as templates, typically using data from the local machine's config file to tune the final contents specific to the local machine.

Use a hosted repo to manage your dotfiles across multiple machines

chezmoi relies on your version control system and hosted repo to share changes across multiple machines. You should create a repo on the source code repository of your choice (e.g. Bitbucket, GitHub, or GitLab, many people call their repo dotfiles) and push the repo in the source directory here. For example:

$ chezmoi cd
$ git remote add origin
$ git push -u origin main
$ exit

On another machine you can checkout this repo:

$ chezmoi init

You can then see what would be changed:

$ chezmoi diff

If you're happy with the changes then apply them:

$ chezmoi apply

The above commands can be combined into a single init, checkout, and apply:

$ chezmoi init --apply --verbose

These commands are summarized this sequence diagram:

sequenceDiagram participant H as home directory participant W as working copy participant L as local repo participant R as remote repo R->>W: chezmoi init <repo> W-->>H: chezmoi diff W->>H: chezmoi apply R->>H: chezmoi init --apply <repo>

Use a private repo to store your dotfiles

chezmoi supports storing your dotfiles in both public and private repos.

chezmoi is designed so that your dotfiles repo can be public by making it easy for you to store your secrets either in your password manager, in encrypted files, or in private configuration files. Your dotfiles repo can still be private, if you choose.

If you use a private repo for your dotfiles then you will typically need to enter your credentials (e.g. your username and password) each time you interact with the repo, for example when pulling or pushing changes. chezmoi itself does not store any credentials, but instead relies on your local git configuration for these operations.

When using a private repo on GitHub without --ssh, when prompted for a password you will need to enter a GitHub personal access token. For more information on these changes, read the GitHub blog post on Token authentication requirements for Git operations

Create a config file on a new machine automatically

chezmoi init can also create a config file automatically, if one does not already exist. If your repo contains a file called .chezmoi.$FORMAT.tmpl where $FORMAT is one of the supported config file formats (e.g. json, toml, or yaml) then chezmoi init will execute that template to generate your initial config file.

Specifically, if you have .chezmoi.toml.tmpl that looks like this:

{{- $email := promptString "email" -}}

    email = {{ $email | quote }}

Then chezmoi init will create an initial chezmoi.toml using this template. promptString is a special function that prompts the user (you) for a value.

To test this template, use chezmoi execute-template with the --init and --promptString flags, for example:

$ chezmoi execute-template --init --promptString < ~/.local/share/chezmoi/.chezmoi.toml.tmpl

Re-create your config file

If you change your config file template, chezmoi will warn you if your current config file was not generated from that template. You can re-generate your config file by running:

$ chezmoi init

If you are using any prompt* template functions in your config file template you will be prompted again. However, you can avoid this with the following example template logic:

{{- $email := "" -}}
{{- if hasKey . "email" -}}
{{-   $email = .email -}}
{{- else -}}
{{-   $email = promptString "email" -}}
{{- end -}}

    email = {{ $email | quote }}

This will cause chezmoi to first try to re-use the existing $email variable and fallback to promptString only if it is not set.

Back to top