winget importのキッティング手順書をClaude Codeで再実行可能にする
現行端末のwinget exportから構成ファイルを起こし、手順書と再実行できるPowerShellスクリプトをClaude Codeで作り、検証用VMで2回流して冪等性を確かめる流れをまとめます。
Windows端末のキッティング手順書は、Wordや表計算に手で書くと、次の端末で実際に入っているアプリと食い違いがちです。winget import用の構成ファイル(JSON)を正にして、手順書とセットアップスクリプトをそこから起こせば、この食い違いは構造的に減らせます。この記事では、現行端末から構成ファイルを作り、Claude Codeで手順書とスクリプトを生成し、検証用VMで2回流して冪等性を確かめるまでを順に書きます。
winget exportとimportは何を受け渡すのか
winget exportは端末にインストール済みのアプリ一覧をJSONファイルに書き出し、winget importはそのJSONを読んでアプリをまとめて入れ直します。PCイメージの構築や開発環境の共有に使うコマンドです。
JSONの階層は次のとおりです。
| 項目 | 内容 |
|---|---|
Sources | 内容アプリのマニフェストの取得元 |
Packages | 内容インストール対象の集まり |
PackageIdentifier | 内容wingetのパッケージ識別子 |
Version | 内容任意。入れるバージョンを固定する場合に使う |
importはアプリを1つずつ順番にインストールします。入れられないアプリや、すでに入っているアプリがあった場合は、その旨を表示します。
押さえておく点が2つあります。1つ目は、exportが端末上の全アプリを対象にすることです。wingetのソースに一致するものが見つからないアプリは、警告が出て一覧に入りません。一致の判定にはソース側のマニフェストと、Windowsの「プログラムの追加と削除」にあるメタデータが使われます。2つ目は、Versionが入るのは--include-versionsを付けたときだけで、付けなければimportは最新版を入れることです。
現行端末から構成ファイルを起こす
基準にする端末で、PowerShellから書き出します。
winget export -o apps.json --accept-source-agreementsバージョンを固定したいときは--include-versionsを足します。キッティング直後の状態を全台で揃えたいなら固定、常に最新を入れたいなら付けない、という選び方です。Claude Codeをwinget install Anthropic.ClaudeCodeで入れた場合、WinGet経由のインストールは自動更新されません。固定した版のまま残るので、更新はwinget upgrade Anthropic.ClaudeCodeを手順書の定期作業に書いておく必要があります。
書き出したJSONは、そのまま使わずに編集します。不要なアプリを削ってから使えます。個人用のアプリ、検証で一時的に入れたツール、会社の標準に含めないものを外し、残りを「標準構成」として版管理(Git)に置きます。
取得元を限定して書き出す-s(--source)オプションもあります。wingetソースのアプリだけを標準構成にしたいときに使います。
Claude Codeに手順書の元データを読ませる
構成ファイルができたら、Claude Codeに2つの成果物を作らせます。手順書(Markdown)とセットアップスクリプトです。
apps.json は winget export で作った構成ファイルです。次の3つを行ってください。
1. PackageIdentifier を用途別(開発・業務・ユーティリティ)に分類した表を kitting.md に作る
2. apps.json で入れられない手作業(サインイン、ライセンス入力など)を別の節に分ける
3. apps.json を読んで winget import を実行する kitting.ps1 を作る
実行はせず、ファイルの作成だけにしてください。「実行はせず」と明示するのは、本番に近い端末でClaude Codeがインストールまで走らせないためです。出力された表は、見た目の整形に頼らず、PackageIdentifierがapps.jsonと1対1で対応しているかをdiffや目視で照合します。Claude Codeが「便利そうなアプリ」を一覧に足していないかを見る作業です。
import用スクリプトの骨格
スクリプトの中心はwinget import1行で、周りに確認抜きで最後まで走るための引数とログを置きます。次はkitting.ps1の例です。
param([string]$Config = "$PSScriptRoot\apps.json")
$log = Join-Path $PSScriptRoot ("kitting-{0:yyyyMMdd-HHmmss}.log" -f (Get-Date))
Start-Transcript -Path $log | Out-Null
winget import -i $Config `
--accept-package-agreements `
--accept-source-agreements `
--disable-interactivity `
--no-upgrade `
--ignore-unavailable
Stop-Transcript | Out-Null各引数の役割は次のとおりです。
| 引数 | 役割 |
|---|---|
--accept-package-agreements | 役割パッケージのライセンス同意のプロンプトを抑える |
--accept-source-agreements | 役割ソースの利用条件の同意プロンプトを抑える |
--disable-interactivity | 役割対話プロンプトを無効にする |
--no-upgrade | 役割すでに入っていれば更新をスキップする |
--ignore-unavailable | 役割入れられないアプリがあってもエラーにしない |
--accept-package-agreementsが受け入れるのは、パッケージ自身の使用許諾だけです。インストーラーが勧める同梱ソフトやオプション部品には作用しません。完全にサイレントにしたいときは、winget install側の説明にあるとおり--silentとの併用が前提で、importの引数一覧には--silentがありません。
--ignore-unavailableは、利用者側で見落としにつながる引数でもあります。入らなかったアプリがあってもスクリプトは最後まで進むので、ログで未導入のIDを確認する工程を手順書に残します。
Claude Codeに触らせる範囲を決める
キッティングは端末の状態を変える作業なので、Claude Codeの権限も絞っておきます。WindowsでPowerShellツールが使えるかどうかは構成で変わります。Git for Windowsが入っていないWindowsでは自動で有効になり、入っている場合はclaude.aiやConsoleのアカウントなら既定で有効です。Bedrockなどの経由ではCLAUDE_CODE_USE_POWERSHELL_TOOL=1で有効にします。
PowerShellの権限ルールはBashと同じ形で書けます。次は、読み取り系だけ許可して、アンインストールと削除を拒否する例です。
{
"permissions": {
"allow": [
"PowerShell(winget list *)",
"PowerShell(winget export *)"
],
"deny": [
"PowerShell(winget uninstall *)",
"PowerShell(Remove-Item *)"
]
}
}Remove-Itemの拒否が実際にどう効くかは、PowerShell Remove-ItemがClaude Codeでブロックされる条件に詳しくあります。
リポジトリのCLAUDE.mdには、作業の約束事を短く書いておきます。
## キッティング作業の規約
- 構成ファイルは apps.json だけを正とし、アプリの増減は JSON の編集で行う
- winget import には --accept-package-agreements と
--accept-source-agreements と --disable-interactivity を必ず付ける
- スクリプトは同じ端末で2回実行しても追加の変更が出ないこと
- import の実行は検証用VMでのみ行い、本番端末では行わない検証用VMで冪等性を確かめる
冪等性とは、同じスクリプトを何度流しても結果が同じになる性質です。キッティングでは、途中で失敗して流し直した端末と、一発で通った端末が同じ状態になることを意味します。検証用VMで次の順に確かめます。
検証用VMでの確認手順
- 1
素の状態を保存する
アプリを何も入れていないVMのスナップショットを取り、いつでも戻せるようにします。
- 2
1回目を流す
kitting.ps1を実行し、ログとwinget listの結果を保存します。 - 3
2回目を流す
同じVMで再実行します。2回目のログに「すでにインストール済み」の通知だけが並び、新規インストールが出ないことを見ます。
- 4
途中失敗を再現する
素の状態に戻し、ネットワークを切って1回目を中断してから、つなぎ直して流し直します。最終的な
winget listが正常な1回目と一致するかを比べます。 - 5
結果をClaude Codeに読ませる
ログと2つの
winget list出力を渡して、差分と未導入のIDを一覧にさせます。
1回目と2回目の差が出たときは、ログをClaude Codeに読ませて原因を切り分けさせます。たとえば、--no-upgradeを付け忘れて2回目に更新が走った、といった原因が見つかります。
--ignore-unavailableで隠れた未導入IDは、ログとapps.jsonの突き合わせで拾えます。依頼文は次のように、範囲を限って書きます。
kitting-20261013-101500.log と apps.json を読んでください。
apps.json の PackageIdentifier のうち、ログ上でインストールされた形跡も
「すでにインストール済み」の通知も見当たらないものを一覧にしてください。
ファイルは変更せず、一覧と、ログのどの行を根拠にしたかだけを返してください。一覧に出たIDは、winget searchで今も検索できるかをVMで確かめ、手順書の手作業欄かapps.jsonの修正に回します。
winget importの終了コードの扱いは、importのページに記載がありません。スクリプトの成否を終了コードだけで判定する前に、VMで失敗パターンを作って実際の値を確かめます。
固定した版や取得元で詰まったとき
--include-versionsで版を固定すると、apps.jsonに書かれた版が取得元から後で消える可能性があります。固定した版が取得元に残っているかはimportのページに記載がないので、VMでの実行結果で確かめます。最新版で構わなければ--ignore-versionsを付けると、JSONの版を無視して最新を入れます。固定を保ちたいアプリだけ別のJSONに分ける運用もあります。
同じアプリが複数のソースに一致する場合もあります。ソースが複数設定されていると重複が起きうるので、winget install --id Git.Git -e --source wingetのようにソースを指定して切り分けます。msstoreソースのIDは独自の形式で、XP9KHM4BK9FZ7Qのように英数字の並びになります。標準構成を作るときはexportに-s wingetと-s msstoreを別々に指定して、取得元ごとにJSONを分けておくと、どちらで入れたアプリかが手順書から追えます。
構成ファイルに入らないものを手順書に残す
winget importで再現できるのは、wingetで管理できるアプリだけです。次の作業は手順書に手作業として残します。
exportの警告で一覧から漏れたアプリの導入- Claude Codeの初回起動とサインイン
- 部署ごとに違うアプリの追加(このあと説明するとおり、JSONを分ければ手作業は減らせます)
部署ごとのアプリは、共通用のapps.jsonと部署用のapps-sales.jsonのようにJSONを分け、スクリプトでimportを2回呼ぶ構成にできます。kitting.ps1のparamを次のように広げます。
param(
[string]$Config = "$PSScriptRoot\apps.json",
[string]$DeptConfig = ""
)
foreach ($f in @($Config, $DeptConfig) | Where-Object { $_ }) {
winget import -i $f `
--accept-package-agreements --accept-source-agreements `
--disable-interactivity --no-upgrade --ignore-unavailable
}部署用を渡すときは.\kitting.ps1 -DeptConfig .\apps-sales.jsonと実行します。共通と部署用で同じIDが重なっても、--no-upgradeがあれば2回目はスキップされるだけです。
Claude Codeを組織で配る場合は、管理設定ファイルで方針を固定する方法があります。Windowsでの置き場所はC:\Program Files\ClaudeCode\managed-settings.jsonで、旧パスのC:\ProgramData\ClaudeCode\managed-settings.jsonは読まれません。配布の考え方はClaude Code組織管理ガイドにまとめています。
Claude Codeのネイティブインストールには管理者権限が要りません。Git for Windowsは任意で、入れるとBashツールとMonitorツールが使えるようになります。この2点は、キッティング対象の標準アプリにGitを含めるかを決める材料になります。
手順書が古くなるのを防ぐ運用
手順書と構成ファイルを別々に更新すると、また食い違います。次の運用にすると、食い違いが出にくくなります。
- アプリの追加は
apps.jsonの編集から始め、kitting.mdの表はClaude Codeに再生成させる - 再生成後は、
PackageIdentifierの増減だけをコミットの差分で確認する - 四半期ごとに基準端末で
winget exportし直し、標準構成との差を見て、意図しない追加を拾う
Ansibleのように構成管理ツールで冪等性を検証する考え方は、Claude CodeでAnsibleのPlaybookを書く手順が参考になります。Windowsのインストール方法そのものはClaude Code Windowsインストールにあります。
まとめ
キッティングの正は手順書の文章ではなく、apps.jsonです。そこから手順書の表とスクリプトを生成し、VMで2回流して差が出ないことを確かめると、手順書は読み物から再実行できる資産に変わります。wingetで入らないものは手作業として手順書に明記し、--ignore-unavailableで隠れた未導入はログで拾います。