chezmoi について
chezmoi で複数マシンのドットファイルを管理する開発者向けのスキルです。初期設定やファイル変更、安全な適用を案内し、Go テンプレート、暗号化、属性、適用前の確認を扱います。
主な機能
- 01複数マシン間でドットファイルを管理
- 02Go テンプレートでファイルを生成
- 03属性によるファイル動作と権限の制御
- 04機密ファイルの暗号化保存
- 05一度限りまたは変更時にスクリプトを実行
- 06適用前に差分と計画を確認
活用シーン
- 01新しいマシンでドットファイルを初期設定
- 02OS やホストごとに設定を変更
- 03トークンなどの秘密情報を安全に追加
- 04設定適用による予期しない変更を調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ paulnsorensen/ skillz-that-grillz --skill chezmoiインストール後、Claude Code で/chezmoiを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/bootstrap.mdpitfalls.mdscripts.mdsecrets.mdtemplating.md詳細
chezmoi
chezmoi をラップします。ソース状態のセマンティクス、Go テンプレート、保存時の暗号化を使って、複数のマシン間でドットファイルを管理します。
使用する場面
- 新しいマシンにドットファイルをセットアップするとき
- 既存の chezmoi 管理下のドットファイルに新しいファイルを追加するとき
- OS、ホスト、役割(仕事用か個人用か)ごとにドットファイルをテンプレート化するとき
- 1Password/Bitwarden/age/gpg でシークレットを追加するとき
run_once_インストールスクリプトを作成するとき- 「chezmoi apply で予期しない変更があった」原因を調べるとき
- 複数のマシン向けに
.chezmoi.toml.tmpl設定テンプレートを設計するとき
基本的な考え方
chezmoi は、ソースディレクトリ(~/.local/share/chezmoi。git リポジトリ)をターゲットディレクトリ(ユーザーのホームディレクトリ)に対応付けます。ソースのファイル名には、ターゲット名と動作を決める属性プレフィックスが含まれます。.tmpl 接尾辞の付いたソースファイルは Go の text/template としてレンダリングされ、対応するターゲットパスに書き込まれます。.chezmoitemplates/ 内のファイルは、ほかのテンプレートに含める再利用可能なテンプレート断片です。これらのファイル自体がターゲットファイルを生成することはありません。
~/.config/chezmoi/chezmoi.toml にある設定ファイル(通常は初回の init 時に .chezmoi.toml.tmpl から生成されます)には、マシンごとの変数が保存されます。
問題が起きる原因は主に2つあります。
chezmoi edit $TARGETを使わず、~/.local/share/chezmoi/内のファイルを直接編集することです。これにより、テンプレートと復号の往復処理が壊れます。- 「リポジトリはプライベートだから」という理由で、平文のシークレットをコミットすることです。リポジトリは漏えいし、フォークも漏えいし、履歴は永久に残ります。シークレットバックエンドを使ってください。
設定ファイルの場所
混同しやすいファイルが2つあります。どちらも toml、yaml、json、jsonc にできます(拡張子から自動判定されます。同時に2つの形式が存在する場合は、「最初のものが優先」ではなくエラーになります)。
| ファイル | パス | 書き込む人 |
|---|---|---|
chezmoi.<fmt>(設定) | $XDG_CONFIG_HOME/chezmoi/chezmoi.<fmt>。デフォルトは ~/.config/chezmoi/chezmoi.<fmt>(.toml が最も一般的)。ソースリポジトリには置きません。 | 以下のテンプレートを基に chezmoi init(または apply --init)が生成します。マシンごとのファイルです。シークレット、API トークン、マシン固有の設定を保存します。コミットしないでください。 |
.chezmoi.<fmt>.tmpl(設定テンプレート) | ソース状態のルート:~/.local/share/chezmoi/.chezmoi.<fmt>.tmpl(.toml が最も一般的)。ドットファイルのリポジトリにコミットします。 | ユーザーが作成します。promptBoolOnce/promptChoiceOnce/promptStringOnce を使うことで、新しいマシンで初回 init 時に適切な設定を生成できます。 |
--config <path> で場所を上書きできます(拡張子が一般的でない場合は --config-format <fmt> を使用してください)。有効な値は chezmoi cat-config と chezmoi dump-config で確認できます。
プロトコル
1. ユーザーの目的を確認する
| ユーザーの発言 | 参照先 |
|---|---|
| 「chezmoi をゼロからセットアップしたい」/「新しいマシン」 | §2 ブートストラップ |
| 「このファイルをドットファイルに追加したい」 | §3 ファイルの追加 |
| 「このドットファイルを OS/ホストに応じて変えたい」 | references/templating.md |
| 「これを暗号化したい」/「このトークンを保存したい」 | references/secrets.md |
| 「初回 apply 時にスクリプトを実行したい」 | references/scripts.md |
| 「chezmoi の動作がおかしい」 | references/pitfalls.md |
| 「セットアップ全体を設計したい」 | references/bootstrap.md |
2. ブートストラップ(新しいマシン)
クローン、テンプレートのレンダリング、適用を一度に行う完全なワンライナーです。
sh -c "$(curl -fsLS get.chezmoi.io)" -- init --apply $GITHUB_USERNAME
promptBoolOnce を使って仕事用/個人用/ヘッドレスのいずれかを選ぶ、詳細な .chezmoi.toml.tmpl のレシピについては、references/bootstrap.md を参照してください。
3. ファイルを追加する
chezmoi add ~/.zshrc # plain copy
chezmoi add --template ~/.gitconfig # add as a template (.tmpl suffix added)
chezmoi add --encrypt ~/.ssh/config # encrypted at rest
chezmoi chattr +template ~/.zshrc # turn an existing managed file into a template
chezmoi edit ~/.zshrc # edit the SOURCE — handles decrypt + .tmpl correctly
次に、安全に適用する手順(§5)を実行します。
4. ファイル名の命名規則
ユーザーが最も間違えやすい表です。プレフィックスは特定の順序で付ける必要があり、使用できるプレフィックスのセットは対象の種類によって異なります —
/reference/source-state-attributes/ が正規の情報源です。
| プレフィックス | 対象への影響 |
|---|---|
dot_ | 先頭に . を追加します(dot_zshrc → ~/.zshrc) |
private_ | グループおよびその他のユーザーの権限を削除します(モード 0600 / 0700) |
readonly_ | すべての書き込み権限ビットを削除します |
executable_ | 実行ビットを追加します |
empty_ | 空のファイルを許可します(通常は削除されます) |
encrypted_ | 対象への書き込み前に、age/gpg を使ってソースを復号します |
symlink_ | 通常のファイルではなくシンボリックリンクを作成します(ファイル形式では、対象はリンク先です) |
exact_(ディレクトリ) | ソースにないものを対象ディレクトリから削除します |
create_ | 対象が存在しない場合にのみ作成します — 上書きはしません |
modify_ | ソースを対象の内容を生成するスクリプト(またはテンプレート。下記参照)として扱います |
run_ | ソースを実行するスクリプトとして扱います(対象ファイルではありません) |
before_ / after_ | ファイルの適用に対するスクリプトの実行順序を指定します |
once_(スクリプト) | 内容が以前に正常に実行されたことがない場合にのみ実行します |
onchange_(スクリプト) | このファイル名の内容が変更された場合にのみ実行します |
remove_ | 対象が存在する場合は削除します |
external_(ディレクトリ) | ディレクトリを外部ディレクトリとして指定します — .chezmoiexternal.<fmt> / .chezmoiexternals/ と組み合わせます。chezmoi は子エントリの属性を無視します |
literal_(任意の場所) | 以降の属性の解析を停止します |
対象の種類ごとに許可されるプレフィックスの順序(順序は厳密で、入れ替えると解析エラーになります):
| 対象の種類 | 許可されるプレフィックス(順序どおり) | 省略可能なサフィックス |
|---|---|---|
| ディレクトリ | remove_、external_、exact_、private_、readonly_、dot_ | — |
| 通常のファイル | encrypted_、private_、readonly_、empty_、executable_、dot_ | .tmpl |
| 作成ファイル | create_、encrypted_、private_、readonly_、empty_、executable_、dot_ | .tmpl |
| 変更ファイル | modify_、encrypted_、private_、readonly_、executable_、dot_ | .tmpl |
| 削除ファイル | remove_、dot_ | — |
| スクリプト | run_、once_ または onchange_、before_ または after_ | .tmpl |
| シンボリックリンク | symlink_、dot_ | .tmpl |
サフィックス .tmpl を付けると、そのファイルはテンプレートになります。対応する暗号化が設定されている場合、.age / .asc は自動的に削除されます。
変更ファイルの詳細。 modify_ ソースはデフォルトでスクリプトです。標準入力から現在の対象を読み込み、新しい対象を標準出力に書き込みます。ファイルに文字列 chezmoi:modify-template が含まれている場合、そのマーカーを含む行は削除され、残りはテンプレートとして解釈されます。既存の対象は .chezmoi.stdin から参照できます。構造化ファイル(JSON、TOML、YAML)をきめ細かく編集したい場合はテンプレート形式を、実際のインタープリター(jq、awk、sed)が必要な場合はスクリプト形式を使います。
5. 安全な適用の手順
重要なファイルに影響する変更を適用する前に、次の3つの確認コマンドを実行してください。
chezmoi status # one line per changed file
chezmoi diff # unified diff of pending changes
chezmoi apply --dry-run -v # full plan, including scripts that would run
chezmoi apply # only after the above looks right
信頼できるマシンで通常のプルを行う場合:
chezmoi update # = git pull --autostash --rebase + apply
chezmoi git pull -- --autostash --rebase && chezmoi diff # preview only — no apply
6. 安全に編集する
chezmoi edit ~/.zshrc # opens source in $EDITOR, handles .tmpl + encryption
chezmoi cd # subshell in the source directory (for git operations)
chezmoi re-add # refresh source from current target after editing target
chezmoi merge ~/.zshrc # 3-way merge target ↔ source ↔ destination
chezmoi merge-all # 3-way merge every file whose actual ≠ target (add --init to re-render config first)
エディターの解決順序:edit.command → $VISUAL → $EDITOR → vi(Windows では notepad.exe)。エディターの処理時間が edit.minDuration(デフォルトは 1s)未満の場合、chezmoi は警告を表示します。これにより、「ファイルを開いたが実際には編集しなかった」というケースを検出できます。警告を無効にするには 0 を設定してください。
~/.local/share/chezmoi/encrypted_dot_ssh/... や *.tmpl ファイルをエディターで直接開かないでください。表示されるファイルは chezmoi が認識するファイルとは異なります。
7. 適用順序(メンタルモデル)
chezmoi apply は決定的です。実行のたびに、次の処理を行います。
- ソースの状態と適用先の状態を読み取り、目標状態を計算します。
- ターゲット名の ASCII 順で
run_before_スクリプトを実行します。 - ターゲット名の ASCII 順でエントリーを更新します。ディレクトリ(外部から展開されたディレクトリを含む)は、その中に含まれるファイルより先に書き込まれます。外部ファイルはこのフェーズで取得・展開されます。
- ASCII 順で
run_after_スクリプトを実行します。
影響する点:
run_before_スクリプトでは、外部ファイルが提供するファイルを読み取らないでください。外部ファイルが適用されるのはフェーズ 3 であり、それより前ではありません。- ターゲット名は、すべての属性プレフィックスを取り除いた状態で比較されます。
create_alphaとmodify_dot_betaの場合、ASCII では.beta<alphaとなるため、.betaがalphaより先に更新されます。 - chezmoi は、実行中にソースや適用先が変更されないことを前提としています。
run_before_スクリプトでそのいずれかに書き込むと、この前提に反するため、動作は未定義になります。
8. ファイルの一部の管理
chezmoi にファイル全体を管理させたくない場合は、そのファイルの所有者に応じてパターンを選びます。
modify_ — ファイルはユーザーが所有し、chezmoi はブロックを配置します。 ソースは既存のターゲットを標準入力から読み取り、新しいターゲットを標準出力に書き込みます。
スクリプト形式、modify_dot_zshrc:
#!/usr/bin/env bash
set -euo pipefail
# Strip any prior chezmoi block from the existing file …
awk '/# chezmoi:begin/{s=1;next} /# chezmoi:end/{s=0;next} !s'
# … then append the current managed block.
cat <<'EOF'
# chezmoi:begin
export EDITOR=nvim
alias g=git
# chezmoi:end
EOF
テンプレート形式(構造化ファイル向け)、modify_dot_config_private_app.yaml.tmpl:
{{- /* chezmoi:modify-template */ -}}
{{- $cfg := dict -}}
{{- if .chezmoi.stdin -}}{{- $cfg = .chezmoi.stdin | fromYaml -}}{{- end -}}
{{- $_ := set $cfg "telemetry" false -}}
{{- $_ := set $cfg "user" (dict "email" .email) -}}
{{ toYaml $cfg }}
if .chezmoi.stdin ガードは、ターゲットがまだ存在しない初回適用時に対応します。ラウンドトリップには fromJsonc / fromToml / fromYaml と toPrettyJson / toToml / toYaml を使用します。
.chezmoitemplates/ — ファイルは chezmoi が所有し、フラグメントを共有します。 再利用可能なブロックを .chezmoitemplates/ の下に置き、通常のテンプレートから {{ template "name" . }}(または、結果を関数に渡す必要がある場合は includeTemplate "name" .)で呼び出します。
.chezmoitemplates/zsh-prompt # one file
dot_zshrc.tmpl # {{ template "zsh-prompt" . }}
dot_config/fish/config.fish.tmpl # {{ template "zsh-prompt" . }} too
所有者に応じてパターンを選びます。 ユーザーが管理対象ブロック以外を自由に編集できるファイルには modify_ を使います。chezmoi がファイル全体をレンダリングするものの、共通セクションを再利用したい場合は .chezmoitemplates/ を使います。1 つのターゲットで両方を混在させるのは、たいてい望ましくありません。
厳守すべきルール
これらは譲れないルールです。それぞれ、実際に起こりうる危険を防ぐものです。
- 平文のシークレットは、プライベートリポジトリであっても決してコミットしないでください。 リポジトリは漏えいしたり、フォークされたり、ログに記録されたり、バックアップされたりします。
references/secrets.mdからバックエンドを選んでください。 - 暗号化されたソースファイルやテンプレート化されたソースファイルを直接編集しないでください。
chezmoi edit $TARGETを使って、復号とテンプレートのラウンドトリップを行ってください。 - 共有ファイルや重要なファイルに適用する前に、必ず確認してください —
chezmoi diffまたはchezmoi apply --dry-run -vを使います。ディレクトリに対するexact_は、管理対象外のエントリーを削除します。事前にその動作を確認してください。 prompt*テンプレート関数は、設定ファイルのテンプレート(.chezmoi.toml.tmpl)でのみ使用してください。 通常のドットファイルテンプレートで使うと、適用・差分確認・状態確認のたびにプロンプトが表示され、自動化の妨げになります。
シークレットの選択ツリー(概要)
詳しくは references/secrets.md を参照してください。リポジトリごとに、必ず 1 つだけ選びます。
- パブリックリポジトリ + クラウド型パスワードマネージャー → 1Password CLI / Bitwarden のテンプレート関数。シークレットは適用時に取得され、ディスクには保存されません。
- プライベートリポジトリ + オフラインでも使いやすい方式 → age(
encrypted_プレフィックス)。ID は~/.config/chezmoi/key.txtに置き、リポジトリの外で管理します。 - チーム内で共有する場合 → SOPS で暗号化した
.chezmoidata/secrets.yaml。 - エアギャップ環境 / 初回ブートストラップ → Git の追跡対象外にした平文の
.chezmoidata/local.yaml(一時的な方法であり、長期的な解決策ではありません)。
バックエンドを混在させても、管理対象が増えるだけでセキュリティは向上しません。
テンプレートのクイックリファレンス
詳細は references/templating.md を参照してください。
{{- if eq .chezmoi.os "darwin" }}
export HOMEBREW_PREFIX="/opt/homebrew"
{{- else if eq .chezmoi.os "linux" }}
export PATH="/usr/local/bin:$PATH"
{{- end }}
{{- if and (eq .chezmoi.os "darwin") (lookPath "brew") }}
# brew is installed
{{- end }}
email = {{ .email | quote }}
組み込みのテンプレート変数には、.chezmoi.os、.chezmoi.arch、
.chezmoi.hostname、.chezmoi.username、.chezmoi.homeDir、
.chezmoi.sourceDir があります。ユーザー定義データは、chezmoi.toml
の [data]、または任意の .chezmoidata/*.{toml,yaml,json} ファイルに格納します。
chezmoi は Go の missingkey=error オプションを使ってテンプレートを実行するため、
{{ .gitub.user }} のようなタイプミスがあると、空の値として出力されるのではなく、
適用が失敗します。具体的な理由がある場合に限り、[template] options = ["missingkey=zero"]
で上書きしてください。タイプミスの検出機能を失うことは、ほとんどの場合その価値がありません。
シンボリックリンクのターゲットでは、レンダリング結果の先頭と末尾の空白は
削除され、結果が空の場合はシンボリックリンクが削除されます。ファイルのターゲットでは、
レンダリング結果が空の場合にファイルが削除されます(ファイルを残すには empty_ プレフィックスを使います)。
特殊なファイルとディレクトリ
ソースディレクトリ内で . から始まる項目は、以下の特殊な項目を除き、すべて無視されます。
これらは、すべての操作で次の順に評価されます。
.chezmoiroot → .chezmoi.<fmt>.tmpl → データファイル → .chezmoitemplates/
→ .chezmoiignore → .chezmoiremove → 外部ファイル → .chezmoiversion。
| パス | 役割 |
|---|---|
.chezmoiroot | ソースルートとして使うサブディレクトリを指定する1行のファイル |
.chezmoi.<fmt>.tmpl | 初回の chezmoi init 時(および --init 時)に使う設定ファイルのテンプレート |
.chezmoidata.<fmt> / .chezmoidata/ | いずれかのテンプレートをレンダリングする前に、テンプレートの . 名前空間へマージされるデータ |
.chezmoitemplates/ | 再利用可能なテンプレートフラグメント({{ template "name" . }}) — ターゲットファイルはありません |
.chezmoiscripts/ | ターゲットファイルに紐付かないスクリプト。run_before_ / run_after_ に従います |
.chezmoiignore | ターゲットごとの無視リスト — ソースからの相対パスで指定し、テンプレート化できます |
.chezmoiremove | 適用時に削除するターゲット — テンプレート化できます |
.chezmoiexternal.<fmt> / .chezmoiexternals/ | 適用時に URL からファイルやアーカイブを取得します |
.chezmoiversion | このソースリポジトリで必要な chezmoi の最小バージョン |
.chezmoiignore はソースからの相対パス(例:dot_zshrc)と照合します。
ターゲットパスではありません。これはよく間違えられます。
<fmt> は toml、yaml、json、または jsonc を表します。ディレクトリ形式
(.chezmoidata/、.chezmoiexternals/)は、同じ接頭辞を持つファイル形式の項目と
内容を辞書順にマージします。設定を複数のファイルに分割したり、役割ごとに外部ファイルを
組み合わせたりするのに便利です。
やってはいけないこと
- 競合するドットファイルマネージャーや、
chezmoi applyを囲むシムを書く - テンプレートまたは暗号化されたファイルを、
~/.local/share/chezmoi/内で直接編集する - 「プライベート」リポジトリに
.env/secrets.yamlをコミットする - 共有マシンで事前に
chezmoi diffを実行せずにchezmoi applyを提案する .chezmoi.toml.tmpl以外でprompt*テンプレート関数を使う- 明確な理由を書き残さずに、同じリポジトリで複数のシークレットバックエンド(age + 1Password + SOPS)を混在させる
注意点
- テンプレート化されたスクリプトの実行時に
fork/exec ...: exec format errorが発生する場合は、#!の前に改行が入っています。最初のテンプレート行の閉じる}}内に-を追加すると、その改行を抑制できます。 - スクリプトで
fork/exec ...: permission deniedが発生する場合は、$TMPDIRがnoexecでマウントされています。chezmoi.tomlでscriptTempDirを設定してください。 - テンプレート内の Windows 改行コード(CRLF)によって、Linux/macOS でシェルスクリプトが壊れることがあります。dotfiles リポジトリの
.gitattributesに* text eol=lfを追加するか、core.autocrlf = inputを設定してください。 - 新しいマシンで
.chezmoi.toml.tmplが存在する前にchezmoi initを実行すると、マシンごとのプロンプトが警告なくスキップされます。ホスト固有のファイルを追加する前に、そのテンプレートをコミットしてください。 - 問題が発生したときに最初に実行するコマンドは
chezmoi doctorです。不足している依存関係(op、ageなど)、不正なパス、シェル統合の問題をまとめて報告します。 - Context7 を利用できない場合があります。chezmoi CLI は
chezmoi helpとchezmoi help <command>で自己文書化されているため、そちらを利用してください。 ~/.config/chezmoi/に設定ファイルが2つ(たとえばchezmoi.tomlとchezmoi.yamlの両方)あると、エラーになります。「最初のファイルが優先」されるわけではありません。形式を移行する際は、同じコミットで古いファイルを削除してください。- 設定形式は拡張子で判定されます。通常とは異なるパスから設定をパイプする場合は、
--config-formatで形式を指定してください。 chezmoi <unknown>は失敗する前に、$PATH上のchezmoi-<unknown>(git 形式のプラグイン規約)を探します。リポジトリ内のヘルパーを追加する際に便利ですが、タイプミスによって無関係なバイナリが警告なく実行されると意外に感じることがあります。
リファレンス URL インデックス
chezmoi のドキュメントは頻繁に更新されます。数回のリリースごとに、新しいテンプレート関数、新しい設定キー、新しいプレフィックスが追加されます。このスキルの範囲を超える質問の場合は、トレーニングデータから推測するのではなく、最新のページを取得してください。 mcp__tavily__tavily_extract(単一 URL、extract_depth: "advanced"、format: "markdown")を優先してください。正規の
/reference/* コンテンツが直接返されます。Context7 はフォールバックとしてのみ使用してください。
Tavily_map やクロールは行わないでください。以下の URL は安定しているため、該当するものを選んでください。
呼び出し例:
mcp__tavily__tavily_extract(
urls: ["https://www.chezmoi.io/reference/templates/functions/jq/"],
extract_depth: "advanced",
format: "markdown",
)
各項目の場所:
| トピック | URL |
|---|---|
| 概念(ソース/ターゲット/宛先/ワーキングツリー) | /reference/concepts/ |
| ターゲットの種類ごとのソース状態属性の順序 | /reference/source-state-attributes/ |
| ターゲットの種類(ファイル/ディレクトリ/シンボリックリンク/スクリプト/変更/作成/削除) | /reference/target-types/ |
chezmoi apply の適用順序 | /reference/application-order/ |
| すべてのコマンドラインフラグ(グローバル/共通/開発者向け) | /reference/command-line-flags/ |
コマンドごとのリファレンス(chezmoi <name>) | /reference/commands/<name>/ |
| 設定ファイルの構造 | /reference/configuration-file/ |
| フック(read-source-state/apply など) | /reference/configuration-file/hooks/ |
| 拡張子ごとのスクリプト用インタープリター | /reference/configuration-file/interpreters/ |
特殊ファイル(.chezmoiignore など) | /reference/special-files/<name>/ |
特殊ディレクトリ(.chezmoidata/ など) | /reference/special-directories/<name>/ |
テンプレート変数(.chezmoi.os など) | /reference/templates/variables/ |
テンプレートディレクティブ(chezmoi:template: など) | /reference/templates/directives/ |
| 組み込みテンプレート関数 | /reference/templates/functions/<name>/ |
init テンプレート関数(promptBoolOnce など) | /reference/templates/init-functions/<name>/ |
| パスワードマネージャー用テンプレート関数 | /reference/templates/<vendor>-functions/<name>/(1password、bitwarden、dashlane、doppler、ejson、gopass、keepassxc、keeper、keyring、lastpass、pass、passhole、protonpass、vault、aws-secrets-manager、azure-key-vault、secret) |
| GitHub テンプレート関数 | /reference/templates/github-functions/<name>/ |
| プラグイン | /reference/plugins/ |
目安:「プレフィックス X は何をするのか」という質問には → source-state-attributes、「chezmoi <cmd> は何をするのか」には → commands/<cmd>、「Y を保持するテンプレート変数は何か」には → templates/variables、「Z からシークレットを読み取る方法」には → templates/<vendor>-functions を参照してください。必要なページだけを mcp__tavily__tavily_extract で取得してください。単一 URL、advanced depth を指定すれば、回答は常に、最後にこのスキルが編集された時点の知識ではなく、今日時点の正規ドキュメントに基づいたものになります。