RepoPilotOpen in app →

reactiveui/refit

The automatic type-safe REST library for .NET Core, Xamarin and .NET. Heavily inspired by Square's Retrofit library, Refit turns your REST API into a live interface.

Healthy

Healthy across the board

Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 3d ago
  • 17 active contributors
  • Distributed ownership (top contributor 45% of recent commits)
Show 3 more →
  • MIT licensed
  • CI configured
  • Tests present

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/reactiveui/refit)](https://repopilot.app/r/reactiveui/refit)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/reactiveui/refit on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: reactiveui/refit

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/reactiveui/refit shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across the board

  • Last commit 3d ago
  • 17 active contributors
  • Distributed ownership (top contributor 45% of recent commits)
  • MIT licensed
  • CI configured
  • Tests present

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live reactiveui/refit repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/reactiveui/refit.

What it runs against: a local clone of reactiveui/refit — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in reactiveui/refit | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 33 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>reactiveui/refit</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of reactiveui/refit. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/reactiveui/refit.git
#   cd refit
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of reactiveui/refit and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "reactiveui/refit(\\.git)?\\b" \\
  && ok "origin remote is reactiveui/refit" \\
  || miss "origin remote is not reactiveui/refit (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
  && ok "default branch main exists" \\
  || miss "default branch main no longer exists"

# 4. Critical files exist
test -f "src/InterfaceStubGenerator.Shared/InterfaceStubGenerator.cs" \\
  && ok "src/InterfaceStubGenerator.Shared/InterfaceStubGenerator.cs" \\
  || miss "missing critical file: src/InterfaceStubGenerator.Shared/InterfaceStubGenerator.cs"
test -f "src/InterfaceStubGenerator.Shared/Emitter.cs" \\
  && ok "src/InterfaceStubGenerator.Shared/Emitter.cs" \\
  || miss "missing critical file: src/InterfaceStubGenerator.Shared/Emitter.cs"
test -f "src/InterfaceStubGenerator.Shared/Parser.cs" \\
  && ok "src/InterfaceStubGenerator.Shared/Parser.cs" \\
  || miss "missing critical file: src/InterfaceStubGenerator.Shared/Parser.cs"
test -f "src/InterfaceStubGenerator.Shared/Models/ContextGenerationModel.cs" \\
  && ok "src/InterfaceStubGenerator.Shared/Models/ContextGenerationModel.cs" \\
  || miss "missing critical file: src/InterfaceStubGenerator.Shared/Models/ContextGenerationModel.cs"
test -f "README.md" \\
  && ok "README.md" \\
  || miss "missing critical file: README.md"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 33 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~3d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/reactiveui/refit"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Refit is a type-safe REST client library for .NET that automatically generates HTTP client implementations from C# interfaces decorated with attributes, inspired by Square's Retrofit for Java. It eliminates boilerplate by converting interface methods into actual HTTP requests, supporting .NET Core, Xamarin, and .NET Framework with built-in serialization, authentication, and HttpClientFactory integration. Modular structure with separate concerns: InterfaceStubGenerator.Shared/ contains core Roslyn-based code generation logic (Emitter.cs, InterfaceStubGenerator.cs), versioned in three parallel projects for Roslyn 3.8, 4.1, and 5.0 compatibility. Main src/ contains implementation; test fixtures and integration tests follow alongside. Multiple NuGet package targets (Refit core, HttpClientFactory, Newtonsoft.Json variant) built from single codebase.

👥Who it's for

.NET backend and mobile developers building REST API consumers who want strongly-typed, compile-time-safe API clients without manually writing HttpClient wrappers. Particularly valuable for teams using Xamarin cross-platform mobile development or microservices architectures where multiple services consume external APIs.

🌱Maturity & risk

Production-ready and actively maintained. The codebase shows 1.1M+ lines of C#, organized CI/CD via GitHub Actions (ci-build.yml, release.yml), multiple NuGet packages with stable versioning (6.x and 11.x major versions released), and a responsive issue/PR workflow. Active development visible with recent breaking changes documented (6.x, 11.x) and Roslyn source generators for modern .NET versions.

Low-to-moderate risk for established projects. The library is widely used (ReactiveUI organization backing) but has undergone significant breaking changes between major versions (6.x, 11.x), requiring careful upgrade planning. Source generator maintenance across multiple Roslyn versions (Roslyn38, Roslyn41, Roslyn50 in src/) adds complexity; developers must match their Refit version to their .NET SDK's Roslyn version. No visible single-maintainer risk given organizational backing.

Active areas of work

Active development on Roslyn source generators (InterfaceStubGenerator.Shared/) to replace older code generation, supporting modern .NET incremental generators. Recent tooling: renovate.json indicates automated dependency updates, lock.yml workflow for issue management, signclient.json for code signing. Breaking changes in 11.x suggest major refactoring underway, likely modernizing API surface.

🚀Get running

Clone, restore, and build: git clone https://github.com/reactiveui/refit.git && cd refit && dotnet restore && dotnet build. Dev environment includes .devcontainers/devcontainer.json for containerized setup (run post-create.sh). Use dotnet test to verify installation; see CodeCoverage.runsettings for test configuration.

Daily commands: dotnet build src/Refit.sln compiles all projects. Unit tests: dotnet test. Integration tests require running service mock (check test projects). Dev changes: modify InterfaceStubGenerator.Shared/ for code gen logic, src/Refit/ for core library, rebuild to see generated code in obj/.

🗺️Map of the codebase

  • src/InterfaceStubGenerator.Shared/InterfaceStubGenerator.cs — Core incremental source generator that parses REST API interfaces and emits implementation code—the foundation of Refit's type-safe generation pipeline.
  • src/InterfaceStubGenerator.Shared/Emitter.cs — Generates the actual C# source code for REST client implementations, handling all HTTP method binding and response mapping logic.
  • src/InterfaceStubGenerator.Shared/Parser.cs — Parses Refit interface attributes (Get, Post, Headers, etc.) and extracts method signatures, parameters, and REST metadata into structured models.
  • src/InterfaceStubGenerator.Shared/Models/ContextGenerationModel.cs — Central data model passed through the generation pipeline containing parsed interface and method information needed for code emission.
  • README.md — Documents the public API surface, usage patterns, and architectural intent behind Refit's type-safe REST client generation.
  • .github/workflows/ci-build.yml — Defines the build, test, and release pipeline validating all Roslyn source generator versions and ensuring multi-platform compatibility.
  • src/Directory.Build.props — Central build property configuration managing version numbers, target frameworks, and shared compiler settings across all projects.

🛠️How to make changes

Add Support for a New HTTP Attribute (e.g., [Patch])

  1. Define the new attribute in the core library alongside [Get], [Post], etc. (src/InterfaceStubGenerator.Shared/Models/MethodModel.cs)
  2. Update Parser.cs to recognize and extract the new attribute when analyzing interface methods. (src/InterfaceStubGenerator.Shared/Parser.cs)
  3. Extend Emitter.cs to generate HttpMethod binding code for the new verb in the emitted client. (src/InterfaceStubGenerator.Shared/Emitter.cs)
  4. Add diagnostic descriptors if validation rules apply to the new attribute. (src/InterfaceStubGenerator.Shared/DiagnosticDescriptors.cs)
  5. Add test cases in GeneratedTest.cs to validate the new attribute's generated code. (src/Refit.GeneratorTests/GeneratedTest.cs)

Add a New Parameter Binding Type (e.g., [Cookie])

  1. Define the binding attribute and add it to ParameterModel.cs to track parameter bindings. (src/InterfaceStubGenerator.Shared/Models/ParameterModel.cs)
  2. Update Parser.cs to detect the new binding attribute on method parameters. (src/InterfaceStubGenerator.Shared/Parser.cs)
  3. Modify Emitter.cs to generate code that extracts and applies the parameter value according to the new binding type. (src/InterfaceStubGenerator.Shared/Emitter.cs)
  4. Add validation rules in DiagnosticDescriptors.cs if the binding has usage constraints. (src/InterfaceStubGenerator.Shared/DiagnosticDescriptors.cs)

Extend Generator to Support a New Return Type

  1. Register the new return type in WellKnownTypes.cs with its full type symbol information. (src/InterfaceStubGenerator.Shared/Models/WellKnownTypes.cs)
  2. Update Emitter.cs to generate appropriate response-unwrapping code for the new return type. (src/InterfaceStubGenerator.Shared/Emitter.cs)
  3. Add test cases in GeneratedTest.cs covering the new return type with various success/error scenarios. (src/Refit.GeneratorTests/GeneratedTest.cs)
  4. If the return type requires incremental caching changes, update IncrementalValuesProviderExtensions.cs. (src/InterfaceStubGenerator.Shared/IncrementalValuesProviderExtensions.cs)

Optimize Generator Performance or Add Incremental Caching

  1. Analyze the incremental generation flow in InterfaceStubGenerator.cs to identify bottlenecks. (src/InterfaceStubGenerator.Shared/InterfaceStubGenerator.cs)
  2. Use ImmutableEquatableArray.cs to wrap results that participate in incremental caching. (src/InterfaceStubGenerator.Shared/ImmutableEquatableArray.cs)
  3. Run incremental benchmarks in IncrementalTest.cs to validate that caching invalidation is correct. (src/Refit.GeneratorTests/Incremental/IncrementalTest.cs)
  4. Measure end-to-end impact using SourceGeneratorBenchmark.cs. (src/Refit.Benchmarks/SourceGeneratorBenchmark.cs)

🪤Traps & gotchas

Roslyn version coupling: InterfaceStubGenerator.Shared is shared via .shproj (shared project, not NuGet), so changes propagate to all three Roslyn versions—build all three targets to catch version-specific issues. Breaking changes between major versions (6.x→11.x visible in README) mean test fixtures may need updates. SignClient config (signclient.json) required for release builds but not local development. Generated code lands in obj/ folder, easy to miss during debugging.

🏗️Architecture

💡Concepts to learn

  • Roslyn Incremental Source Generators — Refit uses Roslyn 5.0+ incremental generators (src/InterfaceStubGenerator.Shared/) to generate HTTP client code at compile time with zero runtime reflection; understanding this is essential for contributing to code generation logic
  • Type-Safe REST Bindings — Refit's core value: converting interface method signatures into type-safe HTTP calls, eliminating magic strings and runtime errors—this design pattern is crucial for understanding why attributes map to HTTP semantics
  • Symbol-based Code Analysis — InterfaceStubGenerator.cs uses ISymbol introspection (ITypeSymbol, IMethodSymbol) to analyze interface contracts without executing code; essential for understanding how Refit extracts API metadata
  • HttpClient Message Handlers & DelegatingHandler Pipeline — Refit's request/response pipeline uses DelegatingHandlers (mentioned in README) for cross-cutting concerns like auth and logging; understanding this chain is critical for implementing middleware
  • Attribute-Driven Code Generation — Refit's architecture: attributes like [Get], [Post], [Body] drive Emitter.cs logic to generate corresponding HTTP operations; this declarative pattern is central to the library's design
  • HttpClientFactory Lifetime Management — Refit.HttpClientFactory integration (separate NuGet package) manages HttpClient pooling and disposal via dependency injection; critical for production apps to avoid socket exhaustion
  • Shared Projects (.shproj) vs. NuGet Packages — InterfaceStubGenerator.Shared is a .shproj (shared project, not packaged) linked into three separate Roslyn-versioned projects; understanding this prevents accidental breaking changes across versions
  • square/retrofit — The original Java library that inspired Refit's design and attribute-based API definition model
  • reactiveui/ReactiveUI — Parent organization; Refit integrates with ReactiveUI observables and shares architectural patterns
  • App-vNext/Polly — Companion resilience library; Refit README documents Polly + Polly.Context integration for retry/timeout policies
  • dotnet/roslyn — Dependency for source generators; understanding Roslyn incremental generators is essential for modifying InterfaceStubGenerator
  • dotnet/aspnetcore — HttpClientFactory and System.Text.Json come from here; Refit's HTTP and serialization layers depend on these

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive unit tests for InterfaceStubGenerator.Shared source generators

The InterfaceStubGenerator.Shared project contains critical code generation logic (Parser.cs, Emitter.cs, InterfaceStubGenerator.cs) but there's no visible test project in the file structure. Source generators are notoriously difficult to debug, and comprehensive tests would catch regressions early and help contributors understand expected behavior. This is high-value because it directly impacts code quality of the generated REST interfaces.

  • [ ] Create new test project: src/InterfaceStubGenerator.Shared.Tests/InterfaceStubGenerator.Shared.Tests.csproj
  • [ ] Add unit tests for src/InterfaceStubGenerator.Shared/Parser.cs covering various HTTP method decorations, parameter attributes, and type constraints
  • [ ] Add unit tests for src/InterfaceStubGenerator.Shared/Emitter.cs validating generated code structure for different return types (Task, Task<T>, Observable, etc.)
  • [ ] Add snapshot/golden file tests for generated output validation across Roslyn 3.8, 4.1, and 5.0 versions

Add GitHub Actions workflow for backward compatibility testing across .NET versions

The repo targets multiple frameworks (Xamarin, .NET Core, .NET Framework) and has multiple Roslyn versions (3.8, 4.1, 5.0), but the ci-build.yml workflow isn't visible in detail. A dedicated compatibility workflow would ensure generated code works across all supported .NET versions and Roslyn analyzers. This prevents silent regressions for users on older frameworks.

  • [ ] Review .github/workflows/ci-build.yml for current .NET version coverage
  • [ ] Create .github/workflows/compatibility-matrix.yml to test against net472, net6.0, net7.0, net8.0
  • [ ] Add matrix testing for InterfaceStubGenerator against Roslyn 3.8, 4.1, and 5.0 separately
  • [ ] Validate that Refit.Benchmarks runs successfully on all target frameworks

Document and test dev container setup for source generator development

The .devcontainers configuration exists (Dockerfile, devcontainer.json, post-create.sh) but there's likely no documentation on how to use it effectively for source generator development, which has unique debugging requirements. Contributors working on the InterfaceStubGenerator projects need clear guidance on local setup, testing incremental generators, and validating code generation. This lowers friction for potential contributors.

  • [ ] Create docs/DEVELOPMENT.md documenting dev container setup and source generator debugging workflow
  • [ ] Verify .devcontainers/post-create.sh installs all necessary tools for Roslyn development (dotnet-script, source generator debugging extensions)
  • [ ] Add instructions for testing incremental source generators locally with sample projects in the dev container
  • [ ] Document how to validate generated code output using the dev container environment

🌿Good first issues

  • Add missing XML documentation comments to InterfaceStubGenerator.Shared/Models/*.cs—high-value, low-risk documentation improvement visible from file list
  • Expand test coverage for ParameterModel.cs edge cases (collection formatting, null handling, custom constraints)—tests likely thin given code size
  • Create example integration test in a new examples/ directory showing HttpClientFactory registration + Polly pipeline setup—README mentions both but no runnable demo files visible

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 58c2a4e — Update dependency Microsoft.SourceLink.GitHub to v10 (#2093) (renovate[bot])
  • 03c7cc4 — Modernize the Refit solution for TUnit, source-gen AOT, and theme support (#2092) (ChrisPulman)
  • da50704 — Avoid extra allocations when deserializing with Newtonsoft.Json (#2085) (yzhoholiev)
  • 0bbe911 — Add AddRefitClient overloads and tests (#2084) (ChrisPulman)
  • de57efa — Support sync interface members & enum names (#2068) (ChrisPulman)
  • 96a25c6 — Update .NET test stack to v10 (major) (#2080) (renovate[bot])
  • 8bc7ee6 — Update dependency Microsoft.NET.Test.Sdk to 18.4.0 (#2078) (renovate[bot])
  • dda425c — Simplify sponsor logos layout in README (#2075) (ChrisPulman)
  • 748c4ec — Add sponsors section and update platforms (#2074) (ChrisPulman)
  • 35f8bf7 — Add sponsors section and update platforms (#2073) (ChrisPulman)

🔒Security observations

The Refit repository shows a moderate security posture. The main concerns are the presence of cryptographic signing keys (buildtask.snk) and configuration files that may contain secrets in version control. These should be immediately remediated. The codebase structure suggests good practices (separate concerns, organized file structure), but dependency analysis and Docker configuration require verification. No obvious code-level vulnerabilities (SQL injection, XSS) detected in the provided file structure, as this is a REST client library with generated code patterns. Recommend implementing automated dependency scanning in CI/CD and ensuring secrets management best practices are followed.

  • Medium · Potential Secret in Configuration File — config/signclient.json. The file 'config/signclient.json' is present in the repository. Configuration files that contain signing credentials or API keys should not be committed to version control, even if they appear to be template files. Fix: Ensure signclient.json contains no actual secrets. Use environment variables or secure secret management systems for sensitive credentials. Consider adding this file to .gitignore if it contains credentials.
  • Medium · Build Task Signing Key in Repository — buildtask.snk. The file 'buildtask.snk' (Strong Name Key) is committed to the repository. Cryptographic keys should not be stored in version control as they can be used to forge assemblies. Fix: Remove this key from version control immediately. Generate a new key for production use. Store the actual signing key securely outside the repository, and use environment variables or secure key vaults during the build process.
  • Low · Missing Dependency Information — Dependencies/Package files. No package dependency file content was provided for analysis (packages.config, .csproj, or package.json). Cannot verify for known vulnerable dependencies. Fix: Perform a regular security audit of all NuGet package dependencies using tools like 'dotnet list package --vulnerable' or integrate OWASP Dependency-Check into CI/CD pipeline.
  • Low · Docker Configuration Requires Review — .devcontainers/Dockerfile. A Dockerfile is present (.devcontainers/Dockerfile). Docker configuration files should follow security best practices to prevent container escape and supply chain attacks. Fix: Review Dockerfile for: non-root user usage, minimal base images, no secrets in layers, proper dependency pinning, and regular security scanning. Consider using Docker Scout or Trivy for image scanning.
  • Low · Post-Create Script Execution — .devcontainers/post-create.sh. A post-create.sh script exists in the devcontainer configuration. Scripts that execute automatically should be reviewed to ensure they don't introduce security risks. Fix: Review the script contents for: arbitrary command execution, unvalidated inputs, privilege escalation, and credential exposure. Ensure it follows the principle of least privilege.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · reactiveui/refit — RepoPilot