CLI Reference
Install
Homebrew
brew install hotdata-dev/tap/cli
Shell (macOS, Linux)
curl -fsSL https://github.com/hotdata-dev/hotdata-cli/releases/latest/download/hotdata-cli-installer.sh | sh
From source (requires Rust)
cargo install --path .
Or download a binary from Releases. Update with hotdata manage upgrade.
Connect
Authenticate via browser:
hotdata auth login
This launches a browser window where you can sign in and authorize the CLI. To create a new account:
hotdata auth register # GitHub OAuth; add --email for email + password
Check status or sign out:
hotdata auth status
hotdata auth logout
Alternatively, pass an API key directly:
hotdata <command> --api-key <api_key>
Or set the HOTDATA_API_KEY environment variable (also loaded from .env files):
export HOTDATA_API_KEY=<api_key>
hotdata <command>
API key priority (lowest to highest): config file → HOTDATA_API_KEY env var → --api-key flag.
Command reference
The full command surface. The top level has eight groups — auth, workspaces, databases, query, jobs, ingest, search, and manage. Run hotdata <command> --help for the complete flags on any of them.
| Command | Description |
|---|---|
auth login | Log in via browser |
auth register | Create a new account via browser (GitHub OAuth; --email for email + password) |
auth logout | Remove authentication for a profile |
auth status | Show authentication status |
workspaces list | List all workspaces |
workspaces use | Set the default workspace |
databases list | List instant databases in the workspace |
databases count | Count instant databases in the workspace |
databases show | Show details for an instant database |
databases create | Create a new instant database |
databases fork | Fork a database into a new, independent database |
databases attach | Attach a catalog so its tables are queryable |
databases detach | Detach a previously attached catalog |
databases use | Set the current (default) database |
databases unset | Clear the current database |
databases remove | Delete a database and all its tables |
databases load | Load a parquet file or saved result into a table |
databases tables list | List tables in a database |
databases tables show | Show column definitions for a table |
databases tables load | Load parquet/result into a table (create or replace) |
databases tables remove | Delete a table from a database |
databases context list | List named contexts in a database |
databases context show | Print context content to stdout |
databases context pull | Download context to ./<NAME>.md |
databases context push | Upload ./<NAME>.md as named context |
databases query | Execute a SQL query against a database |
databases query status | Check a running query and retrieve results |
databases queries list | List query runs |
databases results get | Show a stored query result by ID |
databases results list | List stored query results |
query "<sql>" | Execute a SQL query (shortcut for databases query) |
query status | Check a running query and retrieve results |
jobs list | List background jobs (active by default) |
jobs <id> | Show one background job |
ingest create | Create a load definition |
ingest list | List the ingests in the workspace |
ingest show | Show one ingest: state, selector, destination, schedule |
ingest pause | Stop an ingest (cancel the active run and future runs) |
ingest resume | Clear a stop and let the schedule dispatch again |
ingest schedule | Change when a scheduled/continuous ingest runs next |
ingest logs | List the runs of one ingest |
ingest run | Show one run: status, snapshots, timings |
ingest remove | Delete an ingest and release its destination table |
ingest sources test | Check a config and credentials without creating anything |
ingest sources add | Create a datasource and its first config version |
ingest sources list | List the datasources in the workspace |
ingest sources show | Show one datasource: state, config, discovery |
ingest sources update-config | Append a config version (rotate credentials) |
ingest sources remove | Delete a datasource |
ingest sources types | Browse the catalog of source types |
ingest sources fields | Show the fields a source family accepts |
search "<text>" --index <name> | Run a full-text or vector search against an index |
search create | Create a search index over a table column |
search list | List search indexes |
search show | Show one search index by name |
search remove | Remove a search index by name |
search embeddings list | List embedding providers |
search embeddings show | Show one embedding provider |
search embeddings add | Create a new embedding provider |
search embeddings update | Update an embedding provider |
search embeddings remove | Delete an embedding provider |
manage usage | Show workspace usage: queries, bytes scanned, stored bytes |
manage completions | Generate shell completions (bash, zsh, fish) |
manage upgrade | Upgrade the CLI to the latest release |
manage skills install | Install/update the agent skill into agent directories |
manage skills status | Show the agent skill's installation status |
manage skills list | List installed skills (alias for status) |
Global options
| Option | Description |
|---|---|
--api-key <key> | API key (overrides env var and config) |
--no-input | Disable interactive prompts; error instead |
-v, --version | Print version |
-h, --help | Print help |
Most commands also accept -w, --workspace-id <id> and -o, --output <table\|json\|yaml>.
Four commands trade yaml for csv — they accept table\|json\|csv and never yaml: query, databases query, search "<text>", and databases results get. Note that databases results list is not one of them; it stays on table\|json\|yaml. query status, databases query status, and search create take no -o at all.
Workspaces
hotdata workspaces list
hotdata workspaces use [<workspace_id>]
listshows all workspaces with a*marker on the active one.useswitches the active workspace. Omit the ID for interactive selection.- The active workspace is the default for all commands that accept
-w.
Databases
Instant databases are Hotdata-owned catalogs you populate with parquet files. Tables are addressed as <catalog>.<schema>.<table> in SQL, where <catalog> is the alias set with --catalog at create time.
hotdata databases list [--limit <n>] [--cursor <token>] [-o table|json|yaml]
hotdata databases count
hotdata databases show <name_or_id>
hotdata databases create \
[--catalog <alias>] \
[--name <label>] \
[--table <name>]... \
[--schema <schema>] \
[--attach <catalog[=alias]>]... \
[--expires-at <duration>]
hotdata databases use <database_id>
hotdata databases unset
hotdata databases remove <name_or_id>
createmints a database.--catalogsets the SQL alias (SELECT … FROM <alias>.schema.table); it must be[a-z_][a-z0-9_]*and globally unique.--nameis a free-form display label.--table(repeatable) declares tables up front and acceptsschema.tabledot notation to span schemas.--schemasets the default schema for bare--tableentries (defaultpublic).--attach(repeatable) attaches a catalog as a queryable catalog on the new database; accepts a catalog name or id, optionallycatalog=aliasto set the SQL alias (--attach github --attach salesdb=sales).--expires-ataccepts a relative duration (24h,7d,90m) or RFC 3339 timestamp; omitting it means the database never expires.usemarks a database as the default for subsequent commands and takes the database id printed bycreate(unlikeshow/removeand-d/--database, it does not resolve a name or catalog alias);unsetclears it.removedeletes the database and all its tables.
Fork a database
hotdata databases fork [<database>] [--name <label>] [--expires-at <duration>]
- Forks an instant database into a new, independent database with the same schemas, tables, and data. It answers to the same SQL catalog alias inside its own query scope; the two databases diverge freely afterwards — writes to one never affect the other. Useful for safe experiments before risky changes.
- The source defaults to the current database.
--namedefaults to<source-name>-fork. - Attached catalogs are re-attached to the fork; indexes are not carried over.
Attach a catalog
hotdata databases attach <catalog> [-d <name_or_id>] [--alias <alias>]
hotdata databases detach <catalog> [-d <name_or_id>]
attachmakes a catalog's live tables visible inside an instant database's query scope, so you can join across catalogs in a single query without exporting data. Reachable in SQL as<alias>.<schema>.<table>, or<catalog-name>.<schema>.<table>when--aliasis omitted.-d/--databaseselects the database to attach into (defaults to the current database).detachremoves a previously attached catalog.
Load parquet into a table
hotdata databases load --catalog <alias> --table <table> --file <path.parquet>
hotdata databases load --catalog <alias> --table <table> --url <https://...>
hotdata databases load --catalog <alias> --table <table> --upload-id <id>
hotdata databases load --catalog <alias> --table <table> --result-id <id>
--catalogis the alias set at create time;--schemadefaults topublic.- Sources:
--fileuploads from a local path;--urldownloads a remote parquet file;--upload-iduses a pre-staged upload fromPOST /v1/uploads;--result-idloads a saved query result (which must belong to the target database). - Load replaces the table contents on each call.
Manage tables
hotdata databases tables [<database>]
hotdata databases tables list [--database <name_or_id>] [--schema <p>] [--table <p>] [--limit <n>]
hotdata databases tables show <catalog.schema.table>
hotdata databases tables load <table> [--database <name_or_id>] [--schema <s>] (--file|--url|--upload-id|--result-id)
hotdata databases tables remove <table> [--database <name_or_id>] [--schema <s>]
tables(ortables list) lists the tables in a database;--databasedefaults to the current database.showprints column definitions forcatalog.schema.table(orschema.tablewith an active database).tables loadcreates or replaces a table from parquet or a saved result, addressing the database by--databaserather than by--catalog.tables removedrops a table from the database.
Context
Sync named Markdown context files with an instant database — persistent notes and schema documentation scoped to a database, useful for giving agents durable context.
hotdata databases context list [-d <database>] [--prefix <p>]
hotdata databases context show <name> [-d <database>]
hotdata databases context pull <name> [--force] [--dry-run] [-d <database>]
hotdata databases context push <name> [--dry-run] [-d <database>]
pulldownloads context to./<NAME>.md(--forceoverwrites an existing file);pushuploads./<NAME>.mdto the database as named context.<name>follows SQL identifier rules; a trailing.mdis ignored (e.g.USER.md→USER).
Query run history & results
hotdata databases queries list [--status <csv>] [--limit <n>] [--cursor <token>]
hotdata databases queries <query_run_id>
hotdata databases results list [--limit <n>] [--offset <n>]
hotdata databases results get <result_id> [-o table|json|csv]
queries listshows past runs with status, timing, row count, and a truncated SQL preview (default limit 20);--statusfilters by run status (comma-separated, e.g.running,failed). View a run by ID for full metadata (timings,result_id, SQL).- Every query result is stored automatically — retrieve rows with
results get <result_id>(theresult-idprinted in a query's footer) without re-running the query.
Query
query is a top-level shortcut into databases query.
hotdata query "<sql>" \
[-d <database>] \
[--dialect hotsql|duckdb|postgres|snowflake] \
[-o table|json|csv]
hotdata query status <query_run_id>
- Default output is
table, which prints results with row count and execution time. -d/--databaseruns against a specific instant database (defaults to the current database set viadatabases use). It is sent as theX-Database-Idheader, so it takes the database id — it does not resolve a name or catalog alias.--dialectnames the SQL the query is written in. Anything other thanhotsql(the default) is transpiled to HotSQL server-side before it runs — read-only queries only. See SQL dialects.- Long-running queries fall back to async execution and return a
query_run_id. Poll it withhotdata query status <query_run_id>. - Exit codes for
query status:0succeeded,1failed,2still running (poll again),3succeeded but the result is a truncated preview.
Ingest
An ingest is a saved load definition: it reads from an external source and writes rows into an instant database. Add the source first (hotdata ingest sources add), then create an ingest that reads it. Selector and destination are fixed at creation; creating an ingest starts nothing — the scheduler dispatches every run, so watch it with hotdata ingest logs <id> rather than expecting a run id back.
# Create a load definition (source + what to read + where it lands)
hotdata ingest create --source <name_or_id> --sql "SELECT * FROM <schema>.<table>" --database-id <db>
hotdata ingest create --source <name_or_id> --all --database-id <db>
hotdata ingest create --source <name_or_id> --table <t>... --type scheduled --every 1h --database-id <db>
# Inspect and control ingests
hotdata ingest list [--datasource-id <id>] [--type <t>] [--state <s>]
hotdata ingest show <ingest_id>
hotdata ingest logs [<ingest_id>] [--status <s>] [--wait] [--wait-timeout <s>]
hotdata ingest run <run_id> [--wait]
hotdata ingest pause <ingest_id>
hotdata ingest resume <ingest_id>
hotdata ingest schedule <ingest_id> [--every <dur>] [--next now|<rfc3339>]
hotdata ingest remove <ingest_id>
createneeds a--source(ads_…id or a display name) and a selector. Selector shorthands:--sql(SQL sources:SELECT <cols|*> FROM [<schema>.]<table> [WHERE …] [LIMIT n]),--raw-sql(a verbatim query in the source's own dialect),--all,--table/--topic/--table-path(per family), or--selectorfor raw family JSON. Destination flags:--database-id,--dest-table/--dest-table-prefix,--dest-schema(defaultpublic), and--write-mode replace|upsert.--typeisone-time(default),scheduled, orcontinuous(--stream); recurring types need--everyor--schedule.- There is no
run-nowverb — bring a run forward withhotdata ingest schedule <id> --next now. pausecancels the active run and stops future ones;resumeclears the stop but runs nothing immediately (one-time ingests can't be resumed — create a new one).logslists an ingest's runs (newest first);run <run_id>shows one run. Both accept--waitto watch until a terminal state (exit0succeeded,1failed/cancelled,2still queued/running).removesoft-deletes the ingest and releases its destination table; the table, its data, and the source are never deleted.
Sources
A source (datasource) stores an external system's connection config and credentials. It's surfaced under ingest sources so a source and the ingests that read it share one command tree.
hotdata ingest sources types [<name>]
hotdata ingest sources fields [<family>]
hotdata ingest sources test --family <family> [--config <json>] [--credentials <json>] [--bucket-url <url>]
hotdata ingest sources add [--family <family>] [--display-name <name>] [--config <json>] [--credentials <json>]
hotdata ingest sources list [--family <f>] [--state <s>]
hotdata ingest sources show <datasource_id>
hotdata ingest sources update-config <datasource_id> [--config <json>] [--credentials <json>]
hotdata ingest sources remove <datasource_id>
- Families:
sql,rest,filesystem,iceberg,delta,ducklake,kafka,derived. Usesqlfor any SQL dialect (the dialect goes in the config),filesystemfor buckets, andderivedto build a table from another table in your own workspace.hotdata ingest sources fieldsprints the list with each family's required config. typesbrowses the catalog of source types and their families;fields <family>shows the config, credentials, and selector fields a family accepts (generated by the service, so it matches exactly what the API accepts).testchecks a config and credentials without creating anything —validmeans the shape was accepted,probedmeans the source was actually contacted.addreturns a stableds_…id and loads no data; on a terminal it prompts for the source type and fields (skip with--no-inputand--config). Config and credentials are JSON — inline,@file.json, or@-for stdin; keep secrets out of argv with@file.update-configappends a config version — rotate credentials by passing the same config plus new--credentials.removesoft-deletes a source; its ingests must be removed first.
Search
Full-text (BM25) and vector search over an indexed table column, plus index and embedding-provider management.
hotdata search "<query text>" \
--index <name> \
[-d <database>] \
[--select <columns>] \
[--limit <n>] \
[-o table|json|csv]
- The search type (full-text vs vector) is inferred from the index.
--indexaddresses the index by name (fromhotdata search list);-d/--databaseis the database the index lives in (defaults to the active database). - Full-text results are ordered by relevance (descending); vector results by distance (ascending).
--selectlimits the returned columns (comma-separated, defaults to all).
Manage indexes
hotdata search create [<name>] --type text|vector|sorted --from <catalog.schema.table> --column <col> \
[--metric l2|cosine|dot] \
[--provider <embedding_provider_id>] \
[--dimensions <n>] [--output-column <name>] [--description "..."] \
[--async]
hotdata search list [--schema <s>] [--table <t>]
hotdata search show <name> [-d <database>]
hotdata search remove <name> [-d <database>]
--type:text(BM25 full-text),vector(similarity), orsorted(range/equality filters). The index name is derived from table, column, and type when omitted.--metricapplies to vector indexes.--providerenables server-side auto-embeddings on a text column;--dimensionsoverrides the embedding output dimensions and--output-columnnames the generated column (default{column}_embedding).--typevalues are not freely combinable. An index created with--provider(auto-embedding vector) must be the only index on its table: creating one fails if the table already has an index, and no other index can be added while it exists. Avectorindex over an existing embedding column carries no such restriction, so it coexists withtextandsortedindexes. See vector indexes.--asyncsubmits index creation as a background job — poll withhotdata jobs <job_id>.
Embedding providers
Embedding providers are the models behind vector search.
hotdata search embeddings list
hotdata search embeddings show <id>
hotdata search embeddings add --name <name> --provider-type local|service \
[--config '{"model":"..."}'] \
[--provider-api-key <key> | --secret-name <name>]
hotdata search embeddings update <id> [--name <name>] [--config <json>] [--provider-api-key <key> | --secret-name <name>]
hotdata search embeddings remove <id>
--provider-type localuses a local embedding model;servicecalls an external API (e.g. OpenAI).--provider-api-keyauto-creates a managed secret for the provider's API key;--secret-namereferences an existing secret instead.
Jobs
hotdata jobs list \
[--job-type <type>] \
[--status <status>] \
[--all] \
[--limit <n>] [--offset <n>] \
[-o table|json|yaml]
hotdata jobs <job_id>
listshows only active jobs (pendingandrunning) by default; use--allto see every job.--job-typeaccepts:data_refresh_table,data_refresh_connection,create_index,managed_load.--statusaccepts:pending,running,succeeded,partially_succeeded,failed.
Manage
Account, configuration, and CLI maintenance.
hotdata manage usage [--since <rfc3339>] [-o table|json|yaml]
hotdata manage completions bash|zsh|fish
hotdata manage upgrade
hotdata manage skills install [--project]
hotdata manage skills status
usageshows workspace usage: query count, bytes scanned, and stored bytes.--sincecounts usage from an RFC 3339 timestamp (e.g.2026-06-01T00:00:00Z); defaults to the current billing window.completionsprints a shell completion script;upgradeupdates the CLI to the latest release.skills installinstalls or refreshes the hotdata agent skill into agent directories (Claude Code, Cursor, etc.);--projectinstalls into the current project instead of globally. See Agent Skills.
Configuration
Config is stored at ~/.hotdata/config.yml, keyed by profile (default: default). Override the config directory with HOTDATA_CONFIG_DIR.
| Variable | Description |
|---|---|
HOTDATA_API_KEY | API key (overrides the config file) |
HOTDATA_WORKSPACE | Default workspace ID for the current process |
HOTDATA_DATABASE | Default instant database for the current process |
HOTDATA_API_URL | Override the API endpoint (default https://api.hotdata.dev/v1) |
HOTDATA_APP_URL | Override the app URL used for browser auth |
See also
- Quick Start — Install, authenticate, and run your first query
- API Reference — Full HTTP API documentation
- Pull Data — Supported source types