$npx -y skills add wshaddix/dotnet-skills --skill dotnet-cli-packagingPublishing to package managers. Homebrew, apt/deb, winget, Scoop, Chocolatey manifests.
| 1 | # dotnet-cli-packaging |
| 2 | |
| 3 | Multi-platform packaging for .NET CLI tools: Homebrew formula authoring (binary tap and cask), apt/deb packaging with `dpkg-deb`, winget manifest YAML schema and PR submission to `winget-pkgs`, Scoop manifest JSON, Chocolatey package creation, `dotnet tool` global/local packaging, and NuGet distribution. |
| 4 | |
| 5 | **Version assumptions:** .NET 8.0+ baseline. Package manager formats are stable across .NET versions. |
| 6 | |
| 7 | **Out of scope:** CLI distribution strategy (AOT vs framework-dependent vs dotnet tool decision) -- see [skill:dotnet-cli-distribution]. Release CI/CD pipeline that automates packaging -- see [skill:dotnet-cli-release-pipeline]. Native AOT compilation -- see [skill:dotnet-native-aot]. Container-based distribution -- see [skill:dotnet-containers]. General CI/CD patterns -- see [skill:dotnet-gha-patterns] and [skill:dotnet-ado-patterns]. |
| 8 | |
| 9 | Cross-references: [skill:dotnet-cli-distribution] for distribution strategy and RID matrix, [skill:dotnet-cli-release-pipeline] for automated package publishing, [skill:dotnet-native-aot] for AOT binary production, [skill:dotnet-containers] for container-based distribution, [skill:dotnet-tool-management] for consumer-side tool installation and manifest management. |
| 10 | |
| 11 | --- |
| 12 | |
| 13 | ## Homebrew (macOS / Linux) |
| 14 | |
| 15 | Homebrew is the primary package manager for macOS and widely used on Linux. Two distribution formats exist for CLI tools. |
| 16 | |
| 17 | ### Binary Tap (Formula) |
| 18 | |
| 19 | A formula downloads pre-built binaries per platform. This is the recommended approach for Native AOT CLI tools. |
| 20 | |
| 21 | ```ruby |
| 22 | # Formula/mytool.rb |
| 23 | class Mytool < Formula |
| 24 | desc "A CLI tool for managing widgets" |
| 25 | homepage "https://github.com/myorg/mytool" |
| 26 | version "1.2.3" |
| 27 | license "MIT" |
| 28 | |
| 29 | on_macos do |
| 30 | on_arm do |
| 31 | url "https://github.com/myorg/mytool/releases/download/v1.2.3/mytool-1.2.3-osx-arm64.tar.gz" |
| 32 | sha256 "abc123..." |
| 33 | end |
| 34 | # Optional: remove on_intel block if not targeting Intel Macs |
| 35 | on_intel do |
| 36 | url "https://github.com/myorg/mytool/releases/download/v1.2.3/mytool-1.2.3-osx-x64.tar.gz" |
| 37 | sha256 "def456..." |
| 38 | end |
| 39 | end |
| 40 | |
| 41 | on_linux do |
| 42 | on_arm do |
| 43 | url "https://github.com/myorg/mytool/releases/download/v1.2.3/mytool-1.2.3-linux-arm64.tar.gz" |
| 44 | sha256 "ghi789..." |
| 45 | end |
| 46 | on_intel do |
| 47 | url "https://github.com/myorg/mytool/releases/download/v1.2.3/mytool-1.2.3-linux-x64.tar.gz" |
| 48 | sha256 "jkl012..." |
| 49 | end |
| 50 | end |
| 51 | |
| 52 | def install |
| 53 | bin.install "mytool" |
| 54 | end |
| 55 | |
| 56 | test do |
| 57 | assert_match version.to_s, shell_output("#{bin}/mytool --version") |
| 58 | end |
| 59 | end |
| 60 | ``` |
| 61 | |
| 62 | ### Hosting a Tap |
| 63 | |
| 64 | A tap is a Git repository containing formulae. Create a repo named `homebrew-tap`: |
| 65 | |
| 66 | ``` |
| 67 | myorg/homebrew-tap/ |
| 68 | Formula/ |
| 69 | mytool.rb |
| 70 | ``` |
| 71 | |
| 72 | Users install with: |
| 73 | |
| 74 | ```bash |
| 75 | brew tap myorg/tap |
| 76 | brew install mytool |
| 77 | ``` |
| 78 | |
| 79 | ### Homebrew Cask |
| 80 | |
| 81 | Casks are for GUI applications or tools with an installer. For pure CLI tools, prefer formulae over casks. |
| 82 | |
| 83 | ```ruby |
| 84 | # Casks/mytool.rb -- only if the tool has a GUI component |
| 85 | cask "mytool" do |
| 86 | version "1.2.3" |
| 87 | sha256 "abc123..." |
| 88 | |
| 89 | url "https://github.com/myorg/mytool/releases/download/v#{version}/mytool-#{version}-osx-arm64.tar.gz" |
| 90 | name "MyTool" |
| 91 | homepage "https://github.com/myorg/mytool" |
| 92 | |
| 93 | binary "mytool" |
| 94 | end |
| 95 | ``` |
| 96 | |
| 97 | --- |
| 98 | |
| 99 | ## apt/deb (Debian/Ubuntu) |
| 100 | |
| 101 | ### Building a .deb Package with dpkg-deb |
| 102 | |
| 103 | Create the package directory structure: |
| 104 | |
| 105 | ``` |
| 106 | mytool_1.2.3_amd64/ |
| 107 | DEBIAN/ |
| 108 | control |
| 109 | usr/ |
| 110 | bin/ |
| 111 | mytool |
| 112 | ``` |
| 113 | |
| 114 | **Control file:** |
| 115 | |
| 116 | ``` |
| 117 | Package: mytool |
| 118 | Version: 1.2.3 |
| 119 | Section: utils |
| 120 | Priority: optional |
| 121 | Architecture: amd64 |
| 122 | Maintainer: My Org <dev@myorg.com> |
| 123 | Description: A CLI tool for managing widgets |
| 124 | MyTool provides fast widget management from the command line. |
| 125 | Built with .NET Native AOT for zero-dependency execution. |
| 126 | Homepage: https://github.com/myorg/mytool |
| 127 | ``` |
| 128 | |
| 129 | **Build the package:** |
| 130 | |
| 131 | ```bash |
| 132 | #!/bin/bash |
| 133 | set -euo pipefail |
| 134 | |
| 135 | VERSION="${1:?Usage: build-deb.sh <version>}" |
| 136 | ARCH="amd64" # or arm64 |
| 137 | PKG_DIR="mytool_${VERSION}_${ARCH}" |
| 138 | |
| 139 | mkdir -p "$PKG_DIR/DEBIAN" |
| 140 | mkdir -p "$PKG_DIR/usr/bin" |
| 141 | |
| 142 | # Copy the published binary |
| 143 | cp "artifacts/linux-x64/mytool" "$PKG_DIR/usr/bin/mytool" |
| 144 | chmod 755 "$PKG_DIR/usr/bin/mytool" |
| 145 | |
| 146 | # Write control file |
| 147 | cat > "$PKG_DIR/DEBIAN/control" << EOF |
| 148 | Package: mytool |
| 149 | Version: ${VERSION} |
| 150 | Section: utils |
| 151 | Priority: optional |
| 152 | Architecture: ${ARCH} |
| 153 | Maintainer: My Org <dev@myorg.com> |
| 154 | Description: A CLI tool for managing widgets |
| 155 | Homepage: https://github.com/myorg/mytool |
| 156 | EOF |
| 157 | |
| 158 | # Build the .deb |
| 159 | dpkg-deb --build --root-owner-group "$PKG_DIR" |
| 160 | echo "Built: ${PKG_DIR}.deb" |
| 161 | ``` |
| 162 | |
| 163 | **RID to Debian architecture mapping:** |
| 164 | |
| 165 | | .NET RID | Debian Architecture | |
| 166 | |----------|-------------------| |
| 167 | | `linux-x64` | `amd64` | |
| 168 | | `linux-arm64` | `arm64` | |
| 169 | |
| 170 | ### Installing the .deb |
| 171 | |
| 172 | ```bash |
| 173 | sudo dpkg -i mytool_1.2.3_amd64.deb |
| 174 | ``` |
| 175 | |
| 176 | --- |
| 177 | |
| 178 | ## winget (Windows Package Manager) |
| 179 | |
| 180 | ### Manifest YAML Schema |
| 181 | |
| 182 | winget manifests consist of multiple YAML files in |