outputs.devShells
誰が期待しているか?
どういう形式で書く必要があるか?
devShells.<system>.<名前>
Claude Code.icon
FlakesにおけるdevShellは、shell.nixをFlakeの世界で再定義したものです
nix developで入る開発環境を、Flakeのoutputsの中で宣言します。
基本構造
code:nix
{
description = "My project";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};
outputs = { self, nixpkgs }:
let
system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system};
in {
devShells.${system}.default = pkgs.mkShell {
packages = [
pkgs.nodejs_20
pkgs.go
];
shellHook = ''
echo "dev環境へようこそ"
'';
};
};
}
これでnix developを実行するとdefaultのdevShellに入れます。
出力スキーマの構造
devShellは**devShells.<system>.<name>**という2段の階層を持ちます。
code:_
devShells
├── x86_64-linux
│ ├── default ← nix develop
│ └── ci ← nix develop .#ci
├── aarch64-darwin
│ └── default
...
<system>: アーキテクチャごとに分ける必要がある(x86_64-linux, aarch64-darwinなど)。Flakesは「どのマシン用か」を明示することを強制する
<name>: defaultが省略時に使われる名前。複数の環境を名前で使い分けられる
複数環境の使い分け
code:nix
devShells.${system} = {
default = pkgs.mkShell {
};
# nix develop .#ci で入る
ci = pkgs.mkShell {
};
};
table:_
コマンド 入る環境
nix develop devShells.<system>.default
nix develop .#ci devShells.<system>.ci
nix developの挙動
引数なし → devShells.<現在のsystem>.defaultに入る
nix develop .#name → 名前指定
nix develop -c <cmd> → 環境に入ってコマンドを1回実行して抜ける(CIで便利)
nix develop github:owner/repo → リモートのFlakeの環境に直接入ることも可能
system分岐の定型句
<system>を手で書くのは面倒なので、実務では**flake-utils**でループするのが定番です。
code:nix
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let pkgs = nixpkgs.legacyPackages.${system};
in {
devShells.default = pkgs.mkShell {
};
});
}
eachDefaultSystemが主要な全アーキテクチャ分のdevShells.<system>.defaultを自動生成してくれるので、Linux/Macどちらでも動くようになります。
direnv連携
.envrcに以下を書くと、ディレクトリにcdするだけで自動的にdevShellが有効になります。
code:bash
use flake
毎回nix developを打つ必要がなくなり、エディタやターミナルが自動的にプロジェクトの環境を認識します。nix-direnvを使うとキャッシュも効いて高速です。