nao CLI
Command-line interface for nao chat.
Installation
Install the core package (lightweight, no database or LLM dependencies):
pip install nao-core
Then add only the providers you need:
# Database backends
pip install 'nao-core[postgres]'
pip install 'nao-core[bigquery]'
pip install 'nao-core[snowflake]'
pip install 'nao-core[duckdb]'
pip install 'nao-core[clickhouse]'
pip install 'nao-core[databricks]'
pip install 'nao-core[mysql]'
pip install 'nao-core[mssql]'
pip install 'nao-core[athena]'
pip install 'nao-core[trino]'
pip install 'nao-core[redshift]'
pip install 'nao-core[fabric]'
pip install 'nao-core[starrocks]'
# LLM providers
pip install 'nao-core[openai]'
pip install 'nao-core[anthropic]'
pip install 'nao-core[mistral]'
pip install 'nao-core[gemini]'
pip install 'nao-core[ollama]'
# Integrations
pip install 'nao-core[notion]'
# Semantic layer (dbt MetricFlow)
pip install 'nao-core[semantic-layer]'
Obsidian support is included in the core package and does not require an extra.
Combine multiple extras in a single install:
pip install 'nao-core[postgres,openai]'
pip install 'nao-core[snowflake,bigquery,anthropic]'
Or install everything at once (equivalent to the previous default):
pip install 'nao-core[all]'
Convenience groups are also available:
pip install 'nao-core[all-databases]' # all database backends
pip install 'nao-core[all-llms]' # all LLM providers
Usage
nao --help
Usage: nao COMMAND
╭─ Commands ────────────────────────────────────────────────────────────────╮
│ chat Start the nao chat UI. │
│ debug Test connectivity to configured resources. │
│ init Initialize a new nao project. │
│ sync Sync resources to local files. │
│ test Run and explore nao tests. │
│ --help (-h) Display this message and exit. │
│ --version Display application version. │
╰───────────────────────────────────────────────────────────────────────────╯
Initialize a new nao project
nao init
This will create a new nao project in the current directory. It will prompt you for a project name and ask you to configure:
- Database connections (BigQuery, DuckDB, MotherDuck, DuckLake, Databricks, Snowflake, PostgreSQL, Redshift, MSSQL, Trino, StarRocks)
- Git repositories to sync
- LLM provider (OpenAI, Anthropic, Mistral, Gemini, OpenRouter, Requesty, Ollama)
ai_summarytemplate + model (prompted only when you enableai_summaryfor databases)- Slack integration
- Notion integration
The resulting project structure looks like:
<project>/
├── nao_config.yaml
├── .naoignore
├── RULES.md
├── databases/
├── queries/
├── docs/
├── semantics/
├── repos/
├── agent/
│ ├── tools/
│ └── mcps/
└── tests/
Options:
--force/-f: Force re-initialization even if the project already exists--yes/-y/--no-tty: Run non-interactively. Skips all prompts and uses sensible defaults — useful for AI agents and automation scripts. When combined with a pre-writtennao_config.yaml(e.g. written by an agent skill), only scaffolds the folder structure.--name/-n: Project name. When set without an existingnao_config.yaml, this is used as the project name (and folder). In--yesmode without--name, the current directory name is used and the project is initialized in place.
Non-interactive (agent-friendly) mode
For LLM agents and automation, run nao init without any prompts:
# Initialize the current directory as a nao project (uses the directory name)
nao init --yes
# Or create a new sub-folder named "my-project"
nao init --yes --name my-project
# Pre-write nao_config.yaml then scaffold folders without prompting
cat > nao_config.yaml <<'YAML'
project_name: my-project
databases:
- type: duckdb
name: local
path: ":memory:"
YAML
nao init --yes
# MotherDuck (DuckDB-compatible cloud) — token via env recommended
cat > nao_config.yaml <<'YAML'
project_name: my-project
databases:
- type: motherduck
name: md-analytics
database: my_db
token: "{{ env('MOTHERDUCK_TOKEN') }}"
YAML
nao init --yes
# DuckLake — a postgres or mysql catalog is recommended for concurrent access;
# file-based catalogs (duckdb/sqlite) allow only a single connection at a time.
# The session denies local filesystem and network access once the lake is
# attached, so queries can only read the configured lake, not arbitrary files.
cat > nao_config.yaml <<'YAML'
project_name: my-project
databases:
- type: ducklake
name: lake
catalog:
type: postgres
host: localhost
port: 5432
database: ducklake_catalog
user: "{{ env('DUCKLAKE_CATALOG_USER') }}"
password: "{{ env('DUCKLAKE_CATALOG_PASSWORD') }}"
data_path: "s3://my-bucket/lake/"
storage:
type: s3
key_id: "{{ env('AWS_ACCESS_KEY_ID') }}"
secret: "{{ env('AWS_SECRET_ACCESS_KEY') }}"
region: eu-west-1
YAML
nao init --yes
In non-interactive mode, nao init never asks for input. Configure databases, LLM provider, and integrations by editing nao_config.yaml directly (or by pre-writing it before nao init).
Start the nao chat UI
nao chat
This will start the nao chat UI. It will open the chat interface in your browser at http://localhost:5005.
To let the agent run code in a micro-VM, download the sandbox runtime once with nao chat --sandbox, then enable
Sandboxes in Settings → Experimental. The runtime and the DuckDB engine used by nao test are ~100 MB each, so they
are not shipped in the package: nao fetches them on first use and caches them in ~/.nao/native. Set
NAO_NATIVE_REGISTRY to download them from an npm mirror instead of registry.npmjs.org.
Test connectivity
nao debug
Tests connectivity to all configured databases and LLM providers. Displays a summary table showing connection status and details for each resource.
Sync resources
nao sync
Syncs configured resources to local files:
- Databases - generates configured markdown docs for each table into
databases/(columns.mdandpreview.mdby default; optionalprofiling.md,query_history.md, andai_summary.md) - Git repositories — clones or pulls repos into
repos/ - Notion pages — exports pages as markdown into
docs/notion/. Databases are exported as markdown tables, whether configured directly or embedded inline in a page. A database embedded in a page is exported through one of its views — Notion exposes no way to tell which view a page renders, so the first one listed is used — applying that view's filters, sorts and visible columns rather than dumping the whole data source. A database configured by URL exports every row and column, unless the URL carries?v=<view_id>, in which case that view applies. When a database cannot be exported, its page fails to sync and the previously synced markdown is left untouched, rather than being rewritten without its table. - Obsidian notes — copies markdown notes from a local vault into
docs/obsidian/, skipping hidden folders such as.obsidian/and.trash/
After syncing, any Jinja templates (*.j2 files) in the project directory are rendered with the nao context.
Optional ai_summary generation:
- Add
ai_summaryto a database connectiontemplateslist to renderai_summary.md. - AI summaries use profiling statistics for data-quality and distribution observations. The row preview is a tiny, non-representative shape sample.
- Use
prompt("...")inside Jinja templates to generateai_summarycontent. prompt(...)requires anllm.providersentry with anapi_key(except for ollama), plusllm.annotation_model.- Configure
profilingandai_summaryrefreshes independently withrefresh_policy: always,once, orinterval. Interval policies also acceptinterval_days(default:7):
databases:
- type: duckdb
name: analytics
path: analytics.duckdb
templates: [columns, preview, profiling, ai_summary]
profiling:
refresh_policy: once
ai_summary:
refresh_policy: interval
interval_days: 7
Log in
nao login
Connects the CLI to your nao account: it opens the app in your browser, asks you to approve the CLI, and stores the resulting session. Commands that talk to the backend (like nao test) trigger the same browser flow automatically when you are not logged in yet, and fall back to an email/password prompt when no browser is available. Use nao logout to revoke the stored session.
Run tests
nao test
Runs test cases defined as YAML files in tests/. Each test has a name, prompt, and optional expected sql and/or assertions. Results are saved to tests/outputs/.
Final-output checks use reference sql (dataframe equality). Intermediate agent actions use assertions against the run's tool-call trace — for example, requiring a clarifying follow-up:
name: ambiguous_revenue_period
prompt: What was the revenue?
assertions:
- type: tool_call
tool: clarification
tool_call assertions can also require a specific tool (e.g. execute_sql), optional arg subset match via args (omit it to match any call; an empty mapping is rejected), and min_count. SQL verification and assertions can be combined; the run passes only if every check passes. A test file with an invalid assertions block fails the whole run instead of being skipped.
Options:
--model/-m: Models to test against (default:openai:gpt-4.1). Can be specified multiple times.--threads/-t: Number of parallel threads (default:1)--k/-k: Number of times to run each test case, used to compute pass@k and pass^k (default:1)--select/-s: Run only selected tests by name, yaml stem, or subfolder. Comma-separated.--username/-u,--password: Credentials for the nao backend, for non-interactive runs. Fall back toNAO_USERNAME/NAO_PASSWORD. When omitted, the CLI uses your stored login or opens the browser login flow.
Examples:
nao test -m openai:gpt-4.1
nao test -m openai:gpt-4.1 -m anthropic:claude-sonnet-4-20250514
nao test --threads 4
nao test --k 5
Defaults for every run live in the test block of nao_config.yaml, and the --model / --threads / --k flags override them:
test:
models:
- openai:gpt-4.1
- anthropic:claude-sonnet-4-5
threads: 4
# k: 5 # run each case 5 times to compute pass@k / pass^k
comparison:
rtol: 0.00001
atol: 0.00000001
decimals: 2
Explore test results
nao test server
Starts a local web server to explore test results in a browser UI showing pass/fail status, token usage, cost, and detailed data comparisons.
Options:
--port/-p: Port to run the server on (default:8765)--no-open: Don't automatically open the browser
BigQuery service account permissions
When you connect BigQuery during nao init, the service account used by credentials_path/ADC must be able to list datasets and run read-only queries to generate docs. Grant the account:
- Project:
roles/bigquery.jobUser(orroles/bigquery.user) so the CLI can submit queries - Each dataset you sync:
roles/bigquery.dataViewer(or higher) to read tables
The combination above mirrors the typical "BigQuery User" setup and is sufficient for nao's metadata and preview pulls.
Snowflake authentication
Snowflake supports three authentication methods during nao init:
- SSO: Browser-based authentication (recommended for organizations with SSO policies)
- Password: Traditional username/password
- Key-pair: Private key file with optional passphrase
Development
Building the package
cd cli
python build.py --help
Usage: build.py [OPTIONS]
Build and package nao-core CLI.
╭─ Parameters ──────────────────────────────────────────────────────────────────╮
│ --force -f --no-force Force rebuild the server binary │
│ --skip-server -s --no-skip-server Skip server build, only build Python pkg │
│ --bump Bump version (patch, minor, major) │
╰───────────────────────────────────────────────────────────────────────────────╯
This will:
- Build the frontend with Vite
- Compile the backend with Bun into a standalone binary
- Bundle everything into a Python wheel in
dist/
Installing for development
cd cli
pip install -e '.[all]'
Publishing to PyPI
# Build first
python build.py
# Publish
uv publish dist/*
Architecture
nao chat (CLI command)
↓ spawns
nao-chat-server (Bun-compiled binary, port 5005)
+ FastAPI server (port 8005)
↓ serves
Backend API + Frontend Static Files
↓
Browser at http://localhost:5005
Metadata
Release files for nao-core 0.3.22
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| nao_core-0.3.22-py3-none-win_amd64.whl | Python 3 | none | Windows x86-64 | Details |
| nao_core-0.3.22-py3-none-manylinux2014_x86_64.whl | Python 3 | none | Linux glibc 2.17+ x86-64 | Details |
| nao_core-0.3.22-py3-none-manylinux2014_aarch64.whl | Python 3 | none | Linux glibc 2.17+ ARM64 | Details |
| nao_core-0.3.22-py3-none-macosx_15_0_x86_64.whl | Python 3 | none | macOS 15.0+ x86-64 | Details |
| nao_core-0.3.22-py3-none-macosx_15_0_arm64.whl | Python 3 | none | macOS 15.0+ ARM64 | Details |
Total release size: 344.3 MB
Release files / nao_core-0.3.22-py3-none-win_amd64.whl
| Download URL | nao_core-0.3.22-py3-none-win_amd64.whl |
|---|---|
| Size | 76.8 MB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
4173cebbc663829d1bb34c0c6c3323cebd02042b3af715301d875629e967342b
|
|
BLAKE2b-256 checksum How to use checksums |
4faa5bb1df56ec763dac6366ce7cf441d9f8593323f3d14b69205fb2a68a4a21
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / nao_core-0.3.22-py3-none-manylinux2014_x86_64.whl
| Download URL | nao_core-0.3.22-py3-none-manylinux2014_x86_64.whl |
|---|---|
| Size | 75.8 MB |
| Tags | Linux glibc 2.17+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
561a0e061f891d8e3da8508611457d0164498304208886ef0c21fd20a6db71e1
|
|
BLAKE2b-256 checksum How to use checksums |
67aecc2333d75dde15c61b4549014a1ca544d2054f37ff4640569b98bba28ad5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / nao_core-0.3.22-py3-none-manylinux2014_aarch64.whl
| Download URL | nao_core-0.3.22-py3-none-manylinux2014_aarch64.whl |
|---|---|
| Size | 74.6 MB |
| Tags | Linux glibc 2.17+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
2315775c9ac4eb329d401ade7fe378c7b1ddcaeb82a11aaf6297bc14b495765a
|
|
BLAKE2b-256 checksum How to use checksums |
e24f1366889854e77c7ed2ec3198249d1dc5e716bf42ae3548b331032bdd573d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / nao_core-0.3.22-py3-none-macosx_15_0_x86_64.whl
| Download URL | nao_core-0.3.22-py3-none-macosx_15_0_x86_64.whl |
|---|---|
| Size | 60.2 MB |
| Tags | Python 3 macOS 15.0+ x86-64 |
|
SHA-256 checksum How to use checksums |
a54f8b1fa6df26c2ab9ed363d50ea29e07fe0a890dbdd562d45266f2a4400ab1
|
|
BLAKE2b-256 checksum How to use checksums |
8588feeb134aefc8b61a981d6ea92c99270e3e9833784446ea78ab716e26c81f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / nao_core-0.3.22-py3-none-macosx_15_0_arm64.whl
| Download URL | nao_core-0.3.22-py3-none-macosx_15_0_arm64.whl |
|---|---|
| Size | 56.8 MB |
| Tags | Python 3 macOS 15.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
34b8d132bc803f0402efb1f6c20327e4c5e9c4cb749cdea42a412818df99a607
|
|
BLAKE2b-256 checksum How to use checksums |
977d2f3cf50ba0b1ead467ef9eba791f197d3d1b49cbc55524d3db4e7c338a8a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|