Best Practices for Writing dotnet/skills Plugins: A Complete Guide

The most effective dotnet/skills plugins follow a strict folder structure under plugins/<name>/, include a descriptive README.md, define capabilities in SKILL.md files with YAML metadata, and declare all dependencies in a .csproj file to ensure compatibility with the built-in skill-validator.

The dotnet/skills repository provides a framework for building self-contained C# capabilities that integrate with the Skills ecosystem. Writing maintainable and discoverable plugins requires adherence to specific architectural conventions regarding file layout, documentation standards, and dependency management. Following these best practices ensures your plugins pass automated validation and remain portable across different runtime environments.

Establish the Standard Folder Structure

Every plugin must reside in its own folder under plugins/<name>/ to guarantee predictable discovery by the skill-validator and other tooling. This location is mandatory for the framework to locate and load your capabilities correctly.

The required layout includes:

  • A top-level README.md describing the plugin's purpose, prerequisites, runtime requirements (e.g., .NET SDK), and LSP server configuration details.
  • One or more SKILL.md files within skills/<skill-name>/ subdirectories that define individual capabilities with machine-readable metadata.
  • An optional agents/ subfolder containing agent definitions used by the skill.
  • A .csproj file at the root of the plugin folder declaring all NuGet packages and SDK components.

For example, the plugins/dotnet/README.md file demonstrates this scaffold, listing required runtimes and explaining how to enable the LSP server.

Define Skills with SKILL.md Metadata

Each skill requires a SKILL.md file that centralizes metadata, inputs, outputs, and implementation notes. This format provides the skill-validator with a machine-readable specification for automated testing and schema validation.

According to the source code, a properly structured SKILL.md includes:

  • title: A concise name for the skill.
  • description: Detailed explanation of what the skill accomplishes.
  • inputs: Dictionary of parameter names with type and description.
  • outputs: Expected return values with type information.

Reference the plugins/dotnet-test/skills/writing-mstest-tests/SKILL.md file for a real-world implementation showing how to document complex testing scenarios.

Configure Agents Using YAML Front-Matter

When your plugin requires automated agents, define them in files following the *.agent.md pattern within the agents/ subfolder. These files use YAML front-matter to allow the framework to load agent configurations without additional parsing code.

The agents/test-quality-auditor.agent.md file in the dotnet-test plugin illustrates this convention, specifying agent names, descriptions, and execution steps directly in the YAML header.

Manage Dependencies and Ensure Self-Containment

Declare all dependencies explicitly in your plugin's .csproj file. This guarantees repeatable builds and enables the skill-validator to restore packages automatically during CI pipelines. For C# analysis capabilities, you may need references such as Microsoft.CodeAnalysis.Workspaces.MSBuild or Microsoft.CodeAnalysis.CSharp.Workspaces.

Critical architecture requirements from the repository specification include:

  • Self-contained design: No code should be imported from outside the plugin's src/ directory (except for explicit packaging assets). This constraint ensures the produced NuGet package remains portable.

  • Unit testing: Write unit tests for any custom C# logic within a tests/ subfolder to prevent regressions when the .NET runtime evolves.

  • Validation: Run the built-in skill-validator located at eng/skill-validator/src/ before committing. This tool enforces JSON schema compliance and catches missing fields or malformed descriptors.

Document Migration Paths and Versioning

When updating a skill's contract or breaking changes, provide migration documentation in a references/ folder within the skill directory. The dotnet-upgrade plugin demonstrates this practice, storing upgrade guides for .NET version transitions in plugins/dotnet-upgrade/skills/.../references/.

Additionally, keep your plugin version synchronized with the repository tag. This practice enables downstream consumers to pin specific skill versions reliably using the release tag mentioned in the repository's main README.md.

Minimal dotnet/skills Plugin Example

The following structure represents a complete, minimal "Hello World" plugin following all architectural guidelines:

my-plugin/
├─ README.md
├─ MyPlugin.csproj
├─ skills/
│  └─ hello-world/
│     └─ SKILL.md
└─ agents/
   └─ hello-agent.agent.md

README.md:


# MyPlugin

A simple example plugin that prints "Hello, World!" from a C#-based skill.

## Prerequisites

- .NET 8 SDK (or newer)
- `dotnet` on the PATH

## LSP

This plugin registers a C# language server via the standard .NET CLI launch.

MyPlugin.csproj:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.9.0" />
  </ItemGroup>
</Project>

skills/hello-world/SKILL.md:

title: Hello World
description: Emits a greeting string.
inputs:
  name:
    type: string
    description: Optional name to address.
outputs:
  message:
    type: string
    description: The generated greeting.

agents/hello-agent.agent.md:

name: hello-agent
description: Executes the Hello World skill.
steps:
  - run: echo "Running Hello World skill"
  - run: skill hello-world --input name=${NAME}

This layout follows mandatory conventions: the skill description lives in SKILL.md, the C# project declares its runtime and packages, and the LSP configuration appears in the top-level README.

Summary

  • Place each plugin under plugins/<name>/ to ensure discovery by the validator.
  • Provide a clear README.md documenting includes, LSP requirements, and prerequisites.
  • Describe every skill in a SKILL.md file with proper YAML metadata defining inputs and outputs.
  • Use YAML front-matter for agent definitions in *.agent.md files.
  • List all NuGet dependencies in the plugin's .csproj and keep the plugin self-contained within its src/ directory.
  • Run the skill-validator from eng/skill-validator/src/ locally before committing changes.
  • Document breaking changes and migration paths in a references/ folder when skill contracts evolve.

Frequently Asked Questions

Where must I place my plugin files for the dotnet/skills framework to recognize them?

The framework requires all plugins to reside under the plugins/<name>/ directory at the repository root. This location is hard-coded into the skill-validator discovery mechanism at eng/skill-validator/src/. Placing files elsewhere prevents the automated tooling from loading your SKILL.md definitions or running validation checks.

What fields are required in a SKILL.md file?

A valid SKILL.md must include YAML front-matter with at minimum a title, description, inputs dictionary, and outputs dictionary. Each input and output requires a type and description. The validator at eng/skill-validator/src/ enforces this schema; missing fields will cause CI failures.

Can my plugin reference code outside its own directory?

No. The repository architecture requires plugins to be self-contained. You cannot import code from outside the plugin's src/ folder except for explicit packaging assets. This constraint ensures that the resulting NuGet package is portable and that the skill-validator can analyze dependencies correctly.

How do I test my plugin before submitting a pull request?

Run the built-in skill-validator located in eng/skill-validator/src/ against your plugin locally. This tool validates your SKILL.md files against the JSON schema, checks for malformed descriptors, and verifies that your .csproj dependencies are resolvable. Additionally, write unit tests for any custom C# logic in a tests/ subfolder to catch regressions against newer .NET runtime versions.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →