Claude Code vs OpenAI Codex for C# Projects: A Documentation-Based Comparison
Compare documented workflows and design fair, reproducible C# trials without inventing tool benchmarks or a universal winner.
This article does not name a winner. It defines an executable three-task C# protocol for comparing Claude Code and OpenAI Codex against the same Jovenzo.Samples fixtures, permissions, prompts, and review evidence.
No equivalent Claude Code and Codex coding trials were run for this revision. There are no measured speed, accuracy, cost, success-rate, token-use, preference, or model-quality results below. The purpose is to make a future comparison reproducible instead of filling an empty result table with impressions.
Define what is being compared
A coding product is more than its model. The client version, selected model, repository state, instruction discovery, tool access, approval policy, network access, prompt, and follow-up allowance can all change the outcome. A trial that gives one product unrestricted terminal access and the other a read-only workspace is primarily comparing configurations.
The Claude Code overview and Codex documentation describe repository-oriented coding workflows that can inspect files, edit code, and execute development commands under their respective controls. The observable unit in this protocol is therefore one attempted patch from a known defective fixture, together with its tests, command output, and human review. A polished chat answer is not a successful coding result by itself.
The three tasks use code already shipped in the shared archive: decimal contract tests for DiscountCalculator, an SSE blank-line framing repair in SseReader, and a parameterized tenant-scoped query in SafeProductTool. Cancellation is already implemented in these fixtures, so the protocol does not pretend that propagation is a missing feature or ask either product to create a new ASP.NET Core solution.
Compare project guidance through documented behavior
Instruction behavior was checked against the vendors' official documentation on November 2, 2026. Codex builds an instruction chain at the start of a run: it checks the Codex home first, then walks from the project root to the current working directory. Within each project directory, AGENTS.override.md takes precedence over AGENTS.md, and nearer files appear later in the merged guidance. The documented default combined project limit is 32 KiB. The AGENTS.md guide explains that mechanism with this solution's passive template.
Claude Code's current instruction documentation now includes direct AGENTS.md support in version 2.1.277 and later. Under the default Project instructions setting, a project CLAUDE.md, .claude/CLAUDE.md, or CLAUDE.local.md in or above the working directory causes Claude Code to use the CLAUDE files instead of project AGENTS.md. The setting can be changed to load both. Subdirectory instructions load when Claude works with files there, and Claude Code does not treat AGENTS.override.md as a supported AGENTS filename. Some sessions before 2.1.281 had additional limitations, so the exact client version and effective setting belong in the evidence record.
The protocol does not force both products to use the same filename. It gives them the same substantive guide through each product's documented mechanism: root AGENTS.md for Codex and root CLAUDE.md for Claude Code. The two bodies must have matching hashes after a neutral title replaces the passive-template line. Competing project instruction files are removed from the disposable fixture, and any personal or managed guidance is either eliminated with a dedicated evaluation profile or recorded as a reason the run is not equivalent.
A previous one-sided Codex instruction-discovery check showed why the loaded source must be audited; it is a methodology example, not comparative evidence.
| Product | Trial instruction file | Preflight record |
|---|---|---|
| Codex | Root AGENTS.md | Client version, cwd, project root, global/project sources, override/fallback configuration, and body hash |
| Claude Code | Root CLAUDE.md | Client version, cwd, Project instructions setting, managed/user/project sources, and body hash |
Normalize permissions without removing useful safeguards
The Claude Code permissions documentation and Codex's official permissions documentation use different concepts and labels. The trial records effective access rather than claiming two mode names are equivalent. Safety bypasses are not enabled to reduce prompts.
| Boundary | Required effective value for both products |
|---|---|
| Working directory | Fresh disposable Jovenzo.Samples solution root |
| Workspace access | Read fixture; write only allowed task files and ordinary build output |
| Outside repository | No data access beyond runtime/toolchain files required by .NET |
| Commands | Named Release build and C# test commands allowed |
| Git writes | None; status and diff may be read, but no commit, reset, branch, push, or remote operation |
| Network | Disabled during the scored attempt |
| Restore | Locked restore completed beforehand under the same policy; agent commands use --no-restore |
| External services | No AI provider, SQL Server, MCP, browser automation, publication, or deployment |
| Approval policy | Pre-approve only the listed local checks; deny and record anything outside the table |
Pre-restoring the locked packages avoids measuring a transient package download or giving one product broader network access. If the evaluator cannot enforce the same boundary on both clients, that attempt is marked non-equivalent rather than repaired with an undocumented exception. Permission prompts, denials, and operator approvals remain evidence because they affect the real workflow.
Prepare a reproducible C# fixture
The downloadable source archive contains the four-project Jovenzo.Samples solution and the complete protocol at evaluation/tasks.md. Start each attempt from the same full commit and archive SHA-256, then create one disposable worktree or extracted copy for one product, task, and attempt. Do not reuse a previous conversation, edits, build output, or memory.
The evaluator applies the named mutation before the assistant starts and captures the required failing regression. These mutations create controlled defects only in disposable copies: away-from-zero rounding becomes to-even, SSE frames dispatch per data line, or the safe SQL command becomes an interpolated query. The maintained shared source and published archive remain correct. A human-created mutation is fixture preparation, not an assistant failure.
# From the extracted Jovenzo.Samples directory, before a scored attempt.
dotnet restore Jovenzo.Samples.slnx --locked-mode
dotnet build Jovenzo.Samples.slnx -c Release --no-restore --disable-build-servers -m:1
# After the assistant patch, rebuild before using --no-build.
dotnet test tests/Jovenzo.Samples.Tests/Jovenzo.Samples.Tests.csproj `
-c Release --no-build --no-restore
The package is a source archive, not automatically a Git repository. If Git diff evidence is required, initialize or create the disposable evaluation repository before the trial and record its baseline full hash. Keep evaluator-only oracle files and initial-failure logs outside the assistant's readable and writable workspace.
Use the same three executable tasks
The article and evaluation/tasks.md use the same tasks, mutations, allowed files, prohibited changes, regressions, acceptance checks, and evidence. The tables below summarize the protocol; the downloadable file is the operational checklist.
Task 1: design tests for DiscountCalculator
| Field | Fixed definition |
|---|---|
| Baseline and mutation | Real DiscountCalculator.cs; in a disposable copy change AwayFromZero to ToEven. Move the existing test file outside the agent-readable worktree. |
| Intent | Write xUnit tests from the human business contract, including a midpoint that distinguishes the policies, and correct the one-line mutation. |
| Allowed files | DiscountCalculator.cs and one new test file under the existing test project. |
| Prohibited | No hidden-test restoration, project/package/public-signature changes, unrelated edits, or expectations copied from the implementation formula. |
| Initial regression | Evaluator preflight with the hidden existing tests: FinalPrice(0.05m, 10m) must expect 0.05 and receive 0.04. |
| Acceptance | New tests pass on correct code and fail when the evaluator reapplies only the to-even mutation; valid boundaries, fractional percentage, midpoint, and three invalid ranges are covered. |
| Evidence | Mutation, hidden preflight, submitted tests, clean and mutation results, commands/exit codes, and human decimal-oracle review. |
Task 2: repair SSE blank-line framing
| Field | Fixed definition |
|---|---|
| Baseline and mutation | Real SseReader.cs; in a disposable copy dispatch each data: line immediately instead of waiting for a blank line. |
| Intent | Restore blank-line frame dispatch while preserving joined multiline data, strict fragmented UTF-8, LF/CRLF/CR, comments, event names, limits, EOF behavior, and cancellation. |
| Allowed files | SseReader.cs and SseReaderTests.cs. |
| Prohibited | No browser/endpoint/package/limit edits and no weakened, skipped, renamed, or deleted assertions. |
| Initial regression | HandlesAllSseLineEndingsAcrossSingleByteReads must fail because two data lines become separate events rather than Türkiye ✓ 😀\nsecond. |
| Acceptance | Unchanged focused tests cover multiline data, fragmented UTF-8, all line endings, EOF without delimiter, invalid UTF-8, accumulation limits, and in-flight cancellation; the full C# suite passes. |
| Evidence | Exact mutation, initial failure, final patch and assertion diff, focused/full outputs, exit codes, and remaining limitations. |
Task 3: constrain a synthetic SQL product tool
| Field | Fixed definition |
|---|---|
| Baseline and mutation | Real SafeProductTool.cs; replace CreateCommand only in a disposable checkout with dynamic SQL interpolating count, tenant, and prefix, without parameters or the five-second timeout. |
| Intent | Restore fixed SQL with typed @take, @tenant, and escaped @prefix; trusted tenant binding; count 1–20; prefix at most 80; deterministic order; timeout; and cancellation. |
| Allowed files | SafeProductTool.cs and SafeProductToolTests.cs. |
| Prohibited | No credentials/live database, model-visible tenant/connection string, public-signature/package edits, or descriptive security in place of enforcement. |
| Initial regression | The untrusted-text test must fail because injected text reaches CommandText and typed parameters/timeout are absent; wildcard, bound, and empty-tenant checks remain meaningful. |
| Acceptance | Existing focused tests pass unchanged; inspection confirms fixed SQL, typed parameters, escaped prefix, bounds, timeout, trusted tenant, and cancellation. No database call is required. |
| Evidence | Synthetic mutation, initial failures, final diff, focused/full outputs, command inspection, and human review separating parameterization from authorization. |
Each product receives the same initial prompt and the same follow-up allowance. Clarifications, approvals, pasted build errors, repair requests, and human edits are interventions and must be logged. Use the same number of independent clean attempts, alternate or randomize product order, retain failed attempts, and blind diff reviewers when practical.
Score the resulting change, not the confidence of the answer
Record binary evidence before subjective review. For each task and attempt, capture contract correctness, the named regression and final acceptance checks, test quality under the mutation, allowed-file scope, security boundaries, build/test honesty, and the number and type of corrections. A skipped or weakened test is not a pass, and a correct warning about an unrun check is better evidence than an invented success.
| Dimension | Binary evidence | Separate reviewer judgment |
|---|---|---|
| Contract correctness | Named acceptance checks pass without changing the contract | Clarity of the implementation |
| Regression | Initial defect reproduced; focused and full checks executed | Important missing boundaries |
| Test quality | Tests fail under the named mutation and pass on correct code | Independence and maintainability |
| Scope | Only allowed files changed; no dependency drift or weakened checks | Whether every line is justified |
| Security | No credentials/live services; SQL rules enforced for Task 3 | Correct separation of parameterization and authorization |
| Honesty | Commands, exit codes, failures, skips, and unrun checks recorded | Trustworthiness of the handoff |
| Corrections | Human interventions and repair turns counted by type | Remaining review effort |
If elapsed time is eventually measured, separate tool execution, approval waiting, package restore, and human review. Record product/client version, exact model when visible, model-selection mode, OS, .NET SDK, full baseline hash, cwd, instruction files and hashes, effective permissions, network policy, prompt, follow-ups, timestamps, touched files, commands and exit codes, corrections, and remaining failures. Use unverified rather than guessing any unavailable field.
What this comparison can establish today
Today, the article establishes a protocol and a tested source package—not a product ranking. The maintained calculator, SSE reader, and SQL tool are real fixtures with offline tests. The three evaluation defects are specified as disposable mutations and are not present in the shared source. Successful package tests show that the fixture is buildable; they do not show which product would repair it, how quickly, or with how much review.
No Claude Code coding trial was executed, and no equivalent Codex coding trial was executed. The earlier one-sided instruction inventory is deliberately excluded from the comparison. There is therefore no sample result table, score, winner, cost statement, model preference, or success percentage to interpret.
Future results should retain every independent attempt, including failures, and identify the exact environment and evidence record. A report may describe a bounded observation about these three tasks on those versions. It should not turn a small fixture into a universal claim about C# engineering or the underlying models.
Make an adoption decision from your workflow
Run the protocol only when both authorized environments are ready. A missing account, incompatible client version, undisclosed managed instruction, or unequal permission boundary is not something to hide; mark the attempt non-equivalent and reschedule it. Equal access to a clean fixture matters more than finishing a comparison on a particular day.
Review the evidence by task before combining observations. A product may repair the parser but write weak decimal tests, or produce safe SQL while touching unrelated files. Those are different engineering signals. Team adoption also depends on administration, editor fit, review flow, and approved access, which this three-task protocol does not attempt to score.
Keep the human engineering loop intact: an evaluator defines the contract and defect, the assistant proposes and verifies a patch, and a reviewer decides whether the evidence satisfies acceptance. Neither product's confident explanation replaces source inspection or executed checks.
Key takeaways
- No Claude Code versus Codex winner or runtime benchmark is claimed.
- The shared package supplies three real C# fixtures and exact disposable mutations.
- Instruction content is equal, while filenames follow each product's documented mechanism.
- Effective permissions, pre-restored dependencies, prompts, follow-ups, and review evidence are normalized.
- Future results must retain failed attempts and distinguish binary checks from subjective review.
Frequently asked questions
Which tool is better for C#?
This article has no evidence for a winner. Run authorized equivalent attempts on the three tasks, preserve all results, and state the exact versions and environment with any conclusion.
Can I reuse the same instruction file?
Reuse the same substantive content, not necessarily the same filename. This protocol uses root AGENTS.md for Codex and root CLAUDE.md for Claude Code, with matching body hashes and verified discovery settings.
What should the first pilot task be?
Start with the calculator task because the human contract and mutation outcome are compact. Then use the SSE guide fixture for protocol framing and the SQL task for security-boundary review. The xUnit testing guide explains the calculator's current test design, but its prior editor exercise is not a result for this comparison.
Conclusion and next step
Use evaluation/tasks.md from the shared archive as the executable checklist. Prepare clean disposable copies, capture the required initial failures, complete one evidence record per attempt, and schedule the future run only when both products have authorized equivalent environments. Until those records exist, the accurate conclusion is simple: the protocol is ready, and the comparison result is unmeasured.
Verification results
November 2, 2026: the article and evaluation/tasks.md were aligned to the same three tasks, permission table, evidence fields, and review rubric. Official Codex instruction/permission and Claude Code instruction/permission documentation was rechecked on that date, including Claude Code's current AGENTS.md conditions and minimum supported version.
The maintained source built all four projects in Release with 0 warnings and 0 errors. Fresh runs passed 226 C# tests and 45 JavaScript tests with no failures or skips; 32 focused C# cases for the calculator, SSE reader, and safe SQL tool are included in the 226 total. The source-only ZIP was rebuilt at the same URL, opened in a separate directory, restored in locked mode, and again passed the four-project Release build, 226 C# tests, and 45 JavaScript tests. The archive contains 45 files and no bin, obj, credentials, transcripts, or evaluation results. Package revision: comparison-protocol-1. ZIP SHA-256: b630f17d4d9576a22524f66507bbc8b6061d1d9afc645fa19ef33fe85681c32f.
No equivalent Claude Code and Codex coding trials, live AI-provider request, SQL connection, browser automation, model-quality evaluation, cost measurement, or product preference study was performed. Those outcomes remain unverified rather than inferred from source-package tests.
