<!-- markdownlint-disable MD024 -->

# RelationalAI CLI Reference

The RelationalAI Command Line Interface (CLI) is used to initialize RelationalAI projects and manage project resources.

## Installation

The CLI is bundled with the RelationalAI Python Package.
See [Install the `relationalai` Python Package](../../getting_started.md#install-the-relationalai-python-package) for details.

## Basic Usage

The CLI is invoked using the `rai` command.
Execute `rai` without any arguments to see a list of all available commands:

```sh
rai
```

> [!IMPORTANT]
> If you encounter the error `command not found: rai`, you may need to activate your project's virtual environment.

To execute a command, type `rai`, followed by the command name and any arguments you want to pass.
For example, the following creates a new RelationalAI engine named `my-engine` of size `S`:

```sh
rai engines:create --name my-engine --size S
```

To view help for a command, use the `--help` flag:

```sh
rai engines:create --help
```

## Commands

### `init`

```sh
rai init
```

Initialize a RelationalAI project.

`rai init` walks you through setting up a RelationalAI project,
connecting to a cloud platform, and saving a configuration file.

The first time you run `rai init`, you will be prompted to enter your connection information:

- **For Snowflake:** Enter your Snowflake username and password.
  Then, select the Snowflake account and role to use for the project.
  The account must have the RelationalAI Native App installed and the role must be granted permission to use the app.
  Finally, select the RelationalAI native app and Snowflake compute warehouse to use with your project.
- **For Azure:** Enter your RelationalAI OAuth client ID and client secret.
  See [RAI Accounts, User Profiles, and OAuth Clients](https://docs.relational.ai/preview/snowflake/integration-management/accounts)
  for more information.

Connection information and other settings are saved in a `raiconfig.toml` file in the same directory from which `rai init` is run.
You have the option of saving your settings as the default configuration profile or as a named profile.

The next time you invoke `rai init`, the current working directory and its parents are searched for a `raiconfig.toml` file.
If an existing configuration file is found, settings from the default profile are presented as suggestions.
You may override these suggestions as needed.

### `debugger`

```sh
rai debugger
```

Launch the RelationalAI debugger.

Invoke `rai debugger` from the same directory from which you execute your project.
As your project runs, debugging information is emitted to a `debug.jsonl` file in your current working directory.
The contents of this file are read by a local web server which you can view at `http://localhost:8080`.

The debugger shows the RelationalAI graph queries generated by your Python query builder code
and is primarily intended for internal use.

### `engines:list`

```sh
rai engines:list
```

List all available RelationalAI engines.

### `engines:create`

```sh
rai engines:create [OPTIONS]
```

Create a new RelationalAI engine.

All RelationalAI projects require a RelationalAI engine,
which is a cloud virtual machine that executes RelationalAI graph queries.
Engines are typically created and/or selected when you initialize your project with [`rai init`](#init).
Use `rai engines:create` to create a new engine without re-initializing your entire project.

#### Options

| Option | Type | Required | Description |
| :--- | :--- | :--- | :------ |
| `--name` | String | Yes | The name of the engine. Must be at least three characters. May only contain letters, numbers, and underscores. |
| `--size` | String | Yes | The size of the engine. Must be one of `XS`, `S`, `M`, or `L`. |

#### Example

Create an engine named `my-engine` with size `S`:

```sh
rai engines:create --name my-engine --size S
```

### `engines:delete`

```sh
rai engines:delete [OPTIONS]
```

Delete a RelationalAI engine.

All RelationalAI projects require a RelationalAI engine,
which is a cloud virtual machine that executes RelationalAI graph queries.
Engines are typically created and/or selected when you initialize your project with [`rai init`](#init).
Use `rai engines:delete` to delete a RelationalAI engine that you no longer need.

#### Options

| Option | Type | Required | Description |
| :--- | :--- | :--- | :------ |
| `--name` | String | Yes | The name of the engine to be deleted. |

#### Example

Delete the engine named `my-engine`:

```sh
rai engines:delete --name my-engine
```

### `imports:list`

```sh
rai imports:list [OPTIONS]
```

List objects imported into a RelationalAI model.

#### Options

| Option | Type | Required | Description |
| :--- | :--- | :--- | :------ |
| `--model` | String | No | The name of the [model](../python/Model/README.md) for which imports are filtered. |

#### Example

List all objects imported into any RelationalAI model:

```sh
rai imports:list
```

List all objects imported into the RelationalAI model `myModel`:

```sh
rai imports:list --model myModel
```

### `imports:snapshot`

```sh
rai imports:snapshot [OPTIONS] [schema:<col_name>=<type>, ...]
```

Load data from a CSV file into a RelationalAI model.

> [!IMPORTANT]
> `imports:snapshot` is only available for Azure-based models.

#### Options

| Option | Type | Required | Description |
| :--- | :--- | :--- | :------ |
| `--source` | String | No | The path to the CSV file to import. |
| `--model` | String | No | The name of the [model](../python/Model/README.md) in which to import the data. |
| `--name` | String | No | The name to assign to the resource in the model. Defaults to the file name, including the extension. |
| `--type` | String | No | The file type. May be one of `"auto"` (default) or `"csv"`. |

#### Arguments

<!-- markdownlint-disable no-inline-html -->

| Argument | Required | Description |
|---|---|---|
| `schema:<col_name>=<type>` | No | Set the type of the column named `<col_name>` to `<type>`.<br><br>`<type>` may be one of:<br><br>- `string`<br>- `boolean`<br>- `int`<br>- `float` |

<!-- markdownlint-enable no-inline-html -->

#### Example

Run `rai imports:snapshot` without any arguments to use the built-in CLI prompts to select and upload a file.
After you select the model to use and the file to upload, you are asked to provide a resource name,
which defaults to the name of the file, and verify the file's schema:

```sh
$ rai imports:snapshot

---------------------------------------------------
 
▰▰▰▰ Models fetched   

? Select a model: myModel

? Select a file: data/transactions.csv
? name: transactions.csv
                                  
  Field    Type     Ex.           
 ──────────────────────────────── 
  id       String   TXN-00004052  
  date     String   2023-10-12    
  from     String   P-00013130    
  to       String   P-00015417    
  amount   Number   5214          
                                  
? Use this schema for transactions.csv: Yes
▰▰▰▰ Snapshot for transactions.csv created   

---------------------------------------------------
```

Use the `--source`, `--model`, and `--name` flags to load a file without interactively selecting the file, model, and resource name.
You must still interactively confirm the schema of the file:

```sh
$ rai imports:snapshot --source data/transactions.csv --model myModel --name transactions

---------------------------------------------------
                                  
  Field    Type     Ex.           
 ──────────────────────────────── 
  id       String   TXN-00004052  
  date     String   2023-10-12    
  from     String   P-00013130    
  to       String   P-00015417    
  amount   Number   5214          
                                  
? Use this schema for transactions: Yes
▰▰▰▰ Snapshot for transactions created   

---------------------------------------------------
```

To change the default schema, pass additional command-line arguments of the form `schema:<column_name>=<type>`.
For example, to use `string` for the `amount` column, pass the arg `schema:amount=string`.
As usual, you are asked to verify the schema before the snapshot is uploaded:

```sh
$ rai imports:snapshot --source data/transactions.csv --model myModel --name transactions schema:amount=string

---------------------------------------------------
 
? name: transactions.csv
                                  
  Field    Type     Ex.           
 ──────────────────────────────── 
  id       String   TXN-00004052  
  date     String   2023-10-12    
  from     String   P-00013130    
  to       String   P-00015417    
  amount   String   5214          
                                  
? Use this schema for transactions: Yes
▰▰▰▰ Snapshot for transactions created   

---------------------------------------------------
```

You may provide multiple `schema:*` arguments to customize the schema as needed.

Once you create the snapshot, you may add objects from the file to your model in
a [`model.read()`](../python/Model/read.md) context:

```python
import relationalai as rai

model = rai.Model("myModel")
Transaction = model.Type("Transaction")

# Create `Transaction` objects from the rows of the "transactions.csv" resource.
with model.read("transactions.csv") as row:
    # Columns, like `id`, are accessed as attributes of the `row` object.
    transaction = Transaction.add(id=row.id)
    # If a column name is a Python keyword, such as the `from` column, use `getattr()`.
    transaction.set(
        date=row.date,
        from_=getattr(row, "from"),
        to=row.to
    )
```

In the preceding example, `from` is a [Python keyword](https://docs.python.org/3/reference/lexical_analysis.html#keywords),
so accessing `row.from` raises a `SyntaxError`.
To circumvent this, rename the column in the file or use Python's built-in
[`getattr()`](https://docs.python.org/3/library/functions.html#getattr) function.

### `imports:stream`

```sh
rai imports:stream [OPTIONS]
```

Stream data from a Snowflake table or view into RelationalAI.

An import stream utilizes [change data capture](https://docs.snowflake.com/en/user-guide/streams) technology
to synchronize your Snowflake data with your RelationalAI model at an interval of once per minute.

#### Options

| Option | Type | Required | Description |
| :--- | :--- | :--- | :------ |
| `--source` | String | Yes | The [fully-qualified name](https://docs.snowflake.com/en/sql-reference/name-resolution) of a Snowflake table or view. |
| `--model` | String | Yes | The name of the [model](../python/Model/README.md) to which the data in the Snowflake table or view is streamed. |

#### Example

Stream the data from the Snowflake table `my_database.my_schema.my_table`
to the RelationalAI model `myModel`:

```sh
rai imports:stream --object my_database.my_schema.my_table --model myModel
```

Once the stream is finished setting up,
data from the table may be accessed using the `relationalai` Python package:

```python
import relationalai as rai
from relationalai.clients.snowflake import Snowflake

model = rai.Model("myModel")

# Initialize a Snowflake object with your model.
sf = Snowflake(model)

# Access `my_table` as a Python object.
MyTable = sf.my_database.my_schema.my_table
```

### `imports:delete`

```sh
rai imports:delete [OPTIONS]
```

Delete a table or view imported from Snowflake.

Once deleted, data from the Snowflake table or view is no longer available to the RelationalAI model.
No data is removed from Snowflake.

#### Options

| Option | Type | Required | Description |
| :--- | :--- | :--- | :------ |
| `--object` | String | Yes | The [fully-qualified name](https://docs.snowflake.com/en/sql-reference/name-resolution) of the Snowflake table or view to remove from your imports. |
| `--model` | String | Yes | The name of the [model](../python/Model/README.md) to which the data in the Snowflake table or view is streamed. |

#### Example

Delete the data imported from `my_database.my_schema.my_table` to the RelationalAI model `myModel`:

```sh,
rai imports:delete --object my_database.my_schema.my_table --model myModel
```

### `exports:list`

```sh
rai exports:list [OPTIONS]
```

List all of the SQL objects, such as stored procedures, exported from RelationalAI to Snowflake.

#### Options

| Option | Type | Required | Description |
| :--- | :--- | :--- | :------ |
| `--model` | String | No | The name of the [model](../python/Model/README.md) from which exports originate. |

#### Example

List all exports:

```sh
rai exports:list
```

List all exports from the RelationalAI model named `myModel`:

```sh
rai exports:list --model myModel
```

### `exports:delete`

```sh
rai exports:delete [OPTIONS]
```

Delete a SQL object, such as a stored procedure, that has been exported from RelationalAI to Snowflake.

#### Options

| Option | Type | Required | Description |
| :--- | :--- | :--- | :------ |
| `--export` | String | Yes | The [fully-qualified name](https://docs.snowflake.com/en/sql-reference/name-resolution) of the exported Snowflake object. |
| `--model` | String | Yes | The name of the [model](../python/Model/README.md) from which the export originates. |

#### Example

Delete the stored procedure named `my_export` generated by the RelationalAI model `myModel`:

```sh
rai exports:delete --export my_database.my_schema.my_export --model myModel
```
