> ## Documentation Index
> Fetch the complete documentation index at: https://infino.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Infino CLI: create tables, ingest, and search

> The infino command-line interface — create tables, ingest data, and run BM25, vector, and SQL search from your terminal or a coding agent.

`infino` is the command-line interface to the retrieval engine: SQL, full-text
(BM25), and vector search over a single copy of your data on object storage, run
straight from your terminal — or driven by a coding agent. It wraps the same
engine as the [Python, Node, and Rust SDKs](/docs/quickstart); there's nothing extra
to run.

## Install

<CodeGroup>
  ```bash Homebrew theme={null}
  brew install infino-ai/tap/infino-cli
  ```

  ```bash npm theme={null}
  npm install -g @infino-ai/infino-cli   # or run once with: npx @infino-ai/infino-cli
  ```

  ```bash cargo theme={null}
  cargo install infino-cli
  ```

  ```bash shell theme={null}
  curl --proto '=https' --tlsv1.2 -LsSf \
    https://github.com/infino-ai/infino-cli/releases/latest/download/infino-cli-installer.sh | sh
  ```
</CodeGroup>

All install the `infino` binary. Check it landed:

```bash theme={null}
infino --version   # prints e.g. `infino 0.6.0`
```

<Note>
  On npm 11 and later the install prints a warning that it blocked a
  `postinstall` script. That is expected and the install is fine: the platform
  binary is fetched on first run instead. If you would rather avoid the warning,
  use Homebrew or the shell installer.
</Note>

## Connect

Every command targets a storage location with `--uri` (or the `INFINO_URI`
environment variable):

| `--uri`                     | Storage                                           |
| --------------------------- | ------------------------------------------------- |
| `memory://`                 | in-process, ephemeral                             |
| `file://<path>`             | local disk                                        |
| `s3://<bucket>/<prefix>`    | Amazon S3 (or S3-compatible: MinIO, Ceph, RustFS) |
| `az://<container>/<prefix>` | Azure Blob                                        |
| `gs://<bucket>/<prefix>`    | Google Cloud Storage                              |
| `https://<host>/<database>` | [Infino Cloud](/docs/cloud/quickstart)                 |

Cloud credentials are passed explicitly with `--storage-option KEY=VALUE`
(repeatable), keyed by object\_store's config strings — the same `storage_options`
map the [SDKs](/docs/api-reference) take. Nothing is read from `AWS_*` / `AZURE_*`;
omit them to use ambient cloud identity (IAM role / managed identity).

```bash theme={null}
infino table ls --uri s3://my-bucket \
  --storage-option aws_access_key_id=… \
  --storage-option aws_secret_access_key=… \
  --storage-option aws_region=us-east-1 \
  --storage-option aws_endpoint=https://minio.internal:9000   # S3-compatible
```

Add `--validate` to any command to fail fast at connect on bad credentials or an
unreachable endpoint, instead of on the first query.

### Infino Cloud

Point `--uri` at your `https://api.platform.infino.ws/<database>` URL and pass an
API key with `--api-key` (or the `INFINO_API_KEY` environment variable). Every
command is identical to local use — only the `--uri` changes. Provision the
database once with `database create`:

```bash theme={null}
export INFINO_API_KEY=inf_…
infino database create --uri https://api.platform.infino.ws/my-app
infino bm25-search docs body "object storage" -k 10 --uri https://api.platform.infino.ws/my-app
```

<Note>
  `--fields` names the columns to return, and it is worth passing on every search:
  without it a search returns `_id` and `score` only, never your text. On Infino
  Cloud `vector-search` requires it; everywhere else it is optional but usually
  what you want. See the hosted [Quickstart](/docs/cloud/quickstart) and
  [Authentication](/docs/cloud/authentication).
</Note>

## Quickstart

A table becomes durable on its first commit, so `table create` loads initial
rows too: either from a Parquet file (`--from-parquet`, which also infers the
schema) or from a YAML schema plus a data file. Taking the second path, write
the two input files first.

<CodeGroup>
  ```yaml schema.yaml theme={null}
  - { name: id, type: int64 }
  - { name: body, type: large_utf8 }
  ```

  ```json seed.ndjson theme={null}
  {"id": 1, "body": "Infino stores your data on object storage and searches it in place."}
  {"id": 2, "body": "One copy of the data serves SQL, full-text, and vector search."}
  ```

  ```json more.ndjson theme={null}
  {"id": 3, "body": "A table becomes durable on its first commit."}
  ```
</CodeGroup>

The schema is a list of `{name, type}` columns (see [column
types](#column-types)); a full-text index needs a `large_utf8` column. Each line
of the `.ndjson` file is one row, keyed by column name.

```bash theme={null}
# Create the table and load its first rows (body full-text indexed)
infino table create docs --uri file://./data --schema schema.yaml --fts body --file seed.ndjson
# created table `docs` with 2 rows

# Append more rows from another NDJSON file
infino row insert docs --uri file://./data --file more.ndjson --format ndjson

# Search. `--fields` names the columns to return; without it you get
# `_id` and `score` only.
infino bm25-search docs body "object storage" -k 10 --fields _id,body --uri file://./data
```

```
+----------------------------------+---------------------------------------------------------------------+
| _id                              | body                                                                |
+----------------------------------+---------------------------------------------------------------------+
| 32964926044218061712633356091392 | Infino stores your data on object storage and searches it in place. |
+----------------------------------+---------------------------------------------------------------------+
```

```bash theme={null}
# SQL over the same table
infino query "SELECT id, body FROM docs LIMIT 10" --uri file://./data --output json
```

### Column types

Use these in a `--schema` YAML file. `nullable: true` is optional per column.

| Type                               | Notes                                               |
| ---------------------------------- | --------------------------------------------------- |
| `int8` `int16` `int32` `int64`     | `int` is an alias for `int64`                       |
| `uint8` `uint16` `uint32` `uint64` |                                                     |
| `float32` `float64`                | `float` and `double` are aliases                    |
| `utf8`                             | short strings; `string` and `str` are aliases       |
| `large_utf8`                       | text; **required for a full-text (`--fts`) column** |
| `bool`                             | `boolean` is an alias                               |
| `date32`                           | days since the Unix epoch                           |
| `fixed_size_list<float32,N>`       | a vector column of dimension `N`, for `--vector`    |

## Commands

Commands are grouped by what they act on. `query` and the search commands stay
at the top level, since those are what a session mostly runs.

| Command                       | Description                                                                          |
| ----------------------------- | ------------------------------------------------------------------------------------ |
| `table create`                | Create a table and load initial rows; declare `--fts` / `--vector` indexes           |
| `table ls` / `table describe` | List tables / show a table's schema                                                  |
| `table rm`                    | Remove a table and reclaim its storage (`--keep-storage` leaves the bytes)           |
| `table optimize`              | Compact a table                                                                      |
| `table gc`                    | Reclaim orphaned storage objects (requires durable storage)                          |
| `row insert`                  | Append rows from Parquet or NDJSON (file or stdin)                                   |
| `row update` / `row delete`   | Change or remove rows matching a `--where` SQL predicate                             |
| `database create`             | Provision an [Infino Cloud](/docs/cloud/quickstart) database (a no-op for local backends) |
| `bm25-search`                 | Ranked keyword (BM25) search                                                         |
| `vector-search`               | Vector similarity (kNN) search                                                       |
| `hybrid-search`               | Hybrid BM25 + vector search, fused with reciprocal-rank fusion                       |
| `token-match` / `exact-match` | Unranked token / exact-value match                                                   |
| `count`                       | Count rows matching a keyword query, without fetching them                           |
| `query`                       | Run SQL, including the `bm25_search()` / `vector_search()` table functions           |
| `skills install`              | Install the bundled agent skills for Claude Code / Cursor                            |

<Note>
  The commands were flat before 0.6.0 (`create-table`, `tables`, `ingest`, and so
  on). The old names still parse and report their replacement, so an existing
  script tells you what to change rather than failing with a generic error. They
  will be removed in a later release.
</Note>

Run `infino <command> --help` for the full flags. Every row-returning command
takes `--output table` (default), `json`, or `csv`.

## Vector search

The CLI does not embed text — embed your query with your own model and pass the
vector as a JSON array (or `-` for stdin):

```bash theme={null}
infino vector-search docs embedding --vector-file query.json -k 10 --uri file://./data
```

Declare the column as `fixed_size_list<float32,384>` in the schema and index it
when you create the table: `--vector embedding:384:cosine`
(`column:dim:metric`). Pass `--fields` here too, or results come back as `_id`
and `score` alone.

## Agent skills

`infino skills install` writes skill files into `~/.claude/skills` so coding
agents (Claude Code, Cursor) can drive the CLI in natural language:

```bash theme={null}
infino skills install
infino skills status
```

This complements the [MCP server](/docs/integrations/mcp): skills are for shell-native
agents, MCP is for tool-calling agents.

## Learn more

* Source, issues, and releases: [github.com/infino-ai/infino-cli](https://github.com/infino-ai/infino-cli)
* Packages: [crates.io](https://crates.io/crates/infino-cli) · [npm](https://www.npmjs.com/package/@infino-ai/infino-cli)
