dotfiles管理、miseに全部任せてみた
はじめに
miseとは
上記公式ドキュメントのHomeで強調されている通りですが、
- Dev Tools
- asdfのような開発ツール管理
- Environments
- direnvのような環境変数管理
- Tasks
- makeのようなタスクランナー
の3つの機能をコンセプトに挙げているCLIツールです。
zenn記事での実践例だと、以下が参考になります。
経緯
私は業務・個人開発共にmiseを愛用しているのですが、開発環境をIaCのように静的なmiseの設定ファイルで記述するのはプロジェクト(リポジトリ)単位がほとんどでした。
マシンに対してグローバルに適用するdotfiles管理での設定ファイル記述はmise Dev Tools機能の活用に留めていましたが、今回その他の機能も活用してdotfiles管理をmiseに集約したので記事として残します。
成果物
以下、dotfilesリポジトリです
今回紹介する設定ファイル群は以下のような配置になっています
dotfiles/
├── mise/
│ ├── config.toml
│ ├── hooks/
│ │ └── postinstall.sh
│ └── tasks/
│ └── fbr
├── .zshrc
└── setup-mise.sh
上記ディレクトリ構造の中でmiseのグローバル設定を置いているのは dotfiles/mise で
ln -nfs ~/dotfiles/mise ~/.config/mise
コマンドによって標準のグローバル設定として認識されます
CLIツールのbrew->mise Dev Tools管理移行
これまでグローバルな開発ツールに対しては、 mise use -g node のように動的にインストールをすることが多かったのですが、mise Registryに登録されているCLIツールは全てbrewからmise設定ファイル管理に移行しました。
miseはnpm,cargoといったBackend経由でのCLIインストールにも対応しているのでかなりの数のCLIツールを管理できます。
サンプルコード:
[tools]
node = "24"
python = "3"
# CLI tools (migrated from brew)
"aqua:sharkdp/bat" = "0.26.1"
"aqua:dandavison/delta" = "0.18.2"
"asdf:mise-plugins/mise-eza" = "0.23.4"
"aqua:junegunn/fzf" = "0.67.0"
"aqua:extrawurst/gitui" = "0.28.0"
"aqua:neovim/neovim" = "0.11.5"
...
例としてRenovateはmise設定ファイルのバージョン更新に対応しているので、静的バージョン管理を行うことができます。
"latest" 指定してローカルで mise up するのも楽だとは思いつつ、個人的にはバージョンアップ内容をRenovate PR上で確認できるのが嬉しいです。
環境変数のzshrc->mise Environments移行
これはmiseの基本機能であり移行をサボっていただけですが、 EDITOR = "nvim" のようなグローバル環境変数もmiseに集約させました。環境変数一覧はmise envコマンドから閲覧可能です。
サンプルコード:
[env]
XDG_CONFIG_HOME = "{{env.HOME}}/.config"
LANG = "ja_JP.UTF-8"
EDITOR = "nvim"
BAT_THEME = "Nord"
余談ですが、miseの環境変数管理はプロジェクト単位でスコープを切るのに加え、 MISE_ENV 引数で実行環境を切り替える機能が便利で推しています。
シェルエイリアスのzshrc->mise shell_alias移行
miseに集約するにあたりzshrcファイルをなるべく軽くしようと考えていたところ、2025年11月にリリースされた新機能として [shell_alias] の設定が可能でした。
サンプルコード:
[shell_alias]
vi = "nvim"
ls = "eza"
ll = "eza -l -g --icons --git"
la = "eza -l -g --icons --git -a"
lt = "eza --tree --icons --git-ignore"
zshのようなシェルに依存しないで書けるのがよいですね
カスタムスクリプトのzshrc->File Tasks移行
mise Tasksはmakeのようなタスクランナー機能を提供しますが、個人的にはその中でもTask別にファイルを切るFile Tasksの記法が気に入っています。グローバルに利用するカスタムスクリプトもmise Taskとして扱い、前述したシェルエイリアスで mise run Task呼び出しをできるようにしました。
以下は、fzfによってブランチ検索+checkoutするスクリプト例です
サンプルコード:
#!/usr/bin/env bash
#MISE description="checkout git branch (including remote branches)"
#MISE dir="{{cwd}}"
branch=$(git branch --all | grep -v HEAD | fzf +m) &&
git checkout $(echo "$branch" | sed "s/.* //" | sed "s#remotes/[^/]*/##")
[shell_alias]
fbr = "mise run fbr"
[task_config]
dir = "{{ config_root }}/tasks"
スクリプトファイルの #MISE dir="{{cwd}}" によって実行元ディレクトリでのブランチ検索を行う考慮が必要です。このような考慮から少々無理矢理感はありましたが、せっかくなので。
セットアップスクリプトのpostinstall移行
setup.shのような初期セットアップスクリプトがあったのですが、Dev Toolsのインストールを行う mise install コマンド実行後に発火する postinstall hooksによってセットアップスクリプトの実行をワークフロー化しました。
mise Registryには含まれていないツールのbrew installや、dotfilesディレクトリ内に含む各開発ツール設定ファイルのシンボリックリンクを貼るスクリプトを移行しています。
サンプルコード:
[settings]
experimental = true
[hooks]
postinstall = "sh ./hooks/postinstall.sh"
#!/bin/sh
dotfiles=$(cd "$(dirname "$0")/.." && pwd)
# Install brew tools (GUI apps, fonts, tools not in mise registry)
brew_tools=(procs arc wezterm font-hack-nerd-font visual-studio-code)
for tool in "${brew_tools[@]}"; do
if ! brew list "$tool" &>/dev/null; then
brew install "$tool"
fi
done
# Create symlinks
ln -sf "$dotfiles/.gitconfig" ~/.gitconfig
ln -sf "$dotfiles/git" ~/.config/git
ln -sf "$dotfiles/zellij" ~/.config/zellij
ln -sf "$dotfiles/wezterm" ~/.config/wezterm
ln -sf "$dotfiles/nvim" ~/.config/nvim
これにより mise install コマンドで開発ツールのインストールとセットアップを行うようになり、認知負荷が減りました。
hooks機能はexperimentalではありますがかなり便利なのでgeneral昇格に期待です。
まとめ
miseは抽象的に開発環境を扱うので、zshへの依存を減らすことができてハッピーです。
これからのAI開発にはIDEが要らないと呼ばれるような世の中ですし、改めてCLI環境に目を向けて楽しいdotfiles管理を行うことができました。
Discussion