GNU Stow から Chezmoi への移行

2026/06/19 2:09

GNU Stow から Chezmoi への移行

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

著者は、GNU stow から chezmoi へ移行し、3 台の Mac および Linux 仮想マシン間でのドットファイル管理を簡素化し、苦痛だったシンクリンクの競合問題を解決しました。破損したリンクの代わりに、chezmoi は実際のファイルをソースディレクトリ(

~/.local/share/chezmoi
)に格納し、ファイル名で特定の属性をエンコードします——具体的には
dot_
がパスマッピング用の指示、
private_
が制限された権限を示すもの、
.tmpl
は非標準パス(例:Anthropic の agent skills など)を扱う Go テンプレートです。この構成では、1 つの Git リポジトリが真実の単一ソースとして機能し、idempotent コマンドを利用して、zsh、git、shellcheck、ghostty、GitHub CLI、Claude Code、Codex agents といったツールの一貫したツリートップ構造を維持します。個人と勤務というアイデンティティの間での厳格な分離を実現するために、メインルートスクリプトによって管理される分かれた
Gitconfig
ファイルが使用されます。新しいデバイスのプロビジョニングは、
brew install chezmoi
を実行し、続いて
chezmoi init --apply
を実行することで処理され、この際
.chezmoiscripts/
内にあるスクリプト(before、after、onchange イベント用の特定のフックを含む)が実行されて、環境固有の論理を処理します。最後に、埋め込まれた SHA256 ハッシュチェックを備えた
Brewfile
により、Homebrew パッケージは必要な場合のみアップデートされ、多様なオペレーティングシステム間での信頼性があり競合のない管理が可能となります。

本文

GNU stow から chezmoi への移行:Mac dotfiles 管理の再構築

長年、GNU

stow
を使用して設定ファイル(dotfiles)を管理しておりましたが、2023 年には環境について冗談めかしたタイトルでブログ記事も執筆するほどでした。しかし、複数のデバイス間をまたぐシンボリックリンクの管理は負担となり、より優れたツールを探求し、最終的には同僚から紹介された
chezmoi
に切り替えました。現在、必要な機能はすべて満たされており、エージェント向けスキルファイルの追跡にも採用しています。

運用環境と課題

マシン構成

私の環境には以下の 3 台の Mac が存在します。

  • 「仕事用」MacBook Pro
  • 「個人用」MacBook Air
  • 「Mac Mini」:小規模な個人サーバーとして運用し、他の 2 台から主に SSH で接続。

これら 3 台はすべて同じ dotfiles を共有しています。また、数台の Linux ボックスを仮想マシンとして維持していますが、それらの設定は Ansible でプロビジョニングするため頻繁には必要としません。このワークフローは厳密にデスクトップ用マシン向けです。

stow を離脱した理由

stow は単一マシンの場合は非常に優れていましたが、マルチデバイス環境では以下の問題が生じました。

  • シンボリックリンクの双方向性

    • stow はリンクが「双方向」に機能するモデルです。
    • どのマシンでも設定ファイルを編集すると、変更はそのマシンの Git クローンを通じて直接書き込まれてしまいます。
    • 結果として、数ヶ月後には Air 上で行いながら記憶していない変更が見つかり、Pro でプッシュした内容と競合します。3 つのクローンを収束させるのは面倒でした。
  • 新マシンへの導入が困難

    • stow は実際のファイル上へのリンク作成ができないため、新規 Mac に Homebrew やツールをインストールした時点で
      ~/.zprofile
      ~/.gitconfig
      などが既に存在してしまいます。
    • セットアップ手順:リポジトリのクローン → 競合するファイルの手動削除 → パッケージごとの再ストウ化 → ナメ付けの記録など、手間がかかるものでした。
  • 機能の制限

    • stow はファイルのみを扱います。
    • Homebrew パッケージや macOS 自体の設定は、実行順序を管理する別々のスクリプト記述が必要です。

chezmoi の仕組みと特徴

chezmoi は

~/.local/share/chezmoi
というソースディレクトリ(通常 Git リポジトリ)を使用します。

ファイル名の符号化

  • 例:
    chezmoi add ~/.zshrc
    を実行すると、実際のファイルはこのディレクトリにコピーされ、名前が
    dot_zshrc
    となります。
  • ディレクトリ構造はホームディレクトリを反映し、ドット設定(dot)はすべて
    dot_
    プレフィックス
    で管理されます(例:
    ~/.config/gh/config.yml
    dot_config/gh/config.yml
    )。
  • 名前付けは手動ではなく、
    chezmoi add
    コマンドが自動的にパスから導き出してくれます。

メタデータと属性

  • _private
    プレフィックス
    :ファイルからグループおよびワールドへのアクセス権限を除去します(例:
    dot_config/gh/config.yml
    の設定)。
  • .tmpl
    サフィックス
    :ファイルを Go テンプレートに変換し、マシン固有のデータを参照できるようにします。

「apply」の動作

chezmoi apply
は逆方向に動作します。名前から読み取ったホームパス(例:
dot_zshrc
~/.zshrc
)へ実際のファイルとして書き込みます。

  • コピーはシンボリックリンクではなく、実際のファイル です。
  • ソースディレクトリが唯一の情報源となります。
  • ホームディレクトリのファイルとソースの一致度が保たれていない場合、
    chezmoi diff
    で差分を表示し、次の apply で元通りに戻してくれます。

最も気に入っている点:シンボリックリンクによる自動的な双方向書き込みがないため、リポジトリへの変更は意図的に行うことが保証されます。


リポジトリの構成概要

chezmoi cd
コマンドでサブシェルへ移行すると、以下の構造となります(一部のカスタマイズを除きデフォルト値を利用しています):

~/.local/share/chezmoi
├── .chezmoi.toml.tmpl          # chezmoi 設定テンプレート
├── .chezmoiignore              # ソースに残しホームに書込まないファイルの除外リスト
├── .chezmoiscripts             # apply 時の実行スクリプト
│   └── macos/                  # macOS 用スクリプト群
├── .gitignore
├── Brewfile                    # Homebrew パッケージ管理
├── README.md
├── dot_agents/                 # エージェント向けスキル (skills)
├── dot_claude/                 # Claude Code の設定とマッピング
├── dot_codex/                  # Codex の設定 (private_config.toml)
├── dot_config/                 # 各種設定 (gh, ghostty など)
├── dot_gitconfig               # アイデンティティを分断した git 設定
├── dot_shellcheckrc
└── dot_zsh_aliases             # zshrc のソースもここに格納
    └── dot_zshrc

Git とアイデンティティの分離

すべてのプロジェクトは以下の 2 つのディレクトリ下に存在し、主に gitconfig でルーターしています。

  • ~/canvas/werk/
    :仕事用(業務用メールアドレス)
  • ~/canvas/pers/
    :個人用(個人的なメールアドレス)
[includeIf "gitdir:~/canvas/pers/"]
    path = ~/.gitconfig-pers

[includeIf "gitdir:~/canvas/werk/"]
    path = ~/.gitconfig-werk

Note: この仕組みは chezmoi テンプレティングではなく、通常の Git 機能ですが、

chezmoi
はすべてのマシーン上でこれら 3 つのファイルが存在することを保証します。

マシン固有の設定

トップにある

.chezmoi.toml.tml
は、マシンの名前を一度だけ入力し、
~/.config/chezmoi/chezmoi.toml
に記憶させます:

{{- $machineName := promptStringOnce . "machineName" "machineName" .chezmoi.hostname -}}

[data]
    machineName = {{ $machineName | quote }}

これはリポジトリ全体における唯一のマシン固有データです。

除外ファイルの設定

.chezmoiignore
には
README.md
,
Brewfile
,
Brewfile.lock.json
が記述されており、これらはソースディレクトリに残しつつホームディレクトリへは書き込まれません(
.gitignore
で lock ファイルを除外しています)。


新しい Mac のセットアップ(ブートストラップ)

最初に Homebrew を導入した後、以下のコマンドだけで全設定が可能です。

brew install chezmoi
chezmoi init --apply \
    --promptString machineName=mini \
    https://github.com/rednafi/dotfiles.git
  • --apply
    オプション:追跡されているファイルを即時に配置します。
  • --promptString
    :対話形式ではなく、マシン名の質問に事前回答を与えます。

スクリプトの自動実行

.chezmoiscripts/
以下のスクリプトは
apply
の際に自動的に実行されます。ファイル名がタイミングを制御します。

  • before_
    :ファイル配置前に実行。
  • after_
    :ファイル配置後に実行。
  • run_onchange_
    :最初の apply で発火し、以降は内容変更時のみ発火(onchange 手法)。

Homebrew & macOS 設定スクリプト

Homebrew パッケージのインストールや macOS 自体の設定は、以下の順序で処理されます。

Brewfile の管理

Brewfile ハッシュをコメントに埋め込み、ファイルが変更されたら自動的に再実行するロジックです。

#!/usr/bin/env bash
# Brewfile checksum: {{ include "Brewfile" | sha256sum }}

# ... elided

brewfile={{ joinPath .chezmoi.sourceDir "Brewfile" | quote }}

"$brew_bin" bundle check --no-upgrade --file "$brewfile" >/dev/null 2>&1 \
    || "$brew_bin" bundle install --no-upgrade --file "$brewfile"

Brewfile の例

brew "chezmoi"
brew "fzf"
brew "gh"
brew "micro"
brew "ripgrep"
brew "uv"

cask "claude-code"
cask "codex"
cask "ghostty"
cask "raycast"

macOS 設定スクリプト

  1. マシンの初期化:ホスト名の設定、システムデフォルトの書き込み。
  2. アニメーション無効化
    defaults write
    を経由して UI アニメーションを無効にするスクリプト。

すべてのスクリプトは

Darwin
チェックで始まり、Linux ボックスでの実行時は早期終了(何事も発生しません)。


日常運用のルーティン

全体の作業フローは以下の約 5 つのコマンドで行えます。

1. 編集(ソースから)

通常はソースから編集します。

chezmoi edit --apply
はホームファイルを開き、エディタを閉じたときに即座に適用して書き込みます。

chezmoi edit --apply ~/.zshrc

逆方向の編集(ライブファイル)

インストーラーによる追加や、直感的な編集からライブファイルを直接改訂する場合、ホームディレクトリがソースよりも先行し、apply で変更を元に戻すことになります。これを防ぐには

chezmoi re-add
を使います。

# 単一ファイルの再インポート
chezmoi re-add ~/.zshrc

# ※複数のファイルがソースより先に移動している場合も一括で処理可能

2. Git の共有

リポジトリの状態を整理し、Git でコミットします。

chezmoi cd
git add -A
git commit -m "Update dotfiles"
git push
exit

他のマシンを追跡するには:

chezmoi init --apply https://github.com/rednafi/dotfiles.git

3. 差分の確認と適用

確認してから適用します。

chezmoi git pull -- --autostash --rebase
chezmoi diff
chezmoi apply --verbose

4. Brew の同期

パッケージが Brewfile と同步外れた場合、以下のコマンドで報告および修正を行います。

brew bundle check --no-upgrade --file "$(chezmoi source-path)/Brewfile"
brew outdated --greedy
brew bundle cleanup --file "$(chezmoi source-path)/Brewfile"

エージェントスキルの追跡

リポジトリへの最新な追加は、LLM エージェント向けのスキルファイルです。

スキルフォルダ構造

スキルとは、

SKILL.md
と必要な参照ファイルを持つフォルダです。

  • SKILL.md
    :フロントマター(タイトル・説明)と指示を含みます。
  • Anthropic の標準に従い、どこでも動作するようオープンスタンダードを採用しています。

環境での検出箇所

  • Codex
    ~/.agents/skills
    をデフォルトとして検出。
  • Claude Code:まだこの慣習に追いついておらず、
    ~/.claude/skills
    を探求します。

シンボリックリンクの統一 (
dot_claude
)

Claude Code が標準的な

~/.agents/skills
を使用していないため、chezmoi でマッピングしています。 ファイル:
dot_claude/symlink_skills.tmpl

{{ .chezmoi.homeDir }}/.agents/skills

この仕組みにより、以下の 3 つの要素が協力して機能します。

  1. ターゲットマッピング
    ~/.claude/skills
    dot_claude/
    を通じてマッピング。
  2. リンク指定
    symlink_
    プレフィックスにより、内容を示す場所へのシンボリックリンクとして作成するよう指示。
  3. テンプレート展開
    .tmpl
    サフィックスにより、
    {{ .chezmoi.homeDir }}
    がマシン固有に展開されます。

結果

lrwxr-xr-x 1 rednafi staff 29 Jun 11 17:37 /Users/rednafi/.claude/skills -> /Users/rednafi/.agents/skills

皮肉:stow を捨ててシンボリックリンクから逃れ、結局 chezmoi が管理するのは「私が必要な唯一つのシンボリックリンク」であるという状況に至りました。しかし、Anthropic の仕様追従のため仕方ありません。これで両方のエージェントが同じスキルを読み取り、Git は単一のコピーを保持できます。


利用のススメ

ここにあるものはすべて私の dotfiles リポジトリ上にあります。有用そうなものをご利用ください。

同じ日のほかのニュース

一覧に戻る →

2026/06/19 3:31

私は彼らに強制的同意は違法だと告げた。その結果、5年後エルクヨプは 180 万ユーロの損失を負った。

## Japanese 翻訳: 2021年7月、Elgiganten Kundklubb に加入後、著者はマーケティングメールからの脱退に際し、店舗会員の全キャンセルが必要となることを発見しました。この問題は、2021年7月30日に Elkjop のデータ保護官に通知され、GDPR 第 4 条 (11) 、第 7 条および第 21 条 (2)、また電子プライバシー指令への違反を指摘しました。Elkjop が同意と会籍の分離を拒否した際、著者は処理制限の要請(第 18 条)および開示請求(第 15 条)を提出することで対応をエスカレートさせました。その後、スウェーデン当局 (IMY) に提出された苦情(参照番号 DI-2021-6660)は、GDPR 第 56 条 (1) のワンストップ・ショップ規則に基づき、Elkjop Nordic AS がノルウェーに拠点を有することから、ノルウェーの Datatilsynet に移管されました。 2026年6月1日、Datatilsynet は Elkjop グループに対して 2,000 万ノルウェークローナ(約 180 万ユーロ)の制裁金を科しました。決定では、同意が強制されたものかつ非具体的であるため無効と認定され、GDPR 第 6 条 (4) の適合性評価に準拠せずに広告およびコンバージョン追跡のためにデータを利用したことは承認されていないと指摘されました。裁判所は GDPR 第 4 条 (11)、第 5 条 (1)(a)、第 5 条 (2)、第 6 条 (1)(a)、第 6 条 (1)(f) および第 6 条 (4) を引用しました。 著者は、この決定を GDPRhub を通じて初めて約五年後に発見し、IMY に対して苦情通知を行わなかったことについて(第 77 条 (2) )問い合わせを実施しており、五営業日以内に回答を求める旨を求めています。未解決の場合は Elkjop グループに対する民事訴訟を検討し、欧州委員会へのエスカレーションを行う可能性があります。この事例は重要な先例を示しています:企業は必須サービスに対して強制的な「オプトイン」条件を用いて、厳格な GDPR 同意要件を回避することはできません。

2026/06/18 20:45

トロージャンマルウェアの配布用に 1 万カ所の GitHub リポジトリを発見しました

## Japanese Translation: 数値のニュアンス、具体的なファイル形式、および著者がツールをリリースする能動的な役割に関する微妙な点を捉えるために、改善されたバージョンの使用が推奨されます。 **改善されたサマリー:** 2026 年 6 月時点での GitHub マルウェア分散に関する故事への最近の更新は、フォークではなく新しいリポジトリを利用してトロイの木馬マルウェアを分散させる高度なキャンペーンを明らかにしています。攻撃者は明確なパターンに従います:独自の名称とコントリビューターを持つリポジトリを作成し、合法的なプロジェクトからコミット履歴を複製して元の履歴を消去し、README に悪意のある ZIP アーカイブへのリンクで置換します。これらのアーカイブは特定の可执行ファイル(例:`Application.cmd`、`Launcher.cmd`、`loader.exe`)およびランダムな DLL を含んでおり、特に VirusTotal の直接リンクスキャンでは通常クリーンな結果が返される一方、アーカイブファイル自体をスキャンするとトロイの木馬が検出されます。以前の調査では、日間のリポジトリ更新の約 10% が数ヶ月または数年間継続する悪意ある脅威であることが特定されましたが、GitHub の手動報告プロセスは当初、応答期間が週間単位に及ぶため非効率的でした。この問題を解決するために著者は「Git Malware Finder」というスクリプトをリリースし、特定されたリポジトリの完全なリストを公開しました。最近、GitHub はこのツールでフラグ付けされたリポジトリを自動的に削除し始めており、既知のケースの大部分を排除しています。ただし、なぜ検出が現在主に新しいリポジトリに限られているか、キャンペーンの実際の規模と確認された一致との違い、そして検索インデックスおよび検出アルゴリズムから回避するために使用される具体的な戦術についてはまだ未解明な点が残っています。

2026/06/16 7:36

アメリカン・エキスプレス:回復性決済システムのためのセルベースアーキテクチャ

## 日本語訳: American Express は、2018 年以来、その決済エコシステムを、アーキテクチャに直接リゼリアンス(回復力)を組み込むことで強化し、取引の失敗がシステム全体に影響を与えることを極めて稀にするようにしています。核心となる革新は、「セルベース」設計であり、これはマイクロサービスとデータベースを特定の地域内で複数エリアにまたがることなく、それぞれが一つの障害ドメインとして機能するように、孤立した単位である「セル」にグループ化したものです。このアプローチは、不安定なモノリシック構造を、数百万件の日次ライブ取引を確実に処理する堅牢で自律的なインスタンスに置き換えます。速度の向上と隔離の確保のため、同期的ルックアップを避けるために静的データは事前に複製され、動的データについては Global Transaction Router が決定論的ルーティングを使用して、権威のあるデータを保持するセルへのトラフィックを誘導します。ログ記録などのクリティカルパス依存関係は非同期に保たれ、ブロッキングを防ぎます。また、安全な再試行のために一意の識別子を通じて冪等性を維持しています。システムには、不安定になっているセルを漸次的にドレインして健康なセルへトラフィックをシフトさせるインテリジェントなトラフィックシフティングのメカニズムが含まれており、これにより急激な障害なしに処理が行われます。ただし、このリゼリアンスには限界があり、取引が外部システム(例:カード発行会社)に到達した時点で、「戻れない点」に達し、それ以降はルーティングの変更が不可能となります。最終的に、この戦略はエラーを局所的境界内に収容することで安定したユーザー体験を保証し、要求の厳しい金融環境でハイアベイラビリティシステムを拡張するための実証済みブループリントを提供します。