agentleFS
StackExchangeStackExchange/StackExchange.Redis/AGENTS.md

StackExchange.Redis

AGENTS.md6.2k starsChanged 3 days agoMITView on GitHub

Guidance for AI coding agents working in this repository. Claude Code reads this via a CLAUDE.md that imports it. StackExchange.Redis — a high-performance .NET client for RESP servers (Redis, Valkey, Garnet, Azure Managed Redis, AWS ElastiCache, etc.). This is the v3 line (VersionPrefix 3.0, current branch work on marc/agents), whose defining change is that the low-level IO core has been extracted into a separate RESPite library that StackExchange.Redis now sits on top of. Build.csproj is a Microsoft.Build.Traversal project that references…

We split this AGENTS.md into the rules it gives an agent

3 rules. About 0 are common, 2 are distinctive, and 1 is very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Add new members to PublicAPI.Unshipped.txt.

    line 58
  2. Distinctive:

    Prefer additive, non-breaking patterns instead:

    line 64
  3. Distinctive:

    When unsure whether a change is breaking, treat it as breaking and reach for an overload — or raise it for human review.

    line 67

≈ “Common” is an estimate: at least 1 in 5 of the 36,368 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
AGENTS.md

AGENTS.md

Guidance for AI coding agents working in this repository. Claude Code reads this via a CLAUDE.md that imports it.

What this is

StackExchange.Redis — a high-performance .NET client for RESP servers (Redis, Valkey, Garnet, Azure Managed Redis, AWS ElastiCache, etc.). This is the v3 line (VersionPrefix 3.0, current branch work on marc/agents), whose defining change is that the low-level IO core has been extracted into a separate RESPite library that StackExchange.Redis now sits on top of.

Solution layout

  • src/StackExchange.Redis/ — the client library (the NuGet package). Public surface: ConnectionMultiplexer, IDatabase/IDatabaseAsync, IServer, ISubscriber, ITransaction/IBatch, ConfigurationOptions, RedisValue/RedisKey/RedisResult.
  • src/RESPite/ — standalone low-level RESP protocol library (separate package, Marc Gravell copyright). Owns wire-level parsing/writing: RespReader, RespFrameScanner, RespPrefix, buffer pooling (CycleBuffer, MemoryTrackedPool). StackExchange.Redis depends on it via ProjectReference. RESPite has no dependency on StackExchange.Redis.
  • eng/StackExchange.Redis.Build/ — a Roslyn analyzer/source-generator project that every other project references OutputItemType="Analyzer". It generates code (e.g. AsciiHashGenerator) and enforces project-specific rules. Not shipped.
  • tests/ — StackExchange.Redis.Tests (xUnit v3, the main integration suite), RESPite.Tests, *.Benchmarks (BenchmarkDotNet), and RedisConfigs (server configs + docker compose, see Testing).
  • toys/ — runnable samples and an in-process RESP server (StackExchange.Redis.Server, used by tests as a managed fake server), Kestrel-hosted server, console tools.
  • docs/ — published documentation site source (markdown). docs/ReleaseNotes.md is the changelog (frozen at 3.0 — from v3 onward release notes live in GitHub Releases).

Build.csproj is a Microsoft.Build.Traversal project that references everything under eng/src/tests/toys — build/pack it to act on the whole repo. StackExchange.Redis.slnx is the IDE solution (XML SLNX format, not classic .sln); it is also what dotnet test --solution runs, because tests use the Microsoft.Testing.Platform runner (selected in global.json), which cannot see a traversal project on the .NET 10 SDK.

Build, test, pack

# Build everything (CI uses Release)
dotnet build Build.csproj -c Release /p:CI=true

# Full local build + start servers + run tests (Windows-oriented, also build.cmd)
pwsh ./build.ps1 -StartServers

# Start the Redis test servers in the background (preferred; see "Testing topology")
docker compose --file tests/RedisConfigs/docker-compose.yml up -d --wait

# Run the main test suite against one target framework (fastest inner loop)
dotnet test --project tests/StackExchange.Redis.Tests/StackExchange.Redis.Tests.csproj -c Release -f net10.0

# Run a single test class / method (xUnit v3 on Microsoft.Testing.Platform; names are fully qualified, '*' allowed at either end)
dotnet test --project tests/StackExchange.Redis.Tests/StackExchange.Redis.Tests.csproj -f net10.0 --filter-class StackExchange.Redis.Tests.ClassName
dotnet test --project tests/StackExchange.Redis.Tests/StackExchange.Redis.Tests.csproj -f net10.0 --filter-method StackExchange.Redis.Tests.ClassName.MethodName

# Every test project at once (what build.ps1 does)
dotnet test --solution StackExchange.Redis.slnx -c Release --no-build

# Pack the library
dotnet pack src/StackExchange.Redis/StackExchange.Redis.csproj --no-build -c Release /p:Packing=true
  • SDK is pinned (global.json, allowPrerelease: false); CI installs the 6/8/10 runtimes. LangVersion is 14.
  • TreatWarningsAsErrors=true everywhere and Features=strict — warnings fail the build. Analyzers (StyleCop + the custom eng analyzer + PublicApiAnalyzers) run as part of the build.
  • Analyzers run on one TFM per project — the newest it builds (see Directory.Build.targets), because they cost ~40% of a clean build otherwise and every rule is TFM-agnostic. Source generators still run on every TFM. If you touch code inside a down-level #if, build it with /p:RunAnalyzers=true to get the full per-TFM sweep. StyleCop applies to src/ only, not tests/ or toys/.
  • Library multi-targets net461;netstandard2.0;net472;net6.0;net8.0;net10.0. Conditional compile symbols: VECTOR_SAFE (all but net461), UNIX_SOCKET (net6.0+). The test project targets net481;net8.0;net10.0; BUILD_CURRENT is defined on the newest TFM (disables some parallelism for brittle tests).

Public API tracking (important — easy to trip over)

Both shipped libraries use Microsoft.CodeAnalysis.PublicApiAnalyzers. Any change to the public surface fails the build until you update the API text files:

  • src/StackExchange.Redis/PublicAPI/PublicAPI.{Shipped,Unshipped}.txt (and the net6.0/ subfolder for APIs that only exist on newer TFMs — each folder is effectively NET_X_Y_OR_GREATER).
  • src/RESPite/PublicAPI/... likewise (with net8.0/).

Add new members to PublicAPI.Unshipped.txt. The build error message tells you the exact line to add.

Backwards compatibility is paramount

This library is heavily used and referenced across the .NET ecosystem, so hard breaks to shipped public APIs are extremely discouraged — especially binary breaks that surface as MissingMethodException/MissingFieldException at runtime for callers compiled against an older version. Note that source-compatible changes can still be binary breaks: adding an optional parameter to an existing method changes its signature and breaks already-compiled callers, so do not do it. The same applies to changing parameter/return types, renaming members, or removing them.

Prefer additive, non-breaking patterns instead:

  • Add a new overload rather than modifying an existing method's signature; use [OverloadResolutionPriority(...)] to steer the compiler toward the preferred overload when several would otherwise be ambiguous.
  • Deprecate, don't delete: mark the old member [Obsolete(...)] (keeping it functional) and point callers at the replacement.
  • When unsure whether a change is breaking, treat it as breaking and reach for an overload — or raise it for human review.

Experimental APIs

Newer features (especially pre-release server APIs) are typically gated behind [Experimental(...)] diagnostic IDs defined in src/RESPite/Shared/Experiments.cs (SER001–SER006, e.g. Respite = "SER004", version-gated server features Server_8_4/8_6/8_8). These IDs are in the root NoWarn list so consuming them internally doesn't error; docs live under docs/exp/.

Architecture (the big picture)

Request flow, roughly outer → inner:

  1. ConnectionMultiplexer (split across many ConnectionMultiplexer.*.cs partials) is the root object — one per logical Redis deployment, meant to be shared/long-lived. It owns endpoints, configuration, pub/sub, sentinel logic, and server selection.
  2. IDatabase / RedisDatabase (RedisDatabase.cs, ~6k lines) is the command surface. Each command builds a Message and hands it to the multiplexer with a ResultProcessor<T> that knows how to parse the reply into the typed result. Message.cs and ResultProcessor.cs are the two hubs to understand command implementation — to add/modify a command, you create the message + pick/extend a result processor.
  3. ServerEndPoint represents one physical server; PhysicalBridge manages the queue/backlog and connection lifecycle for a server; PhysicalConnection is the actual socket + read/write loop. This is where pipelining and the backlog policy live (see docs/PipelinesMultiplexers.md).
  4. RESPite does the byte-level RESP framing beneath PhysicalConnection — scanning frames off the buffer (RespFrameScanner), reading values (RespReader, a ref struct with many .cs partials), and pooled buffers.

Cross-cutting: CommandMap (command renaming/disabling per server type), ServerType/cluster slot routing (ClusterConfiguration, ServerSelectionStrategy), CommandFlags (sync/async, fire-and-forget, replica preference), keyspace isolation (KeyspaceIsolation/), profiling (Profiling/), and maintenance events (Maintenance/). RESP3 push/attribute support is reflected in both the reader and result processors.

Partial-class file naming is heavily used: Foo.cs + Foo.Bar.cs are one type (the csproj wires DependentUpon). When editing a type, check for sibling Foo.*.cs files.

Testing topology

Many tests are pure unit tests, or run against the in-process managed test server (toys/StackExchange.Redis.Server) and need no external Redis at all. The rest are integration tests that talk to a real server.

The integration suite needs a full local Redis topology, not a single server. Bring it up with docker compose:

cd tests/RedisConfigs && docker compose up -d --wait

Expected servers (defaults in tests/StackExchange.Redis.Tests/Helpers/TestConfig.cs):

  • 6379 primary, 6380 replica (standalone tests use 6379,6380)
  • 6382/6383 failover pair, 6381/6384 secure/TLS
  • 7000-7005 cluster nodes
  • 7010/7011 + 26379-26381 sentinel

Tests skip as inconclusive when their required server is absent (e.g. cluster tests skip with "Unable to connect to server"). Override hosts/ports for local runs by editing tests/StackExchange.Redis.Tests/RedisTestConfig.json — note that it is tracked, and is read as an embedded resource rather than from disk, so changes need a rebuild and show up as a dirty working tree rather than acting as a private override. RunLongRunning there also unlocks the tests gated behind Skip.UnlessLongRunning(), which CI never runs. A stray container squatting on 6379 is a common failure: it makes the primary reachable but leaves no replica/cluster, so replica/cluster tests fail or skip — clear it before bringing the compose up.

To probe these servers ad hoc, the local user may have resp-cli installed — a dotnet global tool that is functionally similar to redis-cli (same basic flags: -p, -a, -n, --tls, -3). Prefer resp-cli when it's available; fall back to redis-cli otherwise.

Scenario tests (the fault-injector tier)

tests/StackExchange.Redis.FaultInjector.Tests/ drives a real Redis Enterprise deployment through the cross-client fault-injector service, instead of the docker topology: maintenance notifications and handoffs, topology changes, and Active-Active geographic failover. net10.0 only, and every test self-skips unless the environment is both present and explicitly opted into:

  • SER_FI_CONFIG_DIR (or FI_CONSOLE_CONFIG_DIR) — the directory mounted into the injector as /app/config; it holds endpoints.json (the cross-client format, shared with Jedis et al.), env_output.json (cluster credentials) and the CA certificate. One path is the whole configuration.
  • E2E_SCENARIO_TESTS=true — required, because these tests create and delete databases.
  • FAULT_INJECTION_API_URL — optional; defaults to http://127.0.0.1:20324.

Absent or not opted in, tests skip; configured, opted in, and broken, they fail — a tier that skips on a broken environment reports success for tests that never ran. Some scenarios sit behind a second gate (SER_FI_DESTRUCTIVE, SER_FI_CLUSTER_FAILURE, SER_FI_RETENTION_AGE_MINUTES). Classes are tagged [Trait("tier", "fault-injector")] plus a scenario family, and the assembly disables test parallelization because the injector queues actions. Build.csproj globs the project so CI compiles it, but CI's dotnet test names only tests/StackExchange.Redis.Tests, so the tier never executes there. See tests/StackExchange.Redis.FaultInjector.Tests/README.md.

Agent skills

Repo-specific Agent Skills (the portable SKILL.md open standard) live under .claude/skills/:

  • implement-resp-command — add a new RESP command to StackExchange.Redis end-to-end (enum, interfaces, RedisDatabase, ResultProcessor, public-API tracking, and the ResultProcessor + RoundTrip unit tests).
  • create-implementation-plan-for-redis-api-change — write the reviewable implementation plan for a Redis API change from a shared client HLD before any code is written (public API, files, ordered steps, test plan, gating version). Read-only: it produces one markdown file and defers to implement-resp-command for the conventions.
  • summarize-database — profile a live (often production) RESP database by sampling: discover key patterns, where data lives by count and size, and what the values are. Read-only.
  • audit-command-coverage — re-diff the upstream Redis command specs against the RedisCommand enum and the coverage ledger (docs/CommandCoverage.md); reports commands the server gained that have no recorded decision, plus resolved/stale ledger rows, and updates the ledger. Edits only the ledger.

That path is where Claude Code discovers them; the files themselves are tool-agnostic, so if your agent reads skills from a different directory (Codex uses .agents/skills/, etc.), point it at this folder or copy the skill across.

Manner

Be consise and direct where possible, but with as much detail as is necessary; no need for flattery, and feel free to challenge anything the user says: users hallucinate too.

Conventions

  • Code style is enforced via .editorconfig + Shared.ruleset + StyleCop (StyleCop in src/ only); 4-space indent, BOM + final newline on .cs, System.* usings first, no redundant this.. Build will fail on violations. Match the surrounding style in tests//toys/ too — the rules are simply not enforced there.
  • InternalsVisibleTo exposes internals to the test/benchmark/server projects, so tests reach into internal types directly.
  • docs/ markdown is the user-facing documentation; update it for user-visible behavior changes.

Download now (ZIP)

Trending

Steady talk.about the whole repository

Dec 2025: 0 mentionsJan 2026: 0 mentionsFeb 2026: 0 mentionsMar 2026: 1 mentionApr 2026: 1 mentionMay 2026: 0 mentionsJun 2026: 0 mentionsJul 2026: 7 mentionsAug 2026: 10 mentionsSep 2026: 13 mentionsOct 2026: 4 mentionsNov 2026: 0 mentions
Dec 2025Jun 2026Nov 2026
Mentions a month of the StackExchange/StackExchange.Redis repository that our weekly crawl found. There is no adoption data for this file yet.

Who's talking about StackExchange/StackExchange.Redis

The biggest 5 of 81 mentions linking to the repository that our crawl found. Each line is their own headline.

See all 81

Talked about on GitHub, Stack Overflow and Hacker News (81 times).

On GitHub · 50

45 more on GitHub

On Stack Overflow · 30

25 more on Stack Overflow

On Hacker News · 1

  • Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.

    Of the AGENTS.md files we read, the 28,693 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.

  • In this repository5 other files it gives its agents.

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.