Dotnet Csharp
novotnyllc/dotnet-artisan
Baseline C skill loaded for every .NET code path. An agent skill from novotnyllc/dotnet-artisan.
C/.NET: LINQ, async/await, DI, records, nullable refs, ASP.NET Core, EF Core, MediatR.
$ npx skills add softspark/ai-toolkit --skill csharp-patterns -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install softspark/ai-toolkit csharp-patterns --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/softspark/ai-toolkit.git skills-src && mkdir -p .claude/skills && cp -r skills-src/app/skills/csharp-patterns .claude/skills/csharp-patterns && 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 "csharp-patterns" agent skill from https://github.com/softspark/ai-toolkit/tree/main/app/skills/csharp-patterns into .claude/skills/csharp-patterns/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "csharp-patterns", 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/softspark/ai-toolkit/tree/main/app/skills/csharp-patternsType 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 softspark/ai-toolkit --skill csharp-patterns -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install softspark/ai-toolkit csharp-patterns --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/softspark/ai-toolkit.git skills-src && mkdir -p .agents/skills && cp -r skills-src/app/skills/csharp-patterns .agents/skills/csharp-patterns && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "csharp-patterns" agent skill from https://github.com/softspark/ai-toolkit/tree/main/app/skills/csharp-patterns into .agents/skills/csharp-patterns/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "csharp-patterns", 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 softspark/ai-toolkit --skill csharp-patterns -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install softspark/ai-toolkit csharp-patterns --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/softspark/ai-toolkit.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/app/skills/csharp-patterns .cursor/skills/csharp-patterns && 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 "csharp-patterns" agent skill from https://github.com/softspark/ai-toolkit/tree/main/app/skills/csharp-patterns into .cursor/skills/csharp-patterns/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "csharp-patterns", 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/softspark/ai-toolkit.git --path app/skills/csharp-patterns--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 softspark/ai-toolkit --skill csharp-patterns -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install softspark/ai-toolkit csharp-patterns --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/softspark/ai-toolkit.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/app/skills/csharp-patterns .gemini/skills/csharp-patterns && 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 "csharp-patterns" agent skill from https://github.com/softspark/ai-toolkit/tree/main/app/skills/csharp-patterns into .gemini/skills/csharp-patterns/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "csharp-patterns", 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 softspark/ai-toolkit csharp-patternsInstalls 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 softspark/ai-toolkit --skill csharp-patterns -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/softspark/ai-toolkit.git skills-src && mkdir -p .github/skills && cp -r skills-src/app/skills/csharp-patterns .github/skills/csharp-patterns && 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 "csharp-patterns" agent skill from https://github.com/softspark/ai-toolkit/tree/main/app/skills/csharp-patterns into .github/skills/csharp-patterns/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "csharp-patterns", 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 softspark/ai-toolkit --skill csharp-patterns -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install softspark/ai-toolkit csharp-patterns --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/softspark/ai-toolkit.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/app/skills/csharp-patterns .opencode/skills/csharp-patterns && 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 "csharp-patterns" agent skill from https://github.com/softspark/ai-toolkit/tree/main/app/skills/csharp-patterns into .opencode/skills/csharp-patterns/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "csharp-patterns", 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.
csharp-patternsC/.NET: LINQ, async/await, DI, records, nullable refs, ASP.NET Core, EF Core, MediatR.
Csharp Patterns is an agent skill from softspark/ai-toolkit. C/.NET: LINQ, async/await, DI, records, nullable refs, ASP.NET Core, EF Core, MediatR. Triggers: C, .NET, dotnet, ASP.NET, EF Core, LINQ, record type, IServiceCollection.
Its SKILL.md is about 3.6k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Development, covering Async programming. It works with C#, ASP.NET Core and .NET. The repository describes itself as: Professional-grade AI coding toolkit: 94 skills, 44 agents, multi-platform (Claude, Cursor, Windsurf, Copilot, Gemini, Cline, Roo Code, Aider, Augment, Antigravity, Codex CLI… The licence is Apache-2.0.
Read from SKILL.md and the folder at commit d64db2b. It shows what the files ask for, not the result of running them.
Pre-approves these tools, so the agent can use them without asking each time:
ReadFrom 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.
Hosts in commands or code, which the agent is likely to contact:
api.payments.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.
Csharp Patterns loads about 3.6k tokens when it runs. Until then it costs about 47 tokens; SKILL.md has 143 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 softspark/ai-toolkit at commit d64db2b, republished under its Apache-2.0 licence (© softspark). 143 words, ~3,584 tokens.
.claude/skills/csharp-patterns/SKILL.md (or your agent's skills folder).MyApp.sln
Directory.Build.props # Shared build properties
Directory.Packages.props # Central package management
src/
MyApp.Api/ # ASP.NET Core host (Controllers, Middleware, Program.cs)
MyApp.Application/ # Use cases, MediatR handlers, Behaviors
MyApp.Domain/ # Entities, value objects, domain events
MyApp.Infrastructure/ # EF Core, external services
tests/
MyApp.UnitTests/
MyApp.IntegrationTests/<Project>
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<AnalysisLevel>latest-recommended</AnalysisLevel>
</PropertyGroup>
</Project><Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="MediatR" Version="12.4.1" />
<PackageVersion Include="FluentValidation" Version="11.11.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
</ItemGroup>
</Project>public class Order
{
public required string Id { get; init; }
public string? Notes { get; set; } // explicitly nullable
public required Customer Customer { get; init; } // never null
public string Summary => $"Order {Id}: {Notes ?? "no notes"}";
}public record Money(decimal Amount, string Currency)
{
public Money Add(Money other) => Currency != other.Currency
? throw new InvalidOperationException("Currency mismatch")
: this with { Amount = Amount + other.Amount };
}
public record CreateOrderRequest(string CustomerId, List<OrderLineDto> Lines);
public record OrderLineDto(string ProductId, int Quantity);public decimal CalculateDiscount(Customer c) => c switch
{
{ Tier: CustomerTier.Gold, TotalSpent: > 10_000m } => 0.20m,
{ Tier: CustomerTier.Gold } => 0.15m,
{ Tier: CustomerTier.Silver } => 0.10m,
{ IsNewCustomer: true } => 0.05m,
_ => 0m
};
// List patterns (.NET 8+)
public string Describe(int[] v) => v switch
{
[] => "empty", [var x] => $"one: {x}", [var f, .., var l] => $"{f}..{l}",
};var activeUsers = users
.Where(u => u.IsActive)
.OrderByDescending(u => u.LastLogin)
.Select(u => new UserDto(u.Id, u.Name))
.ToList();// Always: Async suffix, CancellationToken parameter, never .Result/.Wait()
public async Task<Order?> GetOrderAsync(string id, CancellationToken ct = default)
=> await _db.Orders.Include(o => o.Lines).FirstOrDefaultAsync(o => o.Id == id, ct);
// Parallel independent tasks
var ordersTask = _orderRepo.GetRecentAsync(ct);
var statsTask = _statsService.ComputeAsync(ct);
await Task.WhenAll(ordersTask, statsTask);public class OrderService(IOrderRepository repo, ILogger<OrderService> logger, IPublisher pub)
{
public async Task<Order> CreateAsync(CreateOrderRequest req, CancellationToken ct)
{
logger.LogInformation("Creating order for {CustomerId}", req.CustomerId);
var order = Order.Create(req);
await repo.AddAsync(order, ct);
await pub.Publish(new OrderCreatedEvent(order.Id), ct);
return order;
}
}public sealed class Result<T>
{
public T? Value { get; }
public Error? Error { get; }
public bool IsSuccess => Error is null;
private Result(T value) => Value = value;
private Result(Error error) => Error = error;
public static Result<T> Success(T value) => new(value);
public static Result<T> Failure(Error error) => new(error);
public TOut Match<TOut>(Func<T, TOut> ok, Func<Error, TOut> err) =>
IsSuccess ? ok(Value!) : err(Error!);
}
public record Error(string Code, string Message);public class CreateOrderValidator : AbstractValidator<CreateOrderRequest>
{
public CreateOrderValidator()
{
RuleFor(x => x.CustomerId).NotEmpty().MaximumLength(36);
RuleForEach(x => x.Lines).ChildRules(line =>
{
line.RuleFor(l => l.ProductId).NotEmpty();
line.RuleFor(l => l.Quantity).GreaterThan(0).LessThanOrEqualTo(1000);
});
}
}
public class ValidationBehavior<TReq, TRes>(IEnumerable<IValidator<TReq>> validators)
: IPipelineBehavior<TReq, TRes> where TReq : IRequest<TRes>
{
public async Task<TRes> Handle(TReq req, RequestHandlerDelegate<TRes> next, CancellationToken ct)
{
var failures = validators.Select(v => v.Validate(req)).SelectMany(r => r.Errors).ToList();
return failures.Count > 0 ? throw new ValidationException(failures) : await next();
}
}public sealed class TempFileHandle(string path) : IAsyncDisposable
{
public async ValueTask DisposeAsync()
{
if (File.Exists(path)) await Task.Run(() => File.Delete(path));
}
}
// Usage: await using var handle = new TempFileHandle("/tmp/export.csv");public class OrderServiceTests
{
private readonly IOrderRepository _repo = Substitute.For<IOrderRepository>();
private readonly IPublisher _pub = Substitute.For<IPublisher>();
private readonly OrderService _sut;
public OrderServiceTests() => _sut = new(_repo, Substitute.For<ILogger<OrderService>>(), _pub);
[Fact]
public async Task CreateAsync_ValidRequest_ReturnsOrder()
{
var order = await _sut.CreateAsync(new("cust-1", [new("prod-1", 2)]), CancellationToken.None);
order.Should().NotBeNull();
order.Lines.Should().ContainSingle().Which.Quantity.Should().Be(2);
await _repo.Received(1).AddAsync(Arg.Any<Order>(), Arg.Any<CancellationToken>());
}
[Theory]
[InlineData(0)]
[InlineData(-1)]
public async Task CreateAsync_InvalidQuantity_Throws(int qty)
{
var act = () => _sut.CreateAsync(new("cust-1", [new("prod-1", qty)]), CancellationToken.None);
await act.Should().ThrowAsync<ValidationException>();
}
}public class OrdersApiTests(WebApplicationFactory<Program> factory)
: IClassFixture<WebApplicationFactory<Program>>
{
[Fact]
public async Task PostOrder_Returns201()
{
var client = factory.WithWebHostBuilder(b => b.ConfigureServices(s =>
{
s.RemoveAll<DbContext>();
s.AddDbContext<AppDbContext>(o => o.UseInMemoryDatabase("test"));
})).CreateClient();
var response = await client.PostAsJsonAsync("/api/orders",
new { CustomerId = "cust-1", Lines = new[] { new { ProductId = "prod-1", Quantity = 2 } } });
response.StatusCode.Should().Be(HttpStatusCode.Created);
}
}public class PostgresFixture : IAsyncLifetime
{
private readonly PostgreSqlContainer _pg = new PostgreSqlBuilder().WithDatabase("testdb").Build();
public string ConnectionString => _pg.GetConnectionString();
public Task InitializeAsync() => _pg.StartAsync();
public Task DisposeAsync() => _pg.DisposeAsync().AsTask();
}var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Program).Assembly));
var app = builder.Build();
app.MapGet("/api/orders/{id}", async (string id, ISender sender, CancellationToken ct) =>
await sender.Send(new GetOrderQuery(id), ct) is { } order ? Results.Ok(order) : Results.NotFound());
app.MapPost("/api/orders", async (CreateOrderRequest req, ISender sender, CancellationToken ct) =>
(await sender.Send(new CreateOrderCommand(req), ct)).Match(
o => Results.Created($"/api/orders/{o.Id}", o),
e => Results.Problem(e.Message, statusCode: 400)));
app.Run();public class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options)
{
public DbSet<Order> Orders => Set<Order>();
protected override void OnModelCreating(ModelBuilder mb)
{
mb.Entity<Order>(b =>
{
b.HasKey(o => o.Id);
b.Property(o => o.Id).HasMaxLength(36);
b.HasMany(o => o.Lines).WithOne().HasForeignKey(l => l.OrderId);
b.HasIndex(o => o.CustomerId);
b.Property(o => o.Total).HasPrecision(18, 2);
});
mb.ApplyConfigurationsFromAssembly(typeof(AppDbContext).Assembly);
}
}public record CreateOrderCommand(CreateOrderRequest Request) : IRequest<Result<Order>>;
public class CreateOrderHandler(IOrderRepository repo, IPublisher pub)
: IRequestHandler<CreateOrderCommand, Result<Order>>
{
public async Task<Result<Order>> Handle(CreateOrderCommand cmd, CancellationToken ct)
{
var order = Order.Create(cmd.Request);
await repo.AddAsync(order, ct);
await pub.Publish(new OrderCreatedEvent(order.Id), ct);
return Result<Order>.Success(order);
}
}builder.Services.AddHttpClient("Payments", c => c.BaseAddress = new Uri("https://api.payments.com"))
.AddResilienceHandler("default", p =>
{
p.AddRetry(new() { MaxRetryAttempts = 3, Delay = TimeSpan.FromMilliseconds(500),
BackoffType = DelayBackoffType.Exponential,
ShouldHandle = new PredicateBuilder<HttpResponseMessage>()
.HandleResult(r => r.StatusCode >= HttpStatusCode.InternalServerError) });
p.AddCircuitBreaker(new() { FailureRatio = 0.5, SamplingDuration = TimeSpan.FromSeconds(30),
BreakDuration = TimeSpan.FromSeconds(15) });
p.AddTimeout(TimeSpan.FromSeconds(5));
});builder.Services.AddMassTransit(x =>
{
x.AddConsumer<OrderCreatedConsumer>();
x.UsingRabbitMq((ctx, cfg) => { cfg.Host("rabbitmq://localhost"); cfg.ConfigureEndpoints(ctx); });
});<T> -- Zero-Allocation Parsingpublic static ReadOnlySpan<char> ExtractDomain(ReadOnlySpan<char> email)
{
int at = email.IndexOf('@');
return at >= 0 ? email[(at + 1)..] : ReadOnlySpan<char>.Empty;
}
// Stack-allocated buffer: Span<byte> buf = stackalloc byte[256];public ValueTask<Product?> GetProductAsync(string id, CancellationToken ct)
{
if (_cache.TryGetValue(id, out var cached)) return ValueTask.FromResult<Product?>(cached);
return new ValueTask<Product?>(LoadFromDbAsync(id, ct));
}// JSON -- avoids runtime reflection
[JsonSerializable(typeof(Order))]
[JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
public partial class AppJsonContext : JsonSerializerContext;
// Logging -- avoids boxing
public static partial class Log
{
[LoggerMessage(Level = LogLevel.Information, Message = "Order {OrderId} created")]
public static partial void OrderCreated(ILogger logger, string orderId);
}[MemoryDiagnoser, SimpleJob(RuntimeMoniker.Net90)]
public class ParsingBenchmarks
{
private readonly string _email = "user@example.com";
[Benchmark(Baseline = true)] public string Sub() => _email[(_email.IndexOf('@') + 1)..];
[Benchmark] public ReadOnlySpan<char> Span() => ExtractDomain(_email.AsSpan());
}
// dotnet run -c Release --project Benchmarksdotnet new sln -n MyApp && dotnet new webapi -n MyApp.Api -o src/MyApp.Api
dotnet build -c Release
dotnet test -c Release --collect:"XPlat Code Coverage"
dotnet publish src/MyApp.Api -c Release -o ./publish
dotnet ef migrations add Init --project src/MyApp.Infrastructure --startup-project src/MyApp.Api[*.cs]
dotnet_sort_system_directives_first = true
csharp_style_namespace_declarations = file_scoped:error
csharp_prefer_primary_constructors = true:suggestion
dotnet_diagnostic.CA1848.severity = warningsteps:
- uses: actions/checkout@v6
- uses: actions/setup-dotnet@v4
with: { dotnet-version: '9.0.x' }
- run: dotnet restore
- run: dotnet build --no-restore -c Release -warnaserror
- run: dotnet test --no-build -c Release --collect:"XPlat Code Coverage"
- run: dotnet publish src/MyApp.Api -c Release -o publish --no-buildFROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish src/MyApp.Api -c Release -o /app
FROM mcr.microsoft.com/dotnet/aspnet:9.0
COPY --from=build /app /app
WORKDIR /app
ENTRYPOINT ["dotnet", "MyApp.Api.dll"]async void outside event handlers -- always return Task.Result / .Wait() -- deadlock riskCancellationToken propagation through the call chainException without re-throw or structured loggingIServiceProvider.GetService in business logicIQueryable from repositories -- leaks persistence detailsStringBuilder or string handlers© softspark, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in app/skills/csharp-patterns of softspark/ai-toolkit.
Open the folder on GitHubat commit d64db2b
Csharp Patterns 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 |
|---|---|---|---|---|---|---|
| Csharp Patterns this skillsoftspark/ai-toolkit | 179 | — | ~3.6k | Automated safety check: Pass | Apache-2.0 | |
| Dotnet Csharpnovotnyllc/dotnet-artisan | 233 | — | ~1.7k | Automated safety check: Pass | MIT | |
| Tsp Csharpquerylenshq/ef-querylens | 225 | — | ~1.3k | Automated safety check: Pass | MIT | |
| C# and .NET DeveloperJeffallan/claude-skills | 12k | — | ~1.3k | Automated safety check: Pass | MIT | |
| Migrate Dotnet8 To Dotnet9dotnet/skills | 5.6k | 2 repos | ~3.9k | Automated safety check: Pass | MIT | |
| Akka.NET Best PracticesAaronontheweb/dotnet-skills | 1.2k | 1 repos | ~3.3k | Automated safety check: Pass | MIT |
novotnyllc/dotnet-artisan
Baseline C skill loaded for every .NET code path. An agent skill from novotnyllc/dotnet-artisan.
querylenshq/ef-querylens
Comprehensive C and .NET development skill for TSP projects.
Jeffallan/claude-skills
Guides C# work on .NET 8+: ASP.NET Core APIs, Entity Framework Core data access, Blazor apps and CQRS with MediatR, following a five-step build workflow.
dotnet/skills
Migrate a .NET 8 project to .NET 9 and resolve all breaking changes.
Aaronontheweb/dotnet-skills
Guidance for Akka.NET actor systems covering EventStream versus DistributedPubSub, supervision, Props versus DependencyResolver, work distribution and testable cluster code.
Aaronontheweb/dotnet-skills
Choosing the right concurrency abstraction in .NET - from async/await for I/O to Channels for producer/consumer to Akka.NET for stateful entity management.
softspark/ai-toolkit
Prepare or verify a project QA environment with source identity, readiness, browser access, evidence paths and owned cleanup.
softspark/ai-toolkit
Accessibility validator: WCAG 2.1 AA, EN 301 549, EAA. An agent skill from softspark/ai-toolkit.
softspark/ai-toolkit
Analyzes code quality, complexity, patterns across codebase.
softspark/ai-toolkit
Drives a brief, specification, issue or existing PR through implementation, review, tests and QA to a ready PR.
softspark/ai-toolkit
Direct technical voice for docs, README, user-facing text. An agent skill from softspark/ai-toolkit.
softspark/ai-toolkit
Detect/generate/debug CI pipeline config (GitHub Actions, GitLab CI).
Works with
Categories
C/.NET: LINQ, async/await, DI, records, nullable refs, ASP.NET Core, EF Core, MediatR. Csharp Patterns is an agent skill from softspark/ai-toolkit.NET Core, EF Core, MediatR.
Csharp Patterns fits situations like: tasks that involve Async programming.
Run `npx skills add softspark/ai-toolkit --skill csharp-patterns -a claude-code`. Or copy the skill folder (app/skills/csharp-patterns in softspark/ai-toolkit) into .claude/skills/csharp-patterns in your project. Claude Code loads it when a task matches its description.
Run `npx skills add softspark/ai-toolkit --skill csharp-patterns -a codex`. Or copy the skill folder (app/skills/csharp-patterns in softspark/ai-toolkit) into .agents/skills/csharp-patterns 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 softspark/ai-toolkit --skill csharp-patterns -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/csharp-patterns, .gemini/skills/csharp-patterns, .github/skills/csharp-patterns and .opencode/skills/csharp-patterns in your project.
Going by SKILL.md and its folder, Csharp Patterns needs the command-line tools its instructions call (dotnet). Its frontmatter pre-approves these tools: Read.
SKILL.md names 1 domain. In commands or code: api.payments.com; the agent is likely to contact it when it follows the instructions. 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.
Csharp Patterns is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3.6k tokens (SKILL.md is roughly 14k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Csharp Patterns: Dotnet Csharp (novotnyllc/dotnet-artisan, 233 stars), Tsp Csharp (querylenshq/ef-querylens, 225 stars), C# and .NET Developer (Jeffallan/claude-skills, 12k stars) and Migrate Dotnet8 To Dotnet9 (dotnet/skills, 5.6k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
softspark (a GitHub user) maintains it in softspark/ai-toolkit, which has 179 GitHub stars. The repository holds 112 skills in this directory. The repository was last updated on October 7, 2026.
Source: softspark/ai-toolkit on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.