skills/nuget-package-scaffold/SKILL.md
NuGet package creation with CI/CD pipeline setup and test harness. Use when creating new NuGet packages, configuring package metadata, or setting up publish workflows. Do NOT use when the library is internal-only and not intended for NuGet publication; Do NOT use when the target is an application project.
npx skillsauth add michaelalber/ai-toolkit nuget-package-scaffoldInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
"The best libraries are those that disappear into the code that uses them." -- Krzysztof Cwalina, Framework Design Guidelines
This skill scaffolds production-ready NuGet packages with proper metadata, testing, CI/CD pipelines, and publish workflows. Every package must meet a quality bar before it reaches any feed.
Non-negotiable constraints:
| Principle | Description | Priority |
|-----------|-------------|----------|
| Semantic Versioning | Follow SemVer 2.0.0 strictly: MAJOR.MINOR.PATCH with clear meaning | Critical |
| API Surface Minimization | Expose only what consumers need; use internal by default, public by design | Critical |
| Multi-Targeting | Target net10.0 as the primary TFM; add netstandard2.0 only when broad compatibility is required | High |
| Documentation | Include XML doc comments on all public APIs; ship a README in the package | High |
| Deterministic Builds | Enable deterministic compilation and Source Link for reproducibility | High |
| Strong Naming | Sign assemblies when targeting consumers that require strong-named dependencies | Medium |
| Source Link | Embed source repository metadata so debuggers can step into package source | High |
| License Compliance | Declare license via SPDX expression or embedded file; never ship unlicensed code | Critical |
| Dependency Management | Pin dependency version ranges carefully; prefer minimum viable ranges | High |
| Backward Compatibility | Never break public API in a MINOR or PATCH release; use [Obsolete] before removal | Critical |
| Query | When to Call |
|-------|--------------|
| search_knowledge("NuGet package metadata csproj PackageId authors license README") | At CONFIGURE phase — confirms required metadata fields and MSBuild properties |
| search_knowledge("semantic versioning SemVer MAJOR MINOR PATCH NuGet") | During versioning decisions — confirms SemVer rules and NuGet versioning behavior |
| search_knowledge(".NET multi-targeting TFM net8 net9 net10 TargetFrameworks") | When configuring TFMs — confirms multi-targeting syntax and compatibility |
| search_knowledge("GitHub Actions NuGet publish workflow dotnet pack push") | During CI/CD pipeline setup — confirms workflow patterns for NuGet publishing |
| search_knowledge("XML documentation comments public API IntelliSense .NET") | During documentation phase — authoritative XML doc comment syntax |
Protocol: Search at CONFIGURE and before CI/CD setup. Cite source paths in the scaffold templates and generated project files.
Six-step pipeline: Scaffold → Configure → Test → Pack → Publish (with iterate back if needed).
Create the solution structure:
PackageName/
├── src/
│ └── PackageName/
│ ├── PackageName.csproj
│ └── Class1.cs
├── tests/
│ └── PackageName.Tests/
│ ├── PackageName.Tests.csproj
│ └── Class1Tests.cs
├── .github/
│ └── workflows/
│ ├── ci.yml
│ └── publish.yml
├── PackageName.sln
├── Directory.Build.props
├── README.md
├── LICENSE
└── .editorconfig
Required metadata properties checklist:
PackageId -- unique identifier on the feedVersion -- SemVer-compliant version stringAuthors -- comma-separated author namesDescription -- concise summary of what the package doesPackageLicenseExpression -- SPDX license identifier (e.g., MIT, Apache-2.0)PackageProjectUrl -- link to the project repositoryRepositoryUrl -- source repository URLRepositoryType -- typically gitPackageReadmeFile -- path to the README to embed in the packagePackageTags -- space-separated discovery tagsTargetFrameworks -- semicolon-separated TFMsMulti-target decision: TargetFrameworks: netstandard2.0;net10.0 when pre-.NET 10 consumers need support; TargetFrameworks: net10.0 otherwise.
dotnet test --configuration Release
Verify all unit tests pass on every target framework, public API surface is tested, edge cases and error paths are covered.
dotnet pack --configuration Release --output ./artifacts
dotnet nuget verify ./artifacts/PackageName.1.0.0.nupkg
unzip -l ./artifacts/PackageName.1.0.0.nupkg
# To nuget.org
dotnet nuget push ./artifacts/PackageName.1.0.0.nupkg \
--api-key $NUGET_API_KEY \
--source https://api.nuget.org/v3/index.json
# To a private feed
dotnet nuget push ./artifacts/PackageName.1.0.0.nupkg \
--api-key $FEED_API_KEY \
--source https://pkgs.dev.azure.com/org/project/_packaging/feed/nuget/v3/index.json
<nuget-scaffold-state>
step: [scaffold | configure | test | pack | publish]
package_name: [name]
target_frameworks: [frameworks]
version: [version]
publish_target: [nuget.org | private feed | local]
last_action: [what was done]
next_action: [what's next]
blockers: [issues]
</nuget-scaffold-state>
| Template | Required Content | |----------|-----------------| | Project Scaffold | Created files table (path → purpose), initial state block | | .csproj Configuration | Configured properties list (PackageId, Version, Authors, etc.), Build settings (Deterministic, Source Link, Nullable), state block | | CI/CD Pipeline Setup | Pipeline stages table (Stage / Trigger / Actions: Build=Push/PR, Pack=Tag push, Publish=Tag+approval), state block |
Full templates: references/cicd-templates.md
Never Publish Without Tests: Run dotnet test --configuration Release before any dotnet nuget push. Publishing untested code to a feed is irrecoverable damage to consumers — downstream projects will take the broken version immediately.
Always Validate Package Metadata Before Pack: All 11 required properties (PackageId, Version, Authors, Description, PackageLicenseExpression, PackageProjectUrl, RepositoryUrl, RepositoryType, PackageReadmeFile, PackageTags, TargetFrameworks) must be present before dotnet pack. Missing metadata degrades discoverability and trust on the feed.
Never Skip Multi-Target Verification: When TargetFrameworks lists multiple TFMs, test each independently: dotnet test --framework net10.0 then dotnet test --framework netstandard2.0. A package that fails on one declared target is broken, even if the other passes.
Always Review Public API Surface Before Versioning: List all public types and members. Compare against the previous version. Classify: addition → MINOR, removal or modification → MAJOR, internal-only change → PATCH. Verify no internal types are accidentally exposed. Accidental public API expansion creates maintenance burden forever.
| Anti-Pattern | Why It's Wrong | Correct Approach |
|--------------|----------------|------------------|
| Publishing without version bump | Consumers cannot distinguish builds; caching breaks | Always increment version for every publish |
| Exposing all types as public | Inflates API surface; locks you into supporting everything | Default to internal; promote to public deliberately |
| Hardcoded dependency versions | Forces consumers into version conflicts | Use minimum viable version ranges (e.g., [8.0.0, )) |
| Skipping Source Link | Consumers cannot debug into your package source | Always configure Source Link for public packages |
| Single target framework | Excludes consumers on other frameworks unnecessarily | Multi-target unless APIs require a specific TFM |
| Publishing prerelease to nuget.org without suffix | Stable version number occupies the version space permanently | Use -alpha, -beta, -rc suffixes for prereleases |
| Missing README in package | Consumers see no documentation on nuget.org package page | Always set PackageReadmeFile and include the file |
Action: Run dotnet pack --configuration Release and capture all NU5* warnings. Address each warning — common culprits: missing Description, PackageLicenseExpression, PackageReadmeFile. Re-run pack and verify zero warnings.
Action: NuGet.org does not allow overwriting published versions — increment the version number. Unlist the broken version via nuget.org UI if needed. Update CI/CD to use git tags as version source to prevent duplicate pushes.
Action: Verify the API key is valid and not expired. For nuget.org: check key scopes match the package ID glob. For Azure Artifacts: verify the PAT has Packaging (Read & Write) scope. For GitHub Packages: verify write:packages scope. Rotate the key if compromised and update CI/CD secrets.
Action: Identify the API unavailable on the failing TFM. Add conditional compilation (#if NET9_0_OR_GREATER) for newer APIs. Provide a fallback for older TFMs. If no fallback is possible, remove the incompatible TFM from TargetFrameworks. Re-run dotnet test across all remaining targets.
Action: Identify the behavioral difference (string formatting, floating point, date handling). Add framework-specific test expectations using #if directives or runtime checks. Document the difference if it affects consumers.
dotnet-vertical-slice -- use to structure the internal architecture, then use this skill to wrap it as a distributable NuGet packagetdd-cycle, tdd-pair, tdd-agent) -- develop the package internals using TDD workflows before progressing to the Pack step; the test project created by this scaffold integrates directly with TDD phase managementmcp-server-scaffold -- when building an MCP server that ships as a dotnet tool NuGet package, use this skill for the packaging and mcp-server-scaffold for the server implementationdevelopment
Federal / government security overlay applied ON TOP OF a base language security review (dotnet/python/php/rust/react). Language-agnostic: adds NIST SP 800-53 control mapping, FIPS 140-2/3 cryptographic compliance (with a per-language crypto table), CUI handling, EO 14028 supply-chain requirements, and DOE Order 205.1B, and emits POA&M-ready findings with FIPS 199 impact levels. Use for federal/DOE/DOD/national-laboratory systems. Triggers on "federal security review", "NIST compliance", "NIST 800-53", "FISMA", "CUI", "FIPS audit", "DOE security", "POA&M", "ATO review". Do NOT use alone — run the matching <lang>-security-review FIRST; this overlay maps and extends it.
tools
OWASP-based security review of React / TypeScript front-end applications. Detects the framework (Vite/CRA/Next), entry points, and data flows, scans against the OWASP Top 10 (2025) mapped to React client-side patterns (XSS via raw HTML, URL/protocol injection, secrets in the bundle, insecure token storage, dependency CVEs, missing CSP, open redirects), and produces a manager-friendly executive summary plus a graded technical findings table. Use to audit React code for vulnerabilities. Triggers on "react security review", "frontend security audit", "audit react for vulnerabilities", "owasp react", "react xss", "react security posture", "npm audit review". For federal / gov / DOE / NIST / FIPS / CUI context, run security-review-federal after this base review. Do NOT use to grade architecture/structure — use react-architecture-checklist.
tools
Analyzes legacy React codebases and produces actionable modernization plans. Primary migration paths include class components to function components + hooks, Create React App to Vite, React 16/17 to 18 to 19, JavaScript to TypeScript, Enzyme to React Testing Library, legacy Redux to Redux Toolkit / Zustand / Context, and deprecated lifecycle/API removal. Does NOT perform the migration — assesses, quantifies risk, and plans. Triggers on phrases like "modernize react", "class to hooks", "upgrade react", "migrate CRA to vite", "react legacy migration", "react 17 to 18", "react js to typescript", "react technical debt", "enzyme to RTL".
development
Scaffolds feature-based React / TypeScript architecture using feature folders, presentational + container components, custom hooks, a typed data layer, and structural CQRS (query hooks vs mutation hooks). React analog of dotnet-vertical-slice and python-feature-slice — no DI framework; uses props/context for dependency injection and a query cache for server state. Use when creating feature-based React projects, adding React features, organizing components by feature rather than by technical type, or scaffolding a feature's data layer. Triggers on phrases like "scaffold react feature", "create react slice", "react feature folder", "react vertical slice", "add react feature", "react feature architecture", "organize react by feature".