csharp-api-controller-…
Defines the coding standards, patterns, and conventions for ASP.NET Core REST API controllers. Rules cover routing, HTTP verbs,…
Defines the C# coding standards, patterns, and conventions to be applied consistently across all C# projects. Rules cover naming, structure, async patterns, null handling, dependency injection, logging, result patterns, and formatting. Apply these rules uniformly in all
Claude Code
$ npx -y skills add linuxchata/ai-playbook --skill csharp-coding-standards --agent claude-code
Codex
$ npx skills add linuxchata/ai-playbook --skill csharp-coding-standards -a codex -y
Cursor
$ npx skills add linuxchata/ai-playbook --skill csharp-coding-standards -a cursor -y
Gemini CLI
$ npx skills add linuxchata/ai-playbook --skill csharp-coding-standards -a gemini-cli -y
GitHub Copilot
$ npx skills add linuxchata/ai-playbook --skill csharp-coding-standards -a github-copilot -y
OpenCode
$ npx skills add linuxchata/ai-playbook --skill csharp-coding-standards -a opencode -y
Windsurf
$ npx skills add linuxchata/ai-playbook --skill csharp-coding-standards -a windsurf -y
name: csharp-coding-standards description: Defines the C# coding standards, patterns, and conventions to be applied consistently across all C# projects. Rules cover naming, structure, async patterns, null handling, dependency injection, logging, result patterns, and formatting. Apply these rules uniformly in all production code. metadata: version: 1.1.0
Defines the C# coding standards, patterns, and conventions to be applied consistently across all C# projects. Rules cover naming, structure, async patterns, null handling, dependency injection, logging, result patterns, and formatting. Apply these rules uniformly in all production code.
---
Always use **file-scoped namespaces**:
// ✅ Correct
namespace MyApp.Core.Validators;
internal class OrderValidator { }
// ❌ Wrong
namespace MyApp.Core.Validators
{
internal class OrderValidator { }
}using System.Text; using System.Text.Json; using Microsoft.Extensions.Logging; using MyApp.Core.Abstractions; using MyApp.Domain;
Each file contains exactly one top-level type. The file name must match the type name exactly.
---
| Kind | Convention | Example | |---|---|---| | Classes | PascalCase | `OrderValidator`, `UserService` | | Interfaces | `I` prefix + PascalCase | `IOrderRepository`, `IUserService` | | Enums | PascalCase | `OrderStatus`, `PaymentMethod` | | Structs | PascalCase | `Money`, `DateRange` | | Records | PascalCase | `AppConfiguration`, `UserSettings` |
| Kind | Convention | Example | |---|---|---| | Public properties | PascalCase | `CreatedAt`, `TotalAmount` | | Public methods | PascalCase | `CreateOrder`, `ValidatePayment` | | Private fields | `_camelCase` (underscore prefix) | `_repository`, `_logger` | | Constants | PascalCase | `DefaultTimeout`, `MaxRetryCount` | | Local variables | camelCase | `orderId`, `serializedData` | | Method parameters | camelCase | `cancellationToken`, `userId` | | Lambda parameters | Short camelCase | `x =>`, `e =>`, `o =>` |
> **All async methods MUST end with the `Async` suffix without exception.**
// ✅ Correct public async Task<Order?> GetByIdAsync(Guid id, CancellationToken cancellationToken); // ❌ Wrong – missing Async suffix public async Task<Order?> GetById(Guid id, CancellationToken cancellationToken);
This applies to:
---
// ✅ Correct: public sealed for types exposed via public interface
public sealed class OrderService : IOrderService { }
// ✅ Correct: internal sealed for infrastructure implementations
internal sealed class SqlOrderRepository : IOrderRepository { }Mark classes `sealed` by default unless inheritance is explicitly required. This prevents unintended derivation and enables JIT optimizations.
---
// ✅ Early return guard
if (id is null || id.Length == 0)
{
return null;
}Use modern `ArgumentNullException` helpers for public/internal method boundaries:
// ✅ Correct ArgumentNullException.ThrowIfNull(order); ArgumentNullException.ThrowIfNullOrEmpty(order.UserName);
Prefer `?.` and `??` / `??=` over verbose null checks in expressions:
// ✅ Correct return items?.Select(x => x.ToDto()).ToArray(); var name = input?.Trim() ?? string.Empty;
---
Always inject dependencies via the constructor. Store them as `private readonly` fields prefixed with `_`.
private readonly IOrderRepository _orderRepository;
private readonly ILogger<OrderService> _logger;
public OrderService(IOrderRepository orderRepository, ILogger<OrderService> logger)
{
_orderRepository = orderRepository;
_logger = logger;
}Access configuration via `IOptions<T>`. Extract `.Value` in the constructor and store as a field – do not access `.Value` repeatedly at call sites.
private readonly AppConfiguration _configuration;
public OrderService(IOptions<AppConfiguration> options)
{
_configuration = options.Value;
}Centralize all service registrations in a dedicated `DependencyInjection.cs` static class with `IServiceCollection` extension methods.
public static class DependencyInjection
{
public static void AddMyFeature(this IServiceCollection services, IConfiguration configuration)
{
services.AddTransient<IOrderService, OrderService>();
services.AddKeyedTransient<IPaymentStrategy, CreditCardStrategy>("creditcard");
}
}Lifetime guidance:
Rules, skills, and guidelines for AI coding assistants – Claude, Cursor, and beyond.
Defines the coding standards, patterns, and conventions for ASP.NET Core REST API controllers. Rules cover routing, HTTP verbs,…
Defines the testing standards, patterns, and conventions for all C# unit and integration test projects. Rules cover test…
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.