Mac 2台同期(MacBook Air + Mac mini)chezmoi dotfiles 設計書¶
作成: 2026-07-07 ステータス: 設計承認済み・実装待ち 実装セッションへ: このドキュメントだけで文脈なしに実装に入れるよう書いてある。不明点は推測せずユーザーに確認すること。
背景・目的¶
Mac mini を新規購入した。運用形態は以下のとおり。
- MacBook Air: メインの入力マシン(タイピングの大半はこちら)
- Mac mini: 常時稼働の自動化用 + 家でのサブ利用
開発環境(shell 設定・git 設定・Homebrew・Karabiner・macOS defaults 等)を「共通基盤は同期、マシン固有は分岐」の形で 2 台間で同期し、将来の再セットアップも 1 コマンドで再現可能にする。
受け入れ条件¶
- Air で
.zshrc等を変更 → push → mini でchezmoi update一発で反映される(逆方向も同様) - まっさらな Mac で
chezmoi init --apply <repo>相当の少数コマンドから、brew パッケージ・shell 設定・Karabiner・defaults まで再現できる - マシン別の差分(mini に GUI cask を入れない等)が role 変数の分岐で表現されている
- シークレット・SSH 秘密鍵が dotfiles リポジトリに一切含まれない
- 同期のズレ(ローカル改変・リモート behind・brew 乖離)が毎日自動チェックされ、ズレがあれば macOS 通知が出る
方式: chezmoi¶
比較検討の結果 chezmoi を採用(bare git repo 案・symlink 案は、マシン別分岐・1Password 統合・差分チェックを全部自作する必要があり不採用)。
- 原本(型紙):
~/.local/share/chezmoi/(git リポ。GitHub の private リポyk0817/dotfilesに push) - 実体:
chezmoi applyで$HOMEに生成(symlink ではなくファイル生成) - 導入:
brew install chezmoi
マシン識別: role 変数(hostname 直参照は禁止)¶
初回 chezmoi init 時に promptString で role(air / mini)を 1 回だけ質問し、~/.config/chezmoi/chezmoi.toml に保存する。.chezmoi.toml.tmpl をリポジトリに置いて実現する。テンプレート分岐は {{ if eq .role "mini" }} で書く。hostname のリネームや 3 台目追加に強くするための抽象化。
現状把握(2026-07-07 時点の Air の実測)¶
.zshrc(約 2.7KB): LANG/HISTFILE、compinit + zstyle、peco 連携(Ctrl-R 履歴・Ctrl-U cdr・git branch 選択lb・docker execde)、alias(gcc_p、ssh_jaist、ca、cda関数)、PATH 追加(google-cloud-sdk、~/bin、~/.local/bin/env(uv)、Rancher Desktop 管理ブロック、LM Studio ブロック).zprofile:brew shellenvのみ.bashrc(265B)、.vimrc、.gitconfig(user、insteadOfで https→ssh、fetch.prune)あり- Homebrew: formula 107 個、cask 6 個(1password-cli、ant、claude-code、drawio、gcloud-cli、rancher)、tap
anthropics/tap、npm グローバル多数(brew bundle dumpが npm/uv 行も出す) - Karabiner:
~/.config/karabiner/あり ~/.claude: 既にyk0817/claude-configで git 管理済み(dotfiles には混ぜない。mini ではクローンする)- シークレット: 1Password(op CLI)に集約済み
- 注意:
$HOME直下にコミット 0 件・branch master の git リポが存在する(過去の残骸)。dotfiles 移行の完了後に撤去する(下記「後片付け」)
dotfiles リポジトリの中身¶
| 対象 | 管理方法 |
|---|---|
.zshrc .zprofile .bashrc .vimrc |
dot_zshrc.tmpl 等。role 分岐あり |
.gitconfig |
dot_gitconfig(分岐不要ならテンプレートにしない) |
| Karabiner | ~/.config/karabiner/karabiner.json のみ管理(Karabiner が自動生成するバックアップ類は対象外。diff ノイズ防止) |
| Brewfile | Brewfile.tmpl を 1 ファイル。共通 CLI は両 role、GUI cask(drawio、rancher 等)や重い GUI は air のみ、のように分岐。mini に必要な常時稼働系(temporal 等)は mini 側にも |
| brew bundle 実行 | run_onchange_before_brew-bundle.sh.tmpl(Brewfile のハッシュをコメントに埋めて、変更時のみ brew bundle --file を再実行する chezmoi 定石パターン) |
| macOS defaults | run_onchange_darwin-defaults.sh.tmpl(キーリピート速度等。現行 Mac の実値を defaults read で拾って初期値にする) |
| sync-check | sync-check.sh 本体 + launchd plist(下記) |
.chezmoi.toml.tmpl |
role の promptString |
| README | 新マシン bootstrap 手順・日常運用(chezmoi edit に統一)を記載 |
同期対象にしないもの¶
- SSH 秘密鍵(1Password SSH Agent に移行。下記)
.zsh_history(マシンローカル)gh/gcloud/opの認証状態(各マシンで一度ログイン)- プロジェクトリポジトリ本体(mini には自動化系のみ手動クローン: temporal-workflows、research-orchestrator、st-japan-lab、ai-engineering-digest 等、必要になったもの)
~/.claude(claude-config として別管理継続)
よく使う CLI / MCP の棚卸し(2026-07-07 Air 実測)¶
Brewfile.tmpl の中身を推測しないための実測リスト。role 分岐の目安付き。line 41 の cask 一覧のうち claude-code は下記の移行で無効化する。
Homebrew formula(共通 = 両 role)¶
| CLI | 用途 | mini も必要か |
|---|---|---|
git / gh |
バージョン管理・GitHub | ✅ |
chezmoi |
dotfiles 同期(この仕組み自体) | ✅ |
gitleaks |
commit 前シークレット検知(hook) | ✅ |
op(1password-cli) |
シークレット取得・op run |
✅ |
go |
zotero-cli / personal-finance のビルド | ✅(zotero 使うなら) |
temporal |
Temporal CLI | ✅(mini=常時稼働の自動化) |
peco |
.zshrc の Ctrl-R / cdr / lb / de 連携 |
✅(無いと .zshrc が動かない) |
ghostscript / poppler |
pdf-compress・PDF 処理 | 任意 |
graphviz |
dot 図 | 任意 |
ollama / gollama |
ローカル LLM | mini がホストするなら✅ |
ccusage |
Claude Code 使用量表示 | 任意 |
Homebrew cask(GUI 寄り = 原則 air のみ)¶
| cask | 扱い |
|---|---|
drawio |
air のみ(GUI。CLI export だけ要るなら mini も可) |
rancher(Rancher Desktop) |
air のみ(重い GUI) |
gcloud-cli |
必要な role のみ |
ant |
ほぼ不要(niche) |
~~claude-code~~ |
Brewfile から外す。2026-07-07 にネイティブ install.sh 版(~/.local/bin/claude・自己更新)へ移行。cask/npm 版は自己再インストールで復活するので、Air で cask+npm を撤去してから両機ともネイティブ版に統一する |
npm グローバル(brew 管轄外 → 別スクリプトで npm i -g)¶
line 93 の「npm/uv 行の扱いは実装時判断」はこの3つを対象に解決する。
| パッケージ | コマンド | 用途 |
|---|---|---|
@googleworkspace/cli |
gws |
Google Workspace MCP のバックエンド |
@mermaid-js/mermaid-cli |
mmdc |
Mermaid→PNG(各種スキル) |
md-to-pdf |
md-to-pdf |
Markdown→PDF(zotero-upload 等) |
brew でも npm でもない自作 CLI¶
| CLI | 入れ方 | 依存 |
|---|---|---|
~/zotero-cli/zotero-cli + zotero-mcp |
リポを clone → go build |
Go 必須。Zotero CLI 兼 MCP バイナリ |
~/.claude/scripts/*.sh(bg-notify / block-secret-file-reads / task / drawio-auto-export / sync-home-repos) |
claude-config を clone すれば付いてくる | drawio-auto-export→drawio、bg-notify→macOS 通知 |
MCP は claude-config でも Brewfile でも同期されない¶
MCP サーバ定義(drawio / gws / zotero)は ~/.claude.json(リポ外・$HOME 直下)にあり、claude-config でも dotfiles でも同期対象外。mini では claude mcp add ... -s user で再登録する(env は 1Password 経由)。宣言的に揃えたいなら再登録手順を ~/.claude/scripts/ のセットアップスクリプトにして両機で流す。
シークレットと SSH¶
- GitHub 認証は 1Password SSH Agent に一本化。秘密鍵を 1Password に保管(既存鍵のインポートか新規生成かは実装時にユーザーに確認)し、
~/.ssh/configを chezmoi 管理にしてIdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"を指定。秘密鍵ファイルがディスクから消え、mini のセットアップは 1Password ログインだけで git push まで通る - 1Password 側の設定(Settings → Developer → SSH Agent 有効化)は GUI 操作なのでユーザーが行う(手順を README に書く)
- 設定ファイルに埋めたいシークレットが将来出てきたら、テンプレートの
onepasswordRead "op://..."で apply 時注入(リポには参照だけ残る)
同期自動チェック(sync-check)¶
sync-check.sh を dotfiles に含め、launchd(LaunchAgent)で毎日 1 回実行。ズレ検出時のみ osascript で macOS 通知を出す(正常時は無音)。チェック項目:
chezmoi status— 実体が原本からズレていないか(直接編集の事故検知)chezmoi git -- fetch+ behind 判定 — リモートの未取り込み更新~/.claude(claude-config)の dirty / behind / 未 pushbrew bundle check --file <Brewfile>— 宣言と実インストールの乖離
オプション(実装時にユーザーと相談): 既存の Claude Code SessionStart ブリーフィングに同チェック結果を 1 行追加する。
移行手順(実装フェーズのタスク順)¶
Phase 1: Air 側で dotfiles 構築¶
brew install chezmoichezmoi init→ 既存ファイルをchezmoi add(.zshrc.zprofile.bashrc.vimrc.gitconfigkarabiner.json).chezmoi.toml.tmpl(role prompt)を作成、.zshrc等をテンプレート化して role 分岐を導入brew bundle dumpを元にBrewfile.tmplを作成(npm/uv 行の扱いは実装時に判断。brew 管轄外なら別スクリプトに分離)- defaults スクリプト・brew bundle スクリプト・sync-check + launchd plist を作成
chezmoi applyして Air 上で差分ゼロ・シェル起動正常を確認(検証: 新しいターミナルで zsh が エラーなく起動し、alias/peco が機能すること)- GitHub に private リポ
yk0817/dotfilesを作成して push(リポ作成と push はユーザー承認を取る) - 1Password SSH Agent への切り替え(ユーザーの GUI 操作を含む)
Phase 2: mini 側でセットアップ¶
- 1Password アプリ導入・ログイン、SSH Agent 有効化
- Homebrew 導入 →
brew install chezmoi→chezmoi init --apply yk0817/dotfiles(role=mini と回答) gh auth login、~/.claudeをgit clone git@github.com:yk0817/claude-config.git ~/.claude- 自動化系リポを必要分クローン
- sync-check の launchd 登録確認、通知テスト
Phase 3: 後片付け¶
$HOME直下の空 git リポ(~/.git)を撤去(破壊的操作なのでユーザー確認のうえで)- 移行後の旧 SSH 鍵ファイルの扱い(削除 or 保管)をユーザーに確認
リスクと対処¶
| リスク | 対処 |
|---|---|
| 実体を直接編集 → 次の apply で上書きされ消える | 編集は chezmoi edit に統一(README に明記)。sync-check の status 検知が保険 |
| Karabiner の頻繁な自動書き換えで diff ノイズ | 管理を karabiner.json 1 ファイルに限定 |
| mini ヘッドレス時に 1Password agent ロックで git 認証失敗 | mini の 1Password 自動ロック設定を緩める(手順を README 化)。常時稼働ジョブが SSH を使う場合は要検証 |
run_onchange スクリプトの暴発(意図しない brew 実行) |
スクリプトは冪等に書く。brew bundle は --no-upgrade を検討 |
| chezmoi 学習コスト | README に日常運用チートシート(edit / apply / update / status)を書く |
実装時の注意(実装セッションへの申し送り)¶
- ユーザーのグローバルルール(
~/.claude/CLAUDE.md)に従う: 日本語 Conventional Commits、push 前にユーザー承認(dotfiles リポは新規なのでノート系例外に該当しない)、シークレット値を stdout に出さない - shell スクリプトを書く前に
~/.claude/docs/lang-rules/shell/*.mdを Read する gh repo createなどの外向き操作は実行前にユーザーに一言確認する- 1Password の GUI 設定・GitHub への公開鍵登録など、Claude が代行できない手順は明示的にユーザーへ依頼して止まる
作成: 2026-07-07 / 最終更新: 2026-07-17