dotnet-cli-packaging について
dotnet-cli-packagingは、.NETコマンドラインツールの保守担当者向けに、配布パッケージの作成方法をまとめたスキルです。Homebrew、apt/deb、winget、Scoop、Chocolatey、dotnet tool、NuGetの形式を扱います。
主な機能
- 01Homebrewのformulaとcaskの作成
- 02`dpkg-deb` によるapt/debパッケージの構築
- 03wingetとScoopのマニフェスト準備
- 04Chocolatey向けのツールパッケージ作成
- 05`dotnet tool` パッケージの設定
- 06NuGetへのパッケージ公開
活用シーン
- 01.NETコマンドラインツールのHomebrew向けパッケージ化
- 02DebianまたはUbuntu向け`.deb`の準備
- 03wingetまたはScoopへのツールパッケージ提出
- 04dotnet toolまたはNuGetでのツール配布
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ wshaddix/ dotnet-skills --skill dotnet-cli-packagingインストール後、Claude Code で/dotnet-cli-packagingを入力して読み込まれたか確認します。
詳細
dotnet-cli-packaging
.NET CLI ツールのマルチプラットフォーム向けパッケージング:Homebrew フォーミュラの作成(バイナリータップと Cask)、dpkg-deb を使用した apt/deb パッケージング、winget マニフェストの YAML スキーマと winget-pkgs への PR の提出、Scoop マニフェストの JSON、Chocolatey パッケージの作成、dotnet tool のグローバル/ローカルパッケージング、NuGet による配布。
バージョンの前提: .NET 8.0 以降を基準とします。パッケージマネージャーの形式は .NET のバージョン間で安定しています。
対象外: CLI の配布戦略(AOT、フレームワーク依存、dotnet tool のどれを選ぶか)については、[skill:dotnet-cli-distribution] を参照してください。パッケージングを自動化するリリース CI/CD パイプラインについては、[skill:dotnet-cli-release-pipeline] を参照してください。ネイティブ AOT コンパイルについては、[skill:dotnet-native-aot] を参照してください。コンテナーを使用した配布については、[skill:dotnet-containers] を参照してください。一般的な CI/CD パターンについては、[skill:dotnet-gha-patterns] と [skill:dotnet-ado-patterns] を参照してください。
相互参照:[skill:dotnet-cli-distribution] は配布戦略と RID マトリックス、[skill:dotnet-cli-release-pipeline] はパッケージの自動公開、[skill:dotnet-native-aot] は AOT バイナリーの生成、[skill:dotnet-containers] はコンテナーを使用した配布、[skill:dotnet-tool-management] は利用者側でのツールのインストールとマニフェスト管理について説明しています。
Homebrew(macOS / Linux)
Homebrew は macOS の主要なパッケージマネージャーであり、Linux でも広く使用されています。CLI ツール向けには、2 種類の配布形式があります。
バイナリータップ(フォーミュラ)
フォーミュラは、プラットフォームごとにビルド済みバイナリーをダウンロードします。Native AOT CLI ツールには、この方法を推奨します。
# Formula/mytool.rb
class Mytool < Formula
desc "A CLI tool for managing widgets"
homepage "https://github.com/myorg/mytool"
version "1.2.3"
license "MIT"
on_macos do
on_arm do
url "https://github.com/myorg/mytool/releases/download/v1.2.3/mytool-1.2.3-osx-arm64.tar.gz"
sha256 "abc123..."
end
# Optional: remove on_intel block if not targeting Intel Macs
on_intel do
url "https://github.com/myorg/mytool/releases/download/v1.2.3/mytool-1.2.3-osx-x64.tar.gz"
sha256 "def456..."
end
end
on_linux do
on_arm do
url "https://github.com/myorg/mytool/releases/download/v1.2.3/mytool-1.2.3-linux-arm64.tar.gz"
sha256 "ghi789..."
end
on_intel do
url "https://github.com/myorg/mytool/releases/download/v1.2.3/mytool-1.2.3-linux-x64.tar.gz"
sha256 "jkl012..."
end
end
def install
bin.install "mytool"
end
test do
assert_match version.to_s, shell_output("#{bin}/mytool --version")
end
end
タップのホスティング
タップは、フォーミュラを含む Git リポジトリです。homebrew-tap という名前のリポジトリを作成します。
myorg/homebrew-tap/
Formula/
mytool.rb
ユーザーは次のコマンドでインストールします。
brew tap myorg/tap
brew install mytool
Homebrew Cask
Cask は GUI アプリケーションやインストーラーを含むツール向けです。CLI 専用ツールには、Cask よりフォーミュラをおすすめします。
# Casks/mytool.rb -- only if the tool has a GUI component
cask "mytool" do
version "1.2.3"
sha256 "abc123..."
url "https://github.com/myorg/mytool/releases/download/v#{version}/mytool-#{version}-osx-arm64.tar.gz"
name "MyTool"
homepage "https://github.com/myorg/mytool"
binary "mytool"
end
apt/deb(Debian/Ubuntu)
dpkg-deb を使用した .deb パッケージのビルド
パッケージのディレクトリ構造を作成します。
mytool_1.2.3_amd64/
DEBIAN/
control
usr/
bin/
mytool
Control ファイル:
Package: mytool
Version: 1.2.3
Section: utils
Priority: optional
Architecture: amd64
Maintainer: My Org <[email protected]>
Description: A CLI tool for managing widgets
MyTool provides fast widget management from the command line.
Built with .NET Native AOT for zero-dependency execution.
Homepage: https://github.com/myorg/mytool
パッケージをビルドします。
#!/bin/bash
set -euo pipefail
VERSION="${1:?Usage: build-deb.sh <version>}"
ARCH="amd64" # or arm64
PKG_DIR="mytool_${VERSION}_${ARCH}"
mkdir -p "$PKG_DIR/DEBIAN"
mkdir -p "$PKG_DIR/usr/bin"
# Copy the published binary
cp "artifacts/linux-x64/mytool" "$PKG_DIR/usr/bin/mytool"
chmod 755 "$PKG_DIR/usr/bin/mytool"
# Write control file
cat > "$PKG_DIR/DEBIAN/control" << EOF
Package: mytool
Version: ${VERSION}
Section: utils
Priority: optional
Architecture: ${ARCH}
Maintainer: My Org <[email protected]>
Description: A CLI tool for managing widgets
Homepage: https://github.com/myorg/mytool
EOF
# Build the .deb
dpkg-deb --build --root-owner-group "$PKG_DIR"
echo "Built: ${PKG_DIR}.deb"
RID と Debian アーキテクチャの対応:
| .NET RID | Debian アーキテクチャ |
|---|---|
linux-x64 | amd64 |
linux-arm64 | arm64 |
.deb のインストール
sudo dpkg -i mytool_1.2.3_amd64.deb
winget(Windows パッケージマネージャー)
マニフェストの YAML スキーマ
winget マニフェストは、microsoft/winget-pkgs リポジトリ内のバージョン別ディレクトリ構造にある複数の YAML ファイルで構成されます。
ディレクトリ構造:
manifests/
m/
MyOrg/
MyTool/
1.2.3/
MyOrg.MyTool.yaml # Version manifest
MyOrg.MyTool.installer.yaml # Installer manifest
MyOrg.MyTool.locale.en-US.yaml # Locale manifest
バージョンマニフェスト(MyOrg.MyTool.yaml):
PackageIdentifier: MyOrg.MyTool
PackageVersion: 1.2.3
DefaultLocale: en-US
ManifestType: version
ManifestVersion: 1.9.0
インストーラーマニフェスト(MyOrg.MyTool.installer.yaml):
PackageIdentifier: MyOrg.MyTool
PackageVersion: 1.2.3
InstallerType: zip
NestedInstallerType: portable
NestedInstallerFiles:
- RelativeFilePath: mytool.exe
PortableCommandAlias: mytool
Installers:
- Architecture: x64
InstallerUrl: https://github.com/myorg/mytool/releases/download/v1.2.3/mytool-1.2.3-win-x64.zip
InstallerSha256: ABC123...
- Architecture: arm64
InstallerUrl: https://github.com/myorg/mytool/releases/download/v1.2.3/mytool-1.2.3-win-arm64.zip
InstallerSha256: DEF456...
ManifestType: installer
ManifestVersion: 1.9.0
ロケールマニフェスト(MyOrg.MyTool.locale.en-US.yaml):
PackageIdentifier: MyOrg.MyTool
PackageVersion: 1.2.3
PackageLocale: en-US
PackageName: MyTool
Publisher: My Org
ShortDescription: A CLI tool for managing widgets
License: MIT
PackageUrl: https://github.com/myorg/mytool
ManifestType: defaultLocale
ManifestVersion: 1.9.0
winget-pkgs への提出
- GitHub で
microsoft/winget-pkgsをフォークします - 正しいディレクトリ構造にマニフェストファイルを作成します
- ローカルで検証します:
winget validate --manifest <path> - PR を提出します。マニフェストに対して自動チェックが実行されます
- Microsoft チームがレビューし、マージします
winget の PR 作成を自動化する方法については、[skill:dotnet-cli-release-pipeline] を参照してください。
Scoop(Windows)
Scoop は、Windows のパワーユーザーに人気があります。マニフェストは、バケットリポジトリ内の JSON ファイルです。
Scoop マニフェスト
{
"version": "1.2.3",
"description": "A CLI tool for managing widgets",
"homepage": "https://github.com/myorg/mytool",
"license": "MIT",
"architecture": {
"64bit": {
"url": "https://github.com/myorg/mytool/releases/download/v1.2.3/mytool-1.2.3-win-x64.zip",
"hash": "abc123..."
},
"arm64": {
"url": "https://github.com/myorg/mytool/releases/download/v1.2.3/mytool-1.2.3-win-arm64.zip",
"hash": "def456..."
}
},
"bin": "mytool.exe",
"checkver": {
"github": "https://github.com/myorg/mytool"
},
"autoupdate": {
"architecture": {
"64bit": {
"url": "https://github.com/myorg/mytool/releases/download/v$version/mytool-$version-win-x64.zip"
},
"arm64": {
"url": "https://github.com/myorg/mytool/releases/download/v$version/mytool-$version-win-arm64.zip"
}
}
}
}
Scoop バケットのホスティング
scoop-mytool(または scoop-bucket)という名前の GitHub リポジトリを作成します。
myorg/scoop-mytool/
bucket/
mytool.json
ユーザーは次のコマンドでインストールします。
scoop bucket add myorg https://github.com/myorg/scoop-mytool
scoop install mytool
Chocolatey
Chocolatey は、バイナリー配布において Windows で最も広く確立されたパッケージマネージャーです。
パッケージ構造
mytool/
mytool.nuspec
tools/
chocolateyInstall.ps1
LICENSE.txt
mytool.nuspec:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.xmldata.org/2004/07/nuspec">
<metadata>
<id>mytool</id>
<version>1.2.3</version>
<title>MyTool</title>
<authors>My Org</authors>
<projectUrl>https://github.com/myorg/mytool</projectUrl>
<license type="expression">MIT</license>
<description>A CLI tool for managing widgets.</description>
<tags>cli dotnet tools</tags>
</metadata>
</package>
tools/chocolateyInstall.ps1:
$ErrorActionPreference = 'Stop'
$packageArgs = @{
packageName = 'mytool'
url64bit = 'https://github.com/myorg/mytool/releases/download/v1.2.3/mytool-1.2.3-win-x64.zip'
checksum64 = 'ABC123...'
checksumType64 = 'sha256'
unzipLocation = "$(Split-Path -Parent $MyInvocation.MyCommand.Definition)"
}
Install-ChocolateyZipPackage @packageArgs
ビルドと公開
# Pack the .nupkg
choco pack mytool.nuspec
# Test locally
choco install mytool --source="." --force
# Push to Chocolatey Community Repository
choco push mytool.1.2.3.nupkg --source https://push.chocolatey.org/ --api-key $env:CHOCO_API_KEY
dotnet tool(グローバルとローカル)
dotnet tool は、.NET 開発者にとって最もシンプルな配布方法です。ツールは NuGet パッケージとして配布されます。
ツールのパッケージングに向けたプロジェクト構成
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<PackAsTool>true</PackAsTool>
<ToolCommandName>mytool</ToolCommandName>
<PackageId>MyOrg.MyTool</PackageId>
<Version>1.2.3</Version>
<Description>A CLI tool for managing widgets</Description>
<Authors>My Org</Authors>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/myorg/mytool</PackageProjectUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>
<ItemGroup>
<None Include="../../README.md" Pack="true" PackagePath="/" />
</ItemGroup>
</Project>
ビルドと公開
# Pack the tool
dotnet pack -c Release
# Publish to NuGet.org
dotnet nuget push bin/Release/MyOrg.MyTool.1.2.3.nupkg \
--source https://api.nuget.org/v3/index.json \
--api-key "$NUGET_API_KEY"
dotnet ツールのインストール
# Global tool (available system-wide)
dotnet tool install -g MyOrg.MyTool
# Local tool (per-project, tracked in .config/dotnet-tools.json)
dotnet new tool-manifest # first time only
dotnet tool install MyOrg.MyTool
# Update
dotnet tool update -g MyOrg.MyTool
# Run local tool
dotnet tool run mytool
# or just:
dotnet mytool
グローバルツールとローカルツール
| 項目 | グローバルツール | ローカルツール |
|---|---|---|
| スコープ | システム全体(ユーザー単位) | プロジェクトディレクトリ単位 |
| インストール先 | ~/.dotnet/tools | .config/dotnet-tools.json |
| バージョン管理 | 手動で更新 | ソース管理で追跡 |
| CI/CD | 使用前にインストールが必要 | dotnet tool restoreですべてを復元 |
| 最適な用途 | 個人の生産性向上ツール | プロジェクト固有のビルドツール |
NuGet での配布
NuGet パッケージとして配布されるツール(dotnet toolまたはスタンドアロン)の場合:
パッケージメタデータ
<PropertyGroup>
<PackageId>MyOrg.MyTool</PackageId>
<Version>1.2.3</Version>
<Description>A CLI tool for managing widgets</Description>
<Authors>My Org</Authors>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/myorg/mytool</PackageProjectUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageTags>cli;tools;widgets</PackageTags>
<RepositoryUrl>https://github.com/myorg/mytool</RepositoryUrl>
<RepositoryType>git</RepositoryType>
</PropertyGroup>
NuGet.org への公開
# Pack
dotnet pack -c Release -o ./nupkgs
# Push (use env var for API key -- never hardcode)
dotnet nuget push ./nupkgs/MyOrg.MyTool.1.2.3.nupkg \
--source https://api.nuget.org/v3/index.json \
--api-key "$NUGET_API_KEY"
プライベートフィードでの配布
# Push to a private feed (Azure Artifacts, GitHub Packages, etc.)
dotnet nuget push ./nupkgs/MyOrg.MyTool.1.2.3.nupkg \
--source https://pkgs.dev.azure.com/myorg/_packaging/myfeed/nuget/v3/index.json \
--api-key "$AZURE_ARTIFACTS_PAT"
パッケージ形式の比較
| 形式 | プラットフォーム | .NET が必要 | 自動更新 | 難易度 |
|---|---|---|---|---|
| Homebrew formula | macOS、Linux | いいえ(バイナリタップ) | brew upgrade | 中 |
| apt/deb | Debian/Ubuntu | いいえ(AOT バイナリ) | apt リポジトリ経由 | 中 |
| winget | Windows 10 以降 | いいえ(ポータブル) | winget upgrade | 中 |
| Scoop | Windows | いいえ(ポータブル) | scoop update | 低 |
| Chocolatey | Windows | いいえ | choco upgrade | 中 |
| dotnet tool | クロスプラットフォーム | はい(SDK) | dotnet tool update | 低 |
| NuGet(ライブラリ) | クロスプラットフォーム | はい(SDK) | NuGet の復元 | 低 |
エージェント向けの注意点
- パッケージマニフェストに SHA-256 ハッシュをハードコードしないでください。 プレースホルダー値ではなく、実際のリリース成果物からチェックサムを生成してください。すべてのパッケージマネージャーは、ダウンロードしたファイルに対してチェックサムを検証します。
- winget のポータブル CLI ツールに
InstallerType: exeを使用しないでください。 スタンドアロン実行ファイルには、NestedInstallerType: portableを指定したInstallerType: zipを使用してください。exeタイプは、サイレントインストール用フラグを持つインストーラーを意味します。 - dotnet tool プロジェクトで
PackAsToolを忘れないでください。<PackAsTool>true</PackAsTool>がない場合、dotnet packはインストール可能なツールではなく、ライブラリパッケージを生成します。 - パッケージ化スクリプトに API キーをハードコードしないでください。 環境変数の参照(
$NUGET_API_KEY、$env:CHOCO_API_KEY)を使い、CI のシークレット設定についてのコメントを記載してください。 - 同じ CLI ツールに対して Homebrew formula と cask を併用しないでください。 純粋な CLI ツールには formula を使用してください。cask は、macOS アプリバンドルを含む GUI アプリケーション向けです。
- Homebrew formula の
testブロックを省略しないでください。 Homebrew CI は formula のテストを実行します。テストブロックがないと、レビューで却下されます。最低限、--versionの出力をテストしてください。