v0.22.0—Bounded nullability checks and practical .NET migration guidance.See what's new

Adding Calor to Existing Projects

This guide takes an existing C# project from Calor setup to a small mixed Calor/C# pilot. You will convert one well-tested file, review what could not be translated, build it with the rest of the project, and inspect its impact.


Overview

Adding Calor to an existing project is a gradual process:

  1. Enable Calor - Add MSBuild integration
  2. Analyze the codebase - Find useful pilot candidates
  3. Add a Calor file - Confirm the mixed project builds
  4. Build and verify - Exercise the normal project workflow
  5. Convert one C# file - Validate and review the result
  6. Inspect project impact - Query a converted method and its callers

You don't need to convert everything at once. Calor and C# coexist seamlessly.


Step 1: Enable Calor in Your Project

Enable Calor with MSBuild integration:

Bash
# Initialize Calor in your project
calor init

# Or specify a specific project file
calor init --project MyApp.csproj

Your .csproj is updated with MSBuild targets that compile .calr files automatically during dotnet build.


Step 2: Analyze Your Codebase

Use calor assess to find C# files that would benefit most from Calor:

Bash
# Analyze your source directory
calor assess ./src

# Show top 10 candidates with detailed scores
calor assess ./src --top 10 --verbose

Understanding the Output

Plain Text
=== Calor Migration Analysis ===

Analyzed: 42 files
Average Score: 34.2/100

Top 10 Files for Migration:
--------------------------------------------------------------------------------
 82/100 [Critical]  src/Services/PaymentProcessor.cs
 78/100 [Critical]  src/Services/OrderService.cs
 65/100 [High]      src/Repositories/UserRepository.cs
PriorityScoreRecommendation
Critical76-100Convert to Calor - high benefit
High51-75Good conversion candidate
Medium26-50Optional - some benefit
Low0-25Keep in C# - minimal benefit

Step 3: Add Your First Calor File

Create a new .calr file alongside your existing code:

Calor
§M{m001:Calculator}

  §F{f001:Add:pub}
    §I{i32:a}
    §I{i32:b}
    §O{i32}
    §R (+ a b)


Step 4: Build and Verify

Bash
# Build your project - Calor compiles automatically
dotnet build

The build process:

  1. Finds all .calr files in your project
  2. Compiles each to .g.cs in the obj/calor/ directory
  3. Includes generated C# in the normal compilation

Step 5: Convert High-Scoring C# Files

Based on your analysis results, convert files that score High or Critical:

Bash
# Convert, parse-check, and return the structured loss report
calor convert src/Services/PaymentProcessor.cs --validate --format json

# With benchmark comparison
calor convert src/Services/PaymentProcessor.cs --validate --benchmark

For bulk conversion:

Bash
calor migrate ./src --dry-run  # Preview first
calor migrate ./src            # Execute

Review the Conversion Result

Conversion is not an all-or-nothing claim. The command above returns JSON; without --format json, inspect the equivalent text loss report. Review:

  • losses[] in JSON output or the text loss report,
  • every §CSHARP block that preserves source the converter could not express natively,
  • validation diagnostics,
  • the generated C# and existing tests.

When a member cannot be converted safely, calor convert can preserve the original C# inside §CSHARP rather than discarding the whole file. That is a useful migration boundary, not completed conversion. --passthrough widens the set of members eligible for preservation; --no-fallback asks the command to fail instead.

The converter is continuously exercised against MediatR, Serilog, and FluentValidation. All 364 converted modules currently parse, but parse success does not mean every member is native Calor or that every call binds. The loss report and interop blocks remain the source of truth for each file.

Use a Migration Waiver Deliberately

Converted code often calls APIs the compiler cannot resolve yet. Prefer the project-file permissive setting over switching effect checking off:

xml
<PropertyGroup>
  <CalorPermissiveEffects>true</CalorPermissiveEffects>
</PropertyGroup>

This suppresses the two “cannot tell” diagnostics (Calor0411 and Calor0425) and demotes Calor0410 to a warning. It never waives a known callback mismatch (Calor0424) or an override/interface violation (Calor0420, Calor0421). Because unknown calls are assumed harmless, this waives the full effect guarantee. Record the setting in the pull request, and pass --permissive-effects to calor review-packet so the waiver prints on the packet's first line.


Step 6: Build and Inspect Project Impact

After the converted file builds, create or refresh the project index:

Bash
dotnet build
calor index build .
calor query effects ProcessPayment --in-file src/Services/PaymentProcessor.calr
calor query callers ProcessPayment --in-file src/Services/PaymentProcessor.calr
calor query impact ProcessPayment --in-file src/Services/PaymentProcessor.calr

Replace ProcessPayment with a converted method. Effect queries apply to functions, methods, constructors, and accessors, not to the containing class. Read any PARTIAL residual before relying on a caller count. For an agent-driven workflow, use the equivalent calor_query MCP tool and compile with options.crossModule: true so effects are checked across files.

See Project Intelligence for Agents for the complete pre-edit and post-edit loop.


Optional: Enable Claude Code Integration

For AI-assisted Calor development:

Bash
calor init --ai claude

This adds:

  • /calor and /calor-convert skills
  • CLAUDE.md with guidelines instructing Claude to write new code in Calor and analyze C# files before modifying them

Using Claude Code

Write new Calor code:

Plain Text
/calor

Write a function that validates email addresses with:
- Precondition: input is not null or empty
- Postcondition: returns true only for valid emails

Convert existing C# to Calor:

Plain Text
/calor-convert src/Services/PaymentProcessor.cs

Best Practices

What to Convert First

  1. Small, well-tested files with a clear owner and rollback path
  2. Contract-dense code where preconditions and postconditions add value
  3. Pure or first-order effect-checked code with few dynamic boundaries
  4. High-scoring files from calor assess, after the first three checks

What to Keep in C#

  • Simple DTOs and record types
  • Auto-generated code (EF migrations, gRPC stubs)
  • Code using features Calor doesn't support yet
  • Reflection-heavy, dynamic, or delegate-heavy service layers for the first pilot

Next Steps