yadm + mise で dotfiles 環境構築を整理する
はじめに
Dotfiles についてご存知でしょうか?
.bashrc, .vimrc のような dot 文字 (.) から始まる設定ファイルをまとめたところを由来として、普段用いる開発ツールのための様々な設定ファイルをまとめたものを dotfiles と呼びます。
これらの設定が有効になった開発環境というのはエンジニア/開発者にとって我が家 ($HOME) のようなものであり、生産性の高い快適な開発体験を実現するために無くてはならないものです [1]。
特に、新しい環境で開発を行う際には真っ先に dotfiles が設定された開発環境を整えるというのが、開発に集中できる状態に素早く入るために重要です。
私の場合には、最近複数のマシンや開発用コンテナの中で開発を行う必要のある状況が多く、こうした環境で素早く環境構築を行うために課題を感じている状態でした。
今回、 yadm と mise という 2 つのツールを中心に dotfiles 環境を再整理することで、開発環境構築の体験をかなり改善することができたので紹介します。
やりたいこと
私のユースケースでは、以下の要件を満たすことが重要と考えていました。
- コンテナ/新規マシン (ユーザー権限) で簡単に環境構築したい
- セットアップスピードも重要 (特にコンテナ)
- 設定をできるだけ低コストで維持したい、学習コストを小さくしたい
物理的に異なる複数のマシンやコンテナ内での開発が多く、各環境で同じ開発体験を素早く再現したいといと考えていました。
マシンによっては管理者権限を持っていないケースもあり、一般ユーザー権限のみで設定できることも必須要件になります。
コンテナでは基本的にゼロからの環境構築が必要になるため、セットアップ速度も重要で、環境構築は長くとも 1-2 分で終わらせたいです。
さらに、環境構築方法はできるだけ簡単に、低コストで維持したいです 設定するのが面倒 。
また、学習コスト面では重厚なフレームワークや言語を学習せずとも簡単に使えるほうが望ましいです。
課題感
Dotfiles による設定管理自体は以前から運用していたのですが、環境構築の方法がアドホックで、自動化できていない部分も多く、課題を感じていました (改修前の commit)。
ひとつは、一連の環境構築手順を自動化できておらず、一部設定ファイルの symlink 作成など、手動で行わなければいけない手順が残っていました。
また、一部手順は (別リポジトリの) 自作スクリプトで自動化していましたが、ツールごとの個別のインストール/アンインストール手順の整備などが負担となり、ツールの追加やバージョンアップの手間が大きくなってしまっていました。
このような状況のなか、
- マシンによって開発環境に微妙に差が出てしまう
- 後回しにしていた設定のせいで作業が中断してしまう
- 環境構築手順を自動化しようとすると、今度は自作スクリプトの改修に時間がかかってしまう
といった問題を抱えていました。
yadm/mise について
今回、上述のような環境構築の課題を yadm と mise という 2 つのツールを中心に dotfiles を再整理することで、大きく状況を改善することができました。
これらのツールが自分のケースでどのように重要だったのか紹介します。
yadm
yadm (Yet Another Dotfiles Manager) は、 Git ベースの dotfiles manager です。
yadm では設定ファイルの実体を直接 $HOME 上に配置して管理するという構成をとっています。
そのため、設定ファイルの copy や symlink といった追加のレイヤを挟まないシンプルな管理方法が特徴です。
技術的には、 git の worktree ($HOME) と .git ディレクトリ (~/.local/share/yadm/repo.git) を分離することによって実現されています。
yadm の実体は 2000 行程度の shell script で、実装も比較的理解しやすいです。
yadm は固有の組み込みサブコマンド (clone, bootstrap, alt 等) 以外に対しては、単に git コマンドの wrapper として振舞います。
そのため、基本的に Git でできることは全て yadm でもできるという柔軟性を持っています。
自分のユースケースとしては以下の点が特にうれしかったです。
-
$HOME上に配置したファイルを直接管理できるため、操作がシンプル - git に習熟していればすぐに理解できるため、学習コストが低い
- 強力な Git 操作を全てそのまま適用できるため、柔軟な運用/カスタマイズが可能
mise
mise は開発用ツールや言語ランタイムを管理できるパッケージマネージャです。
"meez" のように発音するそうです。
apt のようなシステムパッケージマネージャと違い、ユーザー権限で全てのパッケージを管理できます。
また、 toml 形式のシンプルな設定ファイルで必要なツール類を宣言できます。
開発ツールと言語ランタイムの両方を管理することができて、例えば Neovim と node が必要な場合には以下などのように記述できます。
[tools]
node = "lts"
neovim = "0.12.2"
自分のユースケースで嬉しかったのは特に以下の点です。
- 全てのパッケージをユーザー権限で管理できる
- Neovim, ripgrep などの開発ツールや node, deno などの言語ランタイムをまとめて管理できる
- シンプルな設定ファイルを用いて必要なツール類をまとめて宣言できる
mise には他にもプロジェクトごとのツールの自動バージョン切り替えなどの機能もありますが、今回のユースケースでは以上の点だけで十分に有用でした。
できたこと
最終的には、クリーンな環境 [2] から以下のコマンドのみでセットアップ (設定ファイルの配置, ツールのインストール) が完了する状態を実現できました。
curl -fsSL https://raw.githubusercontent.com/sankantsu/dotfiles/main/bootstrap.sh | bash
以下の動画は、 Ubuntu 24.04 コンテナ環境で完全にクリーンな状態から dotfiles 環境構築を行ったデモになります [3]。
パッケージのダウンロード速度に大きく依存します [4] が、今回のケースでは 1 分以下で環境構築を完了できています。

自身の過去の dotfiles 管理で課題のかなりの部分を解消して、以下が達成できたと考えています。
- クリーンな環境から非常に簡易な手順かつ実用的な時間でセットアップできるようになった
- 手動セットアップ手順による作業負荷や再現性の低下の問題を大きく軽減した
- 自作ツール管理スクリプトのメンテナンスの労力を大幅に軽減した
工夫した点
今回の dotfiles 整理にあたって工夫した点を少しだけ紹介します。
bootstrap の構成
ほとんど何も入っていないクリーンな環境から一気にセットアップを完了できるというのが今回のひとつの要件でした。
これを実現するため、以下の 2 段階で初期化 (bootstrap) を行いました。
-
bootstrap.sh: yadm の自体のセットアップを行うカスタムの bash script -
.config/yadm/bootstrap: yadm bootstrap で実行される初期化スクリプト
最初のスクリプトは yadm のインストールと dotfiles の clone だけを行うシンプルなものにして、 mise のツールインストールなど残りの初期化は yadm が備えている bootstrap 機能を利用することにしました。
非設定ファイルの Sparse-checkout
Dotfiles のリポジトリにも、自分用とはいえ使いかたなどを記した README.md を project root に置いておきたいです。
しかし yadm が直接 $HOME に work tree を展開するという性質上、普通にやると README.md がホームディレクトリに鎮座することになってしまい、これはちょっと邪魔な気がしてしまいます。
また、 bootstrap.sh に関しても基本的には bootstrap が終わったあとは不要になるため残しておく必要はありません。
最も安易な解決策は bootstrap の最後でこれらの不要ファイルを rm 等で削除してしまうという方法が思いつきますが、こうすると git 管理下のファイルに不要な差分がついてしまいます。
今回は yadm の「 Git でできることはなんでもできる」というパワーを利用して、 git sparse-checkout の機能を活用することにしてみました。
以下のように特定ファイルだけ checkout を除外することで、比較的クリーンに home directory に実体化させるファイルを選択することができました。
Neovim での編集体験
yadm を利用しはじめたあと、 Neovim による dotfiles の編集体験に少し不満がありました。どちらも yadm のやや変則的な Git 運用に起因するものです。
- Dotfiles 管理下の設定ファイルの編集差分が gitsigns.nvim のような差分可視化ツールで表示されない
- 設定ファイルのほとんどが隠しファイル扱いであり telescope.nvim のような file finder で見つけにくい
- しかも
$HOME以下には dotfiles 管理外のファイルも大量にある
- しかも
調べたところ、すでに似たような課題感を持って対処している例があったため、参考にしました。
おおまかには、「 dotfiles 管理対象ファイルを正しく git 管理下のファイルとして認識させる」という方針で対処すれば良さそうです。
ここで、どうしたら「 git 管理下のファイル」として認識してくれるのかという点については、 Neovim 起動時に以下の環境変数を設定すれば良いということがわかりました (参考: Pro Git book)。
-
GIT_DIR=$HOME/.local/share/yadm/repo.git(.gitの実体) -
GIT_WORK_TREE=$HOME(work tree の path)
上記の参考例ではこの環境変数の設定を Neovim plugin で行っていますが、今回は yadm 自体の環境変数を設定する機能を利用して yadm enter nvim のように Neovim を起動することで解決しました。
また、この目的で非常に簡単な dotedit という wrapper script をつくって置いています。
File finder の問題については Git 管理下とさえ認識させてしまえば、あとは telescope.nvim 組み込みの :Telescope git_files を用いて dotfiles 管理対象のファイルのみを効率的に探すことができました。
Alternates による複数環境の対応
環境によって、必要だったり要らなかったり、あるいは環境依存で内容を変えたい設定ファイルがあったりします。
私の場合には例えば、以下のような項目が該当します。
-
.hammerspoon: Mac のときしか要らない -
.wezterm.lua: Mac 用と WSL 用で設定が違う。 SSH 環境 (GUI 無し) では要らない
このようなケースは yadm の alternates という機能を用いることでうまく扱うことができました。
おおざっぱには、例えば ##os.Darwin のような suffix をファイル名につけると該当する環境でのみ有効な設定の symlink がつくられるという仕組みで機能します。
$HOME にこれらの suffix 付きのファイルを不要に増やしたくない場合には、これらのファイルは .config/yadm/alt に押しこめておくことができます。
おわりに
今回の記事では、 yadm と mise という 2 つのツールを用いることで、 dotfiles 環境の構築を簡単かつ素早く行えるようにした取り組みを紹介しました。
今回の取り組みで、環境の再現性や自作スクリプトのメンテナンスの問題を軽減しつつ、新規環境からスクリプト一発で必要な環境が揃うところまで持っていくことができました。
Dotfiles にはそれぞれこだわりがあるところかと思いますが、この取り組みにどこか面白いと思ってもらえる部分があったなら、筆者としては幸いです。
ぜひみなさんの工夫も教えてください!
Discussion
yadm enter nvim
この手がありましたかー!完全に盲点でした(笑)