dbcli β Database CLI for AI Agents
Languages: English | ηΉι«δΈζ
A unified database CLI tool that enables AI agents (Claude Code, Gemini, Copilot, Cursor) to safely query, discover, and operate on databases.
Core Value: AI agents can safely and intelligently access project databases through a single, permission-controlled CLI tool with sensitive data protection.
Security update:
dbcli initnow writes only a small project binding stub into./.dbcli/config.json. The full connection configuration is stored under~/.config/dbcli/projects/<project-id>/config.json, so sensitive settings do not live inside the project workspace by default.
Internationalization (i18n)
dbcli supports multiple languages via the DBCLI_LANG environment variable:
# English (default)
dbcli init
# Traditional Chinese
DBCLI_LANG=zh-TW dbcli init
# Or set in .env
export DBCLI_LANG=zh-TW
dbcli init
Supported languages:
enβ English (default)zh-TWβ Traditional Chinese (Taiwan)
All messages, help text, error messages, and command output respond to the language setting automatically.
Quick Start
Installation
Global Installation (Recommended)
bun install -g @carllee1983/dbcli
# or: npm install -g @carllee1983/dbcli
dbcli runs on Bun. npm and npx are supported as distribution channels, but the
installed dbcli executable requires Bun 1.3.3+ on your PATH β install it first with
curl -fsSL https://bun.sh/install | bash. Only the ./agent-core subpath export is
importable from a plain Node process.
Zero-Install (No Installation Needed)
bunx @carllee1983/dbcli init
bunx @carllee1983/dbcli query "SELECT * FROM users"
# or with npm: npx @carllee1983/dbcli init
Update
# Self-update (recommended)
dbcli upgrade
# Or via npm
npm update -g @carllee1983/dbcli
Development Installation
git clone https://github.com/CarlLee1983/dbcli.git
cd dbcli
bun install
bun run src/cli.ts -- --help
# or: bun run dev -- --help
When dbcli is not on your PATH, use bun run src/cli.ts <subcommand> ... (same as bun run dev -- <subcommand> ...).
First Steps
# Initialize project with database connection
dbcli init
# Interactive shell (SQL + dbcli commands, tab completion)
dbcli shell
# List available tables
dbcli list
# View table structure
dbcli schema users
# Query data
dbcli query "SELECT * FROM users"
# Preview schema DDL (dry-run by default; add --execute to apply)
dbcli migrate create posts --column "id:serial:pk" --column "title:varchar(200):not-null"
# Generate AI agent skill
dbcli skill --install claude
Agent first-look
dbcli inspect --for-agent
A single read-only command that returns a bounded JSON snapshot of the current connection, permission level, blacklist size, schema cache freshness, available saved-query intents, and the safest next commands to run. No host, no port, no credentials β safe to log or pipe to an LLM.
Diagnostic report
dbcli report --format json
Builds on inspect to also run curated read-only built-in @diag/* snippets
grouped into health / capacity / perf sections. Bounded by per-snippet
timeout and per-evidence row cap. Use --format markdown for human reading,
--section health,capacity to scope, or --for-agent for compact JSON.
Guide
dbcli guide slow-query --format json
Deterministic next-command planner. Pick a goal (slow-query, capacity,
health, index-usage, permissions, schema-overview) and dbcli guide
emits an ordered plan that combines dbcli inspect, engine-appropriate
@diag/* snippets, and dbcli queries suggest / dbcli doctor follow-ups.
The planner is cache-first (no network); add --probe to refresh the
underlying inspect context. Use --list to see all goals,
--format markdown for human reading, or --for-agent for compact JSON.
Interactive HTML Dashboards
# Open results in browser
dbcli query "SELECT * FROM orders" --ui
# Run a saved snippet with visualization metadata
dbcli q @analytics/revenue --ui
# Export query results as a standalone HTML file
dbcli export "SELECT * FROM users" --format html --output report.html
dbcli can render query results as fully interactive, standalone HTML dashboards. These reports are powered by React + Recharts and are zero-dependency β the entire application and data are inlined into a single HTML file.
--uiflag: Automatically generates a temporary report and opens it in your default browser.visual:block: Snippet frontmatter can define KPIs and charts (Line, Bar, Area, Pie) to drive the dashboard.- Security: Result sets are redacted by the blacklist before injection, and data is safely escaped for HTML.
- Completeness warnings: Truncation and security metadata are shown before KPIs, charts, and the raw table so incomplete or masked data is never presented as a complete result.
Recovery & Guided Remediation
# Lookup recovery commands for a code
dbcli recovery --code CONN_REFUSED --format json
# Execute a failing command with recovery opt-in
dbcli query "SELECT 1" --recovery
# (v1.17.0+) Inspect or apply the last saved recovery plan
dbcli recover # View last plan (Markdown)
dbcli recover --apply # Execute safe steps (readonly/dry-run)
dbcli recover --apply --allow-write=readonly-cmd # Allow local writes
dbcli recover --apply --allow-write=write-cmd # Allow database writes
# (v1.17.0+) Multi-turn recovery (for AI agents)
dbcli recover --next --after-step 1 --result '{"status":"ok"}'
Machine-readable error envelope with guided remediation. As of v1.16.0 every
first-party command accepts the --recovery flag. In v1.17.0, the recover
command was added to automate the execution of these plans.
- Risk Gating:
--applyis safe-by-default, running onlyreadonlyanddry-runsteps. Elevated tiers require--allow-write. - Verification: After a successful
--apply, dbcli automatically runs a verification step to confirm the fix actually worked. - Multi-turn Protocol: The
--nextflag allows agents to advance recovery one step at a time, providing the result of the previous step to enable deterministic branching.
dbcli inspect --require-schema-cache throws SCHEMA_CACHE_MISSING when the
active SQL connection has no usable schema cache; combine with --recovery
to receive the structured envelope.
For write commands (insert / update / delete), BLACKLIST_COLUMN_WRITE
and PERMISSION_DENIED envelopes lead with a risk: 'dry-run' step
that suggests previewing the SQL with --dry-run before re-attempting.
MongoDB Atlas / SRV Connections
MongoDB connections are supported via both standard mongodb:// URIs and Atlas-style mongodb+srv:// URIs.
# Atlas / SRV connection
dbcli init --system mongodb --conn-name atlas --uri "mongodb+srv://user:[email protected]/mydb"
# List collections in the configured MongoDB database
dbcli list --use atlas
# Query a collection with JSON filter or pipeline
dbcli query '{"status":"active"}' --collection users --use atlas
For MongoDB, list and query operate on the database configured for the connection, and query requires --collection <name>.
For a command-by-command support matrix across PostgreSQL, MySQL, MariaDB, MongoDB, Redis, and Elasticsearch, see docs/feature-matrix.md.
Redis & Elasticsearch Support
dbcli extends its unified interface to Redis and Elasticsearch, providing consistent discovery and querying.
Redis
# Connect to Redis
dbcli init --system redis --host localhost --port 6379
# List keys (uses SCAN)
dbcli list
# Inspect a key (type, TTL, size, sample)
dbcli schema my-key
# Run Redis commands (whitelisted)
dbcli query "GET my-key"
dbcli query "HGETALL user:1"
Elasticsearch
# Connect to Elasticsearch
dbcli init --system elasticsearch --host localhost --port 9200
# List indices and document counts
dbcli list
# Show mapping/structure of an index
dbcli schema my-index
# Query using Lucene or DSL JSON
dbcli query "status:active" --index my-index
dbcli query '{"query": {"match_all": {}}}' --index my-index
Multi-connection Support (v2)
dbcli supports multiple named database connections within a single project. This is useful for managing different environments (development, staging, production) or multiple databases.
The project .dbcli directory now acts as a binding + cache layer. The actual connection config is stored in ~/.config/dbcli/projects/<project-id>/, which keeps sensitive settings out of the workspace by default.
Initializing Named Connections
To create a named connection, use the --conn-name option during init. You can also specify a custom .env file for that connection.
# Add a staging connection using .env.staging
dbcli init --conn-name staging --env-file .env.staging
# Add a production connection with environment variable references
dbcli init --conn-name prod --env-file .env.production --use-env-refs
For connections shared across projects, use the user-global scope. It stores a v2 registry at ~/.config/dbcli/config.json and leaves the current project's .dbcli binding untouched:
dbcli --global init --conn-name shared --system postgresql --host db.example.com \
--port 5432 --user app --password '<secret>' --name appdb \
--skip-test --no-interactive --force
dbcli --global use --list --format json
dbcli --global query "SELECT 1"
Root-level --global must precede the command. Without it, commands continue to use the project configuration.
Managing Connections
Use the dbcli use command to switch between connections or list them.
# List all connections (* marks the current default)
dbcli use --list
# Switch the default connection to 'staging'
dbcli use staging
# Show the current default connection
dbcli use
# Remove a connection
dbcli init --remove staging
# Rename a connection
dbcli init --rename staging:production
Using a Specific Connection Temporarily
You can use the --use <name> global flag, the supported command-level form, or DBCLI_CONNECTION to execute against a specific connection without changing the default. Selection precedence is explicit --use, then DBCLI_CONNECTION, then the configured default. A selector is rejected for legacy v1 single-connection configuration instead of being silently ignored.
# Query the production database once
dbcli query "SELECT count(*) FROM users" --use prod
# Check staging table health
dbcli check users --use staging
# Select one connection for this process
DBCLI_CONNECTION=prod dbcli query "SELECT count(*) FROM users"
query, schema, list, export, and check accept the command-level --use form shown above. Other commands use the global form before the subcommand.
For read-only comparisons, an explicit comma-separated --use fans one query out to multiple named connections:
dbcli query --use primary,staging "SELECT count(*) FROM users" --format json
SQL fan-out permits SELECT, SHOW, DESCRIBE, and EXPLAIN; MongoDB permits filters and read-only pipelines; Elasticsearch permits search. Redis, writes, --recovery, --ui, CSV, and HTML are rejected. Connections run independently: JSON returns an ordered results array, table output labels each section, and one failure does not cancel the others. Exit codes are 0 for all success, 2 for mixed outcomes, and 1 for all failures or a preflight rejection. DBCLI_CONNECTION always names one literal connection and never enables fan-out.
dbcli init
Initialize a new dbcli project with database connection configuration.
Usage:
dbcli init [OPTIONS]
Options (Basic):
--system <type>β Database system:postgresql,mysql,mariadb,mongodb--host <host>β Database host--port <port>β Database port--user <user>β Database user--password <pass>β Database password--name <db>β Database name--permission <level>β Permission level:query-only,read-write,data-admin,admin- MongoDB only:
--uri <uri>β full connection URI (mongodb://β¦ormongodb+srv://β¦);--auth-source <db>β auth database (defaultadminwhen using user/password) --use-env-refsβ Store environment variable references instead of actual values in config--skip-testβ Skip connection test--no-interactiveβ Non-interactive mode (requires all options)--forceβ Overwrite existing config without confirmation
Options (Multi-connection v2):
--conn-name <name>β Create a named connection (e.g.,staging,prod)--env-file <path>β Load credentials from a specific.envfile for this connection--remove <name>β Remove a named connection from the config--rename <old:new>β Rename an existing connection (format:old:new)
Behavior:
- Reads
.envfile if present (auto-fills DATABASE_URL, DB_* variables) - Prompts for missing values (host, port, user, password, database name, permission level)
- Creates a project binding stub in
.dbcli/config.jsonand stores the full config under~/.config/dbcli/projects/<project-id>/ - Tests database connection before saving
Examples:
# Interactive initialization
dbcli init
# Multi-connection setup
dbcli init --conn-name staging --env-file .env.staging
dbcli init --conn-name prod --env-file .env.production --use-env-refs
# Store env var references (non-interactive)
dbcli init --use-env-refs --system mysql \
--env-host DB_HOST --env-port DB_PORT \
--env-user DB_USER --env-password DB_PASSWORD \
--env-database DB_DATABASE \
--no-interactive
dbcli use (Requires v2 config)
Manage or switch the default database connection in multi-connection projects.
Usage:
dbcli use [connection-name] [OPTIONS]
Options:
--listβ List all connections and show the current default
Examples:
# Show current default connection
dbcli use
# Switch default connection to 'prod'
dbcli use prod
# List all connections
dbcli use --list
--use-env-refs: When enabled, the config stores environment variable names (e.g.,{"$env": "DB_HOST"}) instead of actual values. This avoids writing sensitive credentials into the config file, making it suitable for multi-environment deployments and CI/CD pipelines. At connection time, dbcli automatically reads the actual values from the referenced environment variables.
Storage model: The project
.dbclidirectory is now a binding + cache layer, not the canonical home for secrets. If you inspect./.dbcli/config.json, you should only see the binding metadata; the full config lives in the home storage path shown above.
dbcli list
List all tables in the connected database.
Usage:
dbcli list [OPTIONS]
Options:
--format jsonβ Output as JSON instead of ASCII table
Examples:
# Table format (human-readable)
dbcli list
# JSON format (for AI parsing)
dbcli list --format json
# Pipe to tools
dbcli list --format json | jq '.data[].name'
dbcli schema [table]
Show table structure (columns, types, constraints, foreign keys).
Usage:
dbcli schema [table]
dbcli schema # Scan entire database and update .dbcli
dbcli schema users # Show structure of 'users' table
Options:
--format jsonβ Output as JSON--refreshβ Detect and update schema changes incrementally (requires --force for approval)--resetβ Clear all existing schema data and re-fetch from database (useful after switching DB connections)--forceβ Skip confirmation for schema refresh/overwrite/reset
Examples:
# Show users table structure
dbcli schema users
# JSON output with full metadata
dbcli schema users --format json
# Update schema with new tables (incremental)
dbcli schema --refresh --force
# Clear and re-fetch all schema (after switching DB)
dbcli schema --reset --force
# Scan entire database
dbcli schema
dbcli query [query]
Execute a SQL statement, MongoDB filter/pipeline, allow-listed Redis command, or Elasticsearch DSL/Lucene query and return results.
Usage:
dbcli query "SELECT * FROM users"
dbcli query --query-file ./queries/active-users.sql
Options:
--format json|table|csv|htmlβ Output format (default: table)--uiβ Render HTML to a temporary file and open it in the system browser--limit <number>β Cap rows (overrides the automatic limit in query-only mode)--no-limitβ Disable the automatic 1000-row cap in query-only mode-f, --query-file <path>β Read a UTF-8 query from a file; use-for piped stdin--fields <list>β Includea,bor exclude-a,-bfields from SQL/MongoDB results--truncate <number>β Set the table cell limit in Unicode code points (default: 120)--no-truncateβ Show complete table cells
Behavior:
- Enforces permission-based restrictions (Query-only mode blocks INSERT/UPDATE/DELETE)
- Requires exactly one query source: positional text,
--query-file <path>, or piped stdin through--query-file - - Auto-limits results to 1000 rows in Query-only mode, unless
--no-limitor--limitapplies - Uses a one-row lookahead for dbcli-owned limits. Truncated tables say so in the footer, JSON returns
metadata.truncatedandmetadata.limit_applied, and CSV appends a truncation comment - Applies
--fieldsafter SQL execution and pushes it into MongoDB find/pipeline operations. Blacklist masking remains authoritative - Truncates table cells only; JSON and CSV rows remain lossless. Explicit truncation flags with JSON, CSV, HTML, or
--uiare rejected - To write CSV/JSON to a file, use shell redirection or the
exportcommand
Examples:
# Table output (human-readable)
dbcli query "SELECT * FROM users"
# JSON (for AI/programmatic parsing)
dbcli query "SELECT * FROM users" --format json
# CSV to stdout (redirect to a file)
dbcli query "SELECT * FROM users" --format csv > users.csv
# Pipe to other tools
dbcli query "SELECT * FROM products" --format json | jq '.data[] | .name'
# Large result sets (paginate with LIMIT/OFFSET)
dbcli query "SELECT * FROM users LIMIT 100 OFFSET 0"
# Multiline SQL from stdin
dbcli query --query-file - <<'SQL'
SELECT id, email
FROM users
WHERE status = 'active';
SQL
# Include or exclude fields (use = when the value starts with a hyphen)
dbcli query "SELECT * FROM users" --fields id,email,status
dbcli query "SELECT * FROM users" --fields=-password_hash,-raw_payload
dbcli insert [table] (Requires Read-Write or Admin permission)
Insert data into table.
Usage:
dbcli insert users --data '{"name": "Alice", "email": "[email protected]"}'
Options:
--data JSONβ Row data as JSON object (REQUIRED)--dry-runβ Show SQL without executing--forceβ Skip confirmation
Behavior:
- Validates JSON format
- Generates parameterized SQL (prevents SQL injection)
- Shows confirmation prompt before inserting (unless --force used)
Examples:
# Insert single row
dbcli insert users --data '{"name": "Bob", "email": "[email protected]"}'
# Preview SQL without executing
dbcli insert users --data '{"name": "Charlie"}' --dry-run
# Skip confirmation
dbcli insert users --data '{"name": "Diana"}' --force
dbcli update [table] (Requires Read-Write or Admin permission)
Update existing rows.
Usage:
dbcli update users --where "id=1" --set '{"name": "Alice Updated"}'
Options:
--where conditionβ WHERE clause (REQUIRED, e.g., "id=1 AND status='active'")--set JSONβ Updated columns as JSON object (REQUIRED)--dry-runβ Show SQL without executing--forceβ Skip confirmation
Examples:
# Update single row
dbcli update users --where "id=1" --set '{"name": "Alice"}'
# Update multiple rows
dbcli update users --where "status='inactive'" --set '{"status":"active"}'
# Preview SQL
dbcli update users --where "id=1" --set '{"name": "Bob"}' --dry-run
# Skip confirmation
dbcli update users --where "id=2" --set '{"email": "[email protected]"}' --force
dbcli delete [table] (Requires Data-Admin or Admin permission)
Delete rows (blocked for query-only and read-write; requires elevated DML permission).
Usage:
dbcli delete users --where "id=1" --force
Options:
--where conditionβ WHERE clause (REQUIRED)--dry-runβ Show SQL without executing--forceβ Required to actually delete (safety guard)
Examples:
# Delete single row (requires --force)
dbcli delete users --where "id=1" --force
# Preview deletion
dbcli delete products --where "status='deprecated'" --dry-run
# Delete multiple rows
dbcli delete orders --where "created_at < '2020-01-01'" --force
dbcli export "SQL"
Export query results to file.
Usage:
dbcli export "SELECT * FROM users" --format json --output users.json
Options:
--format json|csvβ Output format--output fileβ Write to file (default: stdout for piping)--limit <number>β Deliberately accept a bounded export--no-limitβ Export the complete result
Behavior:
- Query-only mode still applies its automatic 1000-row limit, but reaching it fails closed with exit code
1and writes no partial file - Re-run with
--no-limitfor the complete export or--limit Nto accept a cap explicitly - Generates RFC 4180 compliant CSV
- Creates well-formed JSON arrays
Examples:
# Export to JSON
dbcli export "SELECT * FROM users" --format json --output users.json
# Export to CSV
dbcli export "SELECT * FROM orders" --format csv --output orders.csv
# Pipe compressed export
dbcli export "SELECT * FROM products" --format csv | gzip > products.csv.gz
# Combine with query tools
dbcli export "SELECT * FROM users WHERE active=true" --format json | jq '.data | length'
dbcli skill
Generate or install AI agent skill documentation.
Usage:
dbcli skill # Output skill to stdout
dbcli skill --output SKILL.md # Write to file
dbcli skill --install claude # Install to Claude Code config
dbcli skill --install gemini # Install to Gemini CLI (being phased out)
dbcli skill --install antigravity # Install to Antigravity CLI (Gemini CLI's successor)
dbcli skill --install copilot # Install to GitHub Copilot
dbcli skill --install cursor # Install to Cursor IDE
dbcli skill --install codex # Install to Codex skills
dbcli skill --install windsurf # Install to Windsurf (.windsurfrules)
Behavior:
- Ships canonical
assets/SKILL.md+assets/reference.md(single source of truth: concise skill + long command reference) - Prints the skill to stdout, writes it with
--output, or copies it to a platform-specific path with--install - Actual database access is still enforced by your
.dbclipermission level and blacklist β the skill text describes the full CLI surface
Examples:
# Generate skill for Claude Code
dbcli skill --install claude
# Generate skill manually for documentation
dbcli skill > ./docs/SKILL.md
# View generated skill (stdout)
dbcli skill
# Install for all platforms
dbcli skill --install claude && \
dbcli skill --install gemini && \
dbcli skill --install antigravity && \
dbcli skill --install copilot && \
dbcli skill --install cursor && \
dbcli skill --install codex
dbcli blacklist
Manage the data access blacklist to block AI agents from accessing sensitive tables or columns.
Usage:
dbcli blacklist list
dbcli blacklist table add <table>
dbcli blacklist table remove <table>
dbcli blacklist column add <table>.<column>
dbcli blacklist column remove <table>.<column>
Subcommands:
| Subcommand | Description |
|---|---|
dbcli blacklist list |
Show current blacklist (tables and columns) |
dbcli blacklist table add <table> |
Add table to blacklist (blocks all operations) |
dbcli blacklist table remove <table> |
Remove table from blacklist |
dbcli blacklist column add <table>.<column> |
Add column to blacklist (omitted from SELECT results) |
dbcli blacklist column remove <table>.<column> |
Remove column from blacklist |
Behavior:
- Table blacklist blocks all operations on that table (query, insert, update, delete)
- Column blacklist silently omits columns from SELECT results and shows a security notification
- Blacklist rules are stored in
.dbcliand apply to all permission levels - Override for admin use via
DBCLI_OVERRIDE_BLACKLIST=trueenvironment variable
Examples:
# View current blacklist
dbcli blacklist list
# Block all access to sensitive tables
dbcli blacklist table add audit_logs
dbcli blacklist table add secrets_vault
# Hide sensitive columns from query results
dbcli blacklist column add users.password_hash
dbcli blacklist column add users.ssn
# Remove a table from blacklist
dbcli blacklist table remove audit_logs
# Remove a column from blacklist
dbcli blacklist column remove users.ssn
# Override blacklist (admin use only)
DBCLI_OVERRIDE_BLACKLIST=true dbcli query "SELECT * FROM secrets_vault"
dbcli check
Run data-quality and health checks on tables.
Usage:
dbcli check [table] [OPTIONS]
Options:
--allβ Check every table (skips huge tables unless--include-large)--include-largeβ Include huge tables in--allscan--checks <types>β Comma-separated checks:nulls,duplicates,orphans,emptyStrings,rowCount,size--sample <number>β Sample size for large tables (default: 10000)--format json|tableβ Output format (default: json)
Examples:
# Check users table
dbcli check users
# Run specific checks only
dbcli check orders --checks nulls,orphans --format table
# Scan all tables
dbcli check --all
# Table view + all-tables with selected checks
dbcli check orders --format table
dbcli check --all --checks nulls,duplicates --format json
dbcli diff
Save a schema snapshot, compare the live database to a previous snapshot, or compare an ORM definition with the local SQL schema cache. ORM drift is cache-only: it does not connect, refresh the cache, or execute proposals.
Usage:
dbcli diff --snapshot ./schema-before.json
dbcli diff --against ./schema-before.json
dbcli diff --against ./schema-before.json --format table
dbcli diff --against-orm prisma/schema.prisma --format json
dbcli diff --against-orm drizzle/meta/0001_snapshot.json --orm-format drizzle --format table
dbcli diff --against-orm schema.sql --orm-format typeorm --format table
Options:
--snapshot <path>β Write the current schema to a JSON file--against <path>β Diff live schema vs. the saved snapshot--against-orm <path>β Compare Prisma, Drizzle snapshot, TypeORM/Sequelize DDL, raw DDL, or normalized JSON with the cached SQL schema--orm-format prisma|drizzle|typeorm|sequelize|ddl|jsonβ Override ORM input detection--format json|table|markdownβ Output format (default:json)--config <path>β Config path (default:.dbcli)
dbcli snapshot
Capture a result fingerprint of a query (distinct from diff, which snapshots schema): row count plus per-column aggregates (null/distinct counts, min/max/sum) and an order-independent checksum. Blacklisted columns are masked at the source, so the snapshot is safe to store. Use it as a baseline for dbcli assert --against. SQL engines only.
Usage:
dbcli snapshot "SELECT * FROM orders WHERE created_at >= '2026-05-01'" # β .dbcli/snapshots/snap-<timestamp>.json
dbcli snapshot @analytics/daily-revenue --out base.json
dbcli snapshot "SELECT status, count(*) FROM orders GROUP BY status" --stdout
Options:
--out <path>β Output path (default:.dbcli/snapshots/snap-<timestamp>.json)--rowsβ Also store the full (blacklist-masked) rows--stdoutβ Print snapshot JSON to stdout instead of writing a file--format json|tableβ Output format for--stdout(default:json)--no-limitβ Disable the automatic query-only LIMIT
dbcli assert
Assert an invariant on a query result. Exits 1 on failure (composes in scripts/CI) unless --no-fail. SQL engines only.
Usage:
dbcli assert "SELECT count(*) FROM orders" --expect "value > 0"
dbcli assert "SELECT * FROM orders WHERE total < 0" --expect "rows == 0"
dbcli assert "SELECT email FROM users" --expect "col:email not null"
dbcli assert "SELECT sum(amount) FROM ledger_a" --vs "SELECT sum(amount) FROM ledger_b" --compare value
dbcli assert "SELECT * FROM orders" --against base.json --tolerance 0.01
Options:
--expect <condition>βrows > 0,value == 5000,col:email not null,col:id unique,col:amount between 0 and 100,col:age >= 18--vs <query>β Reconcile against a second query--compare rows|valueβ Comparison mode for--vs(default:value)--against <path>β Compare the current result fingerprint to a saved snapshot--tolerance <pct>β Allowed relative drift for--against(e.g.0.01; default:0= exact checksum match)--no-failβ Always exit 0; report pass/fail in output only--format json|tableβ Output format (default:json)
dbcli proxy (v1.26)
Local-development observability proxy for MySQL, MariaDB, and PostgreSQL. Point an existing app at the proxy port; dbcli relays all TCP frames to the real database and appends one JSONL event per query to .dbcli/proxy/events.jsonl. Observe-only β no rewrite or blocking. Not a production gateway.
Subcommands: mysql Β· mariadb Β· postgresql
dbcli proxy mysql --listen 127.0.0.1:3307 --target 127.0.0.1:3306
dbcli proxy postgresql --listen 127.0.0.1:5434 --target 127.0.0.1:5432
dbcli proxy mysql --slow-ms 500 --redact literals
dbcli proxy mariadb --events ./logs/proxy.jsonl
dbcli proxy analyze --events ./logs/proxy.jsonl --format markdown # QueryLens report
Options:
--listen <addr:port>β Proxy listen address--target <addr:port>β Real database address (inferred from config /--useif omitted)--events <path>β JSONL event log (default:.dbcli/proxy/events.jsonl)--slow-ms <ms>β Flag events slower than this threshold asslow: true(default:1000)--redact none|literalsβ Strip SQL literal values from event records (default:none)--format text|jsonβ Startup output format (default:text)
QueryLens: dbcli proxy analyze --format markdown reads the event log offline and produces a shareable Markdown report. It redacts SQL and error-message literals in memory before analysis; use --redact literals while capturing as well to protect the log on disk.
dbcli status
Show non-sensitive configuration summary (permission level, DB system, blacklist counts, config metadata version). Does not print connection credentials β intended for AI agents.
Usage:
dbcli status
dbcli status --format text
dbcli status --format json
Options:
--format text|jsonβ Output format (default:json)
Note: This command reads the default project config path .dbcli (not the global --config flag).
dbcli doctor
Run diagnostic checks on environment, configuration, connection, and data.
dbcli doctor # Colored text output
dbcli doctor --format json # JSON output for AI agents
Checks:
- Environment: Bun version compatibility, dbcli version (compares with npm registry)
- Configuration: Config file exists/valid, permission level, blacklist completeness
- Connection & Data: Database connectivity, schema cache freshness (> 7 days warning), large table warnings (> 1M rows)
- MongoDB SRV diagnostics: For
mongodb+srv://connections,doctorreports whether the current execution environment can resolve SRV records directly or only through the DNS-over-HTTPS fallback used bydbcli
Options: --format <text|json>
Exit code: 0 = all pass or warnings only, 1 = errors found
dbcli completion [shell]
Generate shell completion scripts for tab auto-complete.
dbcli completion bash # Output bash completion to stdout
dbcli completion zsh # Output zsh completion to stdout
dbcli completion fish # Output fish completion to stdout
dbcli completion --install # Auto-detect shell and install to rc file
dbcli completion --install zsh # Install for specific shell
Supported shells: bash, zsh, fish
Installed completions cover nested subcommands β for example dbcli queries list --<TAB>, dbcli migrate add-column --<TAB>, and dbcli verify safe-backfill --<TAB>.
Inside dbcli shell, command completion follows the current command surface, so newly added commands (q, queries, inspect, verify, proxy, snapshot, β¦) complete and dispatch automatically.
--install is marker-managed: it writes a single block to your shell rc file and re-running it replaces that block rather than duplicating it.
dbcli upgrade
Check for updates and self-upgrade dbcli.
dbcli upgrade # Check and upgrade if newer version available
dbcli upgrade --check # Only check, do not upgrade
Options: --check β check only, don't install
Background checks (stderr, skipped when --quiet or for upgrade / skill):
- CLI version: dbcli checks the npm registry (cached, about once per 24 hours). If a newer package exists, a one-line hint prints after normal command output.
- Installed skills: If you used
dbcli skill --install <platform>, dbcli compares each installed primary skill file (SKILL.mdordbcli.mdc) to the bundledassets/SKILL.md. When they differ, a short reminder lists which platforms to re-install (dbcli skill --install <platform>). Rundbcli upgradeto see the same skill status together with version info. Re-installing also refreshesreference.mdnext to the skill.
dbcli shell
Interactive database shell with SQL execution, auto-completion, and syntax highlighting.
Usage:
dbcli shell # Interactive mode (SQL + dbcli commands)
dbcli shell --sql # SQL-only mode
Inside the shell:
- Type SQL statements ending with
;to execute queries - Type dbcli commands without the
dbcliprefix (e.g.,schema users,list) - Press Tab for context-aware auto-completion (SQL keywords, table/column names)
- Use
.helpfor meta commands (.quit,.clear,.format,.history,.timing) - Multi-line SQL: input accumulates until
;is found - History persists across sessions in
~/.dbcli_history
Permission: Inherits from config. SQL and commands are fully permission/blacklist enforced.
dbcli migrate
Schema DDL operations. All commands default to dry-run β use --execute to actually run the SQL.
Usage:
# Create table
dbcli migrate create posts \
--column "id:serial:pk" \
--column "title:varchar(200):not-null" \
--column "body:text" \
--column "created_at:timestamp:default=now()"
# Execute (actually run the SQL)
dbcli migrate create posts --column "id:serial:pk" --execute
# Drop table (destructive β requires --execute --force)
dbcli migrate drop posts --execute --force
# Column operations
dbcli migrate add-column users bio text --nullable --execute
dbcli migrate alter-column users name --type "varchar(200)" --execute
dbcli migrate alter-column users email --rename user_email --execute
dbcli migrate drop-column users temp_field --execute --force
# Index operations
dbcli migrate add-index users --columns email --unique --execute
dbcli migrate drop-index idx_users_email --table users --execute --force
# Constraint operations
dbcli migrate add-constraint orders --fk user_id --references users.id --on-delete cascade --execute
dbcli migrate add-constraint users --unique email --execute
dbcli migrate add-constraint users --check "age >= 0" --execute
dbcli migrate drop-constraint orders fk_orders_user_id --execute --force
# Enum (PostgreSQL only)
dbcli migrate add-enum status active inactive suspended --execute
dbcli migrate alter-enum status --add-value archived --execute
dbcli migrate drop-enum status --execute --force
Column spec format: name:type[:modifier...] β Modifiers: pk, not-null, unique, auto-increment, default=<value>, references=<table>.<column>
Options (all subcommands): --execute (run SQL), --force (skip confirmation for DROP), --config <path>
Permission: admin only
Query Risk Planning
Use lint for read-only static advice about SQL anti-patterns and optional rewrite drafts. It accepts inline SQL, saved queries, files, globs, and bulk input; it never connects or applies a rewrite:
dbcli lint "SELECT * FROM users WHERE LOWER(email) = '[email protected]'" --format json
Use plan to inspect SQL safety before execution. It reads local dbcli config, permissions, blacklist rules, and cached schema metadata only; it does not connect to the database.
dbcli plan "UPDATE users SET status='inactive'" --format json
Decisions are:
ALLOWβ no obvious risk was detected.WARNβ inspect warnings before executing.BLOCKβ unsafe, unsupported, or violates configured safety constraints.
Text output is concise for humans:
Decision: BLOCK
Operation: UPDATE
Target tables: users
Risk factors:
- UPDATE statement has no WHERE clause.
Recommendations:
- Add a WHERE clause.
- Use --dry-run on the actual write command.
JSON output includes suggestedCommands for agents:
dbcli plan "SELECT id FROM users WHERE id = 1 LIMIT 1" --format json
Global Options
All commands support these global options:
| Flag | Description |
|---|---|
--config <path> |
Path to .dbcli config file (default: .dbcli) |
--global |
Use the user-global registry at ~/.config/dbcli/config.json |
--use <connection> |
Use a named v2 connection for this invocation only (does not change the default) |
-v, --verbose |
Increase verbosity (-v verbose, -vv debug) |
-q, --quiet |
Suppress non-essential output |
--no-color |
Disable colored output (respects NO_COLOR env var) |
Internals & Strategy
Schema Update Strategy
dbcli maintains a schema snapshot in your .dbcli config file. This allows AI agents to understand the database structure without constant network overhead. Understanding when this cache updates is key:
- Manual Updates:
dbcli schema: Performs a full scan of the database.dbcli schema --refresh: Incremental update. Detects changes and updates only the affected tables.dbcli schema --reset: Clears the cache and re-fetches everything.
- Automatic Updates (DDL):
- When you execute DDL through
dbcli migrate(e.g.,add-column), the CLI automatically re-scans the affected table and updates the.dbclisnapshot after successful execution.
- When you execute DDL through
- Real-time Validation (Non-cached):
- Commands like
insert,update,delete, andcheckfetch the latest schema from the database immediately before execution to ensure data integrity, but they do not update the long-term snapshot in.dbcli.
- Commands like
Note: If you change the d
No comments yet
Be the first to share your take.