Claude Code Plugins

Community-maintained marketplace

Feedback

Validate C# code through Roslyn compiler before writing to disk. Attempts to fix compilation errors automatically. Use when writing new code to ensure it compiles before committing to disk.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name code-writer
description Validate C# code through Roslyn compiler before writing to disk. Attempts to fix compilation errors automatically. Use when writing new code to ensure it compiles before committing to disk.

Code Writer Skill

This skill validates C# code through the Roslyn compiler BEFORE writing to disk, attempts automatic fixes, and only writes when code compiles successfully.

When to Use This Skill

  • When generating new C# files
  • When you want code validated before writing
  • "Write this code but validate it first"
  • "Create a new service class (validated)"
  • Before writing potentially breaking changes
  • When you want compilation feedback before disk commit

Why This Exists

Traditional approach:

Generate code → Write to disk → Build → Find errors → Fix → Repeat

Code-writer approach:

Generate code → Validate with Roslyn (in-memory) → Auto-fix → Write to disk ✓

Benefits:

  • ✅ No broken code on disk
  • ✅ Real compiler diagnostics (not guesses)
  • ✅ Auto-fix common errors before writing
  • ✅ Faster feedback loop
  • ✅ Safe exploratory coding

CRITICAL: Pre-Write Safety Checks

ALWAYS run these checks BEFORE generating code:

  1. type-collision-detector - Check if type name already exists

    • If collision found → Ask user for different name
    • If name available → Proceed
  2. namespace-explorer - Check target namespace patterns

    • Understand naming conventions
    • Match existing patterns
  3. type-finder (if implementing interface) - Find interface definition

    • Get exact interface location
    • Use member-identifier to see required members
  4. code-reader - When reading files for context

    • ALWAYS use code-reader instead of Read for .cs files
    • Strips XML docs automatically (30-50% context savings)
    • Preserves important comments (TODO, HACK, etc.)

These checks are MANDATORY. Do not skip them.

CRITICAL: Reading C# Files

ALWAYS use code-reader tool instead of Read for C# files.

Exception: Only if user explicitly asks for documentation.

API Endpoint

POST /generation/code

Request:

{
  "template": "class",
  "name": "ProductService",
  "namespace": "MyApp.Services",
  "members": [
    {
      "kind": "method",
      "name": "GetById",
      "returnType": "IGenericResult<Product>",
      "parameters": [{"type": "int", "name": "id"}]
    }
  ]
}

Response:

{
  "isSuccess": true,
  "data": {
    "generatedCode": "...",
    "diagnostics": [],
    "filePath": "src/Services/ProductService.cs"
  }
}

How It Works

1. Start the Server

dotnet run --project D:\FractalDataworks\RoslynTools\src\CyberdineDevelopment.RoslynTools.Server

2. Load Solution

using CyberdineDevelopment.RoslynTools.Client;

var client = new RoslynWorkspaceClient("http://localhost:5000");
await client.LoadSolution(@"D:\MyProject\MyProject.sln");

3. Generate and Validate Code

// Generate code in-memory
var result = await client.GenerateCode(
    template: "class",
    name: "ProductService",
    namespaceName: "MyApp.Services"
);

if (result.IsSuccess)
{
    // Code validated successfully
    Console.WriteLine("Code generated and validated:");
    Console.WriteLine(result.Data.GeneratedCode);

    // Check diagnostics
    if (!result.Data.Diagnostics.Any())
    {
        Console.WriteLine("No errors!");
    }
}

4. Edit and Commit

// Add generated code to workspace
await client.EditDocument(
    projectName: "MyApp.Services",
    filePath: "src/Services/ProductService.cs",
    content: result.Data.GeneratedCode
);

// Validate in workspace
var diagnostics = await client.GetDiagnostics();

// If no errors, commit to disk
if (!diagnostics.Data.Any(d => d.Severity == "Error"))
{
    await client.Commit();
}

Process Flow

┌─────────────────────────────────────────────────────────┐
│ 0. PRE-WRITE CHECKS (MANDATORY)                         │
│    - type-collision-detector                            │
│    - namespace-explorer                                 │
│    - type-finder (if needed)                            │
└────────────────┬────────────────────────────────────────┘
                 │
                 ▼
┌─────────────────────────────────────────────────────────┐
│ 1. GENERATE CODE VIA SERVER API                         │
│    POST /generation/code                                │
└────────────────┬────────────────────────────────────────┘
                 │
                 ▼
┌─────────────────────────────────────────────────────────┐
│ 2. SERVER VALIDATES WITH WORKSPACE                      │
│    - Add to in-memory workspace                         │
│    - Get compilation diagnostics                        │
│    - Try auto-fixes if needed                           │
└────────────────┬────────────────────────────────────────┘
                 │
                 ▼
┌─────────────────────────────────────────────────────────┐
│ 3. CHECK DIAGNOSTICS                                    │
│    Errors? → Try to fix (up to 3 attempts)              │
│    Still errors? → Return diagnostics                   │
│    No errors? → Return generated code                   │
└────────────────┬────────────────────────────────────────┘
                 │
                 ▼
┌─────────────────────────────────────────────────────────┐
│ 4. COMMIT TO DISK (transaction-safe)                    │
│    ✅ Code compiles → client.Commit()                   │
│    ❌ Code doesn't compile → Show diagnostics           │
└─────────────────────────────────────────────────────────┘

Semantic Analysis Benefits

Using the Server API provides significant advantages:

  • Workspace Validation: Generated code validated against entire solution context
  • Full Type Resolution: Uses semantic model to ensure all types are resolved
  • Cross-Project References: Automatically detect and use types from other projects
  • Transaction Safety: Changes only committed if everything validates
  • Auto-Fix Intelligence: Better fixes using semantic understanding
  • No File Locking: Work in-memory until ready to commit

What Gets Validated

Compilation Errors (CS errors)

  • CS0246: Type or namespace not found
  • CS0103: Name does not exist
  • CS0246: Missing using statements
  • CS0535: Missing interface implementation
  • CS0161: Not all code paths return value
  • CS8600-CS8629: Nullable reference warnings
  • All other C# compiler errors

Code Quality Checks

  • Syntax correctness
  • Type resolution
  • Member accessibility
  • Return type matching
  • Parameter types
  • Generic constraints

What's NOT Validated

  • Runtime behavior
  • Logic correctness
  • Performance
  • Business rules
  • Integration with external systems

Auto-Fix Capabilities

The skill attempts these fixes automatically:

Fix 1: Add Missing Using Statements

// Error: CS0246 - Type 'List' not found
// Fix: Add using System.Collections.Generic;

Fix 2: Add Missing References

// Error: CS0012 - Assembly reference missing
// Fix: Add reference to required assembly

Fix 3: Fix Nullable Warnings

// Error: CS8600 - Possible null reference
// Fix: Add null check or null-forgiving operator

Fix 4: Add Missing Return Statements

// Error: CS0161 - Not all paths return value
// Fix: Add return statement or throw

Fix 5: Fix Access Modifiers

// Error: CS0122 - Inaccessible due to protection level
// Fix: Change to public if appropriate

Fix 6: Implement Missing Members

// Error: CS0535 - Missing interface implementation
// Fix: Add method stub with NotImplementedException

Output Format

Success Case

=== CODE WRITER REPORT ===

File: src/Services/ProductService.cs

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
VALIDATION (Attempt 1)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Submitting to Roslyn compiler...

Diagnostics found: 3 errors

1. CS0246: Type 'IRepository' not found
   Line 15: private readonly IRepository<Product> _repository;

2. CS0103: Name 'Result' does not exist
   Line 22: return Result.Ok(products);

3. CS8618: Non-nullable field must contain non-null value
   Line 15: private readonly IRepository<Product> _repository;


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
AUTO-FIX (Attempt 1)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Fixing CS0246: Adding using MyApp.Abstractions;
Fixing CS0103: Adding using MyApp.Core;
Fixing CS8618: Adding constructor parameter


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
VALIDATION (Attempt 2)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Submitting to Roslyn compiler...

✅ No errors found!
✅ Code compiles successfully


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
WRITING TO DISK
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✅ File written: src/Services/ProductService.cs

Final code:
────────────────────────────────────────────────────────
using MyApp.Abstractions;
using MyApp.Core;

namespace MyApp.Services;

public class ProductService
{
    private readonly IRepository<Product> _repository;

    public ProductService(IRepository<Product> repository)
    {
        _repository = repository;
    }

    public IGenericResult<List<Product>> GetAll()
    {
        var products = _repository.GetAll();
        return Result.Ok(products);
    }
}
────────────────────────────────────────────────────────


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
SUMMARY
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✅ Code validated and written successfully

Initial errors: 3
Fixed automatically: 3
Validation attempts: 2
Status: SUCCESS

Fixes applied:
  ✓ Added 2 using statements
  ✓ Added constructor parameter

Failure Case (after 3 attempts)

=== CODE WRITER REPORT ===

File: src/Services/OrderService.cs

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
VALIDATION (Attempt 3)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Submitting to Roslyn compiler...

❌ Errors remain after 3 fix attempts


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
DIAGNOSTICS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

1. CS0029: Cannot implicitly convert type 'int' to 'string'
   Line 45: return totalAmount;
   Severity: Error

   Context:
   public string CalculateTotal()
   {
       decimal totalAmount = CalculateAmount();
       return totalAmount;  // ← Error here
   }

   SUGGESTION: Change return type to 'decimal' or convert value


2. CS1061: 'Order' does not contain definition for 'GetTotal'
   Line 52: var total = order.GetTotal();
   Severity: Error

   Context:
   public void ProcessOrder(Order order)
   {
       var total = order.GetTotal();  // ← Error here
   }

   SUGGESTION:
   - Add GetTotal() method to Order class
   - Or use order.Total property
   - Check if method was renamed


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
FILE NOT WRITTEN
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

❌ Code contains errors that require manual intervention

Code was NOT written to disk.

Please fix the errors above and try again, or provide guidance
on how to resolve them.

Would you like me to:
1. Try a different approach
2. Generate alternative implementation
3. Write the file anyway (not recommended)

Roslyn Workspace Integration

How Workspace Validation Works

// 1. Get project from workspace
var project = workspace.CurrentSolution
    .Projects.First(p => p.Name == targetProject);

// 2. Create new document or update existing
var document = project.AddDocument(fileName, codeText);

// 3. Get updated project with new document
var updatedProject = document.Project;

// 4. Get compilation with all references already configured
var compilation = await updatedProject.GetCompilationAsync();

// 5. Get diagnostics (includes cross-project references)
var diagnostics = compilation.GetDiagnostics()
    .Where(d => d.Severity == DiagnosticSeverity.Error)
    .ToList();

// 6. If errors, attempt semantic-aware fixes
if (diagnostics.Any())
{
    foreach (var diagnostic in diagnostics)
    {
        // Use semantic model to understand error context
        var semanticModel = await document.GetSemanticModelAsync();
        // Apply intelligent fixes based on semantic understanding
    }
}

Reference Resolution

The workspace automatically includes:

  • All project references from the loaded solution
  • NuGet packages configured in each project
  • .NET runtime assemblies
  • Project-to-project dependencies
  • Analyzer references

This ensures validation is accurate to your actual solution context, not a standalone compilation.

Fix Attempt Strategy

Attempt 1: Add Missing Using Statements

Parse error → Identify missing type → Search codebase → Add using

Attempt 2: Fix Common Patterns

Nullable warnings → Add null checks or constructors
Missing returns → Add return statements
Access modifiers → Adjust if safe

Attempt 3: Structural Changes

Missing implementations → Add stubs
Generic constraints → Add constraints
Interface mismatches → Implement missing members

After 3 Attempts: Report Back

If still errors → Return detailed diagnostics with context and suggestions

Integration with Other Skills

Workflow 1: New Class Generation

1. code-writer → Generate + validate class
   ✅ Success → File written

2. complexity-analyzer → Check complexity

3. dotnet-test-automation → Generate tests

4. build → Full solution build

Workflow 2: Code Generation with Type Safety

1. type-collision-detector → Check name available

2. namespace-explorer → Check target namespace

3. code-writer → Generate + validate code
   ✅ Success → File written

4. build → Verify integration

Workflow 3: Failed Validation

1. code-writer → Generate + validate
   ❌ Errors found after 3 attempts

2. Review diagnostics

3. Provide guidance

4. code-writer → Try again with corrections

Example Usage

Example 1: Simple Class

User: "Write a ProductValidator class"

Skill:

  1. Generates class code
  2. Validates with Roslyn → Missing using FluentValidation
  3. Auto-fixes → Adds using statement
  4. Validates again → Success!
  5. Writes to disk

Example 2: Service with Dependencies

User: "Write an OrderService with repository injection"

Skill:

  1. Generates service code
  2. Validates → Missing IRepository reference
  3. Searches codebase → Finds IRepository in Abstractions
  4. Adds using MyApp.Abstractions
  5. Validates → Missing Result type
  6. Adds using MyApp.Core
  7. Validates → Success!
  8. Writes to disk

Example 3: Complex Logic (Manual Intervention)

User: "Write a PaymentProcessor with validation"

Skill:

  1. Generates processor code
  2. Validates → Type conversion error (decimal to string)
  3. Attempts fix → Can't safely determine intent
  4. Returns diagnostics with suggestion
  5. You provide guidance: "Return type should be decimal"
  6. Regenerates with correct type
  7. Validates → Success!
  8. Writes to disk

Configuration Options

Strictness Levels

Strict Mode (default):

- Must compile with zero errors
- Warnings allowed (but reported)
- All types must resolve

Lenient Mode:

- Allow warnings
- Allow some nullable warnings
- Proceed if only warnings exist

Experimental Mode:

- Write even with minor errors
- Report all diagnostics
- Trust manual review

Max Fix Attempts

max_attempts: 3  # Default
# Can be set to 1, 2, 3, 4, or 5

Auto-Fix Categories

auto_fix:
  using_statements: true
  nullable_warnings: true
  missing_returns: true
  interface_stubs: true
  access_modifiers: false  # Require manual decision

Safety Features

Before writing:

  • ✅ Compiles without errors
  • ✅ All types resolve
  • ✅ References are valid

Never writes if:

  • ❌ Compilation errors exist
  • ❌ Fix attempts exhausted
  • ❌ User wants manual review

Always provides:

  • ✅ Full diagnostic information
  • ✅ Context around errors
  • ✅ Actionable suggestions
  • ✅ Option to retry with changes

Performance

Fast validation:

  • In-memory compilation (no disk I/O)
  • Incremental fixes
  • Parallel reference loading
  • Cached assemblies

Typical times:

  • Simple class: <1 second
  • Complex service: 1-2 seconds
  • With auto-fixes: 2-4 seconds

Limitations

Cannot validate:

  • Runtime behavior
  • External API calls
  • Database queries
  • File system operations
  • Network requests

Cannot auto-fix:

  • Logic errors
  • Algorithm mistakes
  • Design flaws
  • Complex type mismatches
  • Business rule violations

These need manual intervention

Advanced Features

Preview Mode

Show what would be written without writing

Diff View

Show original vs fixed code side-by-side

Incremental Validation

Validate as you type (for interactive use)

Batch Validation

Validate multiple files at once

Notes

  • Uses Roslyn Workspace API with full semantic model
  • Validates against actual solution context (all projects loaded)
  • Respects project's target framework and settings
  • Honors nullable reference settings
  • Faster than full build (in-memory compilation)
  • No side effects until commit (transaction-safe)
  • Can be used for "dry run" code generation
  • Cross-project type resolution
  • Server maintains workspace state