Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
bd3f5f1
feat(cli): add JSON output helpers for rvl
limjoobin Apr 24, 2026
ddcd751
feat(cli): add --json to rvl version
limjoobin Apr 24, 2026
96209c9
test(cli): cover rvl version --json and JSON CLI helpers
limjoobin Apr 24, 2026
8ad7da1
feat(cli): improve rvl help discoverability
vishal-bala Apr 24, 2026
3fd2ae6
docs(cli): refresh help examples and command tree
vishal-bala Apr 24, 2026
bead749
feat(cli): add --json to rvl stats with shared _stats_rows
limjoobin Apr 26, 2026
d9bc7e9
test: add unit tests for rvl stats CLI
limjoobin Apr 26, 2026
f77532f
feat(cli): add --json to rvl index listall
limjoobin Apr 26, 2026
7276fa5
test: add unit tests for rvl index listall
limjoobin Apr 26, 2026
8f6118a
feat(cli): add --json to rvl index info
limjoobin Apr 26, 2026
76d45cc
test: add unit tests for rvl index info --json
limjoobin Apr 26, 2026
f2b7e77
Merge branch 'main' into feat/RAAE-1557/cli-json
limjoobin Apr 27, 2026
8b3b2cc
chore: Format index.py and utils.py with black
limjoobin Apr 27, 2026
db1313f
fix(types): coerce index info inputs before make_dict in cli index js…
limjoobin Apr 27, 2026
ce70d09
fix(cli): preserve dict index_definition in index info json
limjoobin Apr 27, 2026
25d0dc7
fix(cli-stats): preserve numeric/null types in --json output
limjoobin Apr 27, 2026
165b755
chore: minor refactor for readability
limjoobin Apr 29, 2026
316e542
chore: updated parser description for readability
limjoobin Apr 29, 2026
6322e19
Revert "feat(cli): add --json to rvl version"
limjoobin Apr 29, 2026
81518d3
reverted tests for JSON output in version.py
limjoobin Apr 29, 2026
f344681
Merge remote-tracking branch 'refs/remotes/origin/main' into cli/RAAE…
vishal-bala Apr 30, 2026
0374033
Merge branch 'main' into feat/RAAE-1557/cli-json
limjoobin Apr 30, 2026
2414320
fix: Fixed syntax error from typo
limjoobin Apr 30, 2026
0f0ed61
fix: Resolved merge conflict
limjoobin Apr 30, 2026
dc90c26
fix: Removed failing exit code assertions
limjoobin Apr 30, 2026
9e8790b
fix: Fixed exit codes for Stats CLI error handling
limjoobin Apr 30, 2026
e1d2bcf
Chore: removed unused import
limjoobin Apr 30, 2026
b2b1292
Merge remote-tracking branch 'origin/feat/RAAE-1557/cli-json' into cl…
vishal-bala Apr 30, 2026
71fbb5c
fix(cli): handle missing index subcommand
vishal-bala Apr 30, 2026
557e422
refactor(cli): remove dead index dispatch check
vishal-bala Apr 30, 2026
d5bf48e
Remove outdated assertions
vishal-bala Apr 30, 2026
71a6711
Merge remote-tracking branch 'origin/main' into cli/RAAE-1554/cli-hel…
vishal-bala Apr 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -527,17 +527,27 @@ router("Hi, good morning")
Create, destroy, and manage Redis index configurations from a purpose-built CLI interface: `rvl`.

```bash
$ rvl -h
$ rvl --help

usage: rvl <command> [<args>]

Commands:
index Index manipulation (create, delete, etc.)
mcp Run the RedisVL MCP server
version Obtain the version of RedisVL
stats Obtain statistics about an index
Redis Vector Library CLI.

Command groups:
index Create, inspect, list, and delete Redis search indexes
stats Show statistics for an existing Redis search index
version Show the installed RedisVL version
mcp Run the RedisVL MCP server

Examples:
rvl index --help
rvl index create -s schema.yaml
rvl stats -i user_index
rvl mcp --config /path/to/mcp.yaml
```

Use `rvl index --help` to see documented subcommands such as `create`, `info`, `listall`, `delete`, and `destroy`. Use `rvl stats --help` to see both index-name and schema-path examples plus the shared Redis connection options for data-plane commands.

Run the MCP server over stdio (default):

```bash
Expand Down
30 changes: 16 additions & 14 deletions docs/user_guide/cli.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"source": [
"# The RedisVL CLI\n",
"\n",
"RedisVL is a Python library with a dedicated CLI to help load and create vector search indices within Redis.\n",
"RedisVL is a Python library with a dedicated CLI to create, inspect, list, and delete Redis search indexes, inspect index statistics, and run the RedisVL MCP server.\n",
"\n",
"This notebook will walk through how to use the Redis Vector Library CLI (``rvl``).\n",
"\n",
Expand Down Expand Up @@ -39,18 +39,20 @@
"metadata": {},
"source": [
"## Commands\n",
"Here's a table of all the rvl commands and options. We'll go into each one in detail below.\n",
"The table below documents the current CLI tree. Use ``rvl index --help`` and ``rvl stats --help`` for detailed flag help and examples.\n",
"\n",
"| Command | Options | Description |\n",
"|---------------|--------------------------|-------------|\n",
"| `rvl version` | | display the redisvl library version|\n",
"| `rvl index` | `create --schema` or `-s <schema.yaml>`| create a redis index from the specified schema file|\n",
"| `rvl index` | `listall` | list all the existing search indices|\n",
"| `rvl index` | `info --index` or ` -i <index_name>` | display the index definition in tabular format|\n",
"| `rvl index` | `delete --index` or `-i <index_name>` | remove the specified index, leaving the data still in Redis|\n",
"| `rvl index` | `destroy --index` or `-i <index_name>`| remove the specified index, as well as the associated data|\n",
"| `rvl stats` | `--index` or `-i <index_name>` | display the index statistics, including number of docs, average bytes per record, indexing time, etc|\n",
"| `rvl stats` | `--schema` or `-s <schema.yaml>` | display the index statistics of a schema defined in <schema.yaml>. The index must have already been created within Redis|"
"| Command | Purpose |\n",
"|---------|---------|\n",
"| `rvl version` | display the installed RedisVL version |\n",
"| `rvl index create` | create a new Redis search index from a schema YAML file |\n",
"| `rvl index info` | display schema and storage details for an index |\n",
"| `rvl index listall` | list Redis search indexes available on the target Redis deployment |\n",
"| `rvl index delete` | delete an index while leaving indexed data in Redis |\n",
"| `rvl index destroy` | delete an index and drop its indexed data |\n",
"| `rvl stats` | display statistics for an existing Redis search index |\n",
"| `rvl mcp` | run the RedisVL MCP server |\n",
"\n",
"Within data-plane commands, ``-i`` or ``--index`` targets an existing Redis index name and ``-s`` or ``--schema`` points to a schema YAML file. Shared Redis connection options such as ``--url``, ``--host``, and ``--port`` apply to ``rvl index`` and ``rvl stats``."
]
},
{
Expand All @@ -59,7 +61,7 @@
"source": [
"## Index\n",
"\n",
"The ``rvl index`` command can be used for a number of tasks related to creating and managing indices. Whether you are working in Python or another language, this cli tool can still be useful for managing and inspecting your indices.\n",
"The ``rvl index`` command groups the index management workflows. Use ``rvl index --help`` to see the documented subcommands: ``create``, ``info``, ``listall``, ``delete``, and ``destroy``. Whether you are working in Python or another language, this CLI can still be useful for managing and inspecting your indexes.\n",
"\n",
"First, we will create an index from a yaml schema that looks like the following:\n"
]
Expand Down Expand Up @@ -251,7 +253,7 @@
"source": [
"## Stats\n",
"\n",
"The ``rvl stats`` command will return some basic information about the index. This is useful for checking the status of an index, or for getting information about the index to use in other commands."
"The ``rvl stats`` command returns basic information about an index. Use ``-i`` or ``--index`` to target an existing Redis index name, or ``-s`` or ``--schema`` to target a schema-defined index. Shared Redis connection options such as ``--url``, ``--host``, and ``--port`` also apply here."
]
},
{
Expand Down
126 changes: 109 additions & 17 deletions redisvl/cli/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,40 +52,132 @@ def exit_redis_search_error(


class Index:
usage = "\n".join(
description = (
"Create, inspect, list, and delete Redis search indexes.\n\n"
"Use `-i/--index` to target an existing Redis index name or "
"`-s/--schema` to load a schema YAML file. Shared Redis connection "
"options apply to these data-plane commands."
)
epilog = "\n".join(
[
"rvl index <command> [<args>]\n",
"Commands:",
"\tinfo Obtain information about an index (use --json for machine output)",
"\tcreate Create a new index",
"\tdelete Delete an existing index",
"\tdestroy Delete an existing index and all of its data",
"\tlistall List all indexes (use --json for machine output)",
"\n",
"Examples:",
" rvl index create -s schema.yaml",
" rvl index info -i user_index",
" rvl index listall --url redis://localhost:6379",
]
)

def __init__(self):
parser = argparse.ArgumentParser(usage=self.usage)

parser.add_argument("command", help="Subcommand to run")
parser = add_index_parsing_options(parser)
parser = add_json_output_flag(parser)
Comment thread
vishal-bala marked this conversation as resolved.
parser = self._build_parser()

args = parser.parse_args(sys.argv[2:])

if not hasattr(self, args.command):
print(f"Unknown command: {args.command}\n", file=sys.stderr)
if not args.command:
parser.print_help(sys.stderr)
sys.exit(2)

Comment thread
vishal-bala marked this conversation as resolved.
try:
getattr(self, args.command)(args)
args.handler(args)
except Exception as e:
logger.error(e, exc_info=True)
print(str(e), file=sys.stderr)
sys.exit(1)

def _build_parser(self) -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
prog="rvl index",
description=self.description,
epilog=self.epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
)
shared_options = argparse.ArgumentParser(add_help=False)
add_index_parsing_options(shared_options)
add_json_output_flag(shared_options)

subparsers = parser.add_subparsers(dest="command", title="Commands")

create_parser = subparsers.add_parser(
"create",
parents=[shared_options],
help="Create a new index from a schema file",
description="Create a new Redis search index from a schema YAML file.",
epilog="\n".join(
[
"Examples:",
" rvl index create -s schema.yaml",
" rvl index create -s schema.yaml --url redis://localhost:6379",
]
),
formatter_class=argparse.RawDescriptionHelpFormatter,
)
create_parser.set_defaults(handler=self.create)

info_parser = subparsers.add_parser(
"info",
parents=[shared_options],
help="Show details about an index (use --json for machine output)",
description="Display schema and storage details for an index.",
epilog="\n".join(
[
"Examples:",
" rvl index info -i user_index",
" rvl index info -s schema.yaml --json",
]
),
formatter_class=argparse.RawDescriptionHelpFormatter,
)
info_parser.set_defaults(handler=self.info)

listall_parser = subparsers.add_parser(
"listall",
parents=[shared_options],
help="List indexes available on the target Redis deployment (use --json for machine output)",
description="List all Redis search indexes available on the target Redis deployment.",
epilog="\n".join(
[
"Examples:",
" rvl index listall",
" rvl index listall --host localhost --port 6379 --json",
]
),
formatter_class=argparse.RawDescriptionHelpFormatter,
)
listall_parser.set_defaults(handler=self.listall)

delete_parser = subparsers.add_parser(
"delete",
parents=[shared_options],
help="Delete an index but leave its data in Redis",
description="Delete an existing Redis search index without dropping indexed data.",
epilog="\n".join(
[
"Examples:",
" rvl index delete -i user_index",
" rvl index delete -s schema.yaml",
]
),
formatter_class=argparse.RawDescriptionHelpFormatter,
)
delete_parser.set_defaults(handler=self.delete)

destroy_parser = subparsers.add_parser(
"destroy",
parents=[shared_options],
help="Delete an index and drop its indexed data",
description="Delete an existing Redis search index and drop its indexed data.",
epilog="\n".join(
[
"Examples:",
" rvl index destroy -i user_index",
" rvl index destroy -s schema.yaml",
]
),
formatter_class=argparse.RawDescriptionHelpFormatter,
)
destroy_parser.set_defaults(handler=self.destroy)

return parser

def create(self, args: Namespace):
"""Create an index.

Expand Down
49 changes: 35 additions & 14 deletions redisvl/cli/main.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,56 @@
import argparse
import sys

from redisvl.cli.index import Index
from redisvl.cli.stats import Stats
from redisvl.cli.version import Version
from redisvl.utils.log import get_logger

logger = get_logger(__name__)


def _usage():
usage = [
"rvl <command> [<args>]\n",
"Commands:",
"\tindex Index manipulation (create, delete, etc.)",
"\tmcp Run the RedisVL MCP server",
"\tversion Obtain the version of RedisVL",
"\tstats Obtain statistics about an index",
return "rvl <command> [<args>]"


def _command_overview():
command_groups = [
"Command groups:",
" index Create, inspect, list, and delete Redis search indexes",
" stats Show statistics for an existing Redis search index",
" version Show the installed RedisVL version",
" mcp Run the RedisVL MCP server",
]
return "\n".join(command_groups)


def _examples():
examples = [
"Examples:",
" rvl index --help",
" rvl index create -s schema.yaml",
" rvl stats -i user_index",
" rvl mcp --config /path/to/mcp.yaml",
]
return "\n".join(usage) + "\n"
return "\n".join(examples)


class RedisVlCLI:
def __init__(self):
parser = argparse.ArgumentParser(
description="Redis Vector Library CLI", usage=_usage()
prog="rvl",
description=f"Redis Vector Library CLI.\n\n{_command_overview()}",
usage=_usage(),
epilog=_examples(),
formatter_class=argparse.RawDescriptionHelpFormatter,
)

parser.add_argument("command", help="Subcommand to run")
parser.add_argument("command", nargs="?", help="Command group to run")

if len(sys.argv) < 2:
parser.print_help(sys.stdout)
sys.exit(0)

args = parser.parse_args(sys.argv[1:2])

if not hasattr(self, args.command):
if not args.command or not hasattr(self, args.command):
print(f"Unknown command: {args.command}\n", file=sys.stderr)
parser.print_help(sys.stderr)
sys.exit(2)
Expand All @@ -47,6 +62,8 @@ def __init__(self):
sys.exit(1)

def index(self):
from redisvl.cli.index import Index

Index()
sys.exit(0)

Expand All @@ -57,9 +74,13 @@ def mcp(self):
sys.exit(0)

def version(self):
from redisvl.cli.version import Version

Version()
sys.exit(0)

def stats(self):
from redisvl.cli.stats import Stats

Stats()
sys.exit(0)
6 changes: 3 additions & 3 deletions redisvl/cli/mcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ class MCP:
epilog = (
"Use this command when wiring RedisVL into an MCP client.\n\n"
"Examples:\n"
" uvx --from redisvl[mcp] rvl mcp --config /path/to/mcp_config.yaml\n"
" uvx --from redisvl[mcp] rvl mcp --config /path/to/mcp_config.yaml --transport streamable-http --port 8000\n"
" uvx --from redisvl[mcp] rvl mcp --config /path/to/mcp_config.yaml --transport sse --host 0.0.0.0 --port 9000"
" rvl mcp --config /path/to/mcp_config.yaml\n"
" rvl mcp --config /path/to/mcp_config.yaml --transport streamable-http --port 8000\n"
" rvl mcp --config /path/to/mcp_config.yaml --transport sse --host 0.0.0.0 --port 9000"
)
usage = "\n".join(
[
Expand Down
20 changes: 17 additions & 3 deletions redisvl/cli/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,28 @@ def _stats_rows(index_info: dict) -> list[tuple[str, object]]:


class Stats:
usage = "\n".join(
description = (
"Display statistics for an existing Redis search index.\n\n"
"Use `-i/--index` to inspect an existing Redis index by name or "
"`-s/--schema` to load the target from a schema YAML file. Shared "
"Redis connection options apply to this data-plane command."
)
epilog = "\n".join(
[
"rvl stats [<args>]\n",
"Examples:",
" rvl stats -i user_index",
" rvl stats -s schema.yaml",
" rvl stats -i user_index --host localhost --port 6379",
]
)

def __init__(self):
parser = argparse.ArgumentParser(usage=self.usage)
parser = argparse.ArgumentParser(
prog="rvl stats",
description=self.description,
epilog=self.epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
)
parser = add_index_parsing_options(parser)
parser = add_json_output_flag(parser)
args = parser.parse_args(sys.argv[2:])
Expand Down
Loading
Loading