Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
513 commits
Select commit Hold shift + click to select a range
e8b0006
Honor select disposition in transactions (#2322)
slorello89 Dec 21, 2023
ad2e69f
Add test for multiplexer GC rooting. (#2427)
kornelpal Dec 22, 2023
b2694b3
Fix #2576: PhysicalConnection: Better shutdown handling (#2629)
NickCraver Jan 11, 2024
7dff15d
Add release notes
NickCraver Jan 16, 2024
d9c9f7b
Fix release notes position for #2322
NickCraver Jan 16, 2024
39eac01
Support Alibaba pseudo-cluster configurations (#2646)
mgravell Feb 13, 2024
e4cdd90
Release notes for 2.7.20
NickCraver Feb 20, 2024
6392871
Sanitize client setinfo metadata (#2654)
mgravell Feb 24, 2024
54a633f
Feature: Add HeartbeatConsistencyChecks (#2656)
NickCraver Feb 26, 2024
2753c37
Add 2.7.23 release notes
NickCraver Feb 26, 2024
7bec9df
Update 2.7.23 release notes
NickCraver Feb 26, 2024
a517561
Support `HeartbeatConsistencyChecks` in `Clone()` (#2658)
mgravell Feb 27, 2024
18c057b
add new AddLibraryNameSuffix API for annotating connections with usag…
mgravell Feb 28, 2024
ae72fb7
release notes
mgravell Mar 1, 2024
9ab79e3
new tunnel-based RESP logging and validation (#2660)
mgravell Mar 1, 2024
441f89a
Normalize release notes
NickCraver Mar 3, 2024
91520e0
simplify property initialization (#2666)
testfirstcoder Mar 7, 2024
baf2b1e
CheckTrustedIssuer: Fixes for invalid chains (#2665)
NickCraver Mar 9, 2024
4da3d62
Fix #2664 Backlog: move to full synchronous behavior since we're on a…
NickCraver Mar 11, 2024
60e5d17
2.7.33 Release notes
NickCraver Mar 11, 2024
2f69707
TLS: Check EKU in X509 chain checks (#2670)
NickCraver Mar 12, 2024
cb8b20d
Correct link to RespLogging doc (#2696)
philon-msft Apr 12, 2024
61c13c2
Replace all occurrences of "nil" in `IDatabase(Async)` xmldoc with le…
bdach May 7, 2024
39b992f
support reading from last message from stream with xread (#2725)
atakavci Jun 8, 2024
1de8dac
Implement high integrity mode for commands (#2741)
mgravell Jun 24, 2024
1c6b59e
release notes; bump minor to 2.8
mgravell Jun 24, 2024
0d38f6f
test against version 7.4-rc1 issue #2738 (#2739)
atakavci Jul 2, 2024
a64ca14
support for CLIENT KILL MAXAGE (#2727)
atakavci Jul 9, 2024
dee9dba
use minimal API for kestrel toy project
mgravell Jul 25, 2024
d9158cd
Merge branch 'main' of https://github.com/StackExchange/StackExchange…
mgravell Jul 25, 2024
1e40509
fix typo (#2766)
wilvk Jul 28, 2024
4852cca
switch to docker compose (#2771)
atakavci Aug 3, 2024
8346a5c
Project: Enable StyleCop and fix existing rules to make PRs easier go…
NickCraver Aug 3, 2024
e208905
Feature: Support for hash field expiration (#2716)
atakavci Aug 17, 2024
3701b50
Build: Simplify Docker layout, fix Envoy, and upgrade tests (#2774)
NickCraver Aug 18, 2024
c0bb4eb
Add support for HSCAN NOVALUES (#2722)
atakavci Aug 18, 2024
fe40d17
Fix #2763: ConnectionMultiplexer.Subscription is not Thread-safe (#2769)
Chuck-EP Aug 18, 2024
e151cd5
docs: fix a PR link (#2776)
WeihanLi Aug 24, 2024
b2b4a88
Fix #2778: Run CheckInfoReplication even with HeartbeatConsistencyChe…
NickCraver Sep 3, 2024
c8d2c28
Adding 2.8.12 release notes
NickCraver Sep 3, 2024
4d94342
Update command map for Envoy (#2794)
dbarbosapn Sep 9, 2024
654859f
Release notes for 2.8.14
NickCraver Sep 9, 2024
322c704
Always perform "last read" check in heartbeat when HeartbeatConsisten…
NickCraver Sep 10, 2024
d7ca832
Add release notes for 2.8.16
NickCraver Sep 10, 2024
c8a7265
format ipv6 endpoints correctly (#2813)
mgravell Oct 31, 2024
ebacf39
Update default Redis version from 4.0.0 to 6.0.0 for Azure Redis (#2810)
philon-msft Nov 5, 2024
0071148
release notes for ipv6
mgravell Nov 5, 2024
11ef77d
Automatically detect and tune for Azure Managed Redis caches (#2818)
philon-msft Nov 25, 2024
33358b7
Packages: update to remove CVE dependencies (#2820)
NickCraver Nov 27, 2024
7170cb4
Update release notes for 2.8.22
NickCraver Nov 27, 2024
0cb7d58
update envoy defs to allow `UNWATCH` (#2824)
mgravell Dec 18, 2024
1a4c66d
Update release notes for 2.8.22
NickCraver Dec 18, 2024
fe04b9a
Improve readme - what even is this? (#2837)
mgravell Feb 18, 2025
3bd3e66
Track client-initiated shutdown for any pipe type. Fixes #2652 (#2814)
bgrainger Mar 4, 2025
437e1ff
Fix: Respect IReconnectRetryPolicy in disconnect loops (#2853)
NickCraver Mar 4, 2025
2a47eb5
Update release notes
NickCraver Mar 4, 2025
50f2218
Fix: Rexpect backoff in the disconnect -> resurrection case as well (…
NickCraver Mar 6, 2025
cd7a3b2
Physical bridge: handle the reconnect count case
NickCraver Mar 6, 2025
be5c8a6
Update release notes for 2.8.31
NickCraver Mar 7, 2025
e93de40
Log multiplexer reconfiguration (#2864)
st-dev-gh Apr 2, 2025
328b4b5
Make it easier to use user certificate files (#2873)
mgravell Apr 15, 2025
28fbe78
Connections: Move all AuthenticateAsClient to async (#2878)
NickCraver May 3, 2025
bb23b57
add package README.md to make NuGet happier (#2875)
mgravell May 3, 2025
e91c3eb
Use up-to-date releases of Redis for CI workflow (#2855)
atakavci May 4, 2025
cfb9105
Add release notes for 2.8.37
NickCraver May 6, 2025
9420b59
Add missing release notes for #2864
NickCraver May 6, 2025
cfbd474
Remove fuget link
mgravell May 15, 2025
ad5f656
Support sharded pubsub commands (#2887)
mgravell Jun 10, 2025
2cb97af
release notes 2.8.41
mgravell Jun 10, 2025
7351ad9
(code-rot) Update package dependencies (#2906)
mgravell Jul 9, 2025
be39ec9
new operations with BITOP command (#2900)
atakavci Jul 10, 2025
0488c42
release notes
Jul 10, 2025
e7b3767
Fix CLIENT ID error during handshake (#2909)
mgravell Jul 17, 2025
8a52783
docs: offer guidance on using framework methods for async timeouts / …
mgravell Jul 17, 2025
894b95e
release notes 2.8.47
mgravell Jul 19, 2025
5f58617
[Tests] Upgrade to xUnit v3 (#2907)
NickCraver Jul 21, 2025
afd66ef
test fix; skip CLIENT PAUSE tests unless long-running enabled (#2916)
mgravell Jul 21, 2025
c54c159
StreamGroupInfo.Lag can be null (#2902)
robhop Jul 21, 2025
6b02ba8
Add xtrim with minid and new 8.2 stream features (#2912)
mgravell Jul 21, 2025
b4aaced
Replaces inline logging with source-generated LoggerMessage (#2903)
Meir017 Jul 21, 2025
cf9f659
Implement internal cancellation for SCAN via WithCancellation (#2911)
mgravell Jul 21, 2025
7b1460a
move logger extensions to LoggerExtensions.cs (extends 2903) (#2917)
mgravell Jul 21, 2025
0b4fd45
fix-zrevrangebylex (#2636)
ArnoKoll Jul 21, 2025
dcae5dd
Fix #2679: connect/config: only access task.Result if we know it comp…
mgravell Jul 21, 2025
4c70460
update release notes
mgravell Jul 21, 2025
c364806
update version in release notes
mgravell Jul 21, 2025
265cc12
Make private & internal stuff sealed (#2915)
Henr1k80 Jul 22, 2025
c07aec9
workaround Mono test failures: (#2921)
mgravell Jul 23, 2025
bf972cc
chore: Replaces string interpolation with structured logging - Server…
Meir017 Jul 23, 2025
cf8b6fb
Support for new HGETDEL, HGETEX and HSETEX commands (#2863)
atakavci Jul 23, 2025
038f3de
Add `Condition.SortedSet[Not]ContainsStarting` condition for transact…
ArnoKoll Jul 24, 2025
2f52c95
Adds support for XPENDING IDLE parameter (#2822)
david-brink-talogy Jul 24, 2025
3c236a4
chore: Replaces string interpolation with structured logging - Result…
Meir017 Jul 24, 2025
b3aeb61
chore: Replaces string interpolation with structured logging - Physic…
Meir017 Jul 24, 2025
45f7af4
Replaces string interpolation with structured logging (#2930)
Meir017 Jul 25, 2025
b995ebc
Tests: Add benchmark suite for easily measuring improvements (#2931)
NickCraver Jul 25, 2025
0f4f469
Improve `double` formatting performance on net8+ and fix equality inc…
mgravell Jul 25, 2025
f6e8b64
intellisense clarification for StreamTrimResult.NotDeleted (#2933)
mgravell Jul 29, 2025
8fffdff
Tests: Improve stability for AbortOnConnectFailTests (#2934)
NickCraver Aug 2, 2025
b03e5f7
fix error in XADD arg-count calculation (#2941)
mgravell Aug 18, 2025
4d2da7a
Implement GetServer(RedisKey, ...) (#2936)
mgravell Aug 19, 2025
d48af3e
Update ReleaseNotes.md
mgravell Aug 20, 2025
a1e4853
Enable CA1852 and fix warnings for it (#2942)
Henr1k80 Sep 9, 2025
6fdbc88
fix: RedisValue/RedisResult: cast to double should respect special va…
mgravell Sep 10, 2025
d5b1d50
Add vector-set API (#2939)
mgravell Sep 10, 2025
91bbd3e
release notes: move vectorsets to unshipped
mgravell Sep 10, 2025
229e9c5
Flush & write concurrently in LoggingTunnel and avoid double lookups …
Henr1k80 Sep 10, 2025
fec2cae
2.9.17 release notes
mgravell Sep 10, 2025
c5f2696
Fix 2951 - Sentinel reconnect failure (#2956)
mgravell Sep 23, 2025
11a919a
Remove supported Envoyproxy commands from exclusions. (#2957)
sshumakov Sep 24, 2025
862a70e
Convert to Hex only on Encoding.UTF8.GetString possible exceptions (#…
jcaspes Sep 24, 2025
f4f66be
eng: prefer Volatile.Read over Thread.VolatileRead (#2960)
mgravell Sep 26, 2025
d4b05ca
Channel routing: revert non-S routing to random, with new API to opt …
mgravell Sep 26, 2025
307129e
release notes
mgravell Sep 26, 2025
0be1df7
eng: remove PublicSign windows-only restriction (#2963)
mgravell Sep 29, 2025
515c47a
release notes
mgravell Sep 29, 2025
a5e6e3d
Actions: support publishing to MyGet off main branch (#2964)
NickCraver Sep 30, 2025
895a2c7
Adjust YAML for main branch builds
NickCraver Sep 30, 2025
9abcef1
Adjust main branches
NickCraver Sep 30, 2025
9ee5f6f
Adjust path globs on file paths to include subdirectories
NickCraver Sep 30, 2025
8a6ad4a
Update README.md (#2967)
mgravell Oct 7, 2025
d5b445a
Fix sharded pub/sub handling over slot migrations (#2969)
mgravell Oct 13, 2025
9c6023f
release notes 2.9.32
mgravell Oct 13, 2025
e5120f7
docker image: use client-libs-test (#2976)
mgravell Nov 4, 2025
24ed30c
Support MSETEX (#2977)
mgravell Nov 5, 2025
416daff
propose support for XREADGROUP CLAIM (#2972)
mgravell Nov 5, 2025
94e0090
Support 8.4 CAS/CAD (IF*) operations (#2978)
mgravell Nov 5, 2025
2c3b3e0
Combine fixups from 8.4 changes (#2979)
mgravell Nov 6, 2025
fe4d5f6
rev 2.10
mgravell Nov 6, 2025
3167fde
2.10.1
mgravell Nov 6, 2025
24d8c1e
fix docs link
mgravell Nov 11, 2025
feb122c
Update Dockerfile to 8.4 GA pre 3 (#2981)
mgravell Nov 18, 2025
d80bcbf
fix incorrect debug assertion in HGETEX; no impact to release build (…
mgravell Jan 23, 2026
84b015e
Propagate PhysicalBridge backlog to ServerCounters (#2996)
nathan-miller23 Jan 27, 2026
c8e3152
handle backlog process startup failures (#3002)
nathan-miller23 Feb 3, 2026
f92f9f4
release notes
mgravell Feb 3, 2026
5695770
trigger CI
mgravell Feb 3, 2026
2da6975
Migrate to codeql 4 (#3004)
mgravell Feb 3, 2026
37a1a5d
Enable manual codeql run
mgravell Feb 3, 2026
f1b7fa7
Allow manual CI run
mgravell Feb 3, 2026
3ce6682
CI: manual run should pack/deploy
mgravell Feb 3, 2026
fb487d6
Release 2.10.14
mgravell Feb 4, 2026
686f118
fix codeql
mgravell Feb 4, 2026
df1db72
Update README to include Azure Managed Redis (#3005)
redis-phil Feb 4, 2026
c979c6b
keyspace notifications including cluster support (#2995)
mgravell Feb 6, 2026
809055e
update API 'shipped' files
mgravell Feb 6, 2026
e71373b
Options: Split out AMR to its own options provider (#2986)
NickCraver Feb 6, 2026
18fdcd7
Support 8.6 idempotent streams (#3006)
mgravell Feb 9, 2026
494b26c
release notes
mgravell Feb 9, 2026
0aa6005
Update CI to 8.6 (#3010)
mgravell Feb 11, 2026
a018b87
8.6 Support HOTKEYS (#3008)
mgravell Feb 11, 2026
8defa55
shipped-files
mgravell Feb 11, 2026
58d2f98
Add additional documentation about client authentication (#3009)
mgravell Feb 11, 2026
98eb6a2
fixup release version
mgravell Feb 11, 2026
a2ac956
Investigate #3007; defensive code in maintenance events, and resubscr…
mgravell Feb 13, 2026
c0c3843
Propose CAS/CAD docs (#3012)
mgravell Feb 13, 2026
2a846a5
Add VRANGE support (#3011)
mgravell Feb 14, 2026
11af75b
release notes
mgravell Feb 19, 2026
d4b2f39
Handle MOVED error pointing to same endpoint. (#3003)
barshaul Feb 24, 2026
aa25c4c
fix time conversion error in HOTKEYS (#3017)
mgravell Feb 24, 2026
05c80ce
doomed test, needs thought
mgravell Feb 25, 2026
248ff15
stabilize -MOVED test (#3020)
mgravell Feb 25, 2026
b8ebdf7
release notes and ship-files for 2.8.11
mgravell Feb 25, 2026
bcf41c2
add test infrastructure for rich in-proc dummy servers (#3021)
mgravell Feb 25, 2026
939cc85
auth/hello
mgravell Feb 26, 2026
ac7ab7f
More powerful virtual test server for unit tests (#3022)
mgravell Feb 27, 2026
a098426
Add Entra ID Auth to Authentication doc (#3023)
philon-msft Mar 3, 2026
bc086f3
Implement pub/sub in the toy server (#3027)
mgravell Mar 9, 2026
ed0e353
Track the number of live multiplexers (#3030)
mgravell Mar 11, 2026
6f1dab4
fix main CI; v2 in-proc server is catastrophically unstable: `Catastr…
mgravell Mar 11, 2026
583f393
duplicated
mgravell Mar 11, 2026
6eeb04d
V3 pre-merge; all the early bits, for V2 (#3028)
mgravell Mar 13, 2026
bf7f846
2.12.1 release notes
mgravell Mar 13, 2026
f9af64f
Improve detection of connect/handshake failures and the retry-policy …
mgravell Mar 19, 2026
6f24522
Fix RESP3 client handshakes on non-RESP3 servers (#3037)
mgravell Mar 19, 2026
600119e
release notes 2.12.4
mgravell Mar 20, 2026
364b847
Filter out 'temporary placeholder' cluster nodes with a handshake fla…
TimLovellSmith Mar 25, 2026
ea5a640
Support multi-DB cluster usage on valkey (#3040)
mgravell Mar 25, 2026
8af9911
Implement GRCA (#3041)
mgravell Mar 25, 2026
b1a60d5
release notes 2.12.8
mgravell Mar 25, 2026
27a381c
Allow heartbeat to restart the pipe thread with only sync commands (#…
frobion Mar 26, 2026
1ca2456
fix merge conflict
mgravell Mar 26, 2026
934dd02
add v3 to CI
mgravell Mar 26, 2026
9281ca6
GitHubActions logger; exclude passed/skipped (#3045)
mgravell Mar 27, 2026
e43dd9b
Resolve critical failure in high-integrity-mode with -MOVED response …
mgravell Apr 2, 2026
0c58866
(version in release notes)
mgravell Apr 2, 2026
244ee3f
interpreting `server_mode` field (to support Valkey 8+ cluster) (#3050)
wipiano Apr 8, 2026
49d6326
Run tests using custom images, new composite action: run-tests (#3052)
Peter-Sh Apr 9, 2026
1081f0c
Provide basic modifiable throughput calculator (#3057)
mgravell Apr 20, 2026
6e5b950
GCRA: rename "requests" to "tokens" (reflect server change) (#3051)
mgravell Apr 21, 2026
2dab656
propose XNACK for 8.8 (#3058)
mgravell Apr 21, 2026
2b592a9
Propose ZUNION ... AGGREATE COUNT for 8.8 (#3059)
mgravell Apr 21, 2026
006cfaf
Recognize Azure Managed Redis in new clouds (#3068)
philon-msft May 6, 2026
89270ea
Support ZADD INCR (#3071)
mgravell May 8, 2026
d53a40c
Upgrade version of some packages needing system.memory (#3056)
jcaspes May 8, 2026
54e01e1
8.8 - subkey (hash field) notifications (#3062)
mgravell May 8, 2026
8e72ad4
Investigate (and fix) VADD CI failure (#3073)
mgravell May 8, 2026
46b60b3
Remove GCRA and stabilize CI (#3074)
mgravell May 8, 2026
1dbba36
post-ship 2.12.27
mgravell May 11, 2026
981ba52
AMR: use RESP3 and disable the default config channel by default (#3067)
mgravell May 12, 2026
d861b44
2.13.1 post-ship
mgravell May 12, 2026
dd18662
clarify AMR only
mgravell May 12, 2026
735c9b5
Move CI to 8.8 rc1 (#3079)
mgravell May 15, 2026
099548b
Draft support for 8.8 arrays (#3076)
mgravell May 15, 2026
4d12984
Don't serialize (ToString() or clone Protocol if it comes from the de…
mgravell May 19, 2026
2f9ae80
enable TCP keep-alives (#3078)
mgravell May 19, 2026
a5eca86
improve logging for ReadNotificationAsync
mgravell May 21, 2026
ce62271
stabilize CI for RetryPolicyFailureCases
mgravell May 21, 2026
3d1b0da
Fix incorrect routing of some sorted-set and stream commands (#3080)
mgravell May 21, 2026
bd2a816
post-ship 2.13.10
mgravell May 21, 2026
45b819d
CI fail; try updating test-reporter
mgravell May 22, 2026
2800b3a
Fix ARGREP NOCASE logic inversion and support ARINFO FULL (#3087)
mgravell May 22, 2026
48301dd
SENTINEL: defensive check around ROLE (#3088)
mgravell May 27, 2026
ce86434
8.8 add support for INCREX (#3065)
mgravell May 27, 2026
73cac33
Tear down connection on write failure to prevent queue desync (#3092)
Pranish-Pantha May 27, 2026
6e0df97
Fix platform-specific TCP keep-alive issues (#3090)
mgravell May 27, 2026
a3d7392
post-release 2.3.17
mgravell May 27, 2026
1b56c7d
Upgrade GitHub Actions versions (#3094)
uglide Jun 4, 2026
18b868e
Fix OperationCount calculation (#3095)
jnyrup Jun 7, 2026
0180afa
V3 combined (#3083)
mgravell Jun 22, 2026
a6c8fea
remove versionHeightOffset
mgravell Jun 22, 2026
534ca92
use MemoryPool<byte> sources for request/response buffering (#3107)
mgravell Jun 23, 2026
ed40e30
avoid unobserved task exceptions during connection teardown; see #310…
mgravell Jun 23, 2026
4cac13d
Update ReleaseNotes for version 2.13.17
mgravell Jun 23, 2026
8f47bf6
improve fault reporting in TouchIdleTimeAsync
mgravell Jun 23, 2026
466c4b7
Stabilize CI, especially on Windows (#3109)
mgravell Jun 24, 2026
145540d
post 3.0.7; update ship files
mgravell Jun 24, 2026
16bde35
support RedisValue backed by ReadOnlySequence (#3112)
pairbit Jun 25, 2026
596d3a5
add package logo (#3115)
mgravell Jun 26, 2026
eab8a35
Optimize RedisValue / reader logic by using canonical parser and new …
mgravell Jun 26, 2026
553cdba
post-release ship file update
mgravell Jun 29, 2026
cbbda97
Update RESP3 documentation for version support
mgravell Jun 29, 2026
afcc0dc
Fix error processing GeoResult (#3124)
mgravell Jul 10, 2026
b334dcf
Build tools: centralize code-gen indent handling in a CodeWriter (#30…
zhengyazhao Jul 10, 2026
51b2090
propose agents guidelines and skills (#3117)
mgravell Jul 10, 2026
0b03ed1
Throw a clear error when an Execute command contains whitespace (#3122)
arpitjain099 Jul 10, 2026
255678d
Allow reasonable CLIENT commands to proceed without admin mode enable…
mgravell Jul 21, 2026
6535119
Server 8.10 HIMPORT support (#3136)
mgravell Jul 27, 2026
4ac0f1a
fix: Queue batch commands to backlog during MOVED reconnection (#3134)
advaMosh Jul 27, 2026
544785c
fix(sentinel): re-elect primary on failover between already-known nod…
rebaseandpanic Jul 27, 2026
1d9308b
remove [Experimental] on established server features (#3137)
mgravell Jul 27, 2026
1720da5
Server 8.10 - LMOVEM, XREAD, XREADGROUP, SDIFFCARD, SUNIONCARD (#3135)
mgravell Jul 28, 2026
56ff9f9
update CI image; 2022 being super flakey (#3142)
mgravell Jul 29, 2026
817419b
update 8.10 test validation image (#3143)
mgravell Jul 29, 2026
c66cb65
shipfiles
mgravell Jul 29, 2026
ad623db
CI: stop dpkg starting redis-server on the Windows/WSL job (#3145)
mgravell Jul 30, 2026
06b2eef
3.1 - Client-side geographic failover (#3025)
mgravell Jul 31, 2026
bf8fac8
3.1 GA shipfiles etc
mgravell Jul 31, 2026
9d6cbb6
Update PackageReleaseNotes (#3146)
martincostello Jul 31, 2026
3cbf452
fix python multidb link (#3149)
mgravell Jul 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
117 changes: 117 additions & 0 deletions .claude/skills/implement-resp-command/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
---
name: implement-resp-command
description: Add a new Redis/RESP command (or overload) to StackExchange.Redis end-to-end — enum, interfaces, RedisDatabase implementation, ResultProcessor, public-API tracking, and the ResultProcessor + RoundTrip unit tests. Use when asked to "add/implement/support a Redis command", wire up a new RESP command, expose a server feature on IDatabase/IDatabaseAsync, or add a result processor.
---

# Implement a new RESP command

This walks through adding a command to **StackExchange.Redis** (the `src/StackExchange.Redis` client). Read `AGENTS.md` first — especially **Public API tracking → Backwards compatibility is paramount** and **Architecture**. Do every step; the build and the API analyzer will fail loudly if you skip the wiring, but the *tests* are what prove the command actually works.

Use an existing, similarly-shaped command as your template (e.g. `StringGet`/`GET` for a simple key command, `StreamAutoClaim`/`XAUTOCLAIM` for a structured aggregate reply). Grep `RedisDatabase.cs` for one and mirror it.

## Source the command's spec first

Before writing anything, get the command's exact argument order and reply shape — you need it for the `Message` (request bytes) and the `ResultProcessor` (reply parsing), and the round-trip test asserts both precisely.

- **Existing / released commands** are described in two authoritative places (substitute the command name, lower-case):
- **Server source, JSON spec** — e.g. `https://github.com/redis/redis/blob/unstable/src/commands/xdelex.json`. This is the most precise: argument tokens/order/optionality, `arity`, key specs, and the **`write`/`readonly` command flags** (which directly tell you the `IsPrimaryOnly` classification) plus, often, a `reply_schema`.
- **HTML docs** — e.g. `https://redis.io/docs/latest/commands/xdelex/`. More readable, with reply examples.
- (For non-Redis targets the equivalents are the Valkey/Garnet/etc. source and docs — but the wire command is usually identical.)
- **Module commands** (RediSearch `FT.*`, RedisJSON `JSON.*`, RedisTimeSeries `TS.*`, RedisBloom, …) live in each module's own repo, usually as a single aggregated `commands.json` (e.g. RediSearch: `https://github.com/RediSearch/RediSearch/blob/master/commands.json`) rather than core Redis's one-file-per-command layout. Use it the same way for argument/reply shape. **But module commands are generally handled by separate companion libraries (e.g. [NRedisStack](https://github.com/redis/NRedisStack)), not core StackExchange.Redis** — so usually you won't add them here at all; ad-hoc use goes through the generic `Execute`/`ExecuteAsync(string command, …)` → `RedisResult` API. If you *do* wire one as first-class, note the wire token is dotted (`FT.SEARCH`) and a C# enum member name can't contain `.`; the token for a member whose name isn't a valid identifier is supplied via the `[AsciiHash("FT.SEARCH")]` override — see `eng/StackExchange.Redis.Build/AsciiHash.md`. Confirm that a first-class typed binding is actually intended before following the enum steps below.
- **New / unreleased commands** may not be in either yet. In that case **ask the user for the spec** — the exact argument order and a concrete sample request/reply (RESP bytes if possible) — rather than guessing; the round-trip and ResultProcessor tests are only as correct as that sample.
- **RESP2 vs RESP3:** the reply (and occasionally argument handling) can differ subtly between protocols — e.g. a map/`%` vs a flat `*` array, a double/`,` vs a bulk-string number, or added attributes. The JSON `reply_schema` sometimes distinguishes them. Capture **both** forms and handle them in the `ResultProcessor` (and cover both in the unit tests).

## Steps

1. **Add the command name to the `RedisCommand` enum** — `src/StackExchange.Redis/Enums/RedisCommand.cs`. The enum member name *is* the wire token (`CommandMap` serializes it via `command.ToString()`), so name it exactly as Redis expects (e.g. `GETEX`, `XAUTOCLAIM`). Keep the existing alphabetical grouping.
- **Then classify it in `IsPrimaryOnly`** (the `switch` in the same file). That switch is **exhaustive** — its `default` *throws* `ArgumentOutOfRangeException` (*"Every RedisCommand must be defined in Message.IsPrimaryOnly…"*) at runtime for any unlisted command, so this is not optional. Put writes/mutations in the primary-only list; pure reads fall through to the replica-eligible branch. Getting it wrong mis-routes the command (e.g. a write sent to a replica).

2. **Declare the method on the interfaces** — `src/StackExchange.Redis/Interfaces/IDatabase.cs` *and* `IDatabaseAsync.cs` (or the `.Arrays.cs` / `.VectorSets.cs` partials when relevant). Always provide both sync and async.
- **Back-compat:** never add an optional parameter to an existing shipped method (binary break → `MissingMethodException`). Add a new **overload** instead; see `AGENTS.md`.
- **Additive-overload trick (avoids ambiguity):** if the shipped method has an all-optional tail (e.g. `Foo(key, int? count = null, CommandFlags flags = CommandFlags.None)`), a new overload that just appends more optional params (`Foo(key, int? count = null, int? extra = null, CommandFlags flags = ...)`) is **ambiguous** for existing calls like `Foo(key, 5)` — both candidates substitute a default, so neither is "better" (compile error `CS0121`, and the analyzer flags `RS0026`). The fix: **make the existing overload's parameters non-optional (remove the `= ...` defaults) and let the new overload carry all the optionals.** Removing a default is binary-safe (the IL signature is unchanged) and source-safe (old calls simply rebind to the new all-optional overload, which is functionally identical). Do this consistently across the interface *and* every implementor (`RedisDatabase`, `KeyPrefixed`/`KeyPrefixedDatabase`), and update the changed signatures in **`PublicAPI.Shipped.txt`** (optional→required is an edit-in-place there; the new all-optional overload goes in `PublicAPI.Unshipped.txt`). Wrap the new overload in `#pragma warning disable RS0026` since the analyzer still flags competing optional-param overloads even when they're unambiguous. Watch for the "richest" existing overload living in a sibling partial (e.g. `IDatabaseAsync.VectorSets.cs`).
- **Implement the new member on every `IDatabase`/`IDatabaseAsync` implementor**, or the build breaks. Chiefly `KeyspaceIsolation/KeyPrefixedDatabase.cs` — and there it must prefix keys via `ToInner(key)`; a stub that forwards without prefixing compiles but **silently breaks keyspace isolation** for the new command. If the command should also be usable in batches/transactions, add it to `IBatch`/`ITransaction` and their implementations (`RedisBatch`/`RedisTransaction`/`KeyPrefixedBatch`) too.

3. **Implement in `RedisDatabase.cs`** (next to the template you picked). The standard shape:
```csharp
public RedisValue StringGet(RedisKey key, CommandFlags flags = CommandFlags.None)
{
var msg = Message.Create(Database, flags, RedisCommand.GET, key);
return ExecuteSync(msg, ResultProcessor.RedisValue);
}
public Task<RedisValue> StringGetAsync(RedisKey key, CommandFlags flags = CommandFlags.None)
{
var msg = Message.Create(Database, flags, RedisCommand.GET, key);
return ExecuteAsync(msg, ResultProcessor.RedisValue);
}
```
For argument shapes `Message.Create` doesn't cover (optional tokens, variadic args, multiple round-trips), write a private `Message` subclass overriding `WriteImpl` (search `RedisDatabase.cs` for `: Message` and `GetStringGetExMessage` for examples), or an `IMultiMessage`.

4. **Pick or write the `ResultProcessor<T>`** — `src/StackExchange.Redis/ResultProcessor.cs`. Reuse an existing one if the reply shape matches (`RedisValue`, `RedisValueArray`, `Int64`, `Boolean`, `Lease`, …). Otherwise add a nested `internal sealed class XProcessor : ResultProcessor<T>` overriding `SetResult(PhysicalConnection, Message, ref RespReader)` to parse the reply with the `RespReader`, and expose it as a `public static readonly` field. Handle RESP2 vs RESP3 and older-server reply variants here.

5. **New result types** go in `src/StackExchange.Redis/APITypes/` (mirror `StreamAutoClaimResult` etc.).

6. **Update public-API tracking** — add every new public member to `PublicAPI.Unshipped.txt` (and the `net6.0/` subfolder if the API only exists on newer TFMs). The build error tells you the exact line. See `AGENTS.md`.

7. **Write the two unit-test layers** (below). These run with **no external server**, so they're the fast, reliable proof of correctness — write them even if you also add live integration tests.

8. **Gate pre-release server features** behind `[Experimental(Experiments.Server_8_x)]` when appropriate (see `src/RESPite/Shared/Experiments.cs`).

## Tests — the two layers that matter

### ResultProcessor unit test (parsing in isolation)

Proves your `ResultProcessor` turns raw RESP bytes into the right typed value. Add a class under `tests/StackExchange.Redis.Tests/ResultProcessorUnitTests/` deriving `ResultProcessorUnitTest`; feed handcrafted RESP wire strings to `Execute(resp, ResultProcessor.X)` and assert on the result; use `ExecuteUnexpected(resp, ...)` for replies that must fail. Model it on `ResultProcessorUnitTests/StreamAutoClaim.cs`:

```csharp
public class MyCommand(ITestOutputHelper log) : ResultProcessorUnitTest(log)
{
[Fact]
public void Basic_Success()
{
var resp = "*2\r\n$3\r\n0-0\r\n*0\r\n"; // hand-built RESP reply
var result = Execute(resp, ResultProcessor.MyCommand);
Assert.Equal("0-0", result.NextStartId.ToString());
}

[Fact]
public void WrongShape_Failure() => ExecuteUnexpected("$5\r\nhello\r\n", ResultProcessor.MyCommand);
}
```
Cover the cases that actually bite: RESP2 **and** RESP3 forms, empty arrays, null (`$-1`/`*-1`), older-server reply shapes (e.g. a 2-element vs 3-element reply across versions), and at least one malformed reply via `ExecuteUnexpected`.

### RoundTrip unit test (full write + read, still no server)

Proves the command **serializes to the exact bytes** Redis expects *and* parses back correctly, exercising `Message.WriteTo` + the command-map. Add to `tests/StackExchange.Redis.Tests/RoundTripUnitTests/` using `TestConnection.ExecuteAsync(message, processor, requestResp, responseResp, ...)`, which asserts the outbound RESP equals `requestResp` and then feeds `responseResp` back through the processor. See `RoundTripUnitTests/AdhocMessageRoundTrip.cs`:

```csharp
[Theory(Timeout = 1000)]
[InlineData("hello", "*2\r\n$4\r\nECHO\r\n$5\r\nhello\r\n")]
public async Task MyCommand_RoundTrips(string payload, string requestResp)
{
var msg = /* build the Message exactly as RedisDatabase does */;
var result = await TestConnection.ExecuteAsync(msg, ResultProcessor.MyCommand, requestResp, ":5\r\n", log: log);
Assert.Equal(5, result.AsInt32());
}
```
Verify the precise outbound bytes (length prefixes included), and ideally that command-map **rename** and **disable** behave (the `MapMode` pattern in that file).

### Optional: live integration test

Only if you need to prove behavior against a real server — these need the docker Redis topology (see `AGENTS.md → Testing topology`). An **absent** server is skipped automatically by the test infrastructure, so you don't write code for that.

What you *do* need to handle for a new command is **server version**: most new commands are new server features, and the test must skip as inconclusive on servers too old to support them. Use the `require:` parameter when creating the connection — it connects and auto-skips when the live server is below the threshold:

```csharp
await using var conn = Create(require: RedisFeatures.v7_4_0_rc1);
var db = conn.GetDatabase();
// ... exercise the command ...
```
Pick the `RedisFeatures.vX_Y_Z` constant matching the version that introduced the command (see `HashFieldTests.cs` / `CopyTests.cs` for the pattern). If your command needs a version threshold that doesn't exist yet, add the constant to `RedisFeatures`. This keeps the suite green across the range of server versions CI and contributors run against.

The in-process managed server (`toys/StackExchange.Redis.Server`) may also need a handler if integration tests run against it.

## Before finishing

- `dotnet build Build.csproj -c Release /p:CI=true` — analyzers + `TreatWarningsAsErrors` must pass (this catches a missing `PublicAPI.Unshipped.txt` entry).
- `dotnet test tests/StackExchange.Redis.Tests/StackExchange.Redis.Tests.csproj -f net10.0 --filter "FullyQualifiedName~MyCommand"` — runs your new unit tests without any server.
- Double-check no shipped signature changed (back-compat).
Loading