Upstash Redis Key-Value Store
Interact with Upstash's Redis-compatible key-value store using the REST interface.
Script Location
bun run scripts/upstash-client.ts <command> [args...]
IMPORTANT: Always run with bun run , not directly.
Configuration
Environment Variables
The script uses these environment variables by default:
-
UPSTASH_REDIS_REST_URL
-
The Upstash REST API URL
-
UPSTASH_REDIS_REST_TOKEN
-
The Upstash REST API token
Overriding Credentials
If the user provides credentials from another source (conversation context, a file, etc.), use the --url and --token flags to override environment variables:
bun run scripts/upstash-client.ts --url "https://..." --token "AX..." GET mykey
Priority: Command-line flags > Environment variables
Command Reference
String Commands
Get/Set
GET <key> SET <key> <value> [--ex seconds] [--px ms] [--nx] [--xx] [--keepttl] [--get] SETNX <key> <value> # Set if not exists SETEX <key> <seconds> <value> # Set with expiration
Multiple keys (key/value pairs)
MGET <key1> [key2...] MSET <key1> <val1> [key2 val2...] MSETNX <key1> <val1> [key2 val2...] # Set all if none exist
Counters
INCR <key> INCRBY <key> <increment> INCRBYFLOAT <key> <increment> DECR <key> DECRBY <key> <decrement>
String manipulation
APPEND <key> <value> STRLEN <key> GETRANGE <key> <start> <end> SETRANGE <key> <offset> <value>
Hash Commands
Hashes store field-value pairs. Pass fields and values as alternating arguments:
Set hash fields (field/value pairs)
HSET <key> <field1> <val1> [field2 val2...] HSETNX <key> <field> <value> # Set field if not exists
Get hash fields
HGET <key> <field> HMGET <key> <field1> [field2...] HGETALL <key>
Hash operations
HDEL <key> <field1> [field2...] HEXISTS <key> <field> HKEYS <key> HVALS <key> HLEN <key> HINCRBY <key> <field> <increment> HINCRBYFLOAT <key> <field> <increment> HSCAN <key> <cursor> [MATCH pattern] [COUNT count]
Examples:
Store user data
bun run scripts/upstash-client.ts HSET user:1 name "John" email "john@example.com" age 30
Get single field
bun run scripts/upstash-client.ts HGET user:1 name
Get all fields
bun run scripts/upstash-client.ts HGETALL user:1
Increment numeric field
bun run scripts/upstash-client.ts HINCRBY user:1 age 1
List Commands
Lists are ordered collections. Values are pushed/popped from left (head) or right (tail):
Push elements
LPUSH <key> <val1> [val2...] # Push to head RPUSH <key> <val1> [val2...] # Push to tail LPUSHX <key> <val1> [val2...] # Push if list exists RPUSHX <key> <val1> [val2...]
Pop elements
LPOP <key> [count] RPOP <key> [count]
Access elements
LRANGE <key> <start> <stop> # Get range (0 = first, -1 = last) LLEN <key> LINDEX <key> <index>
Modify
LSET <key> <index> <value> LREM <key> <count> <value> # Remove count occurrences LTRIM <key> <start> <stop> # Keep only range LINSERT <key> <BEFORE|AFTER> <pivot> <value> LPOS <key> <value> LMOVE <src> <dst> <LEFT|RIGHT> <LEFT|RIGHT>
Examples:
Create a task queue
bun run scripts/upstash-client.ts RPUSH tasks "task1" "task2" "task3"
Get all tasks
bun run scripts/upstash-client.ts LRANGE tasks 0 -1
Pop task from front (FIFO queue)
bun run scripts/upstash-client.ts LPOP tasks
Pop task from back (LIFO stack)
bun run scripts/upstash-client.ts RPOP tasks
Set Commands
Sets store unique, unordered members:
Add/remove members
SADD <key> <member1> [member2...] SREM <key> <member1> [member2...]
Query
SMEMBERS <key> SISMEMBER <key> <member> SMISMEMBER <key> <member1> [member2...] SCARD <key>
Random access
SPOP <key> [count] SRANDMEMBER <key> [count]
Set operations
SINTER <key1> [key2...] SINTERSTORE <dest> <key1> [key2...] SUNION <key1> [key2...] SUNIONSTORE <dest> <key1> [key2...] SDIFF <key1> [key2...] SDIFFSTORE <dest> <key1> [key2...] SMOVE <src> <dst> <member> SSCAN <key> <cursor> [MATCH pattern] [COUNT count]
Examples:
Add tags
bun run scripts/upstash-client.ts SADD article:1:tags "javascript" "redis" "nodejs"
Check membership
bun run scripts/upstash-client.ts SISMEMBER article:1:tags "javascript"
Get all members
bun run scripts/upstash-client.ts SMEMBERS article:1:tags
Find common tags between articles
bun run scripts/upstash-client.ts SINTER article:1:tags article:2:tags
Sorted Set Commands
Sorted sets store members with scores for ranking:
Add members (score/member pairs)
ZADD <key> <score1> <member1> [score2 member2...] [--nx] [--xx] [--gt] [--lt] [--ch]
Remove
ZREM <key> <member1> [member2...] ZREMRANGEBYRANK <key> <start> <stop> ZREMRANGEBYSCORE <key> <min> <max>
Scores and ranks
ZSCORE <key> <member> ZMSCORE <key> <member1> [member2...] ZRANK <key> <member> # Rank (low to high) ZREVRANK <key> <member> # Rank (high to low) ZINCRBY <key> <increment> <member>
Range queries
ZRANGE <key> <start> <stop> [--withscores] [--rev] [--byscore] [--bylex] ZRANGEBYSCORE <key> <min> <max> [--withscores] [--limit off,count] ZREVRANGE <key> <start> <stop> [--withscores] ZREVRANGEBYSCORE <key> <max> <min> [--withscores] [--limit off,count]
Counting
ZCARD <key> ZCOUNT <key> <min> <max>
Pop
ZPOPMIN <key> [count] ZPOPMAX <key> [count]
Set operations
ZINTERSTORE <dest> <numkeys> <key1> [key2...] ZUNIONSTORE <dest> <numkeys> <key1> [key2...] ZSCAN <key> <cursor> [MATCH pattern] [COUNT count]
Examples:
Create leaderboard (score member pairs)
bun run scripts/upstash-client.ts ZADD leaderboard 1000 "player1" 1500 "player2" 1200 "player3"
Get top 3 with scores (highest first)
bun run scripts/upstash-client.ts ZRANGE leaderboard 0 2 --rev --withscores
Get player's rank
bun run scripts/upstash-client.ts ZREVRANK leaderboard "player2"
Increment player's score
bun run scripts/upstash-client.ts ZINCRBY leaderboard 100 "player1"
Get players with scores between 1000 and 1500
bun run scripts/upstash-client.ts ZRANGEBYSCORE leaderboard 1000 1500 --withscores
Key Commands
Delete
DEL <key1> [key2...] UNLINK <key1> [key2...] # Async delete
Existence/Type
EXISTS <key1> [key2...] TYPE <key>
Expiration
EXPIRE <key> <seconds> EXPIREAT <key> <timestamp> PEXPIRE <key> <milliseconds> PEXPIREAT <key> <timestamp> TTL <key> PTTL <key> PERSIST <key> # Remove expiration
Rename
RENAME <key> <newkey> RENAMENX <key> <newkey>
Search
KEYS <pattern> # Use with caution in production SCAN <cursor> [MATCH pattern] [COUNT count]
Other
COPY <src> <dst> DUMP <key> TOUCH <key1> [key2...] RANDOMKEY OBJECT ENCODING|FREQ|IDLETIME|REFCOUNT <key>
Examples:
Set key with 1 hour expiration
bun run scripts/upstash-client.ts SET session:abc "data" bun run scripts/upstash-client.ts EXPIRE session:abc 3600
Or in one command
bun run scripts/upstash-client.ts SET session:abc "data" --ex 3600
Check TTL
bun run scripts/upstash-client.ts TTL session:abc
Scan keys matching pattern
bun run scripts/upstash-client.ts SCAN 0 MATCH "user:*" COUNT 100
Server Commands
PING [message] ECHO <message> DBSIZE TIME INFO [section] FLUSHDB # Delete all keys in current DB (DANGEROUS) FLUSHALL # Delete all keys in all DBs (DANGEROUS)
Command Options
SET Options
--ex <seconds> # Expire in seconds --px <ms> # Expire in milliseconds --exat <ts> # Expire at Unix timestamp (seconds) --pxat <ts> # Expire at Unix timestamp (ms) --nx # Only set if key does not exist --xx # Only set if key exists --keepttl # Retain existing TTL --get # Return old value
ZADD Options
--nx # Only add new members --xx # Only update existing members --gt # Only update if new score > current --lt # Only update if new score < current --ch # Return number of changed elements
ZRANGE Options
--withscores # Include scores in output --byscore # Range by score instead of rank --bylex # Range by lexicographical order --rev # Reverse order --limit off,count # Limit results (e.g., --limit 0,10)
Output Format
-
String values: Printed directly
-
null/nil: Prints (nil)
-
Objects/arrays: Pretty-printed as JSON
Confirmation Behaviour
Default: Ask for Confirmation
Before executing any destructive operation (write, modify, or delete), you MUST ask the user for confirmation. This includes:
Write operations:
-
SET, SETNX, SETEX, PSETEX, MSET, MSETNX
-
HSET, HSETNX
-
LPUSH, RPUSH, LPUSHX, RPUSHX, LSET, LINSERT
-
SADD
-
ZADD
Modify operations:
-
INCR, INCRBY, INCRBYFLOAT, DECR, DECRBY
-
APPEND, SETRANGE
-
HINCRBY, HINCRBYFLOAT
-
LREM, LTRIM, LMOVE
-
ZINCRBY
Delete operations:
-
DEL, UNLINK
-
HDEL
-
LPOP, RPOP
-
SREM, SPOP, SMOVE
-
ZREM, ZREMRANGEBYRANK, ZREMRANGEBYSCORE, ZPOPMIN, ZPOPMAX
-
FLUSHDB, FLUSHALL (extra caution)
TTL/Rename operations:
-
EXPIRE, EXPIREAT, PEXPIRE, PEXPIREAT, PERSIST
-
RENAME, RENAMENX
Example confirmation prompt:
"I'm about to HSET user:1 with fields {name: "John", email: "john@example.com"} . Proceed?"
YOLO Mode: Skip Confirmation
If the user indicates they do not want to be asked for confirmation, respect this for all subsequent operations. Indicators include:
-
"YOLO mode"
-
"Don't ask for confirmation"
-
"You're free to make changes without asking"
-
"Just do it"
-
"No need to confirm"
-
"Auto-approve" or "auto-confirm"
-
Any similar phrasing indicating blanket approval
Once YOLO mode is activated, proceed with destructive operations without asking, but still inform the user what was done.
Example:
Set user:1 with {name: "John", email: "john@example.com"}
- done.
Error Handling
If credentials are missing or invalid, the script will exit with an error message. Ensure the user has configured either:
-
Environment variables (UPSTASH_REDIS_REST_URL , UPSTASH_REDIS_REST_TOKEN )
-
Or provides credentials via --url and --token flags
When to Use This Skill
-
User explicitly asks to store or retrieve data from Upstash/Redis
-
Need to persist data across conversations or sessions
-
Implementing caching for expensive operations
-
Maintaining counters, rate limits, or statistics
-
Storing user preferences or session data
-
Building leaderboards or rankings (sorted sets)
-
Managing queues or task lists (lists)
-
Tagging or categorisation (sets)
-
Storing structured objects (hashes)
-
Any scenario requiring fast key-value storage