feat: nix-darwin と home-manager による macOS 環境の宣言的管理を導入 - #612
Conversation
Homebrew Brewfile ベースの環境管理から nix-darwin + home-manager への 移行を行い、再現性の高い宣言的な macOS 環境構築を実現する。 - flake.nix: nix-darwin + home-manager + nixpkgs-unstable の構成 - packages.nix: CLI ツールを Nix パッケージで管理(60+ パッケージ) - homebrew.nix: GUI アプリ(cask)・tap 依存・macOS 固有ツールは Homebrew で管理 - git.nix: git 設定を home-manager の programs.git で宣言的に管理 - zsh.nix: oh-my-zsh, direnv, シェルエイリアスを宣言的に管理 - hosts/darwin: macOS システム設定(Dock, Finder, キーリピート, Touch ID sudo) - Makefile: nix-switch/build/update/check コマンド追加 - .gitignore: nix build 成果物 (result) を除外 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughAdds a Nix-based macOS configuration (flake + nix-darwin + home-manager), replaces Homebrew Brewfile workflows with Nix targets in the Makefile, removes legacy Brewfile assets and dotfile exports, and introduces Home Manager modules for packages, git, and zsh plus a darwin host configuration. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Dev as Developer
participant Make as Makefile
participant DarwinRebuild as darwin-rebuild
participant Flake as nix flake (nix/flake.nix)
participant NixDarwin as nix-darwin
participant HomeMgr as home-manager
participant Homebrew as Homebrew (casks)
participant System as macOS system
Dev->>Make: run `make nix-switch`
Make->>DarwinRebuild: sudo darwin-rebuild switch --flake ./nix
DarwinRebuild->>Flake: evaluate `nix/flake.nix`
Flake->>NixDarwin: instantiate darwinConfiguration
NixDarwin->>HomeMgr: apply user home configuration
HomeMgr->>Homebrew: manage casks via Homebrew integration
HomeMgr->>System: install home packages, configure zsh/git
NixDarwin->>System: apply system settings (defaults, GC, sudo)
System-->>Dev: configuration applied
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🔍 AI Code Review (Local Hook)Models: Codex (default) / Gemini (default) 🤖 Codex Review指摘事項なし。差分は主に Nix 関連の新規導入で、明確に壊れる・危険・保守性を著しく損なう変更は確認できませんでした。 判定 🤖 Generated by post_pr_ai_review.py hook |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a8cee6b039
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| # Custom functions | ||
| if [[ -d "$HOME/.zsh/functions" ]]; then | ||
| for function in "$HOME"/.zsh/functions/*; do |
There was a problem hiding this comment.
Use null-safe glob before sourcing custom zsh files
The startup loops source files using plain * globs (e.g. "$HOME"/.zsh/functions/* and "$_dir"/post/*) after only checking that the directory exists; when those directories are present but empty, zsh will produce an unmatched-glob/source error (nomatch or a literal * path), which can interrupt shell initialization on fresh or partially migrated setups. Use a null-safe glob qualifier (like *(N-.)) consistently, as already done in the pre block.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (4)
nix/home/packages.nix (3)
31-31: Redundant:fzfis already installed byprograms.fzf.enable.
programs.fzf.enable = trueon line 67 already installsfzf. The package entry here is redundant.♻️ Suggested removal
# === Utilities === coreutils - fzf peco🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@nix/home/packages.nix` at line 31, The package entry "fzf" is redundant because programs.fzf.enable = true already installs it; remove the standalone "fzf" entry from the package list to avoid duplication and potential conflicts, leaving the configuration that enables fzf via programs.fzf.enable intact.
6-7: Redundant:gitis already installed byprograms.git.enable.
programs.git.enable = trueingit.nixalready addsgitto your packages. The explicitgitentry here is redundant.♻️ Suggested removal
home.packages = with pkgs; [ # === Development Tools === - git gh🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@nix/home/packages.nix` around lines 6 - 7, Remove the redundant explicit "git" package entry from the packages list in packages.nix since programs.git.enable = true (in git.nix) already provides git; edit the packages.nix list to keep other entries like "gh" but delete the "git" line so the package set doesn't duplicate programs.git.enable.
22-23:certbotandnginxmay need additional setup for actual use.These are typically run as services. As user packages, they're just CLI tools. If you need to run them as services, consider using nix-darwin's
servicesoptions or launchd configuration rather than just installing the packages.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@nix/home/packages.nix` around lines 22 - 23, The packages certbot and nginx are being installed as user packages but typically must be run as system services; instead of leaving them in the user package list, configure them as services: remove or keep just the CLI if you only need the commands, and enable proper service configuration for nginx (e.g. services.nginx.enable or an equivalent launchd/systemd service) and for certbot use an ACME/certbot service or scheduled job (launchd timer or systemd timer) so certificates are renewed and nginx is started; look for the occurrences of certbot and nginx in your package list and replace them with the appropriate service configuration (nix-darwin services or system-level service activation) or document that they are only CLI tools if you intentionally only wanted the binaries.nix/home/zsh.nix (1)
79-80: Hardcoded repository path reduces portability.The aliases use a hardcoded path
~/develop/github.com/keito4/config/nixwhich will break if the repository is cloned elsewhere or if someone forks this config. Consider using a variable or deriving the path dynamically.💡 Possible alternatives
Option 1: Define a variable for the config path:
sessionVariables = { PNPM_HOME = "$HOME/Library/pnpm"; NIX_CONFIG_PATH = "$HOME/develop/github.com/keito4/config/nix"; };Then use in aliases:
- nix-switch = "darwin-rebuild switch --flake ~/develop/github.com/keito4/config/nix"; - nix-update = "cd ~/develop/github.com/keito4/config/nix && nix flake update"; + nix-switch = "darwin-rebuild switch --flake $NIX_CONFIG_PATH"; + nix-update = "cd $NIX_CONFIG_PATH && nix flake update";Option 2: Use the Makefile targets via
make nix-switch/make nix-updatewhich already exist per the PR description.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@nix/home/zsh.nix` around lines 79 - 80, The aliases nix-switch and nix-update hardcode the repo path; change them to use a configurable variable (e.g., add NIX_CONFIG_PATH to sessionVariables alongside PNPM_HOME) and replace the hardcoded path in the nix-switch and nix-update alias values to reference that variable, or alternatively point those aliases to the existing Makefile targets (e.g., make nix-switch / make nix-update) so the commands work regardless of clone location; update the alias definitions that reference nix-switch and nix-update accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@nix/home/zsh.nix`:
- Around line 61-65: The post-directory sourcing loop is missing the zsh glob
qualifier used in the pre loop, so when $_dir/post is empty it will try to
source the literal glob; update the "post" loop that iterates over
"$_dir"/post/* to use the same (N-.) qualifier as the pre loop (i.e., iterate
over "$_dir"/post/*(N-.)) and keep the body that sources each config (the lines
referencing the post loop and ". \"$config\"").
- Around line 39-44: The for-loop over the function files uses the glob
"$HOME"/.zsh/functions/* which will expand to a literal string when the
directory exists but is empty; update the glob to use the zsh nullglob qualifier
(e.g., "$HOME"/.zsh/functions/*(N)) so the loop is skipped on empty directories,
keeping behavior consistent with the patterns used in _load_settings and
avoiding source errors; ensure the loop still iterates over each file and calls
source "$function" as before.
In `@nix/modules/homebrew.nix`:
- Around line 7-11: The onActivation block uses cleanup = "zap", which will
uninstall any Homebrew packages not explicitly listed (causing removal of tools
now managed by Nix); change this to a safer cleanup mode (or disable cleanup)
and ensure the activation sequence waits for the Nix profile switch before
running brew bundle: update the onActivation configuration (referencing
onActivation, autoUpdate, upgrade, cleanup) to use a non-destructive value
(e.g., disable cleanup or use a less aggressive flag) and add/ensure a
pre-cleanup step that runs nix-switch (or verifies nix/profile is active) before
invoking brew bundle so tools managed in nix/home/packages.nix are not removed
during migration.
---
Nitpick comments:
In `@nix/home/packages.nix`:
- Line 31: The package entry "fzf" is redundant because programs.fzf.enable =
true already installs it; remove the standalone "fzf" entry from the package
list to avoid duplication and potential conflicts, leaving the configuration
that enables fzf via programs.fzf.enable intact.
- Around line 6-7: Remove the redundant explicit "git" package entry from the
packages list in packages.nix since programs.git.enable = true (in git.nix)
already provides git; edit the packages.nix list to keep other entries like "gh"
but delete the "git" line so the package set doesn't duplicate
programs.git.enable.
- Around line 22-23: The packages certbot and nginx are being installed as user
packages but typically must be run as system services; instead of leaving them
in the user package list, configure them as services: remove or keep just the
CLI if you only need the commands, and enable proper service configuration for
nginx (e.g. services.nginx.enable or an equivalent launchd/systemd service) and
for certbot use an ACME/certbot service or scheduled job (launchd timer or
systemd timer) so certificates are renewed and nginx is started; look for the
occurrences of certbot and nginx in your package list and replace them with the
appropriate service configuration (nix-darwin services or system-level service
activation) or document that they are only CLI tools if you intentionally only
wanted the binaries.
In `@nix/home/zsh.nix`:
- Around line 79-80: The aliases nix-switch and nix-update hardcode the repo
path; change them to use a configurable variable (e.g., add NIX_CONFIG_PATH to
sessionVariables alongside PNPM_HOME) and replace the hardcoded path in the
nix-switch and nix-update alias values to reference that variable, or
alternatively point those aliases to the existing Makefile targets (e.g., make
nix-switch / make nix-update) so the commands work regardless of clone location;
update the alias definitions that reference nix-switch and nix-update
accordingly.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: b7f4ff89-7279-4e71-b13a-2a7923d1ee5c
⛔ Files ignored due to path filters (1)
nix/flake.lockis excluded by!**/*.lock
📒 Files selected for processing (9)
.gitignoreMakefilenix/flake.nixnix/home/default.nixnix/home/git.nixnix/home/packages.nixnix/home/zsh.nixnix/hosts/darwin/default.nixnix/modules/homebrew.nix
| # Custom functions | ||
| if [[ -d "$HOME/.zsh/functions" ]]; then | ||
| for function in "$HOME"/.zsh/functions/*; do | ||
| source "$function" | ||
| done | ||
| fi |
There was a problem hiding this comment.
Missing nullglob qualifier can cause errors on empty directory.
If ~/.zsh/functions exists but is empty, the glob "$HOME"/.zsh/functions/* expands to the literal string, causing source to fail. Use the (N) glob qualifier for consistency with the patterns used in _load_settings.
🐛 Proposed fix
# Custom functions
if [[ -d "$HOME/.zsh/functions" ]]; then
- for function in "$HOME"/.zsh/functions/*; do
+ for function in "$HOME"/.zsh/functions/*(N-.); do
source "$function"
done
fi📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| # Custom functions | |
| if [[ -d "$HOME/.zsh/functions" ]]; then | |
| for function in "$HOME"/.zsh/functions/*; do | |
| source "$function" | |
| done | |
| fi | |
| # Custom functions | |
| if [[ -d "$HOME/.zsh/functions" ]]; then | |
| for function in "$HOME"/.zsh/functions/*(N-.); do | |
| source "$function" | |
| done | |
| fi |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@nix/home/zsh.nix` around lines 39 - 44, The for-loop over the function files
uses the glob "$HOME"/.zsh/functions/* which will expand to a literal string
when the directory exists but is empty; update the glob to use the zsh nullglob
qualifier (e.g., "$HOME"/.zsh/functions/*(N)) so the loop is skipped on empty
directories, keeping behavior consistent with the patterns used in
_load_settings and avoiding source errors; ensure the loop still iterates over
each file and calls source "$function" as before.
| if [[ -d "$_dir/post" ]]; then | ||
| for config in "$_dir"/post/*; do | ||
| . "$config" | ||
| done | ||
| fi |
There was a problem hiding this comment.
Inconsistent glob qualifier: post loop missing (N-.).
The pre loop (line 51) uses (N-.) but the post loop does not. If the post directory is empty, this will attempt to source the literal glob pattern and fail.
🐛 Proposed fix for consistency
if [[ -d "$_dir/post" ]]; then
- for config in "$_dir"/post/*; do
+ for config in "$_dir"/post/*(N-.); do
. "$config"
done
fi📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if [[ -d "$_dir/post" ]]; then | |
| for config in "$_dir"/post/*; do | |
| . "$config" | |
| done | |
| fi | |
| if [[ -d "$_dir/post" ]]; then | |
| for config in "$_dir"/post/*(N-.); do | |
| . "$config" | |
| done | |
| fi |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@nix/home/zsh.nix` around lines 61 - 65, The post-directory sourcing loop is
missing the zsh glob qualifier used in the pre loop, so when $_dir/post is empty
it will try to source the literal glob; update the "post" loop that iterates
over "$_dir"/post/* to use the same (N-.) qualifier as the pre loop (i.e.,
iterate over "$_dir"/post/*(N-.)) and keep the body that sources each config
(the lines referencing the post loop and ". \"$config\"").
| onActivation = { | ||
| autoUpdate = true; | ||
| upgrade = true; | ||
| cleanup = "zap"; # Remove unlisted packages | ||
| }; |
There was a problem hiding this comment.
cleanup = "zap" may cause package removal during migration.
With cleanup = "zap", any Homebrew package not explicitly listed here will be uninstalled. Since many CLI tools (git, awscli, terraform, etc.) are now managed by Nix (nix/home/packages.nix) rather than listed in brews, they'll be removed from Homebrew. This is likely intentional, but ensure nix-switch is run successfully before brew bundle triggers cleanup, otherwise you may temporarily lose tools.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@nix/modules/homebrew.nix` around lines 7 - 11, The onActivation block uses
cleanup = "zap", which will uninstall any Homebrew packages not explicitly
listed (causing removal of tools now managed by Nix); change this to a safer
cleanup mode (or disable cleanup) and ensure the activation sequence waits for
the Nix profile switch before running brew bundle: update the onActivation
configuration (referencing onActivation, autoUpdate, upgrade, cleanup) to use a
non-destructive value (e.g., disable cleanup or use a less aggressive flag) and
add/ensure a pre-cleanup step that runs nix-switch (or verifies nix/profile is
active) before invoking brew bundle so tools managed in nix/home/packages.nix
are not removed during migration.
|
PR レビュー: nix-darwin + home-manager 導入 - 全体的に構成は明快で、Nix/Homebrew の役割分担の判断も合理的です。要対応: (1) ADR未作成 (CLAUDE.md違反) - Nixをパッケージ管理の中核として導入することは重大なアーキテクチャ変更であり docs/adr/ への ADR 作成が必要です。(2) ユーザー名・ホスト名がハードコード - flake.nix/home/default.nix/hosts/darwin/default.nix の複数箇所に個人固有値がリテラル埋め込みされており、テンプレートリポジトリとして他の開発者が使用できません。要検討: (3) cleanup=zap は破壊的でリスト外の全パッケージを削除します。(4) git が packages.nix と git.nix で二重定義されています。(5) nix-darwin を master 参照しており破壊的変更を取り込む可能性があります。(6) zsh エイリアスのパスがユーザー固有で Makefile と二重管理。(7) post ディレクトリで (N-.) glob が未使用でエラーの可能性。良い点: Homebrew/Nix 役割分担が明確、flake.lock による再現性確保、Touch ID sudo 設定、direnv+nix-direnv による環境分離、GC自動化。まとめ: ADR作成とハードコードされた個人情報の変数化が最低限のブロッカーです。 |
nix-darwin + home-manager への移行に伴い、Nix で管理されるようになった 既存ファイルを削除し、スクリプト・テスト・ドキュメントを更新する。 削除: - brew/MacOSBrewfile, StandaloneBrewfile, CategorizedBrewfile, categories.json - dot/.zshrc, dot/.zprofile (Nix home-manager で管理) - brew/README.md 修正: - script/export.sh, import.sh: macOS の brew/dotfile 処理を Nix に委譲 - test/config-validation.test.js: MacOSBrewfile テストを Nix flake テストに置換 - test/credential-filtering.test.js: .zshrc テストを削除 - Makefile: brew 系ターゲットを削除 - README.md, docs/tool-catalog.md: Nix 移行を反映 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
🎉 This PR is included in version 1.104.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
Summary
変更内容
新規ファイル
nix/flake.nixnix/flake.locknix/home/default.nixnix/home/packages.nixnix/home/git.nixnix/home/zsh.nixnix/hosts/darwin/default.nixnix/modules/homebrew.nix既存ファイルの変更
nix-switch/nix-build/nix-update/nix-checkコマンド追加result(nix build 成果物)を除外移行判断
Test plan
make nix-buildでビルド成功を確認make nix-switchで適用成功を確認(Xcode アップデートのみネットワークエラー)🤖 Generated with Claude Code
Summary by CodeRabbit