A Redis server clone written in Go from scratch, no external dependencies. Implements a raw TCP server, a wire protocol parser, and a command dispatcher.
make run
Starts on :8091. Change the port with -port:
go run ./cmd/server -port 6380
Then connect with nc/telnet and type commands, one per line:
$ nc localhost 8091
PING
+PONG
SET foo bar
+OK
GET foo
$3
bar
Connect to the server using the official Redis CLI.
➜ redis-clone git:(main) ✗ redis-cli -p 8091
127.0.0.1:8091> SET hi "ryan"
OK
127.0.0.1:8091> GET hi
"ryan"
127.0.0.1:8091>
There's also an MCP server so tools like Claude Code can hit the store directly instead of you typing commands by hand.
go run ./cmd/mcp-server -redis-addr localhost:8091
Register it with Claude Code:
claude mcp add redis-clone -- go run /path/to/redis-clone/cmd/mcp-server -redis-addr localhost:8091
Gives you get, set, delete, keys, info as tools. See
cmd/mcp-server/README.md for the full rundown.
PING, ECHO <msg>, GET <key>, SET <key> <value>, EXISTS <key>,
DEL <key> [key ...], FLUSH. Command names are case insensitive.
The server reads whichever protocol the client sends. If a request starts
with * it's parsed as real RESP (arrays of bulk strings), the format
redis-cli and other real Redis clients use. Anything else is parsed as
plain space-separated text, one command per line, which is what makes the
nc/telnet usage above possible.
The inline text form has no support for quoted arguments, SET foo "two words" just looks like too many args and errors out. RESP requests don't
have that limitation since each argument is length-prefixed.
Responses are always encoded in real RESP regardless of which form the request came in as.
make test
make race
make vet
make fmt
Single test:
go test ./internal/resp -run TestParseRESP_BulkString -v
go test ./internal/command -run TestHandleSetGet_RoundTrip -v
internal/resp- parsing.ReadRequestpicks betweenParseSimple(the inline protocol) andParse/Encode(real RESP) based on the first byte of the request.internal/command-Handlers.Dispatchroutes a request to a handler and encodes the result. Also holds the store, a map guarded by a mutex.internal/server- accepts connections, one goroutine per connection, each reading a request, dispatching it, and writing the response back.cmd/mcp-server- exposes this server as an MCP server, see its README.
- AOF persistence
- append every write command to log on disk
- write, fsync
- replay aof commands on startup
- configurable policies
- always: log after every write
- everysec: once per sec
- impl PX, EX options in SET
- benchmark
- test diff policies and scenarios for aof, tradeoffs and optimizations
- profiling
- pipeline support
- testing
- concurrent stress tests
- race tests
GPLv3, see LICENSE.