dotnet-cli-distribution
Choosing CLI output format. AOT vs framework-dependent, RID matrix, single-file, dotnet tool.
What this skill does
# dotnet-cli-distribution CLI distribution strategy for .NET tools: choosing between Native AOT single-file publish, framework-dependent deployment, and `dotnet tool` packaging. Runtime Identifier (RID) matrix planning for cross-platform targets (linux-x64, osx-arm64, win-x64, linux-arm64), single-file publish configuration, and binary size optimization techniques for CLI applications. **Version assumptions:** .NET 8.0+ baseline. Native AOT for console apps is fully supported since .NET 8. Single-file publish has been mature since .NET 6. **Out of scope:** Native AOT MSBuild configuration (PublishAot, ILLink descriptors, EnableAotAnalyzer, trimming) -- see [skill:dotnet-native-aot]. AOT-first application design patterns (source gen over reflection, DI choices) -- see [skill:dotnet-aot-architecture]. Multi-platform packaging formats (Homebrew, apt/deb, winget, Scoop) -- see [skill:dotnet-cli-packaging]. Release CI/CD pipeline -- see [skill:dotnet-cli-release-pipeline]. Container-based distribution -- see [skill:dotnet-containers]. General CI/CD patterns -- see [skill:dotnet-gha-patterns] and [skill:dotnet-ado-patterns]. Cross-references: [skill:dotnet-native-aot] for AOT compilation pipeline, [skill:dotnet-aot-architecture] for AOT-safe design patterns, [skill:dotnet-cli-architecture] for CLI layered architecture, [skill:dotnet-cli-packaging] for platform-specific package formats, [skill:dotnet-cli-release-pipeline] for automated release workflows, [skill:dotnet-containers] for container-based distribution, [skill:dotnet-tool-management] for consumer-side tool installation and manifest management. --- ## Distribution Strategy Decision Matrix Choose the distribution model based on target audience and deployment constraints. | Strategy | Startup Time | Binary Size | Runtime Required | Best For | |----------|-------------|-------------|-----------------|----------| | Native AOT single-file | ~10ms | 10-30 MB | None | Performance-critical CLI tools, broad distribution | | Framework-dependent single-file | ~100ms | 1-5 MB | .NET runtime | Internal tools where runtime is guaranteed | | Self-contained single-file | ~100ms | 60-80 MB | None | Simple distribution without AOT complexity | | `dotnet tool` (global/local) | ~200ms | < 1 MB (NuGet) | .NET SDK | Developer tools, .NET ecosystem users | ### When to Choose Each Strategy **Native AOT single-file** -- the gold standard for CLI distribution: - Zero dependencies on target machine (no .NET runtime needed) - Fastest startup (~10ms vs ~100ms+ for JIT) - Smallest binary when combined with trimming - Trade-off: longer build times, no reflection unless preserved - See [skill:dotnet-native-aot] for PublishAot MSBuild configuration **Framework-dependent deployment:** - Smallest artifact size (only app code, no runtime) - Users must have .NET runtime installed - Best for internal/enterprise tools where runtime is managed - Can still use single-file publish for convenience **Self-contained (non-AOT):** - Includes .NET runtime in the artifact - Larger binary than AOT but simpler build process - Full reflection and dynamic code support - Good compromise when AOT compat is difficult **`dotnet tool` packaging:** - Distributed via NuGet -- simplest publishing workflow - Users install with `dotnet tool install -g mytool` - Requires .NET SDK on target (not just runtime) - Best for developer-facing tools in the .NET ecosystem - See [skill:dotnet-cli-packaging] for NuGet distribution details --- ## Runtime Identifier (RID) Matrix ### Standard CLI RID Targets Target the four primary RIDs for broad coverage: | RID | Platform | Notes | |-----|----------|-------| | `linux-x64` | Linux x86_64 | Most Linux servers, CI runners, WSL | | `linux-arm64` | Linux ARM64 | AWS Graviton, Raspberry Pi 4+, Apple Silicon VMs | | `osx-arm64` | macOS Apple Silicon | M1/M2/M3+ Macs (primary macOS target) | | `win-x64` | Windows x86_64 | Windows 10+, Windows Server | ### Optional Extended Targets | RID | When to Include | |-----|----------------| | `osx-x64` | Legacy Intel Mac support (declining market share) | | `linux-musl-x64` | Alpine Linux / Docker scratch images | | `linux-musl-arm64` | Alpine on ARM64 | | `win-arm64` | Windows on ARM (Surface Pro X, Snapdragon laptops) | ### RID Configuration in .csproj ```xml <!-- Set per publish, not in csproj (avoids accidental RID lock-in) --> <!-- Use dotnet publish -r <rid> instead --> <!-- If you must set a default for local development --> <PropertyGroup Condition="'$(RuntimeIdentifier)' == ''"> <RuntimeIdentifier>osx-arm64</RuntimeIdentifier> </PropertyGroup> ``` Publish per RID from the command line: ```bash # Publish for each target RID dotnet publish -c Release -r linux-x64 dotnet publish -c Release -r linux-arm64 dotnet publish -c Release -r osx-arm64 dotnet publish -c Release -r win-x64 ``` --- ## Single-File Publish Single-file publish bundles the application and its dependencies into one executable. ### Configuration ```xml <PropertyGroup> <PublishSingleFile>true</PublishSingleFile> <!-- Required for single-file --> <SelfContained>true</SelfContained> <!-- Embed PDB for stack traces (optional, adds ~2-5 MB) --> <DebugType>embedded</DebugType> <!-- Include native libraries in the single file --> <IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract> </PropertyGroup> ``` ### Single-File with Native AOT When combined with Native AOT, single-file is implicit -- AOT always produces a single native binary: ```xml <PropertyGroup> <PublishAot>true</PublishAot> <!-- PublishSingleFile is not needed -- AOT output is inherently single-file --> <!-- SelfContained is implied by PublishAot --> </PropertyGroup> ``` See [skill:dotnet-native-aot] for the full AOT publish configuration including ILLink, type preservation, and analyzer setup. ### Publish Command ```bash # Framework-dependent single-file (requires .NET runtime on target) dotnet publish -c Release -r linux-x64 /p:PublishSingleFile=true --self-contained false # Self-contained single-file (includes runtime, no AOT) dotnet publish -c Release -r linux-x64 /p:PublishSingleFile=true --self-contained true # Native AOT (inherently single-file, smallest and fastest) dotnet publish -c Release -r linux-x64 # (when PublishAot=true is in csproj) ``` --- ## Size Optimization for CLI Binaries ### Trimming (Non-AOT) Trimming removes unused code from the published output. For self-contained non-AOT builds: ```xml <PropertyGroup> <PublishTrimmed>true</PublishTrimmed> <TrimMode>link</TrimMode> <!-- Suppress known trim warnings for CLI scenarios --> <SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings> </PropertyGroup> ``` ### AOT Size Optimization For Native AOT builds, size is controlled by AOT-specific MSBuild properties. See [skill:dotnet-native-aot] for the full configuration. Key CLI-relevant properties include `StripSymbols`, `OptimizationPreference`, `InvariantGlobalization`, and `StackTraceSupport`. ### Size Comparison (Typical CLI Tool) | Configuration | Approximate Size | |---------------|-----------------| | Self-contained (no trim) | 60-80 MB | | Self-contained + trimmed | 15-30 MB | | Native AOT (default) | 15-25 MB | | Native AOT + size optimized | 8-15 MB | | Native AOT + invariant globalization + stripped | 5-10 MB | | Framework-dependent | 1-5 MB | ### Practical Size Reduction Checklist 1. **Enable invariant globalization** if the tool does not need locale-specific formatting (`InvariantGlobalization=true`) 2. **Strip symbols** on Linux/macOS (`StripSymbols=true`) -- keep separate symbol files for crash analysis 3. **Optimize for size** (`OptimizationPreference=Size`) -- minimal runtime performance impact for I/O-bound CLI tools 4. **Disable reflection** where possible -- use source generators for JSON serialization ([skill:dotnet-aot-architecture]) 5. **Audit NuGet dependencies** -- each dependency adds to the binary; remove un
Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.