From dotnet
Runs single-file C# scripts via dotnet for prototyping, concept testing, and API experiments. Supports #:package NuGet refs and #:property MSBuild settings.
npx claudepluginhub dotnet/skills --plugin dotnetThis skill uses the workspace's default tool permissions.
- Testing a C# concept, API, or language feature with a quick one-file program
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Guides MCP server integration in Claude Code plugins via .mcp.json or plugin.json configs for stdio, SSE, HTTP types, enabling external services as tools.
| Input | Required | Description |
|---|---|---|
| C# code or intent | Yes | The code to run, or a description of what the script should do |
Run dotnet --version to verify the SDK is installed and note the major version number. File-based apps require .NET 10 or later. If the version is below 10, follow the fallback for older SDKs instead.
Create a single .cs file using top-level statements. Place it outside any existing project directory to avoid conflicts with .csproj files.
// hello.cs
Console.WriteLine("Hello from a C# script!");
var numbers = new[] { 1, 2, 3, 4, 5 };
Console.WriteLine($"Sum: {numbers.Sum()}");
Guidelines:
Main method, class, or namespace boilerplate)using directives at the top of the file (after the #! line and any #: directives if present)dotnet hello.cs
Builds and runs the file automatically. Cached so subsequent runs are fast. Pass arguments after --:
dotnet hello.cs -- arg1 arg2 "multi word arg"
Place directives at the top of the file (immediately after an optional shebang line), before any using directives or other C# code. All directives start with #:.
#:package — NuGet package referencesAlways specify a version:
#:package Humanizer@2.14.1
using Humanizer;
Console.WriteLine("hello world".Titleize());
#:property — MSBuild propertiesSet any MSBuild property inline. Syntax: #:property PropertyName=Value
#:property AllowUnsafeBlocks=true
#:property PublishAot=false
#:property NoWarn=CS0162
MSBuild expressions and property functions are supported:
#:property LogLevel=$([MSBuild]::ValueOrDefault('$(LOG_LEVEL)', 'Information'))
Common properties:
| Property | Purpose |
|---|---|
AllowUnsafeBlocks=true | Enable unsafe code |
PublishAot=false | Disable native AOT (enabled by default) |
NoWarn=CS0162;CS0219 | Suppress specific warnings |
LangVersion=preview | Enable preview language features |
InvariantGlobalization=false | Enable culture-specific globalization |
#:project — Project referencesReference another project by relative path:
#:project ../MyLibrary/MyLibrary.csproj
#:sdk — SDK selectionOverride the default SDK (Microsoft.NET.Sdk):
#:sdk Microsoft.NET.Sdk.Web
Remove the script file when the user is done. To clear cached build artifacts:
dotnet clean hello.cs
On Unix platforms, make a .cs file directly executable:
Add a shebang as the first line of the file:
#!/usr/bin/env dotnet
Console.WriteLine("I'm executable!");
Set execute permissions:
chmod +x hello.cs
Run directly:
./hello.cs
Use LF line endings (not CRLF) when adding a shebang. This directive is ignored on Windows.
File-based apps enable native AOT by default. Reflection-based APIs like JsonSerializer.Serialize<T>(value) fail at runtime under AOT. Use source-generated serialization instead:
using System.Text.Json;
using System.Text.Json.Serialization;
var person = new Person("Alice", 30);
var json = JsonSerializer.Serialize(person, AppJsonContext.Default.Person);
Console.WriteLine(json);
var deserialized = JsonSerializer.Deserialize(json, AppJsonContext.Default.Person);
Console.WriteLine($"Name: {deserialized!.Name}, Age: {deserialized.Age}");
record Person(string Name, int Age);
[JsonSerializable(typeof(Person))]
partial class AppJsonContext : JsonSerializerContext;
When a script outgrows a single file, convert it to a full project:
dotnet project convert hello.cs
If the .NET SDK version is below 10, file-based apps are not available. Use a temporary console project instead:
mkdir -p /tmp/csharp-script && cd /tmp/csharp-script
dotnet new console -o . --force
Replace the generated Program.cs with the script content and run with dotnet run. Add NuGet packages with dotnet add package <name>. Remove the directory when done.
dotnet --version reports 10.0 or later (or fallback path is used)dotnet build <file>.cs)dotnet <file>.cs produces the expected output| Pitfall | Solution |
|---|---|
.cs file is inside a directory with a .csproj | Move the script outside the project directory, or use dotnet run --file file.cs |
#:package without a version | Specify a version: #:package PackageName@1.2.3 or @* for latest |
#:property with wrong syntax | Use PropertyName=Value with no spaces around = and no quotes: #:property AllowUnsafeBlocks=true |
| Directives placed after C# code | All #: directives must appear immediately after an optional shebang line (if present) and before any using directives or other C# statements |
| Reflection-based JSON serialization fails | Use source-generated JSON with JsonSerializerContext (see Source-generated JSON) |
| Unexpected build behavior or version errors | File-based apps inherit global.json, Directory.Build.props, Directory.Build.targets, and nuget.config from parent directories. Move the script to an isolated directory if the inherited settings conflict |
See https://learn.microsoft.com/en-us/dotnet/core/sdk/file-based-apps for a full reference on file-based apps.