skills/csharp-file-based-apps/SKILL.md
Write and run C# programs without a .csproj or solution file using .NET 10+ file-based apps, including multi-file apps with `#:include` (.NET 11+). Use when the user wants to execute C# code quickly — scripts, utilities, prototyping, quick experiments, data processing, teaching examples, or tool authoring. Triggers on phrases like "run this C# file", "C# script", "no project file needed", "single file C# app", "dotnet run file.cs", "quick C# utility", "split script across files", "#:include directive", or any request to write and immediately execute a small self-contained C# program.
npx skillsauth add arisng/github-copilot-fc csharp-file-based-appsInstall 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.
Run a single .cs file directly — no .csproj required. The SDK generates a virtual project automatically.
#:include): .NET 11 SDK or later.Verify with dotnet --version. If below 10, use the fallback.
Create script.cs outside any existing .csproj directory:
// script.cs — uses top-level statements
using System.Linq;
var numbers = Enumerable.Range(1, 10);
Console.WriteLine($"Sum: {numbers.Sum()}");
Rules:
using directives first| Goal | Command |
|------|---------|
| Run | dotnet script.cs or dotnet run script.cs |
| Pass arguments | dotnet script.cs -- arg1 arg2 |
| Pipe code from stdin | echo 'Console.WriteLine("hi");' \| dotnet run - |
| Build only | dotnet build script.cs |
| Publish (native AOT) | dotnet publish script.cs |
| Package as .NET tool | dotnet pack script.cs |
| Clean build cache | dotnet clean script.cs |
| Convert to full project | dotnet project convert script.cs |
| Restore packages | dotnet restore script.cs |
Builds are cached by source hash; subsequent runs are fast. To avoid cache contention when running multiple parallel instances, build first: dotnet build script.cs, then dotnet run script.cs --no-build.
Place at the top of the file, before any using or code:
#:package [email protected] // NuGet reference — always specify a version
#:package Serilog@* // @* = latest
#:project ../SharedLib/Shared.csproj // Reference a local project
#:sdk Microsoft.NET.Sdk.Web // Alternative SDK (default: Microsoft.NET.Sdk)
#:include helpers.cs // Include another .cs file (.NET 11+)
#:include models/customer.cs // Include from subfolder (.NET 11+)
#:property PublishAot=false // Disable native AOT
#:property TargetFramework=net10.0 // Explicit TFM
#:property OutputPath=./output // Custom build output path
Conditional property using MSBuild expression:
#:property LogLevel=$([MSBuild]::ValueOrDefault('$(LOG_LEVEL)', 'Information'))
Use #:include to split a growing script across files while keeping the file-based workflow:
// models.cs
public record Customer(int Id, string Name, string Email);
// helpers.cs
public static class Helpers
{
public static string Format(Customer c) =>
$"[{c.Id}] {c.Name} <{c.Email}>";
}
// main.cs ← entry point
#:include models.cs
#:include helpers.cs
var customer = new Customer(1, "John Doe", "[email protected]");
Console.WriteLine(Helpers.Format(customer));
Run from the entry point: dotnet run main.cs
Files can live in subfolders: #:include services/email-service.cs. Roslyn provides IntelliSense for #:include in the entry-point file.
See references/examples.md for complete multi-file examples (HTTP health checker, Minimal API with EF Core + SQLite).
Native AOT is on by default. Reflection-based serialization (JsonSerializer without a context, Newtonsoft.Json) fails at runtime under AOT. Use source-generated JSON:
using System.Text.Json;
using System.Text.Json.Serialization;
var person = new Person("Alice", 30);
Console.WriteLine(JsonSerializer.Serialize(person, AppCtx.Default.Person));
record Person(string Name, int Age);
[JsonSerializable(typeof(Person))]
partial class AppCtx : JsonSerializerContext;
To use reflection-based APIs, disable AOT: #:property PublishAot=false.
| Problem | Fix |
|---------|-----|
| Script inside a .csproj directory | Move outside the project tree; or use dotnet run --file script.cs |
| #:package without version | Use @version or @* for latest |
| Reflection JSON fails at runtime | Source-generated JSON, or #:property PublishAot=false |
| Stale / unexpected build behavior | dotnet clean script.cs && dotnet build script.cs |
| Inherits unwanted Directory.Build.props | Move to isolated directory or add a local empty Directory.Build.props |
| Running multiple instances in parallel | Build first, then all instances use --no-build |
| #:include not found | Requires .NET 11+; verify with dotnet --version |
| Included file has top-level statements | Only the entry-point file may have top-level statements; included files declare types only |
#!/usr/bin/env dotnet
Console.WriteLine("Direct execution!");
chmod +x script.cs
./script.cs
Use LF line endings (not CRLF). The shebang line is ignored on Windows.
Create script.run.json alongside script.cs:
{
"profiles": {
"http": {
"commandName": "Project",
"applicationUrl": "http://localhost:5000",
"environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" }
}
}
}
Run with: dotnet run script.cs --launch-profile http
dotnet user-secrets set "ApiKey" "value" --file script.cs
dotnet user-secrets list --file script.cs
File-based apps require .NET 10+. Use a temporary console project:
mkdir -p /tmp/csharp-script && cd /tmp/csharp-script
dotnet new console -o . --force
# Replace Program.cs content, then:
dotnet run
# Add packages with: dotnet add package <Name>
Convert with dotnet project convert main.cs when:
csprojcsproj familiarity mattersStart file-based, grow as needed, convert only when you exceed the approach.
See references/examples.md for: data processing with NuGet packages, ASP.NET Core minimal API, Aspire AppHost, Spectre.Console CLI tool, and multi-file examples (HTTP health checker, Minimal API with EF Core + SQLite).
devops
Programmatically create tldraw whiteboards and visualize them with a self-hosted tldraw instance. Create boards with shapes, text, and connectors, then deploy to a self-hosted server for collaborative editing and gallery management.
tools
Execute Google Cloud Platform operations using the gcloud CLI (and gsutil/bq where applicable). Use when the user wants to: authenticate with GCP, manage GCP resources, deploy applications, configure projects or IAM, view logs, run SQL/BigQuery, or interact with any GCP service from the command line. Triggers on phrases like "gcloud", "Google Cloud CLI", "deploy to GCP", "create a VM", "Cloud Run", "GKE cluster", "Cloud Storage bucket", "set GCP project", "service account", "Cloud Functions", "App Engine deploy", or any request to manage Google Cloud resources via command line.
testing
Grilling session that challenges your plan against the existing domain model, sharpens terminology, and updates documentation (CONTEXT.md, ADRs) inline as decisions crystallise. Use when user wants to stress-test a plan against their project's language and documented decisions.
development
Session-scoped git commit orchestrator that commits only current-session changes and leaves unrelated dirty worktree edits untouched. Inherits git-atomic-commit for atomic grouping and commit message execution, and git-commit-scope-constitution for scope governance and validation. Use when asked to commit this session only or isolate commits from mixed worktree state.