github.com/redis-developer/redisctl
No unified CLI for Redis Cloud and Enterprise REST APIs
# Typical "automation" script
API_KEY="..."
SECRET="..."
# Create database... hope the JSON is right
curl -s -X POST "https://api.redislabs.com/v1/subscriptions/123/databases" \
-H "x-api-key: $API_KEY" \
-H "x-api-secret-key: $SECRET" \
-H "Content-Type: application/json" \
-d '{"name": "mydb", "memoryLimitInGb": 1, ...}'
# Poll for completion... forever
while true; do
STATUS=$(curl -s ... | jq -r '.status')
if [ "$STATUS" = "active" ]; then break; fi
sleep 10 # Hope this is enough
done
# Parse response... pray it doesn't change
ENDPOINT=$(curl -s ... | jq -r '.publicEndpoint')
# What if the field is null? What if the API changes?
First-class CLI for the entire Redis platform
Built around four layers of functionality...
Manage credentials across environments
# Set up profiles for each environment
redisctl profile set dev --cloud-api-key $DEV_KEY --cloud-secret-key $DEV_SECRET
redisctl profile set staging --cloud-api-key $STG_KEY --cloud-secret-key $STG_SECRET
redisctl profile set prod --cloud-api-key $PROD_KEY --cloud-secret-key $PROD_SECRET
# Set a default
redisctl profile set-default prod
# Switch easily
redisctl --profile dev cloud database list
redisctl --profile prod cloud database list
Keep credentials out of scripts and env vars
# Store credentials in OS keychain (macOS Keychain, Windows Credential Manager)
redisctl profile set prod \
--cloud-api-key $KEY \
--cloud-secret-key $SECRET \
--use-keyring
# Or reference environment variables
redisctl profile set prod \
--cloud-api-key '${REDIS_CLOUD_API_KEY}' \
--cloud-secret-key '${REDIS_CLOUD_SECRET_KEY}'
# Credentials never appear in config file
cat ~/.config/redisctl/config.toml
# cloud_api_key = "keyring:prod-api-key"
Direct REST access - better than curl
curl -s -X GET \
"https://api.redislabs.com/v1/subscriptions" \
-H "x-api-key: $KEY" \
-H "x-api-secret-key: $SECRET" \
| jq '.[].name'
redisctl api cloud get /subscriptions \
-q '[].name'
# Any HTTP method
redisctl api cloud get /subscriptions
redisctl api cloud post /subscriptions/123/databases --body '{"name": "test"}'
redisctl api cloud put /subscriptions/123/databases/456 --body '{...}'
redisctl api cloud delete /subscriptions/123/databases/456
# Works for Enterprise too
redisctl api enterprise get /v1/cluster
redisctl api enterprise get /v1/bdbs
redisctl api enterprise post /v1/bdbs --body '{...}'
# JMESPath queries on any response
redisctl api enterprise get /v1/nodes -q '[*].{addr: addr, status: status}'
Day-to-day cluster management and monitoring
# Check cluster health
redisctl enterprise cluster get
redisctl enterprise node list
redisctl enterprise database list
# Monitor performance
redisctl enterprise database stats 1 -o json
redisctl enterprise cluster stats
# Manage databases
redisctl cloud database list --subscription-id 123456
redisctl enterprise database update 1 --memory-size 2147483648
$ redisctl enterprise database list
ID Name Memory Status Endpoints
1 session-cache 1.0 GB active redis-12345.cluster.local:12000
2 user-data 2.0 GB active redis-12346.cluster.local:12001
3 analytics 4.0 GB active redis-12347.cluster.local:12002
$ redisctl enterprise database list -o json
[{"uid":1,"name":"session-cache","memory_size":1073741824,"status":"active"},
{"uid":2,"name":"user-data","memory_size":2147483648,"status":"active"}]
Filter, reshape, and transform any JSON output
# Count all subscriptions
$ redisctl cloud subscription list -o json -q 'length(@)'
192
# Get unique cloud providers
$ redisctl cloud subscription list -o json -q '[*].cloudDetails[0].provider | unique(@)'
["AWS", "GCP"]
# Aggregate statistics
$ redisctl cloud subscription list -o json \
-q '{total: length(@), size_gb: sum([*].cloudDetails[0].totalSizeInGb)}'
{"total": 192, "size_gb": 23.56}
Reshape data with custom fields
# Extract and reshape subscription details
$ redisctl cloud subscription list -o json \
-q '[*].{id: id, name: name, provider: cloudDetails[0].provider} | [:3]'
[
{"id": 2983053, "name": "time-series-demo", "provider": "AWS"},
{"id": 2988697, "name": "workshop-sub", "provider": "AWS"},
{"id": 3034552, "name": "test-db", "provider": "GCP"}
]
Chain operations with |
# Get unique regions -> sort -> count
$ redisctl cloud subscription list -o json \
-q '[*].cloudDetails[0].regions[0].region | unique(@) | sort(@) | length(@)'
7
# Sort by name length (find shortest names)
$ redisctl cloud subscription list -o json \
-q "[*].{name: name, len: length(name)} | sort_by(@, &len) | [:3]"
[{"len": 5, "name": "bgiri"}, {"len": 6, "name": "abhidb"}, {"len": 6, "name": "CM-rag"}]
Transform and filter text
# Convert to uppercase
$ redisctl cloud subscription list -o json -q 'map(&upper(name), [*]) | [:3]'
["XW-TIME-SERIES-DEMO", "GABS-AWS-WORKSHOP-SUB", "BAMOS-TEST"]
# Filter by pattern
$ redisctl cloud subscription list -o json -q "[*].name | [?contains(@, 'demo')] | [:5]"
["xw-time-series-demo", "gabs-redis-streams-demo", "anton-live-demo", ...]
# Replace substrings
$ redisctl cloud subscription list -o json \
-q "[*].{name: name, modified: replace(name, 'demo', 'DEMO')} | [:2]"
[{"name": "xw-time-series-demo", "modified": "xw-time-series-DEMO"}, ...]
Fuzzy Matching
# Find similar names
-q "[*].{name: name, dist: levenshtein(name, 'prod')}"
Math & Stats
# Aggregate stats
-q '{max: max([*].size), avg: avg([*].size)}'
Formatting
# Human-readable bytes
-q '[*].{mem: format_bytes(memory_size)}'
DateTime
# Current timestamp
-q '{checked: now()}'
Type Checking
# Inspect types
-q '[*].{name: name, type: type_of(id)}'
Semver
# Version comparison
-q 'semver_compare(version, `"7.4.0"`)'
End-to-end provisioning for Redis Cloud
# Complete subscription setup with database
redisctl cloud workflow subscription-setup \
--name "production" \
--provider AWS \
--region us-east-1 \
--database-name "cache" \
--database-memory-gb 2 \
--high-availability \
--wait
Looking up payment method...
Creating subscription 'production'...
Waiting for subscription to become active...
Subscription created successfully (ID: 123456)
Database created successfully (ID: 789)
Connection string: redis://redis-12345.c1.us-east-1.ec2.cloud.redislabs.com:12345
Initialize and configure clusters
# Initialize a new Enterprise cluster
redisctl enterprise workflow init-cluster \
--license-file ./license.txt \
--cluster-name "production"
Uploading license...
Creating cluster 'production'...
Waiting for cluster initialization...
Cluster initialized successfully
Cluster: production
Nodes: 3
Status: active
Generate and upload diagnostics in seconds
# Generate, optimize, and upload in one command
redisctl enterprise support-package cluster --optimize --upload
Generating support package...
Optimizing package (removed 847 MB of logs)...
Uploading to Redis Support...
Package: support-package-2024-01-15-cluster.tar.gz
Size: 23 MB (optimized from 870 MB)
Upload: Complete
Case: https://files.redis.com/f/abc123
What used to take 30+ minutes now takes 30 seconds
No installation required
# Run any command
docker run --rm ghcr.io/redis-developer/redisctl \
cloud subscription list
# With environment variables
docker run --rm \
-e REDIS_CLOUD_API_KEY=$KEY \
-e REDIS_CLOUD_SECRET_KEY=$SECRET \
ghcr.io/redis-developer/redisctl cloud database list
# Or mount your config
docker run --rm \
-v ~/.config/redisctl:/root/.config/redisctl \
ghcr.io/redis-developer/redisctl --profile prod cloud database list
GitHub Actions example
- name: Deploy Redis database
env:
REDIS_CLOUD_API_KEY: ${{ secrets.REDIS_CLOUD_API_KEY }}
REDIS_CLOUD_SECRET_KEY: ${{ secrets.REDIS_CLOUD_SECRET_KEY }}
run: |
# Create database and wait for it
redisctl cloud database create \
--subscription-id ${{ vars.SUBSCRIPTION_ID }} \
--name "pr-${{ github.event.number }}" \
--memory-limit-in-gb 1 \
--wait -o json > db.json
# Extract connection info (jq parses the saved JSON file)
echo "REDIS_URL=$(jq -r '.publicEndpoint' db.json)" >> $GITHUB_ENV
- name: Cleanup PR database
if: github.event.action == 'closed'
env:
REDIS_CLOUD_API_KEY: ${{ secrets.REDIS_CLOUD_API_KEY }}
REDIS_CLOUD_SECRET_KEY: ${{ secrets.REDIS_CLOUD_SECRET_KEY }}
run: |
# Find and delete the PR database
DB_ID=$(redisctl cloud database list \
--subscription-id ${{ vars.SUBSCRIPTION_ID }} \
-q "[?name=='pr-${{ github.event.number }}'].databaseId | [0]" -o json)
redisctl cloud database delete \
${{ vars.SUBSCRIPTION_ID }} $DB_ID --wait
Internal Redis teams
Customer teams
Even CLI-savvy executives:
redisctl cloud subscription list -q '[*].{name:
name, monthly: price}'
# Homebrew (macOS/Linux)
brew install redis-developer/homebrew-tap/redisctl
# Cargo (from source)
cargo install redisctl
# With secure credential storage
cargo install redisctl --features secure-storage
# Docker
docker run -it ghcr.io/redis-developer/redisctl --help
# From releases (Linux x86_64)
curl -L https://github.com/redis-developer/redisctl/releases/latest/download/redisctl-x86_64-unknown-linux-gnu.tar.gz | tar xz
./redisctl --help
# Install
brew install redis-developer/homebrew-tap/redisctl
# Setup profile
redisctl profile set mycloud --cloud-api-key $KEY --cloud-secret-key $SECRET
# Start using
redisctl cloud subscription list
redisctl cloud database list --subscription-id 123456
Docs: redis-field-engineering.github.io/redisctl-docs