setup-local-sdk について
プロジェクト内の `.dotnet/` に .NET SDK をインストールし、`global.json` で選択する手順を案内するスキルです。システム全体の SDK に変更を加えず、設定の確認や削除方法も扱います。
主な機能
- 01プロジェクト内への SDK インストール
- 02`global.json` の paths 設定
- 03ホストバージョン要件の確認
- 04OS 別のインストール手順
- 05必要に応じた workload のインストール
- 06チーム向けセットアップスクリプト
活用シーン
- 01プロジェクト単位での SDK 分離
- 02プレビュー版や指定バージョンの SDK 設定
- 03チームや CI 用の再現可能な設定準備
- 04ローカル SDK の削除による設定の取り消し
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ dotnet/ skills --skill setup-local-sdkインストール後、Claude Code で/setup-local-sdkを入力して読み込まれたか確認します。
詳細
setup-local-sdk
目的
.NET SDK をプロジェクトローカルの .dotnet/ ディレクトリにインストールし、global.json の paths 機能(.NET 10 以降)で設定する手順を説明します。
例では .NET 11 を使用していますが、プレビュー版でも安定版でも、どのバージョンでも動作します。
この方法では、完全に分離された SDK を利用できます。
- システム全体の .NET インストールは変更されません。
- プロジェクトのルートから
dotnetコマンドを実行すると、自動的に使用されます。 - 削除すれば元に戻せます(
rm -rf .dotnet/またはRemove-Item -Recurse -Force .\.dotnet)。
使用しない場合
- ユーザーがシステム全体へのインストールを希望している場合は、公式インストーラーを案内してください。
- ホストの
dotnetが v10 より古い場合は、pathsが存在しないことを説明して終了してください。 - ユーザーがランタイムのみのインストールを必要としている場合は、
pathsは SDK の解決にのみ適用されます。
入力/前提条件
| 入力 | 必須 | デフォルト | 備考 |
|---|---|---|---|
| チャネルまたはバージョン | いいえ | 11.0 | 例:11.0、STS、LTS、または 11.0.100-preview.2.26159.112 のような正確なバージョン |
| 品質 | いいえ | preview | daily、preview、ga のいずれか |
| jq | いいえ | — | 既存の global.json を修正する bash チームスクリプトで任意使用します。使用できない場合は、ファイルを上書きしないでください |
前提条件
- .NET 10 以降の SDK がグローバルにインストールされていること —
dotnet --versionを実行し、メジャーバージョンが 10 以上であることを確認します。 - curl(macOS/Linux)または PowerShell(Windows)が使用できること。
ワークフロー
ステップ 1 — インストールする SDK を確認する
ユーザーが指定していない場合は、希望する .NET SDK のバージョンを尋ねます(例:「最新の
.NET 11 プレビュー版」または 11.0.100-preview.2.26159.112 のような正確なバージョン)。
回答に応じて、--channel/--quality フラグまたは --version フラグを指定します。
ステップ 2 — .NET 10 以降のホストを確認する
ユーザーがすでに dotnet --version の出力を提示している場合は、そのバージョンをユーザーのマシンの
正確なバージョンとして扱います。エージェントのワークスペースのバージョンで上書きしないでください。2 つのバージョンが異なる場合は、ワークスペースのバージョンが異なることを説明したうえで、
ユーザーのマシン向けの案内を続けます。
dotnet --version
メジャーバージョンが 10 未満の場合は、何もダウンロードせずに終了します。paths 機能には .NET 10 以降のホスト SDK が必要です。まず .NET 10 以降をシステム全体にインストールしてから、ローカル SDK のセットアップに戻るようユーザーに伝えてください。
ステップ 3 — オペレーティングシステムを検出する
uname -s 2>/dev/null を実行します。成功した場合(MINGW*、MSYS*、CYGWIN* を含む。これらは Git Bash などの bash を使用できる環境です)は、bash/dotnet-install.sh を使用します。
失敗した場合(Git Bash を使っていないネイティブ Windows)は、PowerShell/dotnet-install.ps1 を使用します。
ステップ 4 — 既存のローカル SDK を確認する
macOS/Linux:
test -d .dotnet && echo "exists" || echo "not found"
Windows(PowerShell):
if (Test-Path -LiteralPath .\.dotnet) { "exists" } else { "not found" }
.dotnet/ が存在する場合は、新しいバージョンに更新するか、そのまま残してスキップするかを尋ねます。
ステップ 5 — インストールスクリプトをダウンロードして実行する
macOS/Linux:
INSTALL_SCRIPT="$(mktemp "${TMPDIR:-/tmp}/dotnet-install.XXXXXX")"
trap 'rm -f "$INSTALL_SCRIPT"' EXIT
curl -fsSL https://dot.net/v1/dotnet-install.sh -o "$INSTALL_SCRIPT"
bash "$INSTALL_SCRIPT" --channel <CHANNEL> --quality <QUALITY> --install-dir .dotnet
Windows(PowerShell):
$installScript = Join-Path $env:TEMP "dotnet-install-$([guid]::NewGuid()).ps1"
try {
Invoke-WebRequest -Uri 'https://dot.net/v1/dotnet-install.ps1' -OutFile $installScript
& $installScript -Channel <CHANNEL> -Quality <QUALITY> -InstallDir .dotnet
}
finally {
if (Test-Path -LiteralPath $installScript) {
Remove-Item -LiteralPath $installScript -Force
}
}
正確なバージョンを指定する場合は、チャネル/品質フラグの代わりに --version <VERSION>(bash)または -Version <VERSION>(PowerShell)を使用します。インストールスクリプトの配布元は、Microsoft の公式 URL である https://dot.net/v1/dotnet-install.sh と https://dot.net/v1/dotnet-install.ps1 です。
ステップ 6 — インストールしたバージョンを特定する
./.dotnet/dotnet --version # macOS/Linux
.\.dotnet\dotnet.exe --version # Windows
global.json に指定するため、正確なバージョン文字列(例:11.0.100-preview.2.26159.112)を記録します。
ステップ 7 — global.json を作成または更新する
{
"sdk": {
"version": "<INSTALLED_VERSION>",
"allowPrerelease": true,
"rollForward": "latestFeature",
"paths": [".dotnet", "$host$"],
"errorMessage": "Required .NET SDK not found. Run ./install-dotnet.sh (or .ps1) to install it locally."
}
}
paths:.dotnetを先に指定します(ローカルを優先)。$host$はシステム全体へのフォールバックです。rollForward: "latestFeature":最新プレビュー版またはフィーチャーバンドを固定しないインストールで使用します。- バージョンを正確に指定する場合:SDK の解決で別のフィーチャーバンドに移動しないよう、
rollForward: "disable"を使用します。 allowPrerelease:プレリリース SDK をインストールする場合にのみtrueに設定します。安定版では省略します。errorMessage:チーム用のインストールスクリプトを作成する場合(ステップ 10)にのみ含めます。それ以外では省略します。
global.json がすでに存在する場合は、慎重にマージします。既存のプロパティ(msbuild-sdks、tools など)を保持し、sdk セクションのみを追加または更新します。既存のファイルを先に読み込み、sdk オブジェクトを更新または追加してから、書き戻します。これにより、プロジェクト間で共有する設定(MSBuild 設定など)が失われないようにできます。変更する前に、必ず元のファイルをバックアップしてください(例:global.json.bak)。
最小構成(バージョンの固定が不要な場合):
{"sdk":{"paths":[".dotnet","$host$"]}}
ステップ 8 — .gitignore を更新する
macOS / Linux(または Git Bash):
grep -qxF '.dotnet/' .gitignore 2>/dev/null || printf '\n.dotnet/\n' >> .gitignore
Windows(PowerShell):
if (-not (Test-Path .gitignore) -or -not (Select-String -Path .gitignore -Pattern '^\.dotnet/$' -Quiet)) {
Add-Content -Path .gitignore -Value '.dotnet/'
}
ステップ 9 — ワークロードをインストールする(要望がある場合)
global.json と .gitignore の設定が完了してから実行してください。時間のかかるワークロードのインストールやプラットフォーム上の制約によって、基本的なローカル SDK のセットアップが使用できなくなるのを防げます。
ユーザーが MAUI、モバイル、ワークロード、Blazor WASM、またはクロスプラットフォームに言及した場合は、ローカルバイナリを使用してインストールします(sudo は不要です)。
./.dotnet/dotnet workload install <workload> # macOS/Linux
.\.dotnet\dotnet.exe workload install <workload> # Windows
確認します:./.dotnet/dotnet workload list(または .\.dotnet\dotnet.exe workload list)。
MAUI では、現在の OS とターゲットプラットフォームでサポートされているワークロードを選択します。Linux では、完全な maui メタワークロードは利用できません。Android がターゲットの場合は maui-android などのサポート対象ワークロードを使用するか、プラットフォーム上の制約を説明し、設定するターゲットを確認してください。
ワークロードコマンドには、必ずローカルの dotnet バイナリを使用してください。 ワークロードのメタデータは、ホストプロセスの dotnet ルートを基準に保存されます。システムの
dotnetを使用すると、メタデータが誤った場所に保存されます(dotnet/sdk#49825 を参照)。
ステップ 10 — チーム用のインストールスクリプトを作成する
ユーザーが「team」「share」「CI」「scripts」などに言及した場合は作成します。それ以外の場合は、作成を提案します。以下の例では global.json をバックアップし、既存の設定を保持します。既存の global.json を修正する必要がある場合、bash スクリプトは jq を使用します。jq がない場合は、ファイルの上書きを拒否し、手動でマージする設定を表示します。ステップ 1 で選択したインストール方法に合わせて、スクリプトの変数を調整してください。バージョンを正確に指定する場合は --version / -Version と rollForward: "disable" を使用します。チャネル指定のインストールでは、チャネルと品質を指定し、プレリリース SDK の場合にのみ allowPrerelease: true を設定します。global.json ですでに sdk.version が固定されており、ユーザーが主にチーム用スクリプトを必要としている場合は、そのバージョンをスクリプトで再利用し、先に global.json を更新します。バージョンを確認するためだけに、時間のかかる SDK のダウンロードを開始しないでください。ユーザーがセットアップとスクリプトの両方を求めている場合は、ダウンロードやワークロードのインストールに時間がかかっても再現可能なセットアップを用意できるよう、時間のかかるインストールを始める前にスクリプトと設定を作成します。
install-dotnet.sh:
#!/usr/bin/env bash
set -euo pipefail
INSTALL_DIR=".dotnet"
CHANNEL="11.0"
QUALITY="preview"
VERSION=""
ROLL_FORWARD="latestFeature"
ALLOW_PRERELEASE="true"
WORKLOADS=("${@}")
ERROR_MESSAGE="Required .NET SDK not found. Run ./install-dotnet.sh (or .ps1) to install it locally."
INSTALL_SCRIPT="$(mktemp "${TMPDIR:-/tmp}/dotnet-install.XXXXXX")"
GLOBAL_JSON_TMP=""
cleanup() {
rm -f "$INSTALL_SCRIPT"
[ -n "$GLOBAL_JSON_TMP" ] && rm -f "$GLOBAL_JSON_TMP"
}
trap cleanup EXIT
curl -fsSL https://dot.net/v1/dotnet-install.sh -o "$INSTALL_SCRIPT"
INSTALL_ARGS=(--install-dir "$INSTALL_DIR")
if [ -n "$VERSION" ]; then
INSTALL_ARGS+=(--version "$VERSION")
ROLL_FORWARD="disable"
else
INSTALL_ARGS+=(--channel "$CHANNEL" --quality "$QUALITY")
fi
bash "$INSTALL_SCRIPT" "${INSTALL_ARGS[@]}"
SDK_VERSION=$("$INSTALL_DIR/dotnet" --version)
write_global_json() {
if [ -f global.json ]; then
cp global.json global.json.bak
if ! command -v jq >/dev/null 2>&1; then
echo "global.json exists; install succeeded, but this script will not overwrite it without jq." >&2
echo "Merge these sdk settings manually so existing global.json properties are preserved:" >&2
cat >&2 <<EOF
{
"sdk": {
"version": "$SDK_VERSION",
"allowPrerelease": $ALLOW_PRERELEASE,
"rollForward": "$ROLL_FORWARD",
"paths": [".dotnet", "\$host\$"],
"errorMessage": "$ERROR_MESSAGE"
}
}
EOF
exit 1
fi
GLOBAL_JSON_TMP="$(mktemp "${TMPDIR:-/tmp}/global-json.XXXXXX")"
jq --arg version "$SDK_VERSION" --arg rollForward "$ROLL_FORWARD" --argjson allowPrerelease "$ALLOW_PRERELEASE" --arg errorMessage "$ERROR_MESSAGE" '
.sdk = ((.sdk // {}) + {
version: $version,
allowPrerelease: $allowPrerelease,
rollForward: $rollForward,
paths: [".dotnet", "$host$"],
errorMessage: $errorMessage
})
' global.json > "$GLOBAL_JSON_TMP"
mv "$GLOBAL_JSON_TMP" global.json
GLOBAL_JSON_TMP=""
else
cat > global.json <<EOF
{
"sdk": {
"version": "$SDK_VERSION",
"allowPrerelease": $ALLOW_PRERELEASE,
"rollForward": "$ROLL_FORWARD",
"paths": [".dotnet", "\$host\$"],
"errorMessage": "$ERROR_MESSAGE"
}
}
EOF
fi
}
write_global_json
grep -qxF '.dotnet/' .gitignore 2>/dev/null || printf '\n.dotnet/\n' >> .gitignore
[ ${#WORKLOADS[@]} -gt 0 ] && "$INSTALL_DIR/dotnet" workload install "${WORKLOADS[@]}"
echo "Done. SDK: $SDK_VERSION"
chmod +x install-dotnet.sh
install-dotnet.ps1:
param([string[]]$Workloads = @())
$ErrorActionPreference = 'Stop'
$installDir = '.dotnet'; $channel = '11.0'; $quality = 'preview'
$version = ''; $rollForward = 'latestFeature'; $allowPrerelease = $true
$errorMessage = 'Required .NET SDK not found. Run ./install-dotnet.sh (or .ps1) to install it locally.'
$installScript = Join-Path $env:TEMP "dotnet-install-$([guid]::NewGuid()).ps1"
try {
Invoke-WebRequest -Uri 'https://dot.net/v1/dotnet-install.ps1' -OutFile $installScript
$installArgs = @('-InstallDir', $installDir)
if ($version) {
$installArgs += @('-Version', $version)
$rollForward = 'disable'
} else {
$installArgs += @('-Channel', $channel, '-Quality', $quality)
}
& $installScript @installArgs
}
finally {
if (Test-Path -LiteralPath $installScript) {
Remove-Item -LiteralPath $installScript -Force
}
}
$sdkVersion = & "$installDir\dotnet.exe" --version
$globalJson = if (Test-Path 'global.json') {
Copy-Item 'global.json' 'global.json.bak'
Get-Content -Path 'global.json' -Raw | ConvertFrom-Json
} else {
[pscustomobject]@{}
}
if (-not $globalJson.PSObject.Properties['sdk']) {
$globalJson | Add-Member -MemberType NoteProperty -Name 'sdk' -Value ([pscustomobject]@{})
}
$updates = [ordered]@{
version = $sdkVersion
allowPrerelease = $allowPrerelease
rollForward = $rollForward
paths = @('.dotnet', '$host$')
errorMessage = $errorMessage
}
foreach ($entry in $updates.GetEnumerator()) {
$property = $globalJson.sdk.PSObject.Properties[$entry.Key]
if ($property) {
$property.Value = $entry.Value
} else {
$globalJson.sdk | Add-Member -MemberType NoteProperty -Name $entry.Key -Value $entry.Value
}
}
$globalJson | ConvertTo-Json -Depth 10 | Set-Content -Path 'global.json' -Encoding UTF8
if (-not (Test-Path .gitignore) -or -not (Select-String -Path .gitignore -Pattern '^\.dotnet/$' -Quiet)) {
Add-Content -Path .gitignore -Value '.dotnet/'
}
if ($Workloads.Count -gt 0) { & "$installDir\dotnet.exe" workload install @Workloads }
Write-Host "Done. SDK: $sdkVersion"
チームメンバーが実行できるよう、これらのスクリプトをリポジトリにコミットします。
ステップ 11 — SDK の解決を確認する
dotnet --version
出力がローカルにインストールされたバージョンと一致するはずです。一致しない場合は、global.json の場所、paths 配列の内容、ホストの dotnet バージョンが 10 以上であることを確認してください。
ステップ 12 — クリーンアップを要約して説明する
ユーザーに、SDK をインストールしたこと、global.json を設定したこと、.dotnet/ を gitignore に追加したこと、システムのインストールには変更を加えていないことを伝えます。クリーンアップでは、.dotnet/ を削除し、global.json から paths/errorMessage を削除し、必要に応じてインストールスクリプトも削除します。設定されたバージョン、paths、および errorMessage があれば確認できるよう、最終的な global.json の sdk 値(または短いスニペット)を記載します。ワークロードがリクエストされていた場合は、使用したローカルの dotnet workload install ... コマンドと、ワークロードの検証結果、またはインストールできなかった場合は正確な阻害要因を記載します。
よくある落とし穴
| 落とし穴 | 原因 | 対処方法 |
|---|---|---|
paths が無視される | ホストの dotnet が v10 未満 | .NET 10 以降をシステム全体にインストールする |
| 誤った SDK が解決される | 親ディレクトリに global.json がある | ディレクトリツリーをさかのぼって global.json を確認する |
| チームメイトに「SDK が見つからない」と表示される | .dotnet/ が gitignore されていて、インストールスクリプトが実行されていない | global.json で errorMessage を使う |
| ワークロードが見つからない | ローカルの dotnet ではなくシステムの dotnet を使用した | ./.dotnet/dotnet workload install を使う |
dotnet app.dll で誤ったランタイムが使われる | paths は SDK 専用であり、apphost 用ではない | dotnet run を使うか、DOTNET_ROOT を設定する |