# What Is Chezmoi and How Does It Work for Dotfiles Management?

> Discover chezmoi, the Go-based dotfile manager. Learn how it maintains version-controlled, templated configuration files with machine-specific customizations and encryption.

- Repository: [Ivan Smirnov/dotfiles](https://github.com/issmirnov/dotfiles)
- Tags: how-to-guide
- Published: 2026-03-04

---

**Chezmoi is a cross-platform dotfile manager written in Go that maintains a version-controlled source tree of templated configuration files, expanding them into your home directory with machine-specific customizations and encryption support.**

Chezmoi solves the challenge of synchronizing shell configurations, editor settings, and window manager preferences across multiple machines. For repositories like **issmirnov/dotfiles**, it provides a robust alternative to static installation scripts by introducing dynamic templating and host-specific data injection.

## How Chezmoi Manages Dotfiles: Source vs. Target

Chezmoi operates on a **source state** and a **target state** model. The source state lives in `~/.local/share/chezmoi` by default and contains **templated** versions of your dotfiles using Jinja-style `{{ }}` directives. When you execute `chezmoi apply`, the tool expands these templates—injecting host-specific data, environment variables, or secrets—and writes the resulting files to their **target locations** (e.g., `$HOME/.zshrc`, `$HOME/.config/i3/config`).

## Key Features for Dotfile Management

- **Cross-platform support**: Works on Linux, macOS, and BSD, allowing the same repository to function on laptops, workstations, or servers.
- **Template engine**: Jinja-style directives enable conditional sections (e.g., macOS-only settings) without maintaining separate files.
- **Encryption support**: Sensitive files can be stored encrypted using `age`, keeping passwords or API keys out of plain text.
- **Git integration**: The source tree is a Git repository, providing history, branches, and pull-request workflows automatically.
- **One-command install**: `chezmoi init <URL>` clones the repository and applies the configuration in a single step.
- **Data-driven configuration**: Host-specific values can be supplied through `chezmoi data add` or environment variables, avoiding duplicate nearly-identical files.

## Typical Workflow with Chezmoi

1. **Initialize the repository** (once per machine):

   ```bash
   chezmoi init https://github.com/issmirnov/dotfiles
   ```

   This clones the repo into `~/.local/share/chezmoi` (the source directory).

2. **Edit a dotfile**:

   ```bash
   chezmoi edit .zshrc
   ```

   This opens the source version in your `$EDITOR`.

3. **Apply changes**:

   ```bash
   chezmoi apply
   ```

   This writes the templated files to `$HOME`.

4. **Add host-specific data**:

   ```bash
   chezmoi data add os=macos
   ```

   Templates like `{{ if eq .chezmoi.os "macos" }}` can then enable macOS-only settings.

5. **Encrypt a secret**:

   ```bash
   chezmoi encrypt -c age -r $CHEZMOI_AGE_KEY secret.txt
   ```

   The encrypted file stays in the repository; `chezmoi apply` decrypts it on the target host.

## Integrating Chezmoi with issmirnov/dotfiles

The **issmirnov/dotfiles** repository currently uses **dotbot** for installation via the `./install` script. However, the same directory layout can be consumed by chezmoi:

- **`zsh/zshrc`**: Can become a template for `~/.zshrc`, using `{{ .chezmoi.os }}` for platform-specific paths.
- **[`i3/README.md`](https://github.com/issmirnov/dotfiles/blob/main/i3/README.md) and `i3/*`**: Source files for `~/.config/i3/`.
- **[`tmux/tmux.conf`](https://github.com/issmirnov/dotfiles/blob/main/tmux/tmux.conf)**: Template candidate for `~/.tmux.conf`.
- **`install`**: Can be replaced or complemented by `chezmoi init … && chezmoi apply`.
- **[`default.conf.yaml`](https://github.com/issmirnov/dotfiles/blob/main/default.conf.yaml)**: Can be converted to a chezmoi data file ([`.chezmoidata.yaml`](https://github.com/issmirnov/dotfiles/blob/main/.chezmoidata.yaml)).

Users can maintain both approaches: use `dotbot` for quick bootstrap on fresh systems, then switch to `chezmoi` for ongoing per-host management.

## Practical Configuration Examples

### Minimal Chezmoi Configuration

```yaml

# .chezmoic – tells chezmoi where the source repo lives

source_dir: "~/.local/share/chezmoi"

```

### Templated zshrc

```zsh

# ~/.zshrc – managed by chezmoi

export LANG=en_US.UTF-8

# OS-specific settings

{{ if eq .chezmoi.os "macos" }}
export PATH="/opt/homebrew/bin:$PATH"
{{ else if eq .chezmoi.os "linux" }}
export PATH="/usr/local/bin:$PATH"
{{ end }}

# Load oh-my-zsh from the source directory

source "{{ .chezmoi.sourceDir }}/oh-my-zsh/oh-my-zsh.sh"

```

### Adding Host-Specific Data

```bash

# Mark this machine as a laptop

chezmoi data add device_type=laptop

# Now you can use {{ .chezmoi.device_type }} inside any template

```

### Encrypting Secrets

```bash

# Store the encrypted file in the source tree

chezmoi encrypt -c age -r $CHEZMOI_AGE_KEY \
   ~/.local/share/chezmoi/.git-credentials.age

```

### Single-Line Installation

```bash
bash -c "$(curl -fsSL https://get.chezmoi.io)" && \
chezmoi init https://github.com/issmirnov/dotfiles && \
chezmoi apply

```

## Summary

- Chezmoi stores **templated dotfiles** in `~/.local/share/chezmoi` and applies them to your home directory with `chezmoi apply`.
- It supports **cross-platform** configurations using `{{ .chezmoi.os }}` conditionals and host-specific data via `chezmoi data add`.
- **Encryption** via `age` keeps sensitive files secure in the repository.
- The **issmirnov/dotfiles** repository can migrate from dotbot to chezmoi by converting `zsh/zshrc`, [`tmux/tmux.conf`](https://github.com/issmirnov/dotfiles/blob/main/tmux/tmux.conf), and `i3/` configurations into chezmoi templates.
- The `install` script and [`default.conf.yaml`](https://github.com/issmirnov/dotfiles/blob/main/default.conf.yaml) can be replaced with chezmoi's native `init` and data file workflows.

## Frequently Asked Questions

### What is the difference between chezmoi and symlink-based dotfile managers?

Unlike symlink managers that create direct links from `~/.zshrc` to your repo, chezmoi maintains a **source tree** of templated files. This allows you to use `{{ .chezmoi.os }}` conditionals and store encrypted secrets directly in the repository, whereas symlinks require workarounds for host-specific differences.

### How does chezmoi handle sensitive data like API keys?

Chezmoi integrates with `age` encryption. You run `chezmoi encrypt -c age` on sensitive files, which stores them as `.age` encrypted blobs in the source tree. When you run `chezmoi apply` on a target machine with the correct key, the files are decrypted automatically.

### Can I use chezmoi alongside my existing install script?

Yes. The **issmirnov/dotfiles** repository currently uses a `./install` script with dotbot. You can keep this for initial bootstrapping while using chezmoi for ongoing management, or gradually migrate by converting `zsh/zshrc` and other configs into chezmoi templates while maintaining backward compatibility.

### Where does chezmoi store its configuration and source files?

By default, chezmoi stores the **source state** in `~/.local/share/chezmoi` and the configuration file (`.chezmoic` or [`chezmoi.toml`](https://github.com/issmirnov/dotfiles/blob/main/chezmoi.toml)) in the source directory or `~/.config/chezmoi/`. Target files are written directly to your home directory (`$HOME/.zshrc`, etc.) during `chezmoi apply`.