@carllee1983/dbcli 1.31.0 → 1.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "dbcli-agent",
3
+ "interface": {
4
+ "displayName": "dbcli Agent"
5
+ },
6
+ "plugins": [
7
+ {
8
+ "name": "dbcli-agent",
9
+ "source": {
10
+ "source": "url",
11
+ "url": "https://github.com/CarlLee1983/dbcli.git",
12
+ "ref": "main"
13
+ },
14
+ "policy": {
15
+ "installation": "AVAILABLE",
16
+ "authentication": "ON_INSTALL"
17
+ },
18
+ "category": "Productivity"
19
+ }
20
+ ]
21
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "dbcli-agent",
3
+ "version": "1.32.0",
4
+ "description": "Database CLI skill and command reference for AI agents.",
5
+ "author": {
6
+ "name": "Carl Lee",
7
+ "url": "https://github.com/CarlLee1983"
8
+ }
9
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "dbcli-agent",
3
+ "version": "1.32.0",
4
+ "description": "Database CLI skill and command reference for AI agents",
5
+ "author": {
6
+ "name": "Carl Lee",
7
+ "url": "https://github.com/CarlLee1983"
8
+ },
9
+ "homepage": "https://github.com/CarlLee1983/dbcli",
10
+ "repository": "https://github.com/CarlLee1983/dbcli",
11
+ "license": "MIT",
12
+ "keywords": [
13
+ "database",
14
+ "cli",
15
+ "ai-agent",
16
+ "postgresql",
17
+ "mysql",
18
+ "mongodb",
19
+ "redis",
20
+ "elasticsearch"
21
+ ],
22
+ "skills": "./skills/",
23
+ "interface": {
24
+ "displayName": "dbcli Agent",
25
+ "shortDescription": "Use dbcli safely from Codex.",
26
+ "longDescription": "Installs the dbcli agent skill and reference guide so Codex can inspect schemas, query databases, respect blacklist boundaries, and recover from database errors through the dbcli command workflow.",
27
+ "developerName": "Carl Lee",
28
+ "category": "Productivity",
29
+ "capabilities": [
30
+ "Database",
31
+ "Local CLI",
32
+ "Agent Skill"
33
+ ],
34
+ "websiteURL": "https://github.com/CarlLee1983/dbcli",
35
+ "defaultPrompt": [
36
+ "Inspect my database with dbcli.",
37
+ "Show schema safely with dbcli.",
38
+ "Diagnose a dbcli query failure."
39
+ ]
40
+ }
41
+ }
@@ -0,0 +1,515 @@
1
+ ---
2
+ name: dbcli
3
+ description: Database CLI for AI agents with permission-based access control. Use to set up new connections, query, inspect schemas, insert/update/delete, export results, and blacklist sensitive columns/tables. Supports MySQL, PostgreSQL, MariaDB, MongoDB, Redis, and Elasticsearch with multiple named connections per project and custom env files. Trigger when configuring a database connection (`.dbcli` / `.env`), choosing between v1 single and v2 multi-connection layouts, picking auth modes (URI, env refs, Cloud ID, API key), running SQL / MongoDB JSON / Redis commands / Elasticsearch DSL, exploring table/collection/key/index structures, switching database environments, protecting sensitive data from AI access, or performing automated recovery and guided remediation after command failures. For exhaustive flags and examples, read the sibling `reference.md`.
4
+ ---
5
+
6
+ # dbcli
7
+
8
+ Database CLI for AI agents with permission-based access control.
9
+
10
+ If the `dbcli` executable is not available in `PATH`, use
11
+ `bunx @carllee1983/dbcli <command>` as the command prefix. This is the expected
12
+ fallback for Codex plugin installs where the skill is installed by the plugin but
13
+ the CLI package has not been installed globally.
14
+
15
+ ## AI agent workflow (follow in order)
16
+
17
+ 0. `dbcli skill context --format xml` — LLM prompt context payload: serializes connection metadata, schema caches, and saved queries into a compressed XML/JSON structure for prompt injection.
18
+ 1. `dbcli inspect --for-agent` — bounded snapshot: connection, permission, blacklist, objects, snippets, suggested next commands.
19
+ 2. `dbcli report --format json` — diagnostic report (health/capacity/perf) using built-in snippets.
20
+ 3. `dbcli guide <goal> --format json` — deterministic next-command plan for a fixed goal (`slow-query`, `capacity`, `health`, `index-usage`, `permissions`, `schema-overview`). Use `dbcli guide --list` to see goals.
21
+ 4. `dbcli recovery --code <CODE>` — look up structured recovery commands for a known error code (e.g. `CONN_REFUSED`, `PERMISSION_DENIED`, `SNIPPET_NOT_FOUND`). Pass `--recovery` to `dbcli query` / `dbcli q` to have failures emit a `RecoveryEnvelope` directly. In v1.16.0 the `--recovery` flag is also accepted by `dbcli insert`, `dbcli update`, `dbcli delete`, `dbcli export`, `dbcli schema`, and `dbcli inspect` (which also gained `--require-schema-cache` for the `SCHEMA_CACHE_MISSING` path).
22
+ - **v1.17.0** `dbcli recover` reads the auto-saved envelope (`.dbcli/last-recovery.json`) written by any prior `--recovery` failure. Inspect it (Markdown by default) or pass `--apply` to execute the saved plan under risk gating.
23
+ - **v1.17.0** `dbcli recover --apply` runs `risk=readonly` and `risk=dry-run` steps by default. Open the gate one tier with `--allow-write=readonly-cmd` (run local-side writes such as `blacklist remove`) or `--allow-write=write-cmd` (also run steps that mutate the connected database). Pass `--from <file>` to read an explicit envelope instead of the auto-saved one. Use `--format json` for an aggregated machine-readable result.
24
+ - Exit codes: `0` ok, `1` step failed, `2` envelope missing/malformed, `3` every step skipped (open `--allow-write` or fix interactive/placeholder).
25
+ - GuideStep optional fields agents should respect:
26
+ - `interactive: true` — step requires a TTY (`dbcli init` family). `dbcli recover --apply` skips with `skipped:interactive`.
27
+ - `dbWrite: true` — step mutates the connected database. Gates the highest risk tier; reserved for future write-side recovery steps.
28
+ - `placeholders: ['<token>', ...]` — agent must replace these tokens before `--apply` will execute. Skipped with `skipped:placeholder`.
29
+ - **v1.17.0 P4 Verification.** After `--apply` finishes the main plan, dbcli runs **one extra read-only step** (`envelope.verify`) to probe whether the original failure is gone. The output gains `verifyResult` (the executed step) and `verifyStatus`:
30
+ - `passed` — verifier exited 0 and (where applicable) the expected JSON shape was found.
31
+ - `failed` — verifier exited non-zero or timed out.
32
+ - `indeterminate` — verifier exited 0 but the heuristic could not confirm the fix (JSON parse failure, missing field, gate skip).
33
+ Verify is **only run when** `finalStatus === 'ok'`. Pass `--no-verify` to skip it. Heuristic is intentionally cheap; agents should still re-run their own check against the original failing operation when correctness matters.
34
+ - **v1.17.0 P2 Multi-turn `--next`.** When `--apply` is too coarse — interactive blocks it, the plan needs per-step inspection, or the agent wants to drive recovery with its own tools — execute steps one at a time and ask dbcli for the next:
35
+
36
+ ```bash
37
+ # The agent reads step 1 from the envelope, runs it, then asks dbcli for step 2:
38
+ dbcli recover --next --after-step 1 --result '{"status":"ok","exitCode":0}'
39
+ # Returns a NextResult envelope:
40
+ # {
41
+ # "schemaVersion": 1,
42
+ # "kind": "step",
43
+ # "errorCode": "BLACKLIST_TABLE",
44
+ # "cursor": 2,
45
+ # "totalSteps": 3,
46
+ # "step": { "order": 2, "command": "dbcli inspect --for-agent", ... }
47
+ # }
48
+ # After the last step, dbcli returns kind: "done".
49
+ ```
50
+
51
+ `--result` accepts inline JSON `StepResultSummary` or `@<path>` to read from a file. `stdoutSummary` and `stderrSummary` are capped at 4 KB each — pre-truncate to the **last** 4 KB before passing. `--next` is mutually exclusive with `--apply`. Each call is independent (no persisted cursor) — the agent tracks `--after-step` itself.
52
+
53
+ **Connection branching.** For `CONN_*` codes, the envelope ships a `branches` map + `branchFork` descriptor. Step 1 (`dbcli doctor --format json`) is the fork point: pass the doctor JSON in `--result.stdoutSummary` and `--next` will pick one of four labeled branches (`doctor-clean` / `doctor-config-missing` / `doctor-auth-error` / `doctor-network-error`). NextResult then carries `branchId` and `branchDescription`; subsequent calls must echo `--branch <id>` to walk that branch. Parse failure / unmatched keywords fall back to linear `recovery`. `--apply` ignores branches entirely.
54
+ 5. `dbcli blacklist list` — sensitive data boundaries.
55
+ 6. `dbcli schema <table> --format json` — real column names (SQL/Mongo/ES) or `schema <key>` (Redis). **Never guess.**
56
+ 7. Run `query` / `insert` / `update` / `delete` / `export` within permission.
57
+ 8. All writes: `--dry-run` (SQL/Mongo) → run → `query` read-back to confirm.
58
+ - **v1.21.0 Self-Verification Loops**: If a snippet defines a `verify` block in its frontmatter, run the snippet with `dbcli q @name --verify` to automatically run primary changes, execute the verification query, and validate assertions.
59
+
60
+ Prefer `--format json` for agent-friendly output.
61
+
62
+ ## Agent Task Packs
63
+
64
+ When the user asks for a database workflow (e.g. "diagnose this slow query", "audit
65
+ permissions", "review long-running operations"), prefer published task templates
66
+ over inventing steps from memory.
67
+
68
+ ```bash
69
+ dbcli skill tasks list --format json # discover
70
+ dbcli skill tasks show <task> # inspect
71
+ dbcli skill tasks plan <task> --param key=value --format json # generate plan
72
+ ```
73
+
74
+ The plan output is an ordered list of dbcli commands with rationale and risk
75
+ labels. Execute them one at a time — task plans do **not** override blacklist,
76
+ schema, dry-run, or confirmation requirements.
77
+
78
+ Builtin packs: `diagnose-slow-query` and **(v1.23)** `analyze-table-perf` — a
79
+ read-only `plan-only` pack taking a required `table` parameter that walks
80
+ `blacklist list` → `schema <table> --format json` → `guide index-usage`. `dbcli
81
+ inspect` suggests `analyze-table-perf` automatically for the hottest table in
82
+ recent audit activity. Additional read-only packs: `audit-permissions`,
83
+ `safe-backfill`, `schema-drift-review`, `connection-health` — run
84
+ `dbcli skill tasks list` for the full set.
85
+
86
+ Tasks live under `assets/tasks/` (builtin), `.dbcli-shared/tasks/` (shared), and
87
+ `.dbcli/tasks/` (local override).
88
+
89
+ ## Developer workflows
90
+
91
+ Use these workflows when database impact is implicit in a development task. Keep
92
+ the normal dbcli safety rules: prefer `--format json`, run `blacklist list`
93
+ before touching sensitive data, confirm names with `schema`, dry-run writes, and
94
+ use `--recovery` / `recover` after failures.
95
+
96
+ | Situation | Use dbcli for | Minimum safe path |
97
+ | --- | --- | --- |
98
+ | DB-backed feature | Map product/code terms to real objects before editing code. | `inspect --for-agent` -> `blacklist list` -> `schema <object>` -> `queries suggest <intent>` |
99
+ | Application data bug | Separate stored facts from application-code inference. | `inspect --for-agent` -> `audit tail --for-agent --n 10` -> `blacklist list` -> `schema <object>` -> narrow query/snippet |
100
+ | ORM or migration work | Ground model and migration edits in live schema evidence. | `schema --format json` -> `diff --snapshot <name>` -> generate DDL via `migrate add-index`/`add-column` (preview SQL) -> `diff --against <snapshot>` |
101
+ | PR database review | Check query, write, migration, export, fixture, and blacklist risk. | Review changed persistence paths, then propose concrete `schema`, `plan`, `dry-run`, `report`, or `guide` commands for each material claim. |
102
+ | Slow endpoint or query | Prefer read-only diagnostics before index proposals. | `report --section perf` -> task pack `analyze-table-perf` -> `guide missing-index-for "<query>"`; use `proxy analyze` when logs exist. |
103
+ | Safe data backfill | Scope affected rows and preview mutations before execution. | `blacklist list` -> `schema <object>` -> count/scope query -> `update ... --dry-run` -> read-back or snippet `--verify`. |
104
+ | Environment validation | Check config shape and connectivity without leaking secrets. | `status --format json` -> `doctor --format json` -> `inspect --for-agent --no-connect --format json`. |
105
+
106
+ Copy-paste command anchors:
107
+
108
+ ```bash
109
+ dbcli inspect --for-agent --format json
110
+ dbcli blacklist list --format json
111
+ dbcli schema <object> --format json
112
+ dbcli queries suggest <intent> --format json
113
+ dbcli audit tail --for-agent --n 10
114
+ dbcli schema --format json
115
+ dbcli diff --snapshot <name>
116
+ dbcli migrate add-index <table>
117
+ dbcli diff --against <snapshot>
118
+ dbcli report --section perf --format json
119
+ dbcli skill tasks plan analyze-table-perf --param table=<table> --format json
120
+ dbcli guide missing-index-for "<query>" --format json
121
+ dbcli proxy analyze --format json
122
+ dbcli query "<count/scope query>" --format json
123
+ dbcli update <object> --where "<bounded predicate>" --set '<json>' --dry-run --format json
124
+ dbcli status --format json
125
+ dbcli doctor --format json
126
+ dbcli inspect --for-agent --no-connect --format json
127
+ ```
128
+
129
+ Developer workflow guardrails:
130
+
131
+ - Never invent table, collection, key, index, or field names. Confirm them with
132
+ `schema` before writing code that depends on them.
133
+ - Separate database facts from application-code inference. Report which dbcli
134
+ output shaped the code or review conclusion.
135
+ - For writes and backfills, include scope count, dry-run preview, execution
136
+ command, and read-back or snippet verification.
137
+ - Do not create indexes directly from a performance suggestion; turn them into reviewed migrations.
138
+ - Do not print credentials, copied connection strings, or blacklisted values.
139
+
140
+ Full flags, per-command copy-paste blocks, `migrate` DDL, interactive `shell`, and MongoDB/Redis/ES walkthroughs are in [reference.md](reference.md) (installed next to this file).
141
+
142
+ ## Audit Log usage
143
+
144
+ Use the audit log when you need cross-session history or forensics on what dbcli
145
+ has done on this database, rather than re-querying live DB state from scratch.
146
+
147
+ **Scenario 1 — Session handoff (picking up where another agent left off):**
148
+
149
+ ```bash
150
+ dbcli audit tail --for-agent --n 10 # last 10 entries as JSON envelope
151
+ dbcli audit tail --all --for-agent --n 20 # cross-connection merged view (D4)
152
+ ```
153
+
154
+ Returns an agent-facing JSON envelope with `session_id` / `engine` / `command` /
155
+ `target` / `success` per entry. Metadata-only by design — never raw SQL bodies,
156
+ `--param` values, or result cell contents (D3 lock).
157
+
158
+ **Scenario 2 — Forensics (reconstructing a failure):**
159
+
160
+ ```bash
161
+ dbcli recover --format json # inspect audit_recent embed + recovery_ref
162
+ dbcli audit show <id-prefix> # full entry by id prefix (>=4 chars)
163
+ dbcli audit show --recovery-ref <envelope-id> # find entry that emitted an envelope
164
+ ```
165
+
166
+ The `inspect` / `guide` / `recover` / `recover --apply` agent JSON output embeds
167
+ `audit_recent: AuditEntryBrief[]` (last 5 entries) — a fresh session has immediate
168
+ history context. The envelope's `audit_ref` and the audit entry's `recovery_ref`
169
+ point at each other; agents can pivot either direction.
170
+
171
+ Bi-directional `recovery_ref` / `audit_ref` linkage is wired on every command
172
+ that accepts `--recovery`: `query`, `inspect`, `insert`, `update`, `delete`,
173
+ `export`, `q`, and `schema`. Agents can pivot from an envelope to its audit
174
+ entry via `audit tail --recovery-ref <id>`.
175
+
176
+ Audit entries are written to `.dbcli/audit/<connection>.jsonl` with rotation at
177
+ ~10 MB or 1000 entries. `audit.enabled = false` in `.dbcli` opts out (default ON
178
+ since v1.20.0). For flag reference see [`reference.md`](./reference.md) §audit.
179
+ For end-to-end recovery walkthroughs (per-code scenarios, `--next` multi-turn,
180
+ envelope ⇄ audit pivot, risk-gate cheat sheet) see
181
+ [`reference.md`](./reference.md) §Recovery Cookbook.
182
+
183
+ ## Quick start
184
+
185
+ ```bash
186
+ dbcli init # Create .dbcli config (parses .env automatically)
187
+ dbcli schema # Scan all tables → .dbcli/schemas/
188
+ dbcli query "SELECT * FROM users" # Execute SQL (auto LIMIT 1000)
189
+ ```
190
+
191
+ If `.dbcli` does not yet exist, route through **Connection setup** below before
192
+ touching `schema` / `query`.
193
+
194
+ ## Connection setup (helping the user wire up a database)
195
+
196
+ When the user asks "how do I connect to X?", "set up dbcli for our staging DB",
197
+ or `doctor` / `status` reports a missing or invalid config, follow this flow.
198
+
199
+ > **Default to guiding, not running.** `init` writes credentials to disk. Only
200
+ > execute it for the user with explicit permission and confirmed values.
201
+ > If a `.dbcli` already contains `{"$env": "..."}` references, **do not** rerun
202
+ > `init` to "fill them in" — the env-ref form is intentional for CI/multi-env.
203
+
204
+ ### Decision tree (ask before writing)
205
+
206
+ 1. **One DB or many environments?** One → v1 (single connection). Multiple
207
+ environments / tenants / replicas → v2 (`--conn-name <name>`, optionally
208
+ `--env-file <path>` per connection).
209
+ 2. **Where do credentials live?**
210
+ - Already in a `.env` (`DATABASE_URL` or `DB_HOST` / `DB_PORT` / `DB_USER` /
211
+ `DB_PASSWORD` / `DB_NAME` | `DB_DATABASE`) → `init` parses it automatically.
212
+ - Need to keep secrets out of `.dbcli` (CI/CD, multi-env) → `--use-env-refs`
213
+ plus `--env-host` / `--env-port` / `--env-user` / `--env-password` / `--env-database`.
214
+ - Plain values are acceptable → pass `--host` / `--port` / `--user` /
215
+ `--password` / `--name` (and `--system`).
216
+ 3. **What permission tier?** Default to the **lowest** that satisfies the task:
217
+ `query-only` → `read-write` → `data-admin` → `admin`. Set with `--permission`.
218
+ 4. **Verify, never assume.** After init: `dbcli status` (system + permission +
219
+ blacklist summary, no creds) and `dbcli doctor --format json` (env, config
220
+ shape, connectivity, schema-cache age, Mongo SRV path).
221
+
222
+ ### Per-engine essentials
223
+
224
+ ```bash
225
+ # PostgreSQL / MySQL / MariaDB (v1, plain values)
226
+ dbcli init --system postgresql --host localhost --port 5432 \
227
+ --user app --password '<secret>' --name appdb --permission query-only
228
+
229
+ # Reuse an existing .env (DATABASE_URL=postgresql://user:pw@host:5432/db)
230
+ dbcli init # parses .env in cwd
231
+
232
+ # MongoDB — full URI (Atlas / replica sets / authSource)
233
+ dbcli init --system mongodb \
234
+ --uri "mongodb+srv://user:pw@cluster.example.mongodb.net/mydb?authSource=admin"
235
+ # MongoDB — discrete params (no auth = omit --user/--password)
236
+ dbcli init --system mongodb --host localhost --port 27017 --name mydb
237
+
238
+ # Redis — `--name` is the LOGICAL DB INDEX ("0".."15"), not a database name
239
+ dbcli init --system redis --host localhost --port 6379 --password '<secret>' --name 0
240
+
241
+ # Elasticsearch — basic auth, Cloud ID, or API key
242
+ dbcli init --system elasticsearch --host localhost --port 9200 \
243
+ --user elastic --password '<secret>'
244
+ dbcli init --system elasticsearch \
245
+ --cloud-id "myCluster:dXMtZWFzdC0xLmF3..." --api-key "<base64>"
246
+ # Multi-node / custom CA / self-signed: edit `.dbcli` directly to add
247
+ # `nodes: [...]`, `protocol: https`, `caPath`, `rejectUnauthorized: false`.
248
+ ```
249
+
250
+ ### Multi-connection (v2)
251
+
252
+ ```bash
253
+ dbcli init --conn-name staging --env-file .env.staging --permission query-only
254
+ dbcli init --conn-name prod --env-file .env.production --use-env-refs --skip-test
255
+ dbcli use --list # show all, * marks default
256
+ dbcli use prod # switch default
257
+ dbcli query --use staging "SELECT 1" # one-shot override
258
+ dbcli init --rename staging:stg # rename
259
+ dbcli init --remove stg # remove
260
+ ```
261
+
262
+ Per-connection schema cache lives at `.dbcli/schemas/<connection>/`. Run
263
+ `dbcli schema --use <name>` once per connection before `schema <table>` —
264
+ otherwise the cache may serve another connection's columns.
265
+
266
+ ### env-refs (keep secrets out of `.dbcli`)
267
+
268
+ ```bash
269
+ dbcli init --use-env-refs \
270
+ --env-host DB_HOST --env-port DB_PORT \
271
+ --env-user DB_USER --env-password DB_PASSWORD --env-database DB_NAME
272
+ ```
273
+
274
+ Stored as `{ "$env": "DB_HOST" }` etc. and resolved at runtime. Pair with
275
+ `--env-file <path>` (v2) when each connection has its own env file.
276
+
277
+ ### Common gotchas
278
+
279
+ - **MongoDB `mongodb+srv://`** — `dbcli doctor` reports whether SRV resolves
280
+ natively or via the DoH fallback; useful when the runtime restricts DNS.
281
+ - **MySQL/Postgres password with `@` `:` `/`** — when using `DATABASE_URL`,
282
+ percent-encode (`@` → `%40`); discrete `--password` flags do not need encoding.
283
+ - **Redis `--name`** — accepts only the logical DB index string; non-numeric
284
+ values are rejected.
285
+ - **Elasticsearch TLS** — `caPath` and `rejectUnauthorized` are not exposed as
286
+ flags; edit `.dbcli` after `init` to add them.
287
+ - **Re-running `init`** — refuses to overwrite without `--force`; never use
288
+ `--force` to "fix" a config full of `{ "$env": "..." }` refs.
289
+
290
+ Full flags and edge cases: see [reference.md](reference.md) `init` section.
291
+
292
+ ## Command overview
293
+
294
+ | Command | Min permission | Summary |
295
+ |---------|-----------------|---------|
296
+ | `init` | n/a | Create `.dbcli` (v1 single or v2 multi via `--conn-name` / `--env-file`). **Usually run by the human** — do NOT re-run to strip `{"$env"}` references; that format is intentional. |
297
+ | `use` | n/a | Show/switch default named connection (v2 only). |
298
+ | `list` | query-only+ | Tables (SQL), collections (MongoDB), keys (Redis), or indices (Elasticsearch). |
299
+ | `schema` | query-only+ | SQL: per-table or full scan into `.dbcli/schemas/`. MongoDB: sampled. ES: flattened mapping. Redis: per-key only (type/TTL/size). Supports `--recovery`. |
300
+ | `query` | query-only+ | SQL, Mongo JSON (`--collection`), Redis command, or ES DSL/Lucene (`--collection`). `--format table\|json\|csv\|html`, `--ui` to open the interactive dashboard in a browser. Supports `--recovery`. |
301
+ | `explain` | query-only+ | **(v1.23)** Read-only query plan with annotations. SQL only. Single query, `@saved-query`, `@file.sql`, or `--bulk @glob/*`. `--analyze` (EXPLAIN ANALYZE / MariaDB ANALYZE SELECT), `--format markdown\|json\|table`. |
302
+ | `plan` | n/a | Static SQL risk analyzer (`--format text\|json`); classifies a statement without connecting to the database. |
303
+ | `q` | query-only+ | Run a saved snippet by `@name` with `--param k=v`. Supports `--verify` to run assertions. |
304
+ | `queries` | n/a | Manage saved snippets: `list` / `show` / `search` / `suggest` / `new` / `edit` / `check` / `delete` / `rename` / `copy` / `import` / `export`. |
305
+ | `insert` / `update` | read-write+ | SQL or MongoDB only. JSON `--data` / `--set`; `--where` required on `update`; `--dry-run` first. Redis writes go through `query`. Supports `--recovery`. |
306
+ | `delete` | data-admin+ | SQL or MongoDB only. `--where` required; `--dry-run` first. Supports `--recovery`. |
307
+ | `export` | query-only+ | SQL, MongoDB, or **(v1.22)** Elasticsearch (DSL `--index` or whole-index scroll). Query → `--format json\|jsonl\|csv\|html` file or stdout. `html` emits a standalone interactive dashboard. Supports `--recovery`. |
308
+ | `blacklist` | n/a | `list` / `table` / `column` subcommands redact sensitive data from query results. |
309
+ | `check` | query-only+ | SQL only (best on MySQL/MariaDB). |
310
+ | `diff` | query-only+ | SQL only. Save/compare schema snapshots. |
311
+ | `snapshot` | query-only+ | **(v1.25)** SQL only. Capture a result fingerprint (`rowCount` + per-column null/distinct/min/max/sum + order-independent checksum). `--out` (default `.dbcli/snapshots/snap-<ts>.json`), `--rows`, `--stdout`, `--format`, `--no-limit`. Baseline for `assert --against`. |
312
+ | `assert` | query-only+ | **(v1.25)** SQL only. Verify an invariant; exit 1 on failure unless `--no-fail`. `--expect "rows>0\|value==X\|col:c not null\|unique\|between a and b\|>= n"`, `--vs <query> --compare rows\|value` (reconcile), `--against <snapshot> --tolerance <pct>`. |
313
+ | `proxy` | n/a | **(v1.26)** MySQL/MariaDB/PostgreSQL only. Local-dev observability proxy — relays app traffic to the real DB and appends query/latency/byte/error events to `.dbcli/proxy/events.jsonl`. Subcommands: `mysql` \| `mariadb` \| `postgresql`. `--listen`, `--target`, `--events` (default `.dbcli/proxy/events.jsonl`), `--slow-ms` (default `1000`), `--redact none\|literals` (default `none`). Observe-only. **(v1.27)** `proxy analyze` aggregates the event log offline into a JSON/text report (summary, byFingerprint with suggestedCommands, slowest, errors, hotTables, N+1) — `--format`, `--top`, `--slow-ms`, `--n-plus-one`. |
314
+ | `status` | query-only+ | Safe JSON/text summary (no credentials). |
315
+ | `inspect` | query-only+ | Read-only context snapshot (connection, permission, blacklist, objects, snippets, context-aware `suggestedCommands`, and **(v1.23)** human-readable `hints`). `--for-agent` / `--brief` / `--no-connect` / `--require-schema-cache`. Supports `--recovery`. |
316
+ | `report` | query-only+ | Diagnostic report (health / capacity / perf) built from `@diag/*` snippets. `--section`, `--brief`, `--for-agent`, `--no-connect`. |
317
+ | `guide` | query-only+ | Deterministic next-command plan for a fixed goal (`slow-query`, `capacity`, `health`, `index-usage`, `permissions`, `schema-overview`). `--list` to enumerate. **(v1.23)** `guide missing-index-for <query>` suggests composite indexes for a single SELECT (`--format yaml\|json\|markdown`, `--min-confidence`). |
318
+ | `recovery` | n/a | Look up the structured `RecoveryEnvelope` for a known error code (`--code <CODE>` or `--list`). Standalone synthesizer; does not require a real failure. |
319
+ | `recover` | n/a | Inspect (default) or `--apply` the auto-saved recovery plan in `.dbcli/last-recovery.json`. `--allow-write=readonly-cmd\|write-cmd`, `--no-verify`, `--from <file>`, `--next --after-step <n> --result <json\|@file>` for multi-turn step-at-a-time. |
320
+ | `doctor` | n/a | Environment, config, connection, SRV diagnostics (Mongo), schema cache age. |
321
+ | `completion` | n/a | bash / zsh / fish scripts. |
322
+ | `upgrade` | n/a | Self-update from npm; 24h-cached version hints on every command. |
323
+ | `shell` | (same as query+) | Interactive REPL. SQL engines, MongoDB, and Redis (single-line; `.no-limit on/off`). **(v1.22)** Elasticsearch opens a Kibana Dev Tools-style REPL (`<METHOD> /<path>` + optional JSON body, blank line submits). |
324
+ | `skill` | n/a | Generate / install AI skill docs (`--install <claude\|gemini\|antigravity\|copilot\|cursor\|codex\|windsurf>`); `skill tasks list/show/plan` for Agent Task Packs; `skill context` for LLM prompt context payload. |
325
+ | `migrate` | admin | SQL only. **DDL; dry-run by default** — needs `--execute`. |
326
+
327
+ `--use <name>` on any subcommand targets a v2 connection without changing the default.
328
+ `--recovery` is honoured by `query`, `q`, `insert`, `update`, `delete`, `export`, `schema`, and `inspect`; on failure these emit a `RecoveryEnvelope` JSON to stdout, suppress the human stderr message, and atomically save the envelope to `.dbcli/last-recovery.json` for `dbcli recover` to consume.
329
+
330
+ ## Permission levels
331
+
332
+ | Level | Allowed |
333
+ |-------|---------|
334
+ | query-only | SELECT, list, schema, export |
335
+ | read-write | + INSERT, UPDATE |
336
+ | data-admin | + DELETE (DML, no DDL) |
337
+ | admin | + DDL via `migrate` and destructive ops |
338
+
339
+ ## Multi-connection (v2)
340
+
341
+ - Each named connection has its own schema dir: `.dbcli/schemas/<connection>/`.
342
+ - Run `dbcli schema --use <name>` once per connection before `schema <table>` — otherwise the cache may return another connection's columns.
343
+ - `schema --refresh` / `--reset` manage the cache; see reference.md.
344
+
345
+ ## MongoDB
346
+
347
+ - JSON filter object (`find`) or JSON array (`aggregate`); SQL is rejected. `--collection <name>` is required on `query`.
348
+ - **Supported:** `init`, `list`, `schema` (sampled), `query`, `insert`, `update`, `delete`, `export`, `q` (saved queries), `status`, `use`, `shell`, `doctor`, `upgrade`, `completion`.
349
+ - **Not supported:** `diff`, `migrate`, `check`.
350
+ - Schema is **sampled** by `$sample` (default 100 docs, max 1000). Pass `--sample-method natural` to use `find().limit()` instead. Columns surface as dot-paths (e.g. `profile.tokens.access`) with `presence` (0..1) and `redacted: true` flags for blacklist hits.
351
+ - **Write planner tiers:** `$set`/`$unset` → `ALLOW`; `$rename` → `WARN` (informational); `$inc`/`$mul`/`$min`/`$max`/`$currentDate` → `WARN`; `$push`/`$pull`/`$pullAll`/`$pop`/`$addToSet` → `WARN`; `$bit` → `WARN`; `$where` and unknown operators → `BLOCK`.
352
+ - **Nested blacklist:** `blacklist.columns[<collection>]` accepts dotted paths (`profile.email`) and trailing-wildcard prefixes (`profile.tokens.*`); middle wildcards are rejected with a warning at `dbcli blacklist list`. Read paths replace matched values with the literal string `[REDACTED]`.
353
+ - **Saved queries:** snippet file ends in `.mongodb.sql`. Frontmatter requires `engine: mongodb` and `operation: find` or `operation: aggregate`. `target: <collection>` is the default collection (override with `--collection`). Body is JSON (object for `find`, array for `aggregate`); `{{param}}` placeholders are JSON-encoded.
354
+ - See reference.md MongoDB section for full syntax and examples.
355
+
356
+ ## Redis
357
+
358
+ - Command-style execution; `query` runs a whitelisted Redis command (e.g. `GET`, `HSET`, `DEL`).
359
+ - **Supported:** `init`, `list` (keys via SCAN), `schema <key>` (type / TTL / size / sample), `query`, `shell`, `status`, `use`, `doctor`, `upgrade`, `completion`.
360
+ - **Not supported:** `schema` full scan, `insert`, `update`, `delete`, `export`, `check`, `diff`, `migrate`, `q`.
361
+ Use `query "DEL <key>"` etc. for writes — they go through the same permission gate.
362
+ - Permission tiers map to commands: read commands → `query-only`; mutators (`SET`, `HSET`, ...) → `read-write`; `DEL` / `UNLINK` → `data-admin`.
363
+ - `database` field is the logical DB index (default `0`); `list` returns ≤ 100 000 keys via SCAN.
364
+ - **Size guard:** `SCAN`/`HSCAN`/`SSCAN`/`ZSCAN` inject `COUNT 1000`; `LRANGE`/`ZRANGE` clamp `stop`; `ZRANGEBYSCORE` injects `LIMIT 0 1000`; `HGETALL`/`HKEYS`/`HVALS`/`SMEMBERS`/`KEYS` truncate at 1000. Results carry `warnings[]` (`REDIS_SIZE_REWRITE` / `REDIS_SIZE_TRUNCATE`). Pass `--no-limit` (CLI) or `.no-limit on` (shell) to bypass.
365
+ - **Blacklist:** `dbcli blacklist add 'secrets:*'` registers a Redis-native key glob. Reads/writes whose keys match are rejected (`BlacklistRejection`, audited with `metadata.matched_pattern`); `KEYS`/`SCAN MATCH` overlapping a rule are rejected; non-overlapping listings filter blacklisted keys.
366
+ - **Masking (v1.22):** add a `redis.mask` block to `.dbcli` — keys matching a `keyPattern` glob have their value (or named hash `fields`) returned as `[REDACTED]` on reads (`GET`, `GETRANGE`, `HGETALL`, `HGET`, `HMGET`, `HVALS`). Masking coexists with key-glob rejection, and **rejection always wins over masking**.
367
+ - **Shell:** `dbcli shell` on a Redis connection opens a single-line REPL (history, tab completion of commands + key prefixes, `.no-limit on/off`).
368
+ - See reference.md Redis section.
369
+
370
+ ## Elasticsearch
371
+
372
+ - DSL (JSON body) or Lucene query string; `--collection <index>` is required on `query`.
373
+ - **Supported:** `init`, `list` (indices with doc count), `schema [index]` (flattened mapping), `query`, `export` (v1.22), `shell` (v1.22), `status`, `use`, `doctor`, `upgrade`, `completion`.
374
+ - **Not supported:** `insert`, `update`, `delete`, `check`, `diff`, `migrate`, `q`.
375
+ Writes are not exposed via dedicated subcommands yet — use `query` if the cluster allows or external tools.
376
+ - **Export (v1.22):** `dbcli export` takes a search DSL with `--index <index>` to export hits, or an index name as the query to scroll the whole index via `match_all`. Outputs JSON / JSONL / CSV (default 1000 rows; `--no-limit` scrolls the full index in batches). Index-level blacklist + audit apply.
377
+ - **Shell (v1.22):** `dbcli shell` opens a Kibana Dev Tools-style REPL — request line `<METHOD> /<path>` plus an optional multi-line JSON body, submitted with a blank line; index-level blacklist rejects protected indices and `_search` auto-caps at 1000 when `size` is omitted.
378
+ - Query-only mode caps at 1000 hits; `--no-limit` is bounded at 10 000.
379
+ - Schema flattens nested fields (`a.b.c`) and surfaces `.fields` multi-fields.
380
+ - See reference.md Elasticsearch section.
381
+
382
+ ## Saved queries
383
+
384
+ Run reusable parameterised SELECT snippets stored in your repo.
385
+
386
+ | Step | Command |
387
+ |------|---------|
388
+ | 1. Discover | `dbcli queries list` |
389
+ | 2. Inspect | `dbcli queries show @<name>` |
390
+ | 3. Run | `dbcli q @<name> --param k=v` |
391
+
392
+ ### When you don't know which query to run
393
+
394
+ 1. `dbcli queries search <keywords>` — natural keywords, fuzzy ranked
395
+ 2. `dbcli queries suggest <intent>` — browse a category
396
+ Common intents: perf.slow-query, perf.cache-hit, capacity.size,
397
+ safety.connections, monitor.cluster-health
398
+ 3. Once you find one: `dbcli q @<name>` (blacklist always enforced)
399
+
400
+ Snippets resolve from three layers, **local > shared > builtin** (local wins):
401
+ - `builtin` — bundled with dbcli (e.g. `@diag/*`); read-only at runtime
402
+ - `.dbcli-shared/queries/` — committed, team-shared
403
+ - `.dbcli/queries/` — gitignored, personal override
404
+
405
+ Manage local snippets with `queries new | edit | delete | rename | copy | import | export`
406
+ (see reference.md). Use `copy` / `import` to fork a builtin or shared snippet into the
407
+ local layer for editing.
408
+
409
+ Each `.sql` file may declare YAML frontmatter inside `-- ---` blocks
410
+ (name, description, engine, params, tags, optional `intent`, optional `visual`).
411
+ The `visual:` block drives the interactive dashboard (see "Interactive HTML dashboard"
412
+ below). See `dbcli queries show @<name> --format json` for the machine-readable contract.
413
+
414
+ ### Engine-specific bodies
415
+
416
+ Each snippet's body format is determined by the `engine` frontmatter field:
417
+
418
+ | Engine | Body format | Notes |
419
+ |-------------------|------------------------|-------|
420
+ | postgres / mysql | Single SELECT or WITH | `:name` → driver bind (`$1` / `?`) |
421
+ | elasticsearch | JSON DSL | `:name` → JSON-aware substitution; `index:` field required |
422
+ | redis | Single Redis command | `:name` → raw text; only read commands allowed |
423
+
424
+ Mixed-family `engine` arrays (e.g. `[postgres, elasticsearch]`) are rejected at parse time.
425
+
426
+ ### Built-in diagnostic snippets
427
+
428
+ dbcli ships ready-made diagnostic queries. Run with `dbcli q @diag/<topic>`:
429
+
430
+ | key | purpose |
431
+ |-------------------------|------------------------------------------|
432
+ | `@diag/connections` | active sessions |
433
+ | `@diag/long-running` | queries above `min_seconds` (default 30) |
434
+ | `@diag/table-sizes` | table data/index size with row counts |
435
+ | `@diag/index-usage` | indexes by scan count |
436
+ | `@diag/missing-indexes` | tables dominated by sequential scans |
437
+ | `@diag/locks` | lock-wait chains |
438
+ | `@diag/db-size` | database size summary |
439
+ | `@diag/cache-hit` | buffer cache hit ratios |
440
+ | `@diag/es-cluster-health` | document counts per index (ES connections) |
441
+ | `@diag/redis-key-stats` | sample SCAN over keyspace (Redis connections) |
442
+
443
+ Engine variants are picked automatically based on the active connection.
444
+ Override any of them by placing a same-named file under `.dbcli-shared/queries/`
445
+ or `.dbcli/queries/`.
446
+
447
+ ## Interactive HTML dashboard
448
+
449
+ `query`, `q`, and `export` can render results as a standalone, self-contained HTML
450
+ report powered by a bundled React + Recharts template (`assets/ui-template.html`,
451
+ injected via a hardened `window.__DBCLI_PAYLOAD__ = {...}` block — `<` is escaped
452
+ to neutralise `</script>` payloads).
453
+
454
+ ```bash
455
+ # Open in browser (writes to a temp file, then `open`/`xdg-open`/`start`)
456
+ dbcli query "SELECT day, dau FROM dau_daily" --ui
457
+ dbcli q @analytics/revenue --param days=30 --ui
458
+
459
+ # Pipe HTML to stdout (CI artifacts, email, static hosting)
460
+ dbcli query "SELECT * FROM orders" --format html > orders.html
461
+
462
+ # Export to a file (interchangeable with json/jsonl/csv)
463
+ dbcli export "SELECT * FROM orders" --format html --output orders.html
464
+ ```
465
+
466
+ `--ui` implies `--format html` and opens the file; `--format html` alone prints to
467
+ stdout. Blacklist redaction is applied **before** rendering — the dashboard never
468
+ sees masked columns.
469
+
470
+ ### Snippet `visual:` block
471
+
472
+ To get KPIs and charts (rather than just a sortable table), add a `visual:` block
473
+ to the snippet's frontmatter. Column names must exist in the result row.
474
+
475
+ ```sql
476
+ -- ---
477
+ -- name: Revenue Trend
478
+ -- engine: postgres
479
+ -- params:
480
+ -- days: { type: int, default: 30 }
481
+ -- visual:
482
+ -- title: Revenue (last :days days)
483
+ -- kpis:
484
+ -- - { label: Total Revenue, value_column: total_revenue, format: currency }
485
+ -- - { label: Orders, value_column: order_count, format: number }
486
+ -- - { label: Conversion, value_column: conv_rate, format: percent }
487
+ -- charts:
488
+ -- - { type: line, title: Daily Revenue, x: day, y: [revenue] }
489
+ -- - { type: bar, title: By Channel, x: channel, y: [revenue, refunds] }
490
+ -- ---
491
+ SELECT ...
492
+ ```
493
+
494
+ - `kpis[].format`: `currency` / `number` / `percent` (omit for raw value).
495
+ - `charts[].type`: `line` / `bar` / `area` / `pie` / `scatter`.
496
+ - Raw `query` invocations (no snippet) render a sortable/filterable table only —
497
+ there is no `visual:` to attach.
498
+
499
+ ## Common workflows
500
+
501
+ - **Debug odd state:** `schema` → `check` → `query` with tight `WHERE` → follow FKs from schema JSON. Evidence over theory.
502
+ - **After INSERT/UPDATE:** `--dry-run` → run → `query` read-back; explain mismatches via triggers, defaults, or blacklist.
503
+ - **Migrations:** `diff --snapshot` → `migrate` (dry-run → `--execute`) → `diff --against` → `check` affected tables. DROP requires `--force`.
504
+ - **Health / growth:** `check --all` (huge tables skipped unless `--include-large`); consult schema `sizeCategory` before ad-hoc queries.
505
+ - **Codegen from live DB:** `schema --format json` to drive an ORM; cross-check once with `dbcli query`.
506
+ - **Integration truth:** `query` before → run app → `query` after. Unit-test mocks are not a substitute.
507
+ - **Natural language requests** (e.g. "update order to shipped"): pick `query` vs DML, map terms → columns via `schema` (and enum values in data), respect blacklist and `sizeCategory`, **always `--dry-run` writes first**.
508
+
509
+ ## Notes
510
+
511
+ - Query-only mode auto-appends `LIMIT 1000`; add `--no-limit` for `information_schema` or statements that break with `LIMIT`.
512
+ - Blacklisted tables and columns are redacted from query output.
513
+ - `schema` reports `estimatedRowCount` and `sizeCategory` (small / medium / large / huge). For large/huge tables add `WHERE` or `LIMIT` — bands in reference.md.
514
+ - `doctor` on `mongodb+srv://` reports whether SRV resolves natively or through the DoH fallback — useful when the runtime restricts DNS.
515
+ - **Global flags:** `--config <path>`, `--use <name>`, `-v` / `-vv` / `-q`, `--no-color` (also honours `NO_COLOR`).