Skip to content

Guardrails for AI-Generated Code

How CodeCharter hooks into the build-fix loop of Cursor, Claude Code, Copilot, and Aider and enforces your conventions on AI-generated code.

AI assistants generate code that looks plausible but doesn't reliably know your conventions. They have no memory of your architecture decisions beyond the current session, ignore long convention documents as soon as the context window gets tight, and don't know your architecture boundaries — which means they will happily let the domain layer reference the web layer. CodeCharter catches exactly those violations the moment they appear.

CodeCharter hooks into the AI workflow at three points and keeps the AI within your rules: as a CLI command in the build-fix loop, as executable .ccr rule files living in your repo, and as an MCP server registered directly in your coding tool.

The Build-Fix Loop

Agentic AI tools today have a built-in cycle of code generation, test run, and self-correction. CodeCharter becomes the convention enforcer within that cycle:

AI generates code
  -> codecharter analyze <YourSolution.sln> --fail-on error
    -> Finding: "Controller calls EF directly. Use repository pattern."
      -> AI reads @recommendation
        -> AI fixes it itself
          -> green build

The @recommendation header in every rule becomes the fix prompt for the AI. Your devs write "Inject TimeProvider via constructor" once, and from that point on the AI fixes it itself, every time, for as long as you use it.

Your DSL Rules as an Executable Team Specification

What used to live in the README or in tribal knowledge becomes an executable file in the repo. When the AI composes the next change, it sees not only the existing code but also the .ccr files that express the rules. That is significantly more reliable than a long convention document that runs out of context window.

Example: your team convention "We use IClock instead of TimeProvider because we're not on .NET 8 yet" is something the AI would otherwise have to infer from existing code. With CodeCharter you write a rule:

@name "Use IClock instead of TimeProvider"
@severity error
@category "Team-Conventions"
@recommendation "Inject IClock via constructor and call _clock.UtcNow instead of TimeProvider.System.GetUtcNow()"

from m in Methods
where m.CalledMethods.Any(c => c.FullName.Contains("TimeProvider"))
select m

On the next attempt the AI gets a clear instruction from the recommendation and can produce the fix in one step.

Writing Recommendation Text for AI Loops

A @recommendation is not just a hint for your devs — it's also the fix prompt for the AI. Three rules of thumb for good recommendations.

Specific, not vague

@recommendation "Fix this"

That helps neither humans nor AI. Better:

@recommendation "Add 'CancellationToken cancellationToken = default' as the last parameter"

Code snippets are welcome

@recommendation "Inject TimeProvider via constructor and call _time.GetUtcNow() instead of DateTime.UtcNow"

The AI uses the recommendation as a literal instruction for the fix and generates exactly what you described.

References to established patterns

@recommendation "Move EF access into a repository class under Acme.Infrastructure.Repositories and inject it via the constructor"

Concrete namespace guidance helps the AI place the code in the right location.

Setup for Common Tools

codecharter mcp install registers the CodeCharter MCP server for Claude Code, Claude Desktop, Cursor, Windsurf, and Gemini CLI (.gemini/settings.json). The default scope is project; Claude Desktop and Windsurf only have user-level configuration, so for those two you must pass --scope user. Note that the MCP server requires a valid license: without one, codecharter mcp exits with a license error before starting. For GitHub Copilot and Aider, the MCP server must be configured manually — see the tool's own documentation for MCP server registration, then point it at codecharter mcp.

Cursor

Current Cursor (1.0+) uses rule files under .cursor/rules/. Create a file such as .cursor/rules/codecharter.md:

After every change, run: codecharter analyze <YourSolution.sln> --fail-on error
Fix any findings before considering the change complete. Read the
@recommendation field of each finding for guidance.

Replace <YourSolution.sln> with the path to your solution file, e.g. src/Acme.sln.

Claude Code

In CLAUDE.md:

## Lint-Loop
After making changes, always run `codecharter analyze <YourSolution.sln> --fail-on error`
and fix any errors before reporting completion. The @recommendation field
of each finding tells you how to fix it.

Windsurf

codecharter mcp install --client windsurf --scope user registers the MCP server (Windsurf only supports user scope). Registration makes the MCP tools (scaffold_rule, save_rule, analyze_diff) available to Windsurf. To get the build-fix loop, additionally instruct Windsurf — for example via a rule file or prompt — to run analyze_diff after each change and fix the findings.

GitHub Copilot with Agent Mode

GitHub Copilot does not support codecharter mcp install and requires manual MCP server configuration. Once registered, add to the agent system prompt:

Run `codecharter analyze <YourSolution.sln> --fail-on error` after each
change. Findings under 'error' severity block completion. Read the
@recommendation field for fix guidance.

Aider

Aider is not supported by codecharter mcp install. Integrate CodeCharter via Aider's --lint-cmd flag instead:

aider --lint-cmd "codecharter analyze <YourSolution.sln> --fail-on error"

Aider feeds the lint output back to the AI for the next iteration.

Performance in AI Loops

A CodeCharter analysis takes a few seconds to a minute depending on solution size. In an AI loop where the AI already runs the build after every code change, that overhead is negligible.

For even faster loops, analyze only the changed lines: codecharter analyze <YourSolution.sln> --git-ref main..HEAD --fail-on error restricts findings to lines touched since main (alternatively, --diff accepts a unified diff file). Via MCP, the analyze_diff, analyze_file, and analyze_solution tools serve the same purpose inside the coding tool; after the first call they answer from a warm workspace cache, which makes repeated checks in a loop significantly faster.

Further Reading