# New Cask

> Add a new cask to homebrew-dotnet-sdk-versions. Use this skill whenever asked to support a new .NET SDK version or feature band that doesn't have a cask yet, create a stub cask, add a new major/minor/preview release, or add support for a new dotnet-sdk version (e.g. "add dotnet-sdk12-0-100" or "support .NET 11 preview").

- Skill: `isen-ng/new-cask` (Agent Skill)
- Install (CLI): `npx skillmds@latest add isen-ng/new-cask`
- Raw SKILL.md: https://api.skillmd.com/api/skills/isen-ng/new-cask/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: isen-ng (https://skillmd.com/u/isen-ng)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/isen-ng/new-cask

---


# SKILL: Adding a New Cask to homebrew-dotnet-sdk-versions

## When to use this skill
Use this skill whenever a user asks to:
- Add a new cask / feature band (e.g. "add dotnet-sdk12-0-100")
- Support a new .NET SDK major or minor version that doesn't have a cask yet
- Create a stub cask for a new release band

---

## Repository context

- **Repo**: `https://github.com/isen-ng/homebrew-dotnet-sdk-versions`
- **Casks live in**: `Casks/` directory, Ruby `.rb` files
- **Naming convention**: `dotnet-sdk{MAJOR}-{MINOR}-{FEATURE_HUNDREDS}.rb`
  - Examples: `dotnet-sdk8-0-400.rb`, `dotnet-sdk10-0-100.rb`, `dotnet-sdk11-preview.rb`
- The **filename and cask name inside the file must match** (Homebrew rule)
- **Meta casks** (e.g. `dotnet-sdk8.rb`) are auto-generated by `auto_meta_updater.py` — do NOT hand-edit them
- **Preview casks** follow the naming `dotnet-sdk{MAJOR}-preview.rb`

---

## Cask file structure

### Universal (x64 + arm64) cask — used for .NET 6+ stable

```ruby
cask "dotnet-sdk10-0-200" do
  arch arm: "arm64", intel: "x64"

  version "10.0.200,10.0.0"

  sha256_x64 = "????????????????????????????????????????????????????????????????"
  sha256_arm64 = "????????????????????????????????????????????????????????????????"
  url_x64 = "https://builds.dotnet.microsoft.com/dotnet/Sdk/#{version.csv.first}/dotnet-sdk-#{version.csv.first}-osx-x64.pkg"
  url_arm64 = "https://builds.dotnet.microsoft.com/dotnet/Sdk/#{version.csv.first}/dotnet-sdk-#{version.csv.first}-osx-arm64.pkg"
  on_arm do
    sha256 sha256_arm64

    url url_arm64
  end
  on_intel do
    sha256 sha256_x64

    url url_x64
  end

  name ".NET Core SDK #{version.csv.first}"
  desc "This cask follows releases from https://github.com/dotnet/core/tree/master"
  homepage "https://www.microsoft.com/net/core#macos"

  livecheck do
    skip "See https://github.com/isen-ng/homebrew-dotnet-sdk-versions/blob/master/CONTRIBUTING.md#automatic-updates"
  end

  depends_on macos: :monterey

  pkg "dotnet-sdk-#{version.csv.first}-osx-#{arch}.pkg"

  uninstall pkgutil: "com.microsoft.dotnet.dev.#{version.csv.first}.component.osx.#{arch}"

  zap pkgutil: [
        "com.microsoft.dotnet.hostfxr.#{version.csv.second}.component.osx.#{arch}",
        "com.microsoft.dotnet.pack.apphost.#{version.csv.second}.component.osx.#{arch}",
        "com.microsoft.dotnet.sharedframework.Microsoft.NETCore.App.#{version.csv.second}.component.osx.#{arch}",
        "com.microsoft.dotnet.sharedhost.component.osx.#{arch}",
      ],
      trash:   ["~/.dotnet", "~/.nuget", "/etc/paths.d/dotnet", "/etc/paths.d/dotnet-cli-tools"]

  caveats "Uninstalling the official dotnet-sdk casks will remove the shared runtime dependencies, " \
          "so you'll need to reinstall the particular version cask you want from this tap again " \
          "for the `dotnet` command to work again."
end
```

### Intel-only cask — used for .NET 5 and earlier (arm64 is NOT supported)

```ruby
cask "dotnet-sdk5-0-400" do
  version "5.0.408,5.0.17"
  sha256 "????????????????????????????????????????????????????????????????"

  on_arm do
    FileUtils.ln_sf("/usr/local/share/dotnet/x64/dotnet", "#{HOMEBREW_PREFIX}/bin/dotnetx64")
  end

  url "https://download.visualstudio.microsoft.com/download/pr/<guid>/dotnet-sdk-#{version.csv.first}-osx-x64.pkg"
  name ".NET Core SDK #{version.csv.first}"
  desc "This cask follows releases from https://github.com/dotnet/core/tree/master"
  homepage "https://www.microsoft.com/net/core#macos"

  livecheck do
    skip "See https://github.com/isen-ng/homebrew-dotnet-sdk-versions/blob/master/CONTRIBUTING.md#automatic-updates"
  end

  depends_on macos: :sonoma

  pkg "dotnet-sdk-#{version.csv.first}-osx-x64.pkg"

  uninstall pkgutil: "com.microsoft.dotnet.dev.#{version.csv.first}.component.osx.x64"

  zap pkgutil: [
        "com.microsoft.dotnet.hostfxr.#{version.csv.second}.component.osx.x64",
        "com.microsoft.dotnet.pack.apphost.#{version.csv.second}.component.osx.x64",
        "com.microsoft.dotnet.sharedframework.Microsoft.NETCore.App.#{version.csv.second}.component.osx.x64",
        "com.microsoft.dotnet.sharedhost.component.osx.x64",
      ],
      trash:   ["~/.dotnet", "~/.nuget", "/etc/paths.d/dotnet", "/etc/paths.d/dotnet-cli-tools"]

  caveats "If you are installing this x64 binary on an Apple M1 (arm64) machine, the x64 version of `dotnet`" \
          "command will be symlinked as `dotnetx64`\n\n" \
          "Uninstalling the official dotnet-sdk casks will remove the shared runtime dependencies, " \
          "so you'll need to reinstall the particular version cask you want from this tap again " \
          "for the `dotnet` command to work again."
end
```

### Preview cask — used for preview/RC releases

```ruby
cask "dotnet-sdk11-preview" do
  arch arm: "arm64", intel: "x64"

  version "11.0.100-preview.1.25101.1,11.0.0-preview.1.25103.1"

  sha256_x64 = "????????????????????????????????????????????????????????????????"
  sha256_arm64 = "????????????????????????????????????????????????????????????????"
  url_x64 = "https://builds.dotnet.microsoft.com/dotnet/Sdk/#{version.csv.first}/dotnet-sdk-#{version.csv.first}-osx-x64.pkg"
  url_arm64 = "https://builds.dotnet.microsoft.com/dotnet/Sdk/#{version.csv.first}/dotnet-sdk-#{version.csv.first}-osx-arm64.pkg"

  on_arm do
    sha256 sha256_arm64

    url url_arm64
  end
  on_intel do
    sha256 sha256_x64

    url url_x64
  end

  name ".NET SDK #{version.csv.first}"
  desc "This cask follows releases from https://github.com/dotnet/core/tree/master"
  homepage "https://www.microsoft.com/net/core#macos"

  livecheck do
    skip "See https://github.com/isen-ng/homebrew-dotnet-sdk-versions/blob/master/CONTRIBUTING.md#automatic-updates"
  end

  depends_on macos: :monterey

  pkg "dotnet-sdk-#{version.csv.first}-osx-#{arch}.pkg"

  uninstall pkgutil: "com.microsoft.dotnet.dev.#{version.csv.first}.component.osx.#{arch}"

  zap pkgutil: [
        "com.microsoft.dotnet.hostfxr.#{version.csv.second}.component.osx.#{arch}",
        "com.microsoft.dotnet.pack.apphost.#{version.csv.second}.component.osx.#{arch}",
        "com.microsoft.dotnet.sharedframework.Microsoft.NETCore.App.#{version.csv.second}.component.osx.#{arch}",
        "com.microsoft.dotnet.sharedhost.component.osx.#{arch}",
      ],
      trash:   ["~/.dotnet", "~/.nuget", "/etc/paths.d/dotnet", "/etc/paths.d/dotnet-cli-tools"]

  caveats "Uninstalling the official dotnet-sdk casks will remove the shared runtime dependencies, " \
          "so you'll need to reinstall the particular version cask you want from this tap again " \
          "for the `dotnet` command to work again."
end
```

---

## Step-by-step: how to add a new cask

### 1. Determine the cask name

Use the naming convention `dotnet-sdk{MAJOR}-{MINOR}-{FEATURE_HUNDREDS}`:
- `dotnet-sdk10-0-200` → covers SDK `10.0.2xx`
- `dotnet-sdk11-0-100` → covers SDK `11.0.1xx`
- Preview: `dotnet-sdk11-preview`

### 2. Determine arm64 support

- .NET 6+ → use the **universal** cask template (both x64 and arm64)
- .NET 5 and earlier → use the **Intel-only** cask template

### 3. Determine the `depends_on macos:` value

Copy from an adjacent existing cask for the same .NET generation:
- .NET 8: `:big_sur`
- .NET 9, 10, 11+: `:monterey`

### 4. Create the stub file

Create `Casks/dotnet-sdk{MAJOR}-{MINOR}-{FEATURE}.rb` with:
- Correct cask name matching the filename
- A placeholder version like `"{MAJOR}.{MINOR}.{FEATURE}00,{MAJOR}.0.0"` (auto_updater will fill the real value)
- Placeholder sha256 values (`"????????????????..."` — auto_updater is forced to compute real values)
- For .NET 6+: use `builds.dotnet.microsoft.com` URL pattern (no GUID needed — the URL is predictable)
- For .NET 5 and earlier: use `download.visualstudio.microsoft.com/download/pr/<guid>/...` URL pattern with a placeholder GUID
- Correct `uninstall` and `zap` pkgutil patterns using `version.csv.first` and `version.csv.second`
- Include `caveats` block

### 5. Run auto_updater.py in dry-run mode

```bash
# dry-run (no --really_push) — updates all casks including the new one
./auto_updater.py
```

This will:
- Download `releases.json` for the major.minor band from `github.com/dotnet/core`
- Find the latest patch release for the feature band
- Download the `.pkg`, verify SHA-512, compute SHA-256
- Rewrite the cask file with correct version, sha256, and url

### 6. Validate the cask locally

```bash
brew tap isen-ng/dotnet-sdk-versions $PWD
brew style Casks/dotnet-sdk{MAJOR}-{MINOR}-{FEATURE}.rb
brew audit --cask dotnet-sdk{MAJOR}-{MINOR}-{FEATURE}
```

### 7. Open the PR

**If you are the repo owner** (pushing directly to origin):
```bash
git checkout -b new-cask/dotnet-sdk{MAJOR}-{MINOR}-{FEATURE}
git add Casks/dotnet-sdk{MAJOR}-{MINOR}-{FEATURE}.rb
git commit -m "Add support for dotnet-sdk{MAJOR}-{MINOR}-{FEATURE}"
git push origin new-cask/dotnet-sdk{MAJOR}-{MINOR}-{FEATURE}
```

**If you are an external contributor** (pushing to your fork):
```bash
git checkout -b new-cask/dotnet-sdk{MAJOR}-{MINOR}-{FEATURE}
git add Casks/dotnet-sdk{MAJOR}-{MINOR}-{FEATURE}.rb
git commit -m "Add support for dotnet-sdk{MAJOR}-{MINOR}-{FEATURE}"
git push fork new-cask/dotnet-sdk{MAJOR}-{MINOR}-{FEATURE}
```

Then open a PR from that branch into `master`.

---

## Key rules and gotchas

- **Never use placeholder sha256 that passes validation** — use `"????????????????..."` so `auto_updater.py` is forced to compute the real value.
- **The `version` field has two CSV parts**: `"SDK_VERSION,RUNTIME_VERSION"`. auto_updater.py fills both.
- **URL must contain `#{version.csv.first}`** interpolation to satisfy `brew audit`.
- **For .NET 6+, the URL uses `builds.dotnet.microsoft.com`** with no GUID: `https://builds.dotnet.microsoft.com/dotnet/Sdk/#{version.csv.first}/dotnet-sdk-#{version.csv.first}-osx-{arch}.pkg`. Do NOT use the old `download.visualstudio.microsoft.com/download/pr/<guid>/...` format.
- **Meta casks** (`dotnet-sdk8.rb`) are auto-generated — never create or edit them manually. Run `auto_meta_updater.py` after merging the new versioned cask.
- **`depends_on macos`** — copy from an adjacent existing cask for the same .NET generation to match the minimum macOS requirement.
- **`uninstall pkgutil:`** takes a single string, not an array.
- **`zap`** must include both `pkgutil:` array and `trash:` array.
- **`pkgutil` identifiers** follow the pattern `com.microsoft.dotnet.dev.{sdk_version}.component.osx.{arch}` — double-check against the actual `.pkg` installer if unsure.
- For **preview casks**, the version string includes pre-release labels: `"11.0.100-preview.1.25101.1,11.0.0-preview.1.25103.1"`. The `PreviewSdkVersion` class in `auto_updater.py` handles this format.
- **`name` field**: use `".NET SDK"` for .NET 11+ preview casks; use `".NET Core SDK"` for stable/older casks.

