Metadata-Version: 2.5
Name: ontology-cli
Version: 0.13.4
Summary: Ontology Engine CLI and Python SDK — semantic SQL layer for 20+ data sources
Project-URL: Homepage, https://github.com/yanjin734-ltsm/ontology
Project-URL: Repository, https://github.com/yanjin734-ltsm/ontology
Author: Ontology Engine
License: Apache-2.0
Keywords: analytics,cli,data-modeling,database,datafusion,mdl,ontology,python,sdk,semantic,semantic-layer,sql
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.11
Requires-Dist: boto3>=1.26
Requires-Dist: cryptography>=48.0.1
Requires-Dist: duckdb>=1.5.0
Requires-Dist: loguru>=0.7
Requires-Dist: lxml>=6.1.0
Requires-Dist: opendal>=0.45
Requires-Dist: pandas>=2
Requires-Dist: pyarrow-hotfix>=0.6
Requires-Dist: pyarrow>=14
Requires-Dist: pyasn1>=0.6.3
Requires-Dist: pydantic>=2
Requires-Dist: pygments>=2.20.0
Requires-Dist: pyopenssl>=26.0.0
Requires-Dist: python-dotenv>=1.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: requests>=2.33.0
Requires-Dist: sqlglot>=29
Requires-Dist: typer>=0.12
Requires-Dist: urllib3>=2.7.0
Requires-Dist: wren-core-py>=0.7.5
Provides-Extra: all
Requires-Dist: clickhouse-connect>=0.8; extra == 'all'
Requires-Dist: databricks-sdk; extra == 'all'
Requires-Dist: databricks-sql-connector; extra == 'all'
Requires-Dist: google-auth; extra == 'all'
Requires-Dist: google-cloud-bigquery<4,>=3.40; extra == 'all'
Requires-Dist: inquirerpy>=0.3.4; extra == 'all'
Requires-Dist: jinja2>=3.1; extra == 'all'
Requires-Dist: lancedb>=0.6; extra == 'all'
Requires-Dist: mcp[cli]>=1.19; extra == 'all'
Requires-Dist: mysqlclient>=2.2; extra == 'all'
Requires-Dist: oracledb>=2; extra == 'all'
Requires-Dist: psycopg[binary]>=3; extra == 'all'
Requires-Dist: pyathena[pandas]>=3; extra == 'all'
Requires-Dist: pyodbc<6,>=5; extra == 'all'
Requires-Dist: pyspark>=3.5; extra == 'all'
Requires-Dist: python-multipart>=0.0.31; extra == 'all'
Requires-Dist: redshift-connector; extra == 'all'
Requires-Dist: sentence-transformers>=3.0.0; extra == 'all'
Requires-Dist: snowflake-connector-python[pandas]>=3.10; extra == 'all'
Requires-Dist: starlette>=1.3.1; extra == 'all'
Requires-Dist: trino<1,>=0.333; extra == 'all'
Requires-Dist: uvicorn>=0.29; extra == 'all'
Provides-Extra: athena
Requires-Dist: pyathena[pandas]>=3; extra == 'athena'
Provides-Extra: bigquery
Requires-Dist: google-auth; extra == 'bigquery'
Requires-Dist: google-cloud-bigquery<4,>=3.40; extra == 'bigquery'
Provides-Extra: clickhouse
Requires-Dist: clickhouse-connect>=0.8; extra == 'clickhouse'
Provides-Extra: databricks
Requires-Dist: databricks-sdk; extra == 'databricks'
Requires-Dist: databricks-sql-connector; extra == 'databricks'
Provides-Extra: interactive
Requires-Dist: inquirerpy>=0.3.4; extra == 'interactive'
Provides-Extra: main
Requires-Dist: inquirerpy>=0.3.4; extra == 'main'
Requires-Dist: jinja2>=3.1; extra == 'main'
Requires-Dist: python-multipart>=0.0.31; extra == 'main'
Requires-Dist: starlette>=1.3.1; extra == 'main'
Requires-Dist: uvicorn>=0.29; extra == 'main'
Provides-Extra: mcp
Requires-Dist: mcp[cli]>=1.19; extra == 'mcp'
Provides-Extra: memory
Requires-Dist: lancedb>=0.6; extra == 'memory'
Requires-Dist: sentence-transformers>=3.0.0; extra == 'memory'
Provides-Extra: mssql
Requires-Dist: pyodbc<6,>=5; extra == 'mssql'
Provides-Extra: mysql
Requires-Dist: mysqlclient>=2.2; extra == 'mysql'
Provides-Extra: oracle
Requires-Dist: oracledb>=2; extra == 'oracle'
Provides-Extra: postgres
Requires-Dist: psycopg[binary]>=3; extra == 'postgres'
Provides-Extra: redshift
Requires-Dist: redshift-connector; extra == 'redshift'
Provides-Extra: snowflake
Requires-Dist: snowflake-connector-python[pandas]>=3.10; extra == 'snowflake'
Provides-Extra: spark
Requires-Dist: pyspark>=3.5; extra == 'spark'
Provides-Extra: trino
Requires-Dist: trino<1,>=0.333; extra == 'trino'
Provides-Extra: ui
Requires-Dist: jinja2>=3.1; extra == 'ui'
Requires-Dist: python-multipart>=0.0.31; extra == 'ui'
Requires-Dist: starlette>=1.3.1; extra == 'ui'
Requires-Dist: uvicorn>=0.29; extra == 'ui'
Description-Content-Type: text/markdown

# ontology-cli

[![PyPI version](https://img.shields.io/pypi/v/ontology-cli.svg)](https://pypi.org/project/ontology-cli/)
[![Python](https://img.shields.io/pypi/pyversions/ontology-cli.svg)](https://pypi.org/project/ontology-cli/)
[![License](https://img.shields.io/pypi/l/ontology-cli.svg)](https://github.com/Canner/WrenAI/blob/main/LICENSE)

Ontology Engine CLI and Python SDK — semantic SQL layer for 20+ data sources.

Translate natural SQL queries through an [MDL (Modeling Definition Language)](https://docs.getwren.ai/) semantic layer and execute them against your database. Powered by [Apache DataFusion](https://datafusion.apache.org/).

## Installation

```bash
pip install ontology-cli                 # Core (DuckDB included)
pip install 'ontology-cli[postgres]'     # PostgreSQL
pip install 'ontology-cli[mysql]'        # MySQL
pip install 'ontology-cli[bigquery]'     # BigQuery
pip install 'ontology-cli[snowflake]'    # Snowflake
pip install 'ontology-cli[clickhouse]'   # ClickHouse
pip install 'ontology-cli[trino]'        # Trino
pip install 'ontology-cli[mssql]'        # SQL Server
pip install 'ontology-cli[databricks]'   # Databricks
pip install 'ontology-cli[redshift]'     # Redshift
pip install 'ontology-cli[spark]'        # Spark
pip install 'ontology-cli[athena]'       # Athena
pip install 'ontology-cli[oracle]'       # Oracle
pip install 'ontology-cli[memory]'       # Schema & query memory (LanceDB)
pip install 'ontology-cli[ui]'           # Browser-based profile form (starlette + uvicorn)
pip install 'ontology-cli[main]'         # memory + interactive prompts + ui
pip install 'ontology-cli[all]'          # All connectors + main
```

Requires Python 3.11+.

## Quick start

**1. Initialize a project** — scaffolds a YAML-based MDL project:

```bash
mkdir my-project && cd my-project
ontology context init
```

This creates `wren_project.yml`, `models/`, and `views/`. Edit `wren_project.yml` to set your `data_source` and add models under `models/`:

```yaml
# wren_project.yml
schema_version: 2
name: my_project
catalog: wren
schema: public
data_source: postgres
```

```yaml
# models/orders/metadata.yml
name: orders
table_reference:
  schema: mydb
  table: orders
columns:
  - name: order_id
    type: integer
  - name: customer_id
    type: integer
  - name: total
    type: double
  - name: status
    type: varchar
primary_key: order_id
```

> **Already have an MDL JSON?** Import it directly:
> `ontology context init --from-mdl path/to/mdl.json`

**2. Configure a connection profile:**

```bash
# Browser form (recommended, requires ontology-cli[ui])
ontology profile add my-db --ui

# Interactive terminal prompts
ontology profile add my-db --interactive

# Import from an existing connection file
ontology profile add my-db --from-file connection_info.json
```

**3. Build the manifest:**

```bash
ontology context build
```

This compiles YAML files into `target/mdl.json`. The CLI auto-discovers this file when you run queries from within the project directory.

**4. Run queries:**

```bash
ontology --sql 'SELECT order_id FROM "orders" LIMIT 10'
```

`ontology` walks up from the current directory to find `wren_project.yml` and uses `target/mdl.json`. You can also pass `--mdl path/to/mdl.json` explicitly.

For the full CLI reference and per-datasource connection field reference, see [`docs/cli.md`](docs/cli.md) and [`docs/connections.md`](docs/connections.md).

**4a. (Optional) Aggregation queries with cubes** — define cubes under `cubes/`,
then query them with a structured input instead of writing `GROUP BY` SQL by hand:

```bash
ontology cube list
ontology cube describe revenue
ontology cube query --cube revenue --measures total --time-dimension "order_date:month"
```

The translator produces `DATE_TRUNC` / `GROUP BY` / `WHERE` clauses for you and
runs them through the same engine path as `ontology --sql`. See the
[Cube guide](../../docs/core/guides/modeling/cube.md) for full YAML structure
and the [CLI reference](../../docs/core/reference/cli.md#wren-cube--pre-aggregation-queries) for all
flags.

**5. (Optional) Configure security policy** — create `~/.ontology/config.json`:

```json
{
  "strict_mode": true,
  "denied_functions": ["pg_read_file", "dblink", "lo_import"]
}
```

| Key | Default | Description |
|-----|---------|-------------|
| `strict_mode` | `false` | When `true`, every table in a query must be defined in the MDL. Queries referencing undeclared tables are rejected before execution. |
| `denied_functions` | `[]` | List of function names (case-insensitive) that are forbidden in queries. |

**6. (Optional) Index schema for semantic search** (requires `ontology-cli[memory]`):

```bash
ontology memory index                              # index MDL schema
ontology memory fetch -q "customer order price"    # fetch relevant schema context
ontology memory store --nl "top customers" --sql "SELECT ..."  # store NL→SQL pair
ontology memory recall -q "best customers"         # retrieve similar past queries
ontology memory watch                              # auto-reindex on schema/query changes
```

**7. (Optional) Build a shareable GenBI app** — turn the context layer into a
browser-side dashboard (powered by `wren-core-wasm`) and deploy it to Vercel or
Cloudflare Pages. The CLI owns the build instruction + deterministic state; an
agent authors the app from it:

```bash
ontology genbi build sales --prompt "orders dashboard" --data-mode snapshot  # print build instruction
# agent authors apps/sales/ from the instruction (mdl.json + data/*.parquet)
ontology genbi register sales --data-mode snapshot   # record the app
ontology genbi verify sales                          # preflight (files, MDL, data, secret scan)
ontology genbi open sales                            # local preview
ontology genbi deploy sales --provider vercel        # ship a shareable URL (preview; --prod for production)
```

Tokens come from the env / `.env` (`VERCEL_TOKEN` / `CLOUDFLARE_API_TOKEN`),
never CLI flags; Cloudflare needs `wrangler` installed. See the
[GenBI guide](../../docs/core/guides/genbi.md) and the
[CLI reference](../../docs/core/reference/cli.md#wren-genbi--build--deploy-genbi-apps).

**8. (Optional) Serve an MCP server** — expose the project's query, schema, and
knowledge tools to Claude Desktop/Code, Cursor, or any MCP client. Runs
in-process against the compiled MDL — no ibis-server, no separate service:

```bash
ontology serve mcp                                # stdio (default) — client spawns this as a child process
ontology serve mcp --transport http --port 8080   # local Streamable HTTP for other clients
```

Requires `ontology context build` to have already run and the `mcp` extra:
`pip install 'ontology-cli[mcp]'`. See the
[MCP guide](../../docs/core/guides/mcp.md) and the
[CLI reference](../../docs/core/reference/cli.md#wren-serve--mcp-server) for
the full tool/resource list and client wiring.

---

## Connection profiles

Profiles let you store named connection configurations in `~/.ontology/profiles.yml` and switch between them easily — useful when working across multiple databases or environments.

```bash
# Add a profile (browser form, interactive prompts, or file import)
ontology profile add prod --ui                        # opens http://localhost:<port>
ontology profile add staging --interactive            # terminal prompts
ontology profile add local --from-file conn.json      # import existing file

# List and switch profiles
ontology profile list                                 # * marks the active profile
ontology profile switch prod

# Inspect a profile (sensitive fields masked)
ontology profile debug prod

# Remove a profile
ontology profile rm old-profile --force
```

The `--ui` flag opens a browser-based form that auto-derives fields from each datasource's schema — including file upload for BigQuery credentials, variant selection for Databricks/Redshift, and sensible defaults for all 20+ supported sources. Requires `pip install 'ontology-cli[ui]'`.

Once a profile is active, `ontology` uses it automatically:

```bash
ontology profile switch prod
ontology --sql 'SELECT COUNT(*) FROM "orders"'        # connects using prod profile
```

---

## Python SDK

```python
import base64, orjson
from wren import WrenEngine, DataSource

manifest = { ... }  # your MDL dict
manifest_str = base64.b64encode(orjson.dumps(manifest)).decode()

with WrenEngine(manifest_str, DataSource.mysql, {"host": "...", ...}) as engine:
    result = engine.query('SELECT * FROM "orders" LIMIT 10')
    print(result.to_pandas())
```

---

## Development

Prerequisites: `just` and `uv`. (Rust + Cargo are only needed for the
local-engine recipes below.)

### Standard setup (no Rust toolchain)

```bash
just install        # uv sync — pulls the prebuilt wren-core-py wheel from PyPI
just lint           # Ruff format check + lint
just format         # Auto-fix
```

`just install` is a plain `uv sync`: it installs the locked prebuilt `wren-core-py` engine binding and the development tools from uv's default `dev` dependency group. No compilation required. This is enough for all Python-side development. Use `just install-extra <extra>` or `just install-all` for data-source extras.

### Engine development (changing the Rust core)

Only needed when you modify `../wren-core-py` (or `../wren-core`) and want
`core/wren` to run against your local build. Requires Rust + Cargo.

```bash
just install-local    # uv sync + build the local wheel + overlay it into .venv
just use-local-core   # rebuild + re-overlay after each subsequent Rust change
```

The run recipes (`just test*`, `just lint`, `just dev`) use `uv run --no-sync`,
so they never revert a locally overlaid engine back to the lockfile version. If
dependencies change, re-run an install recipe first.

| Command | What it runs | Docker needed |
|---------|-------------|---------------|
| `just test-unit` | Unit tests (engine, CTE rewriter, field registry, profiles) | No |
| `just test-duckdb` | DuckDB connector tests | No |
| `just test-postgres` | PostgreSQL connector tests | Yes |
| `just test-mysql` | MySQL connector tests | Yes |
| `just test` | All tests | Yes |

Profile web tests (`test_profile_web.py`) require `ontology-cli[ui]`:

```bash
uv sync --extra ui
uv run --no-sync pytest tests/test_profile_web.py -v
```

## Publishing

```bash
./scripts/publish.sh            # Build + publish to PyPI
./scripts/publish.sh --test     # Build + publish to TestPyPI
./scripts/publish.sh --build    # Build only
```

## Package identity

This distribution is **ontology-cli** (Ontology Engine). It is a fork of
WrenAI (Apache-2.0) by Canner, Inc. Internal Python imports remain `import wren`.
The engine dependency remains upstream `wren-core-py`.

- CLI entrypoint: `ontology` (not `wren`)
- Home directory: `~/.ontology` via `ONTOLOGY_HOME` (no fallback to `~/.wren`)
- PyPI name: `ontology-cli` (not published in v0)

```bash
pip install -e ./core/wren
ontology --version                      # ontology-cli 0.13.4
```

## License

Apache-2.0
