feat: add Try It button to CLI code examples#3380
Conversation
Adds a 'Try it' button to code examples that opens redis.io/cli with pre-populated commands and autorun enabled. - Extracts CLI commands from shortcode inner content (lines with '> ' or 'redis> ' prefix) - Renders a red 'Try it' button in the codetabs header - Button only visible when the Redis CLI tab is selected - Clicking opens https://redis.io/cli?commands=[...]&autorun=true in a new tab
🛡️ Jit Security Scan Results✅ No security findings were detected in this PR
Security scan by Jit
|
HTML data attributes with JSON values suffer from double-escaping issues in Hugo (jsonify returns template.HTML, htmlEscape returns string which Hugo then re-escapes). Moving the commands to a JavaScript object (window._tryItCommands) populated via safeJS avoids all escaping issues.
Use printf with safeHTMLAttr to produce the complete attribute key-value pair, preventing Hugo's contextual auto-escaping from double-encoding the htmlEscape output. This matches the correct Hugo pattern for embedding JSON in HTML attributes.
JSON-stringified commands produced repeated %5C%22 sequences in the URL after encodeURIComponent, which Cloudflare's managed SQLi/XSS-bypass rules flagged, returning a 'you have been blocked' page instead of the CLI. Encode the JSON payload as URL-safe base64 (no padding) before placing it in the commands query parameter, and add a getCommandsFromUrl helper in cli.js that decodes the payload when autorun=true is set.
|
This change adds a https://redis.io/docs/staging/DOC-6675/develop/data-types/strings/#set_get?lang=redis-cli |
|
@paoloredis It would definitely be useful to have a feature to run CLI examples like this. However, the commands don't seem to appear in the CLI page when you go to it (you get a working prompt, but it just doesn't seem to receive the commands in the example). Also, we've already got those interactive CLIs that work within the page (eg, https://redis.io/docs/latest/commands/set/#examples). Is there a way we could incorporate those into the CLI tab so that the CLI example just works the same as the client lib examples? |
I tried this example,
We have both the TCE and CLI widget on some command pages, though we could certainly change that. One other thought... a lot of examples aren't complete (for example, they rely on a dataset that might not be present in the fenced code block), so this can't really be global. |
|
@dwdougherty Did you try that in a local build? Maybe it's just the staging that doesn't show the command correctly. Also, regarding the missing dataset issue, maybe we could have hidden sections in the CLI text to set the data up? They wouldn't be shown in the page but still get run during an interactive session. |
|
@andy-stark-redis I forget to include the URL (I just added it to my comment). I used a staging link that @paoloredis gave to me in Slack. Er... okay, it's there now. 🫠 |
|
@andy-stark-redis is it working for you now? so are you suggesting we make the redis cli examples in the tabbed code examples interactive, without the external button taking you to redis.io/cli ? |
Yes, the staging link works fine now, thanks.
Yeah, I'm just thinking that the system we've got for the client examples where they can run in the page is really nice. If the in-page client examples rely on a Jupyter kernel behind the scenes then I guess one (crazy) idea might be to implement our own Jupyter kernel for Redis CLI commands? Probably not all that far-fetched when we've got our AI friends to do the work :-) Anyway, TBH, it's really good just to have the "Try it" button you've already implemented, so I'd certainly approve going ahead with that. I just thought I'd throw in a few ideas while we're thinking about it. |
|
@paoloredis @dwdougherty OK, I've had Claude look into this and it turns out you can add new "magic" commands to a notebook quite easily (you start off with Python and register Python handlers for the commands). So, we could have essentially a Python notebook with something like this in the first cell: Then, in subsequent cells we would have: I don't know if this is more trouble than it's worth, but possibly worth exploring if it enables in-page examples for CLI? |
- Render the redis-cli tab in clients-example blocks as an interactive form.redis-cli terminal instead of a static highlighted code block - Load cli.js on develop single pages so the terminals initialize - Guard codetabs copy button against interactive cli panels (no <code>), copying commands from data-cli-source instead - Add Try It button to the redis-cli shortcode header bar
|
@andy-stark-redis @dwdougherty I've now modified the tabbed code examples so that redis-cli code is executable. What do you think? This means that some pages like redis.io/docs/commands/hget/ will need to be updated to only include the tabbed code example. With this feature should we keep the "Try it" button or maybe not? |
That's basically what I was thinking of. I'd say that looks really neat now :-)
If we go ahead with the notebooks then maybe it could just say "Run in browser" like the others? I guess having links to redis.io/cli is a good idea though, since it's a nice feature. Maybe we could have a link in the footer? ("Try online or check out our other client tools...") |
|
To be honest I'm not really sure I see the point in having a jupyter notebook for the redis cli commands. |
|
@andy-stark-redis, @paoloredis: do you want me to go ahead and remove the CLI widget from pages that also have TCEs? It's only a handful of command pages: AUTH,DEL,EXISTS,EXPIRE,FLUSHALL,GET,HDEL,HEXPIRE,HGET,HGETALL,HMGET,HSET,HVALS,INCR,INFO,KEYS,LLEN,LPOP,LPUSH,LRANGE,MGET,RPOP,RPUSH,SADD,SCAN,SET,SMEMBERS,TTL,XADD,ZADD,ZRANGE |
I think the CLI widgets sometimes have different commands from the ones used in the nearby TCEs (eg, here)? The TCEs don't have Redis CLI tabs in those cases, so you'd need to create a new CLI example corresponding to the client code. So, only a handful of pages but maybe a big-ish job. However, if you're up for it then I think it would tidy those pages up very nicely. |
…ngs via JSON.stringify
Deduplicate the standalone redis-cli widgets that repeated commands already present in the tabbed clients-example. For pages where the tabbed example lacked the CLI commands (get, set), merge them into the tabbed example. Add '>' prefixes on hexpire, hdel, info, and exists so their interactive CLI tab runs only commands.
I've addressed this now @andy-stark-redis @dwdougherty |
|
@paoloredis Awesome - thanks for all your work on this :-) |
The interactive redis-cli widgets previously shared a single module-level session id, but each widget's auto-run fired in parallel with an undefined id, so the backend forked them into separate sessions and the global id kept only the last responder. Typed commands then ran against the wrong session (e.g. INCREX mykey1 resetting to 1 on the multi-widget increx page). Serialize all requests through a queue so the first establishes the session id and every subsequent auto-run or typed command reuses it. All widgets on a page (tabbed examples and standalone snippets) now share one namespace: auto-run data accumulates into a single database and users can query or extend it from any widget.
Introduce two clients-example params: prereq="true" marks a block as its set's setup cell, and needs_prereq="true" makes that block's Try-it replay only the set's prerequisite commands (via window._tryItPrereqs[set]) before its own, instead of the full transitive buildsUpon chain. buildsUpon is retained for the markdown/LLM "Builds upon" exports and as the legacy fallback for blocks without needs_prereq. Apply to develop/data-types/json/path: mark set_bikes as prereq and flag every dependent example with needs_prereq.
Try-it now seeds the CLI session solely from the explicit prereq model (prereq / needs_prereq); data-builds-upon is treated as metadata only (AI/markdown export) and is no longer walked by openTryItCli. Also drop the spurious buildsUpon="set_get" from the strings incr and mset examples, which are self-contained and don't depend on bike:1.
Restore buildsUpon="set_get" on the strings incr and mset examples; keep them unchanged as metadata. Try-it behaviour is unaffected since openTryItCli no longer consults buildsUpon.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 0f3112e. Configure here.
| the regular expression pattern `"(?i)al"`: | ||
|
|
||
| {{< clients-example set="json_tutorial" step="filter3" description="Regex filters: Use =~ operator with regular expressions in filter expressions to match patterns in string values when you need flexible pattern-based filtering" difficulty="advanced" buildsUpon="filter2" >}} | ||
| {{< clients-example set="json_tutorial" step="filter3" description="Regex filters: Use =~ operator with regular expressions in filter expressions to match patterns in string values when you need flexible pattern-based filtering" difficulty="advanced" buildsUpon="filter2" needs_prereq="true" >}} |
There was a problem hiding this comment.
Try It hidden without prefixes
Low Severity
This PR adds needs_prereq="true" to the filter3 example, but its inner lines still lack > / redis> prefixes, so $tryItCommands stays empty, the Try it button is not rendered, and external Try it cannot prepend the set’s prerequisite commands despite the new attribute.
Reviewed by Cursor Bugbot for commit 0f3112e. Configure here.
| .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); | ||
| const url = 'https://redis.io/cli?commands=' + b64 + '&autorun=true'; | ||
| window.open(url, '_blank', 'noopener,noreferrer'); | ||
| }; |
There was a problem hiding this comment.
Duplicate openTryItCli definition
Low Severity
openTryItCli is defined in both tabs/wrapper.html (prerequisite-aware) and the redis-cli shortcode (commands only). Whichever inline script runs first wins via ||, so pages mixing both can lose prereq handling for Try it without an obvious link between the two copies.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 0f3112e. Configure here.


Adds a 'Try it' button to code examples that opens redis.io/cli with pre-populated commands and autorun enabled.
Note
Low Risk
Documentation and front-end UX only; no server or auth changes, with moderate surface area in Hugo partials and client JS.
Overview
Adds a Try it control on tabbed and standalone CLI examples that opens
redis.io/cliwith URL-safe base64-encoded command lists andautorun=true, shown only when the redis-cli language tab is active. Try it seeding uses an explicitprereq/needs_prereqmodel per example set (notbuildsUpon).Command docs drop duplicate
redis-clishortcode blocks in favor ofclients-exampleinner content with>/redis>lines; GET/SET move CLI output into those blocks. The redis-cli codetab becomes an inline interactive terminal (form.redis-cli+ deferredcli.json develop pages), with copy handling for that form.cli.jsuses one queued shared session across widgets; JSONPath tutorial steps wireprereq="true"on setup andneeds_prereq="true"on dependent steps.Reviewed by Cursor Bugbot for commit 0f3112e. Bugbot is set up for automated code reviews on this repo. Configure here.