Redis IntelliSense built from the server's COMMAND DOCS

Redis completion that reads the server's COMMAND DOCS: fitting options, subcommands, key names, and hover cards with Write and Destructive badges.

By Updated

The short version

Redis IntelliSense that asks the server what it knows.

A Redis query tab in SQLly now completes command names, the options that fit where the caret is, subcommands and key names, and it shows each command's syntax on hover with a Write, Destructive or Blocking badge. The vocabulary comes from the connected server's own COMMAND DOCS and COMMAND INFO, so Redis Stack modules and server-specific commands complete too. When the server can't answer, a bundled Redis 7.4 snapshot takes over.

Why not a hard-coded list

The obvious way to build Redis completion is to ship a list of commands. It works until you connect to something that isn't the Redis version the list was written for: a Stack server with JSON.*, FT.* and TS.*, a Valkey build with its own additions, a module you loaded yourself, or an older server that lacks commands the list assumes. Then completion either offers commands that don't exist or misses the ones you came for.

Redis 7 can describe itself. COMMAND DOCS returns each command's summary, the version it appeared in, its complexity and a structured argument tree, with tokens, optional blocks and mutually exclusive groups. COMMAND INFO returns its flags (readonly, write, admin…) and where its keys are. That is enough to build completion, hover and signature help from the server you're actually on, so that's what SQLly does.

Where the vocabulary comes from

On connect, SQLly runs a read-only virtual command, SQLLY.COMMANDS, which returns the server's COMMAND DOCS and COMMAND INFO as rows, one per command. The editor parses those rows into its vocabulary. Commands the server doesn't list aren't offered, except SQLly's own SQLLY.* virtual commands, which are always included.

There are two cases where the server can't answer:

  • An ACL user without +command is refused COMMAND.
  • A server older than Redis 7.0 has no COMMAND DOCS.

For both, SQLly falls back to a bundled snapshot. The snapshot is generated by a script from the live COMMAND DOCS and COMMAND INFO of Redis 7.4 and Redis Stack, and it holds more than 400 commands, so completion always works.

The snapshot needed one hand-written supplement. RediSearch registers its commands without documentation: they report only group=module, with no summary and no arguments. So the generator merges hand-maintained entries for the FT.* family (and a few commands no fixture serves, such as RedisGraph's and the deprecated FT.DROP) into the snapshot. A test checks that FT.SEARCH has a summary and that its syntax starts FT.SEARCH index query.

KeyDB: the KeyDB image we tested reports a Redis 6.3.4 compatibility level and has no COMMAND DOCS, so on KeyDB completion uses the bundled Redis 7.4 snapshot. A command KeyDB lacks can still be offered there; the server's own error tells you when you run it.

What you get as you type

Command names

Start a line and the popup narrows as you type, with each command's one-line summary beside it. Commands you've accepted before in this session come first. Otherwise the data-structure commands (strings, hashes, lists, sets, sorted sets, streams) lead and the administrative ones follow.

HSE|        β†’  HSET, HSETNX
js|         β†’  JSON.ARRAPPEND, JSON.GET, JSON.SET, …   (on Redis Stack)

Press Ctrl+Space (Cmd+Space on macOS) on a blank line to browse every command.

Options in the right position

After the command, the popup follows the documented argument tree, so it knows what can come next, not just which words exist:

ZRANGE k 0 -1 |       β†’  BYSCORE, BYLEX, REV, LIMIT, WITHSCORES
ZRANGE k 0 -1 LIMIT | β†’  (nothing: the next word is a number you type)

Options that can't be combined drop out once one is chosen. SET's expiry options are one exclusive group, so after

SET k v EX 10 |       β†’  GET, NX, XX

That is the whole list. KEEPTTL, PX and the other expiry options are gone, because EX already took that slot, and what's left is the condition (NX / XX) and GET. The popup doesn't offer the option that would turn the line into a syntax error. After a complete GET k, nothing is offered at all.

Subcommands

Container commands offer their subcommands:

XINFO |     β†’  CONSUMERS, GROUPS, HELP, STREAM
CONFIG G|   β†’  GET

Key names, without scanning anything

Where a command takes a key, the popup offers key names the Server Explorer has already scanned for the tab's logical database, with each key's type. Expand a database or a key folder in the explorer, then:

GET us|     β†’  user:1, user:2, users:all   (each with its type)

Names that need quoting (spaces, quotes) are inserted quoted. The popup never runs a SCAN of its own. It only reuses what the explorer already listed. Typing should never walk the keyspace of a busy production server, and with this design it can't.

Screenshot to comeredis-intellisense-zrange-options.webp β€” a Redis query tab with ZRANGE k 0 -1 typed and the completion popup listing BYSCORE, BYLEX, REV, LIMIT and WITHSCORES with their summaries
After ZRANGE k 0 -1 the popup offers only the options that can come next.
Screenshot to comeredis-intellisense-key-names.webp β€” a Redis query tab with GET us typed and the popup listing key names from the explorer's scan (user:1, user:2, users:all) with each key's type, the expanded explorer folder visible beside it
Key names come from what the explorer already scanned for this database. Nothing is scanned for the popup.

Hover cards that agree with the Run gate

Rest the pointer on a command and the card shows its documented syntax, summary, the version it appeared in and its complexity. The card also shows a safety verdict:

  • Write for commands that change keys or state (SET k v).
  • Destructive for FLUSHALL, DEL, CONFIG SET and friends.
  • Blocking, with the reason, for a line that would never answer on a query connection, such as SUBSCRIBE news or BLPOP q 0.

These badges are not a second opinion. They come from the same safety classification the Run gate applies, the one behind read-only connections and the production lock. The blocking verdict looks at the arguments, not just the name: BLPOP q 0 waits forever and is badged Blocking, while BLPOP q 5 returns within five seconds and only gets the Write badge. You find out what a line will do before you press Run, and the answer is the one Run will give.

Hovering an option word such as WITHSCORES explains which argument it belongs to. While the caret is on a command line, signature help shows the whole syntax above it, with the argument you're typing highlighted:

ZRANGE key start stop [BYSCORE | BYLEX] [REV] [LIMIT offset count] [WITHSCORES]

Esc hides it for that line. Both follow the editor's "Show hover info" and "Show signature help" preferences.

Screenshot to comeredis-intellisense-flushall-hover.webp β€” the hover card on FLUSHALL in a Redis query tab showing its syntax, summary, since-version, complexity and the Destructive badge
The hover card carries the same verdict the Run gate will apply.

Keeping two lists honest

The safety classifier has its own lists: commands known to be read-only, and commands treated as destructive. The IntelliSense vocabulary is a third source of truth about the same commands. Two lists that describe the same thing drift apart unless something forces them to agree, so one test does:

  • Every command on the safety classifier's read-only and destructive lists must exist in the bundled vocabulary. A command one side knows and the other doesn't fails the test.
  • No command on the read-only list may carry the write flag in the server's own COMMAND INFO. If Redis says it writes, SQLly can't call it read-only.

A second test pins the badges to the classifier: FLUSHALL is Destructive, SET k v is Write, GET k has no badge, and BLPOP q 0 and SUBSCRIBE news are Blocking. If someone changes one side, the mismatch fails in CI instead of showing up as a user staring at a "read-only" badge on a command that just deleted something.

Fast on long scripts

Redis scripts are one command per line, so completion, hover and signature help only look at the caret's line. A 5,000-line script costs about the same as a one-line one. A test builds a 5,000-line script of HSET lines and requires two completion passes (one in the middle, one at the end), a hover and a signature lookup to finish in under 5 ms together.

HSET user:0 name "user 0" age 0
HSET user:1 name "user 1" age 1
…                                    (5,000 lines)
ZRANGE k 0 -1 |

Things that stay off

The SQL formatter, SQL validation and the SQL lints are off for Redis tabs. A command script isn't SQL, and Validate checks the command lines instead. The F2 "improve IntelliSense" report works on a Redis popup the same way it does on SQL, so a miss can become a test. The command-line tool, sqlly-cli intellisense complete-enriched, accepts Redis scripts with dialect redis and takes key names as objects of kind key.

Limits

  • On servers that refuse COMMAND, predate 7.0, or have no COMMAND DOCS (KeyDB), you get the Redis 7.4 and Stack snapshot, not the server's own list.
  • Key names are only as fresh as the explorer's last scan of that database. Expand or refresh the folder to update them.
  • Completion follows the server's command list, not your connection's topology. On a cluster connection, Run refuses cross-slot multi-key commands, SELECT other than 0, KEYS, SCAN and MULTI/EXEC with a message naming the rule.

The reference is on Redis command IntelliSense. Download SQLly, open a query tab on a Redis or Valkey connection, and type ZRANGE k 0 -1 to see it.