Dynamo Dotnet Expert
DynamoDS/Dynamo
Write and review C/.NET code in Dynamo following Dynamo coding standards, modern C patterns, and repo conventions.
Makes .NET projects compatible with Native AOT and trimming by resolving IL trim and AOT analyzer warnings through annotations rather than suppressions.
$ npx skills add dotnet/skills --skill dotnet-aot-compat -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install dotnet/skills dotnet-aot-compat --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/dotnet/skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/dotnet-upgrade/skills/dotnet-aot-compat .claude/skills/dotnet-aot-compat && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "dotnet-aot-compat" agent skill from https://github.com/dotnet/skills/tree/main/plugins/dotnet-upgrade/skills/dotnet-aot-compat into .claude/skills/dotnet-aot-compat/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dotnet-aot-compat", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/dotnet/skills/tree/main/plugins/dotnet-upgrade/skills/dotnet-aot-compatType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add dotnet/skills --skill dotnet-aot-compat -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install dotnet/skills dotnet-aot-compat --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/dotnet/skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/plugins/dotnet-upgrade/skills/dotnet-aot-compat .agents/skills/dotnet-aot-compat && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "dotnet-aot-compat" agent skill from https://github.com/dotnet/skills/tree/main/plugins/dotnet-upgrade/skills/dotnet-aot-compat into .agents/skills/dotnet-aot-compat/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dotnet-aot-compat", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add dotnet/skills --skill dotnet-aot-compat -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install dotnet/skills dotnet-aot-compat --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/dotnet/skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/plugins/dotnet-upgrade/skills/dotnet-aot-compat .cursor/skills/dotnet-aot-compat && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "dotnet-aot-compat" agent skill from https://github.com/dotnet/skills/tree/main/plugins/dotnet-upgrade/skills/dotnet-aot-compat into .cursor/skills/dotnet-aot-compat/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dotnet-aot-compat", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/dotnet/skills.git --path plugins/dotnet-upgrade/skills/dotnet-aot-compat--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add dotnet/skills --skill dotnet-aot-compat -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install dotnet/skills dotnet-aot-compat --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/dotnet/skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/plugins/dotnet-upgrade/skills/dotnet-aot-compat .gemini/skills/dotnet-aot-compat && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "dotnet-aot-compat" agent skill from https://github.com/dotnet/skills/tree/main/plugins/dotnet-upgrade/skills/dotnet-aot-compat into .gemini/skills/dotnet-aot-compat/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dotnet-aot-compat", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install dotnet/skills dotnet-aot-compatInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add dotnet/skills --skill dotnet-aot-compat -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/dotnet/skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/plugins/dotnet-upgrade/skills/dotnet-aot-compat .github/skills/dotnet-aot-compat && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "dotnet-aot-compat" agent skill from https://github.com/dotnet/skills/tree/main/plugins/dotnet-upgrade/skills/dotnet-aot-compat into .github/skills/dotnet-aot-compat/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dotnet-aot-compat", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add dotnet/skills --skill dotnet-aot-compat -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install dotnet/skills dotnet-aot-compat --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/dotnet/skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/plugins/dotnet-upgrade/skills/dotnet-aot-compat .opencode/skills/dotnet-aot-compat && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "dotnet-aot-compat" agent skill from https://github.com/dotnet/skills/tree/main/plugins/dotnet-upgrade/skills/dotnet-aot-compat into .opencode/skills/dotnet-aot-compat/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dotnet-aot-compat", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
dotnet-aot-compatMakes .NET projects compatible with Native AOT and trimming by resolving IL trim and AOT analyzer warnings through annotations rather than suppressions.
The skill works through warnings such as IL2026, IL2070, IL2067, IL2072 and IL3050, and through enabling `IsAotCompatible` in a `.csproj`. It explains why reflection trips up the trimmer, which cannot see which types and members are used at runtime, and requires a project targeting net8.0 or later with the matching SDK. Projects that target only .NET Framework are out of scope because the analyzers do not exist there.
Its rules are strict: never silence IL warnings with `#pragma warning disable` or `[UnconditionalSuppressMessage]`, because the linker and AOT compiler still see the problem. Prefer `[DynamicallyAccessedMembers]` annotations to carry type information through the call chain, refactor away patterns that break that flow such as boxing a `Type` in an `object[]`, and mark truly incompatible methods with `[RequiresUnreferencedCode]`, `[RequiresDynamicCode]` or `[RequiresAssemblyFiles]` so callers must acknowledge them. It does not cover publishing AOT binaries, shrinking binary size or replacing reflection-heavy libraries.
6 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 8d670fa. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
dotnetFrom the folder's file list and the shell code blocks in SKILL.md.
Links to these hosts (documentation or services it may open):
learn.microsoft.comFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
.NET Native AOT Compatibility loads about 4.2k tokens when it runs, and up to ~4.6k if it reads all its reference files. Until then it costs about 127 tokens; SKILL.md has 1,764 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from dotnet/skills at commit 8d670fa, republished under its MIT licence (© dotnet). 1,764 words, ~4,192 tokens.
.claude/skills/dotnet-aot-compat/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.Make .NET projects compatible with Native AOT and trimming by systematically resolving all IL trim/AOT analyzer warnings.
Do not use this skill when the project exclusively targets .NET Framework (net4x), which does not support the trim/AOT analyzers.
An existing .NET project targeting net8.0 or later (or multi-targeting with at least one net8.0+ TFM) and the corresponding .NET SDK installed.
Native AOT and the IL trimmer perform static analysis to determine what code is reachable. Reflection can break this analysis because the trimmer can't see what types/members are accessed at runtime. The IsAotCompatible property enables analyzers that flag these issues as build warnings (ILXXXX codes).
#pragma warning disable for IL warnings. It hides warnings from the Roslyn analyzer at build time, but the IL linker and AOT compiler still see the issue. The code will fail at trim/publish time.[UnconditionalSuppressMessage]. It tells both the analyzer AND the linker to ignore the warning, meaning the trimmer cannot verify safety. Raising an error at build time is always preferable to hiding the issue and having it silently break at runtime.[DynamicallyAccessedMembers] annotations to flow type information through the call chain.Type through object[]).[RequiresUnreferencedCode] / [RequiresDynamicCode] / [RequiresAssemblyFiles] to mark methods as fundamentally incompatible with trimming, propagating the requirement to callers. This surfaces the issue clearly rather than hiding it — callers must explicitly acknowledge the incompatibility.The trimmer tracks [DynamicallyAccessedMembers] annotations through assignments, parameter passing, and return values. If this flow is broken (e.g., by boxing a Type into object, storing in an untyped collection, or casting through interfaces), the trimmer loses track and warns. The fix is to preserve the flow, not suppress the warning.
Do not explore the codebase up-front. The build warnings tell you exactly which files and lines need changes. Follow a tight loop: build → pick a warning → open that file at that line → apply the fix recipe → rebuild. Reading or analyzing source files beyond what a specific warning points you to is wasted effort and leads to timeouts. Let the compiler guide you.
❌ Do NOT run
find,ls, orgrepto understand the project structure before building. Do NOT read README, docs, or architecture files. Your first action should be Step 1 (enable AOT analysis), then build.
Add IsAotCompatible. If the project doesn't exclusively target net8.0+, add a TFM condition (AOT analysis requires net8.0+):
<PropertyGroup>
<IsAotCompatible Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net8.0'))">true</IsAotCompatible>
</PropertyGroup>This automatically sets EnableTrimAnalyzer=true and EnableAotAnalyzer=true for compatible TFMs. For multi-targeting projects (e.g., netstandard2.0;net8.0), the condition ensures no NETSDK1210 warnings on older TFMs.
dotnet build <project.csproj> -f <net8.0-or-later-tfm> --no-incremental 2>&1 | grep 'IL[0-9]\{4\}'Sort and deduplicate. Common warning codes:
Type parameter missing [DynamicallyAccessedMembers]Type to a method expecting [DynamicallyAccessedMembers]Type.GetType(string) with a non-constant argument[RequiresUnreferencedCode][DynamicallyAccessedMembers] required by constraintAssembly.Location returns empty string in single-file/AOT apps[RequiresDynamicCode]Group the warnings from Step 2 by warning code and count them. Do not open individual files yet. Identify the top 1-2 patterns by count — these drive your fix strategy:
| Pattern | Typical fix |
|---|---|
Many IL2026 + IL3050 from JsonSerializer | Go to Strategy C immediately — create a JsonSerializerContext, then batch-update all call sites |
IL2070/IL2087 on Type parameters | Add [DynamicallyAccessedMembers] to the innermost method, then cascade outward |
IL2067 passing unannotated Type | Annotate the parameter at the source |
In most real projects, IL2026/IL3050 from JsonSerializer dominate. Start with Strategy C unless the warning breakdown clearly shows otherwise. After the batch JSON fix, handle remaining warnings with Strategies A–B. Only use Strategy D as a last resort.
Work from the innermost reflection call outward. Each fix may cascade new warnings to callers.
Stay warning-driven. For each warning, open only the file and line the compiler reported, identify the pattern, apply the matching fix recipe below, and move on. Do not scan the codebase for similar patterns or try to understand the full architecture — fix what the compiler tells you, rebuild, and let new warnings guide the next change. Fix a small batch of warnings (5-10), then rebuild immediately to check progress.
Use sub-agents when available. If you can launch sub-agents (e.g., via a task tool), dispatch multiple sub-agents in parallel to edit different files simultaneously. Keep the main loop focused on building, parsing warnings, and dispatching — delegate actual file edits to sub-agents. For batch JSON updates, give each sub-agent 5-10 files to update in one prompt. After 2 build-fix cycles, dispatch all remaining file edits to sub-agents in parallel — do not continue fixing files sequentially. Example:
Update these files to use source-generated JSON:
src/Models/Resource.Serialization.cs,src/Models/Identity.Serialization.cs,src/Models/Plan.Serialization.cs. In each file, replaceJsonSerializer.Serialize(writer, value)withJsonSerializer.Serialize(writer, value, MyProjectJsonContext.Default.TypeName)andJsonSerializer.Deserialize<T>(ref reader)withJsonSerializer.Deserialize(ref reader, MyProjectJsonContext.Default.TypeName). Only edit the JsonSerializer call sites.
[DynamicallyAccessedMembers] (preferred)When a method uses reflection on a Type parameter, annotate the parameter to tell the trimmer what members are needed:
using System.Diagnostics.CodeAnalysis;
// Before (warns IL2070):
void Process(Type t) {
var method = t.GetMethod("Foo"); // trimmer can't verify
}
// After (clean):
void Process([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t) {
var method = t.GetMethod("Foo"); // trimmer preserves public methods
}When you annotate a parameter, all callers must now pass properly annotated types. This cascades outward — follow each caller and annotate or refactor as needed. The caller's annotation must include at least the same member types as the callee's. If the callee requires PublicConstructors | NonPublicConstructors, the caller must specify the same or a superset — using only NonPublicConstructors will produce IL2091.
When annotation flow is broken by boxing (storing Type in object, object[], or untyped collections), refactor to pass the Type directly:
// BROKEN: Type boxed into object[], annotation lost
void Process(object[] args) {
Type t = (Type)args[0]; // IL2072: annotation lost through boxing
Evaluate(t, ...);
}
// FIXED: Pass Type as a separate, annotated parameter
void Process(
object[] args,
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type calleeType,
...) {
Evaluate(calleeType, ...); // annotation flows cleanly
}Common patterns that break flow and how to fix them:
object[] parameter bags: Extract the Type into a dedicated annotated parameterWhen most warnings are IL2026/IL3050 from JsonSerializer.Serialize/Deserialize, this is a single mechanical fix applied in bulk:
Collect affected types — grep for all JsonSerializer.Serialize and JsonSerializer.Deserialize call sites. Extract the type being serialized (the <T> in Deserialize<T>, or the runtime type of the object in Serialize).
Create one JsonSerializerContext with [JsonSerializable] for every type found. Skip types from external packages (e.g., ResponseError from Azure.Core) — they won't source-generate for types you don't own. Handle external types separately via Gotcha #1 below.
[JsonSerializerContext]
[JsonSerializable(typeof(ManagedServiceIdentity))]
[JsonSerializable(typeof(SystemData))]
// ... one attribute per type YOU OWN
// Do NOT add types from external packages (e.g., ResponseError)
internal partial class MyProjectJsonContext : JsonSerializerContext { }Batch-update all call sites — do not read each file individually. Apply the pattern mechanically:
JsonSerializer.Serialize(obj) → JsonSerializer.Serialize(obj, MyProjectJsonContext.Default.TypeName)JsonSerializer.Deserialize<T>(json) → JsonSerializer.Deserialize(json, MyProjectJsonContext.Default.TypeName)Find and update all call sites in one pass:
# Find all files with JsonSerializer calls
grep -rl 'JsonSerializer\.\(Serialize\|Deserialize\)' src/ --include='*.cs'Then use sequential edit calls to apply the same transformation to every matching file. Do not use sed for C# code — generics like Deserialize<T>() have angle brackets and nested parentheses that sed will mangle.
Build once to verify. Remaining warnings will be non-serialization issues — handle those with Strategies A–B or D.
[RequiresUnreferencedCode] (last resort)When a method fundamentally requires arbitrary reflection that cannot be statically described:
[RequiresUnreferencedCode("Loads plugins by name using Assembly.Load")]
public void LoadPlugin(string assemblyName) {
var asm = Assembly.Load(assemblyName);
// ...
}This propagates to callers — they must also be annotated with [RequiresUnreferencedCode]. Use sparingly; it marks the entire call chain as trim-incompatible.
After each small batch of fixes (5-10 warnings), rebuild with --no-incremental and check for new warnings. Do not attempt to fix all warnings before rebuilding — frequent rebuilds catch mistakes early and reveal cascading warnings. Fixes cascade — annotating an inner method may surface warnings in its callers. Repeat until 0 Warning(s).
Build all target frameworks to ensure:
IsAotCompatible condition handles this)dotnet build <project.csproj> # builds all TFMs[RequiresUnreferencedCode].For multi-targeting projects that include netstandard2.0 or net472, you need polyfills for DynamicallyAccessedMembersAttribute and related types. See references/polyfills.md.
ResponseError from Azure.Core) and it lacks a source-generated serializer, Options.GetConverter<T>() is reflection-based and will produce IL warnings. First check if the type implements IJsonModel<T> (common in Azure SDK) — if so, bypass JsonSerializer entirely:// Before (IL2026 — JsonSerializer uses reflection):
JsonSerializer.Serialize(writer, errorValue);
// After (AOT-safe — uses IJsonModel directly):
((IJsonModel<ResponseError>)errorValue).Write(writer, ModelReaderWriterOptions.Json);
// For deserialization:
var error = ((IJsonModel<ResponseError>)new ResponseError()).Create(ref reader, ModelReaderWriterOptions.Json);Do not add the external type to your JsonSerializerContext — it won't source-generate for types you don't own. If the type doesn't implement IJsonModel<T>, write a custom JsonConverter<T> with manual Utf8JsonReader/Utf8JsonWriter logic and register it via [JsonSourceGenerationOptions] on your context.
Serialization libraries: Most reflection-based serializers (e.g., Newtonsoft.Json, XmlSerializer) are not AOT-compatible. Migrate to a source-generation-based serializer such as System.Text.Json with a JsonSerializerContext. If migration is not feasible, mark the serialization call site with [RequiresUnreferencedCode].
Shared projects / projitems: When source is shared between multiple projects via <Import>, annotations added to shared code affect ALL consuming projects. Verify that all consumers still build cleanly.
Limitations Conceptual: Understanding trimming How-to: trim compat
<IsAotCompatible> with TFM condition to .csproj#pragma warning disable or [UnconditionalSuppressMessage] used for any IL warning© dotnet, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 1 other file (references) in plugins/dotnet-upgrade/skills/dotnet-aot-compat of dotnet/skills.
Open the folder on GitHubat commit 8d670fa
We found 3 copies of this SKILL.md (exact, near-identical or edited) in other folders, from 2 other GitHub owners. This page covers the copy in dotnet/skills, which our catalogue first saw on October 7, 2026.
.NET Native AOT Compatibility next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| .NET Native AOT Compatibility this skilldotnet/skills | 5.6k | 2 repos | ~4.2k | Automated safety check: Pass | MIT | |
| Dynamo Dotnet ExpertDynamoDS/Dynamo | 2k | — | ~909 | Automated safety check: Pass | Apache-2.0 | |
| Systematic Code Refactoringluongnv89/claude-howto | 42k | — | ~3k | Automated safety check: Pass | MIT | |
| Dignified Python Standardsdocling-project/docling | 68k | — | ~1.5k | Automated safety check: Pass | Apache-2.0 | |
| Clean Code GuardamElnagdy/guard-skills | 1.3k | 2 repos | ~4.3k | Automated safety check: Pass | MIT | |
| Code Refactoring Workflowluongnv89/claude-howto | 42k | — | ~3.1k | Automated safety check: Pass | MIT |
DynamoDS/Dynamo
Write and review C/.NET code in Dynamo following Dynamo coding standards, modern C patterns, and repo conventions.
luongnv89/claude-howto
Guides refactoring in phases based on Martin Fowler's method: research, test coverage check, planning and small tested steps, with your approval at each phase.
docling-project/docling
Applies opinionated production Python conventions chosen by the project's Python version: modern type syntax, pathlib, explicit checks and interface guidance.
amElnagdy/guard-skills
Reviews generated or changed production code against Clean Code, SOLID, DRY, KISS, YAGNI and LLM-specific failure modes before it ships, in any language.
luongnv89/claude-howto
Guides systematic, test-backed refactoring in the style of Martin Fowler, moving through research, planning and small incremental changes with your approval at each phase.
Devin-AXIS/iPolloWork
A code-change gate for the iPolloWork repository: search and reuse first, keep one source of truth, justify every new file or dependency, and audit the change.
dotnet/skills
Resolves .NET runtime frames in Apple .ips crash logs to function names, source files and line numbers using dSYM symbols, atos and the Microsoft symbol server.
dotnet/skills
Resolves native crash frames from .NET Android tombstones to function names, source files and line numbers using BuildIds, Microsoft's symbol server and llvm-symbolizer.
dotnet/skills
Scans C# and .NET code for about 50 performance anti-patterns and reports prioritized findings with concrete fixes, at a scan depth you choose.
dotnet/skills
Statically pairs source files with test files to list code that no test references, using Roslyn for C# or tree-sitter for many languages, with no build.
dotnet/skills
Activate this skill when BenchmarkDotNet (BDN) is involved in the task — creating, running, configuring, or reviewing BDN benchmarks.
dotnet/skills
Configures automatic crash dumps or captures dumps from running processes for modern .NET apps on Linux, macOS and Windows, including Docker and Kubernetes.
Works with
Categories
Makes .NET projects compatible with Native AOT and trimming by resolving IL trim and AOT analyzer warnings through annotations rather than suppressions. csproj`.0 or later with the matching SDK.
.NET Native AOT Compatibility fits situations like: making a library or app AOT-compatible; fixing trimming and IL analyzer warnings after upgrading to net8.0; adding DynamicallyAccessedMembers annotations to reflection code.
Run `npx skills add dotnet/skills --skill dotnet-aot-compat -a claude-code`. Or copy the skill folder (plugins/dotnet-upgrade/skills/dotnet-aot-compat in dotnet/skills) into .claude/skills/dotnet-aot-compat in your project. Claude Code loads it when a task matches its description.
Run `npx skills add dotnet/skills --skill dotnet-aot-compat -a codex`. Or copy the skill folder (plugins/dotnet-upgrade/skills/dotnet-aot-compat in dotnet/skills) into .agents/skills/dotnet-aot-compat in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add dotnet/skills --skill dotnet-aot-compat -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/dotnet-aot-compat, .gemini/skills/dotnet-aot-compat, .github/skills/dotnet-aot-compat and .opencode/skills/dotnet-aot-compat in your project.
Going by SKILL.md and its folder, .NET Native AOT Compatibility needs the command-line tools its instructions call (dotnet). Our summary lists: .NET SDK and a project targeting net8.0 or later.
SKILL.md names 1 domain. As links in the text: learn.microsoft.com. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
.NET Native AOT Compatibility is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.2k tokens (SKILL.md is roughly 17k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 407 tokens, read only when the agent opens those files.
Skills that share tags, products or a category with .NET Native AOT Compatibility: Dynamo Dotnet Expert (DynamoDS/Dynamo, 2k stars), Systematic Code Refactoring (luongnv89/claude-howto, 42k stars), Dignified Python Standards (docling-project/docling, 68k stars) and Clean Code Guard (amElnagdy/guard-skills, 1.3k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
dotnet (a GitHub organization, an official publisher) maintains it in dotnet/skills, which has 5,568 GitHub stars. The repository holds 91 skills in this directory. The repository was last updated on October 7, 2026.
Source: dotnet/skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.