Riley CLI
Riley from the terminal, covering the two halves of the product:
- Getting data in — push a SQL/ETL result file into a Riley dataset.
- Asking questions — run agentic BI analyses and pull the tables behind the answers.
It calls the same first-party REST API the web app uses. Human login is browser
PKCE; the CLI stores a Riley-owned riley_cli_ credential (not a Firebase
refresh token). It is not an MCP client and it does not orchestrate managed sync.
Install
The PyPI package is riley-cli. The command it installs is riley.
You need Python 3.11 or newer.
# Humans: isolated tool, `riley` on PATH
pipx install riley-cli
pipx upgrade riley-cli
# CI, Airflow, Docker: install into that job's venv or image
python -m pip install riley-cli
Do not pip install --user riley-cli onto the system interpreter. If
riley --version is not this CLI, another package may own the riley name
on PATH (which riley).
From a clone, for development:
python3.11 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
Sign in
riley login opens app.askriley.io so Google, Okta, MFA,
and password all work the same way as the web app. A CLI login credential is
cached in ~/.config/riley/credentials.json (directory mode 700, file mode 600)
for 12 hours, or until you riley logout or revoke it in Integrations → Command
line access. That file is a bearer token. Treat it like a password: do not
commit it, paste it into tickets, or copy it onto a shared machine.
riley login
riley whoami
riley logout
riley token list
--no-browser prints the URL instead of opening it (the callback still has to
reach this machine). Headless or CI hosts should not use riley login. Create
an automation token in Integrations → Command line access and export it:
export RILEY_CLI_TOKEN=riley_cli_…
Automation tokens inherit your Riley role. They are not org/service-account
identities. Signing out of the website does not revoke CLI tokens. riley logout
revokes a file credential on this machine; it does not revoke a token provided
via RILEY_CLI_TOKEN (revoke those in Integrations → Command line access).
A CLI credential cannot create another CLI credential.
Accounts with an unverified email are rejected by the API on everything except
whoami.
Pipeline upload
This is a non-interactive pipeline step: a query result on one side, Riley on
the other. The first named upload creates the dataset from the file schema.
Later uploads of the same --dataset-name apply --mode.
The command stays attached until Riley is ready and streams each first-upload
stage: schema validation, dataset/table creation, staging, row loading, column
classification, and final query readiness.
psql ... -o /tmp/orders.csv
riley upload --dataset-name orders --source /tmp/orders.csv --mode replace
# entity snapshots
riley upload --dataset-name accounts --source ./accounts.csv \
--mode upsert --merge-key account_id
# one-off (dataset name taken from the file stem)
riley upload --source ./scratch.csv
--mode is replace (default), append, or upsert. Watch the load with
riley datasets pipeline and riley datasets history orders.
Checking what's queryable
riley datasets list
riley datasets pipeline
riley datasets schema orders
riley datasets history orders
riley datasets export orders --out orders.csv
riley datasets export orders --limit 5000 --out orders.csv
Default export is 1,000 rows, with a hard max of 50,000. --json without --out
returns a row envelope; --out writes CSV or jsonl.
Asking questions
riley ask "What are the top 5 accounts at risk of churning?"
riley ask "And how did that change last quarter?" -c <conversation_id>
riley analysis citation 456 1 --out accounts.csv
riley analysis feedback 456 "Missed the enterprise segment"
riley ask mirrors the web app: it queues the analysis, reports each tool call as
the agent works, then streams the summary token by token over SSE. Add --no-wait
to just queue it and get an analysis_result_id back.
Scripting
Every command takes --json, which prints a machine-readable payload on stdout.
Progress chatter and prompts go to stderr, so pipes stay clean:
riley --json datasets list | jq -r '.tables[].name'
Configuration
| Variable | Purpose |
|---|---|
RILEY_API_URL |
Backend host. Also --api-url. Defaults to https://api.askriley.io |
RILEY_APP_URL |
Website host for riley login. Defaults to https://app.askriley.io |
RILEY_CLI_TOKEN |
Automation token from Integrations → Command line access (overrides the credentials file) |
RILEY_CONFIG_DIR |
Where credentials are cached |
A file login is bound to the API host it was issued for. riley login against
prod will not send that token to --api-url / RILEY_API_URL for a different
host (for example http://localhost:8000). Log in against that host, or use
RILEY_CLI_TOKEN. localhost and 127.0.0.1 are different hosts.
RILEY_CLI_TOKEN is meant for CI: it is sent to whatever API URL the command
uses. Prefer the environment (or your orchestrator's secret store) over putting
the token in a file on a runner.
RILEY_APP_URL only changes where riley login opens the browser. Point it
at a host you trust.
The CLI does not follow HTTP redirects, so a mis-typed http:// API URL is
an error rather than a silent hop that could replay the bearer.
Layout
| Module | Role |
|---|---|
browser_auth.py |
Loopback PKCE for riley login |
client.py |
REST client: envelope unwrapping, multipart, SSE |
commands/uploads.py |
Pipeline file ingest |
commands/datasets.py |
Catalog, schema, pipeline health |
commands/analyze.py |
Agentic BI |
commands/tokens.py |
riley token list |
Tests
pytest
tests/fake_riley.py is an in-process stand-in for the Riley REST API, including
the SSE stream, so the suite exercises real HTTP without touching a live backend.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file riley_cli-0.1.0.tar.gz.
File metadata
- Download URL: riley_cli-0.1.0.tar.gz
- Upload date:
- Size: 25.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9a3e6811bb98fb0aa44019e7537cc9e14afd357da1b62e71840ad8b68950f8d1
|
|
| MD5 |
4f0aadd7ddea391c239334fdec796958
|
|
| BLAKE2b-256 |
060868e917ccafb1db97f7681a9f73dc34e6d67ff0754c79a7845a74d284be0e
|
File details
Details for the file riley_cli-0.1.0-py3-none-any.whl.
File metadata
- Download URL: riley_cli-0.1.0-py3-none-any.whl
- Upload date:
- Size: 24.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6a8c2143f909b99c715341a0a7b6fef3ce68d0ef5139ec02a58c02ef8634ddce
|
|
| MD5 |
a5382b8d0a8a686808c9c096fb7acb70
|
|
| BLAKE2b-256 |
250b7d3c1139dc822b6cf16318e31ac3332d7ed61519c9cd68a387648e16e2ca
|