AI Assistant
DBCrust includes an opt-in AI assistant that turns natural language into SQL, directly in the interactive session. Type ?? followed by what you want, and the assistant generates the query using your database’s actual schema as context.
Privacy at a glance: AI is disabled by default.
??sends your question, recent AI history, and schema metadata — not row data.???and Django “Investigate with AI” can send bounded query results, query plans, captured SQL, and source/model context to the configured provider. Generated SQL is shown before execution; use a local provider or read-only role for sensitive databases.
dbcrust postgres://localhost/shop
?? top 10 customers by total order value this yearSELECT c.name, SUM(o.total) AS total_valueFROM customers cJOIN orders o ON o.customer_id = c.idWHERE o.created_at >= date_trunc('year', now())GROUP BY c.nameORDER BY total_value DESCLIMIT 10;The generated SQL is shown first and only runs after you confirm (see execution modes).
AI features are disabled by default. Run the interactive wizard once:
\ai setupThe wizard walks you through:
- Provider — Anthropic, OpenAI, Gemini, Ollama, Groq, DeepSeek, xAI, OpenRouter, Z.AI, GitHub Copilot, Cohere, or Together. The choice is saved (
providerunder[ai]) and drives authentication and routing. - Authentication — an API key stored in your OS keychain, an encrypted file, or an environment variable. For OpenAI you can instead sign in with ChatGPT and use your subscription.
- Model — picked from a live list fetched from your provider (so it reflects what your key can access), with type-to-filter and a free-text escape hatch. Falls back to curated suggestions when the list can’t be fetched.
Local providers like Ollama need no API key — just a model name and optionally an endpoint.
Pressing Ctrl-C anywhere in the wizard cancels the whole setup without saving; Esc skips the current step where a skip makes sense.
Using ??
Section titled “Using ??”| Input | What happens |
|---|---|
?? show all users created last week | Generates SQL from your schema, asks to execute |
?? now only the active ones | Follow-ups work — the last 5 exchanges are kept as conversation context |
\ai clear | Reset the conversation history |
Schema context is built from your current database: table and column metadata for up to max_schema_tables tables (50 by default). For ??, row data is not sent to the provider — only schema metadata, your question, and recent AI history.
Responses stream to the terminal as they arrive (streaming = true); press Ctrl-C to cancel a generation in progress.
Investigating with ???
Section titled “Investigating with ???”Where ?? does one-shot text-to-SQL, ??? runs an agentic investigation loop: the assistant calls read-only tools, observes the results, and iterates until it can answer a question with evidence — ideal for “why is this slow?” questions.
??? counting rows on the orders table with a join is slow — why?The agent works through tools and narrates its progress (dim lines), then prints a structured answer:
🔍 Investigating with claude-sonnet-4-6… (Ctrl-C cancels)🔧 describe_table: orders 🗂 orders: 9 cols🔧 explain: SELECT count(*) FROM orders o JOIN customers c … 📊 8 rows × 1 cols
## FindingThe join sequentially scans `orders` because `orders.customer_id` has no index.## EvidenceThe plan shows a Seq Scan on orders (rows=1.2M) feeding a Hash Join.## RecommendationCREATE INDEX idx_orders_customer_id ON orders (customer_id);The agent has four tools: list_tables, describe_table, run_sql, and explain. Key properties:
- Read-only. Every query is gated — only
SELECT/WITH/SHOW/EXPLAINrun; writes, DDL, and many known side-effecting patterns (sequence bumps, named/advisory locks, notifications,SELECT … INTO, file writes, mutatingPRAGMA) are rejected back to the model, which self-corrects. So it runs without per-step confirmation. This is best-effort SQL inspection, not a hard sandbox — aSELECTcan still call a user-defined side-effecting function. For sensitive databases, point the agent at a read-only role or a replica for real enforcement. - Bounded. It takes at most
agentic_max_iterationstool turns (8 by default), and each tool result is capped toagentic_max_rows_per_toolrows (50). If it hits the limit it is forced to summarize rather than stop silently. - Cancelable.
Ctrl-Cstops the loop at any point. - Remembers its own context.
???keeps a conversation history separate from??, so follow-up investigations build on earlier ones without polluting text-to-SQL prompts.\ai clearresets both. - Works with API keys or a ChatGPT subscription. The loop runs over streaming requests, so it works on the Codex/subscription backend (
\ai login) as well as any API-key provider.
Execution modes
Section titled “Execution modes”The assistant never silently runs writes unless you explicitly opt in:
| Mode | Behavior |
|---|---|
confirm (default) | Always ask before executing. Defaults to Yes for SELECT, No for writes |
auto_select | Run SELECT statements automatically; ask (default No) for anything else |
auto_execute | Run everything without asking — use with care |
Set it in the config file (execution_mode under [ai]) or during \ai setup.
\ai commands
Section titled “\ai commands”| Command | Description |
|---|---|
\ai or \ai status | Show provider, model, credential status, and settings |
\ai setup | Interactive setup wizard |
\ai provider [name|auto] | Set the active provider (auto = infer from the model name) |
\ai model [name] | Switch model — without an argument, pick from the provider’s live model list |
\ai login | Sign in with ChatGPT (use your subscription instead of an API key) |
\ai logout | Sign out of ChatGPT and return to API-key auth |
\ai on / \ai off / \ai toggle | Enable / disable AI features |
\ai clear | Clear the conversation history |
Sign in with ChatGPT
Section titled “Sign in with ChatGPT”If you have a ChatGPT plan (Plus, Pro, Business, …), the assistant can use it directly instead of a pay-per-use OpenAI API key:
\ai loginThis opens your browser for an OAuth sign-in (the same flow Codex CLI uses), stores the tokens in your OS keychain (encrypted-file fallback), and routes requests through the ChatGPT Codex backend on your plan’s quota. If you already ran codex login, the setup wizard also offers to reuse your Codex CLI session — no second sign-in needed.
Things to know:
- Model choice is limited to what that backend serves (
gpt-5.5,gpt-5-codex, …); the picker shows the supported set. \ai logoutdeletes the stored tokens and returns to API-key auth.- This rides an OpenAI surface that is tolerated but not officially documented for third-party tools — it can change or break without notice. dbcrust only ever reads
~/.codex/auth.json, never writes it.
Providers and models
Section titled “Providers and models”Provider handling is delegated to the genai crate (25+ providers over their native protocols). The active provider is whatever provider is set to under [ai]; with provider = "auto" it is inferred from the model name (claude-* → Anthropic, gpt-* → OpenAI, …). provider::model syntax still forces it per-model:
\ai model groq::llama-3.1-70b\ai model without an argument fetches the live model list from your provider’s /models endpoint using your stored key — so restricted keys only show what they can use — and falls back to curated suggestions when the endpoint is unreachable.
For self-hosted gateways, Ollama, LM Studio, or any OpenAI-compatible service, set a custom endpoint in the config:
[ai]model = "llama3.2"endpoint = "http://localhost:11434/v1/"API key storage
Section titled “API key storage”Keys are resolved in order:
- Environment variable — the provider’s standard name (
ANTHROPIC_API_KEY,OPENAI_API_KEY, …) - OS keychain — stored under the
dbcrustservice - Encrypted file — AES-GCM encrypted, in the DBCrust config directory
\ai setup lets you pick where to store the key. Keys never appear in config.toml.
Configuration reference
Section titled “Configuration reference”All settings live under [ai] in ~/.config/dbcrust/config.toml:
[ai]enabled = false # opt-in; \ai setup or \ai on enables itprovider = "auto" # "auto" infers from the model name, or e.g. "openai"model = "claude-sonnet-4-6" # model identifierauth_method = "api_key" # api_key | chatgpt_subscription (OpenAI, via \ai login)# endpoint = "http://..." # custom/self-hosted endpoint (optional)max_tokens = 4096temperature = 0.0streaming = true # stream responses as they arrivemax_schema_tables = 50 # cap on tables sent as schema contextshow_generated_sql = true # display SQL before/after generationexecution_mode = "confirm" # confirm | auto_select | auto_executehistory_length = 5 # conversation exchanges kept for follow-upsagentic_max_iterations = 8 # max tool-call turns for ??? investigationsagentic_max_rows_per_tool = 50 # rows from one ??? tool query fed back to the modelDjango-aware AI
Section titled “Django-aware AI”In a Django project, the AI can investigate with your models and ORM code as context — not just the raw SQL schema — so it recommends Django-level fixes (select_related / prefetch_related / only / db_index / Meta.indexes) with exact file:line references.
A management command for ad-hoc questions:
python manage.py dbcrust_ai "why is the order list view slow?"Or, inside an analysis block, so the agent also sees the actual captured queries and the code that issued them:
from dbcrust.django import analyze
with analyze() as a: list(Order.objects.all()) # exercise the slow pathprint(a.investigate_ai("why are there so many queries here?"))Django AI entrypoints normally reuse your \ai setup configuration and run the same read-only agent against your Django database (API-key or ChatGPT-subscription auth — same as ???). If Django runs with a different HOME than your shell, point it at the CLI config directory with DBCRUST_CONFIG_DIR=/path/to/.config/dbcrust (or DBCRUST_CONFIG_DIR = "/path/to/.config/dbcrust" in Django settings).
For Dockerized Django debug with a ChatGPT subscription, you can skip dbcrust config entirely: run codex login on the host, then make that Codex login available at the container user’s normal ~/.codex/auth.json. The Django AI entrypoints auto-detect it and use subscription auth.
# docker-compose.yml — adjust /home/app to the container user's HOMEservices: web: volumes: - ~/.codex:/home/app/.codex:roThat’s the only required mount. If you prefer file-based dbcrust configuration, a mounted DBCRUST_CONFIG_DIR still works.
Privacy notes
Section titled “Privacy notes”What is sent to the configured provider depends on which feature you use:
??(text-to-SQL): your question, recent conversation history, and schema metadata (table/column names and types). Query results are never sent — the generated SQL runs locally, after generation.???(agentic) and the Django dashboard’s “Investigate with AI”: the same metadata plus the output of the read-only queries the agent runs — i.e. up toagentic_max_rows_per_tool(default 50) rows of actual data per query, query plans, and (for the Django-aware paths) your model definitions, sourcefile:linelocations, and the captured SQL of flagged queries. This is what lets the agent reason with evidence, but it means real row data can leave the machine automatically. Loweragentic_max_rows_per_tool, or avoid???on sensitive tables, if that matters.- For air-gapped or sensitive environments, use a local provider (Ollama / LM Studio) via
endpoint.