4 分で読了 #tools

chezmoi

chezmoi は dotfiles を 1 つの git リポジトリにまとめ、各マシンで apply して展開し、システムごとにテンプレート差分を適用できます。使い方はネット上にたくさんありますが、ここで本当に伝えたいのは境界線です。⁠何を任せ、何を任せないか。

私の基準は「自分で書き、複数マシンで一貫性を保つ必要があるもの」のみを対象とすることです。現在では、クロスプラットフォームな以下の設定が対象です: WezTerm の ~/.wezterm.lua、Windows 上の Neovim 設定、Windows の PowerShell プロファイルと AutoHotKey。これらは 2 台のマシン間で頻繁に編集するため、一貫性の価値があります。

一方、Linux デスクトップの大きな塊——Hyprland、Quickshell、waybar——は取り込みませんでした。理由は、規模が大きいこと(Quickshell だけで 7 万行)、そしてそれらが upstream の rice リポジトリと連動して更新されるためです。私は「upstream に追従し、ローカルで数箇所だけ修正する」方を選び、他人の数万行の QML コードを自分の dotfiles リポジトリに抱え込むのは避けたいと考えています。また、秘密鍵を含むものも一切対象外です。それらは環境変数や個別の gitignore で管理すべきであり、リポジトリの履歴に含めてはいけません。

残った日常の作業はシンプルです:

chezmoi edit ~/.wezterm.lua    # ソースを編集
chezmoi diff                   # apply 時に何が変わるかを確認
chezmoi apply                  # 適用
chezmoi cd && git commit -a && git push

新しいマシンでは chezmoi init --apply <repo> 1 文でリポジトリをクローンして展開完了です。

知っておくべきchezmoiの2つの仕組みは、十分で十分です:

ファイル名のプレフィックスが属性を表す⁠——chezmoi はメタデータを保存せず、属性をソースファイル名にエンコードします: dot_foo~/.fooprivate_ → 権限 600、executable_ → 実行ビット付与、readonly_encrypted_(age/gpg と組み合わせて適用時に復号)、run_ で始まるスクリプトは適用時に実行されます(run_once_ は一度だけ実行され、パッケージインストールや初期化に適しています)。ファイル名を見るだけで、それがどのように展開されるかが分かります。

テンプレートでマシンごとの差分を処理⁠——*.tmpl は Go テンプレート形式で、.chezmoi.os.chezmoi.hostname といった組み込み変数や、.chezmoidata / 設定ファイルで定義した独自値を読み取ることができます:

{{ if eq .chezmoi.os "windows" }}
shell = "pwsh"
{{ else }}
shell = "zsh"
{{ end }}

同じソースでも、Windows と Linux で適用すると異なる結果になります——これが、クロスプラットフォームな設定(WezTerm、PowerShell、Windows 上の Neovim)を 1 つのソースで共有できる理由です。chezmoi diff は適用前に、テンプレートがレンダリングされた後に実際に何を書き込むのかを必ず確認させてくれます。

十分で、複雑ではありません——複雑なのはツールではなく、「何でもかんでも詰め込まないという自制心」にあります。