Database CLI built for AI agents. One command to understand any database.
dbcli snapusers(id:INTEGER PK, name:TEXT, email:TEXT, role:TEXT) [1523]
name:TEXT distinct=1488 sample=[Alice,Bob,Charlie]
email:TEXT distinct=1523 nulls=0 sample=[alice@co.com,bob@co.com]
role:TEXT distinct=3 values=[user=1200,admin=300,moderator=23]
orders(id:INTEGER PK, user_id:INTEGER FK->users.id, amount:REAL, status:TEXT) [8491]
user_id:INTEGER distinct=1102 min=1 max=1523 avg=761.5
amount:REAL distinct=4853 min=0.99 max=2999.99 avg=87.34
status:TEXT distinct=4 values=[delivered=5102,shipped=2001,pending=1200,cancelled=188]
---
users -< orders.user_id
Schema, row counts, column profiling, and relationships — in a single call. No other database tool does this.
AI agents already have shell access. MCP wastes hundreds of tokens per message on tool schemas and protocol overhead. dbcli is a simple CLI — zero context cost, zero setup, maximum speed.
| MCP | dbcli | |
|---|---|---|
| Cost per message | ~200-500 tokens overhead | 0 |
| Commands to understand a DB | 5-10 tool calls | 1 (snap) |
| Setup | server, config, SDK | pip install dbcli |
| Works with any agent | needs MCP support | just needs a shell |
pip install dbcliWith optional database drivers:
pip install "dbcli[postgres]" # PostgreSQL
pip install "dbcli[mysql]" # MySQL
pip install "dbcli[mariadb]" # MariaDB
pip install "dbcli[duckdb]" # DuckDB
pip install "dbcli[clickhouse]" # ClickHouse
pip install "dbcli[sqlserver]" # SQL Server
pip install "dbcli[all]" # all drivers# Connect
dbcli connect mydata.db
dbcli connect "postgresql://user:pass@localhost/mydb" --as pg
# Understand the database instantly
dbcli snap
# Query
dbcli q "SELECT * FROM users WHERE role = 'admin'"
dbcli q "SELECT * FROM users" -f json
dbcli q "SELECT * FROM users" --limit 0 # no limit (default: 100)
# Write
dbcli exec "INSERT INTO users (name) VALUES ('Alice')"
dbcli exec-file migrations/001.sql
# Multiple connections
dbcli connect staging.db --as staging
dbcli use staging
dbcli status| Command | Output | Description |
|---|---|---|
connect <url> [--as name] |
connected:mydb |
Connect to a database |
use <name> |
active:mydb |
Switch connection |
status |
mydb|sqlite|data.db |
Show active connection |
tables |
one per line | List tables |
schema [table] |
users(id:INTEGER PK, name:TEXT) |
Compact schema |
describe <table> |
rows:1523 |
Row count, indexes, FKs |
indexes <table> |
idx_email(UNIQUE email) |
List indexes |
fks <table> |
user_id->users.id |
List foreign keys |
q <sql> [-f fmt] |
CSV/JSON/JSONL/TSV | Query (default limit 100) |
sample <table> [N] |
like query | Random rows (default 5) |
count <table> [where] |
42 |
Count rows |
exec <sql> |
affected:3 |
Execute statement |
exec-file <path> |
affected:47 |
Execute SQL file |
explain <sql> |
plan lines | Query execution plan |
profile <table> |
per-column stats | Data profiling |
snap |
schema+profiles+ERD | Full DB context |
audit |
no_pk:orphan_table |
Find structural issues |
erd |
users -< orders.user_id |
Entity-relationship map |
diff --from a --to b |
+/-/~ lines |
Compare schemas |
| Database | URL format |
|---|---|
| SQLite | mydata.db or sqlite:///path/to/db |
| PostgreSQL | postgresql://user:pass@host:5432/db |
| MySQL | mysql://user:pass@host:3306/db |
| MariaDB | mariadb://user:pass@host:3306/db |
| DuckDB | file.duckdb or duckdb:///path |
| ClickHouse | clickhouse://user:pass@host:8123/db |
| SQL Server | mssql://user:pass@host:1433/db |
Supabase, Neon, CockroachDB, and any PostgreSQL-compatible database work with the postgres driver.
Every output is optimized for LLM consumption, not human terminals:
- Compact schema —
users(id:INTEGER PK, name:TEXT FK->accounts.id)instead of multi-line\doutput - One-shot context —
snapreplaces 5-10 exploration commands with one - Data profiling —
profileshows what data means (distributions, ranges, cardinality), not just types - Default LIMIT 100 — protects agent context from large result sets
- Errors on stderr —
error:<type>|<message>format, stdout stays clean for piping - Semantic exit codes — 0=ok, 1=sql_error, 2=conn_error, 3=no_conn, 4=not_found, 5=usage
- Lazy imports — drivers loaded only when used, no errors if a package isn't installed
Add to CLAUDE.md:
Database access: use `dbcli` CLI.
- `dbcli snap` for full DB context
- `dbcli q "SQL"` to query (default limit 100)
- `dbcli exec "SQL"` to write
Add to .cursorrules or .windsurfrules:
Database access: use `dbcli` CLI. Run `dbcli snap` for full context, `dbcli q "SQL"` to query, `dbcli exec "SQL"` to write.
system_prompt += """
Database access: use `dbcli` CLI.
- `dbcli snap` for full DB context
- `dbcli q "SQL"` to query (default limit 100)
- `dbcli exec "SQL"` to write
"""Or load the full skill for richer context:
from pathlib import Path
skill = Path("skills/dbcli/SKILL.md").read_text()
system_prompt = f"You have database access via dbcli CLI.\n\n{skill}"Skip connect — set DBCLI_URL and query immediately:
export DBCLI_URL="postgresql://user:pass@host/db"
dbcli snap # works without connectpip install -e ".[dev]"
pytest tests/ -v # 94 tests