@carllee1983/dbcli 1.37.1 → 1.39.1

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.
@@ -1,6 +1,6 @@
1
1
  ---
2
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`.
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, generate DB reports or interactive HTML dashboards, 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, generating a report/dashboard/HTML UI from raw SQL or saved snippets, 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
4
  ---
5
5
 
6
6
  # dbcli
@@ -12,65 +12,55 @@ If the `dbcli` executable is not available in `PATH`, use
12
12
  fallback for Codex plugin installs where the skill is installed by the plugin but
13
13
  the CLI package has not been installed globally.
14
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
-
35
- Verification outcome vocabulary: use `verified` only when required evidence matched;
36
- use `not_verified` when the check ran and contradicted the expected state; use
37
- `indeterminate` when the check ran but evidence was ambiguous; use `blocked` when
38
- verification could not run because of config, permission, schema, placeholder, or
39
- safety gates.
40
-
41
- - **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:
42
-
43
- ```bash
44
- # The agent reads step 1 from the envelope, runs it, then asks dbcli for step 2:
45
- dbcli recover --next --after-step 1 --result '{"status":"ok","exitCode":0}'
46
- # Returns a NextResult envelope:
47
- # {
48
- # "schemaVersion": 1,
49
- # "kind": "step",
50
- # "errorCode": "BLACKLIST_TABLE",
51
- # "cursor": 2,
52
- # "totalSteps": 3,
53
- # "step": { "order": 2, "command": "dbcli inspect --for-agent", ... }
54
- # }
55
- # After the last step, dbcli returns kind: "done".
56
- ```
57
-
58
- `--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.
59
-
60
- **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.
61
- 5. `dbcli blacklist list` — sensitive data boundaries.
62
- 6. `dbcli schema <table> --format json` — real column names (SQL/Mongo/ES) or `schema <key>` (Redis). **Never guess.**
63
- 7. Run `query` / `insert` / `update` / `delete` / `export` within permission.
64
- 8. All writes: `--dry-run` (SQL/Mongo) → run → `query` read-back to confirm.
65
- - **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.
15
+ ## How to use dbcli
16
+
17
+ **Safety baselineapply to every operation:**
18
+
19
+ 1. `dbcli blacklist list` — confirm sensitive-data boundaries.
20
+ 2. `dbcli schema <object> --format json` — confirm real column/field names. **Never guess.**
21
+ 3. All writes: `--dry-run` (SQL/Mongo) run `query` read-back to confirm.
22
+
23
+ > `report` and `guide` already embed an `inspect` snapshot you do **not** need to run
24
+ > `dbcli inspect` first. Run `dbcli inspect --for-agent` manually only when you want the
25
+ > audit-recent context or to diagnose a connection problem.
26
+
27
+ **Then route by task:**
28
+
29
+ | Task | Path |
30
+ | --- | --- |
31
+ | A named workflow fits ("diagnose slow query", "audit permissions") | `skill tasks list` → `skill tasks plan <pack>` **prefer this; do not invent steps** |
32
+ | A fixed diagnostic goal | `guide <goal>` (`slow-query` / `capacity` / `health` / `index-usage` / `permissions` / `schema-overview`; `guide --list`) |
33
+ | A DB report / dashboard / HTML UI | `blacklist list` `queries search <keywords>` or `queries suggest <intent>` `queries show @<name>` browser: `q @<name> --param k=v --ui`; file: `q @<name> --format html > report.html` or `export "<SQL>" --format html --output report.html` |
34
+ | Setting up a connection | see **Connection setup** |
35
+ | Anything else | run commands manually; consult the **Developer workflows** cheat-sheet |
36
+
37
+ Slow-query diagnosis has three canonical paths (pick by what you already know):
38
+
39
+ - Known slow SQL → `skill tasks plan diagnose-slow-query --param query="<SQL>"` → `guide missing-index-for "<SQL>"`
40
+ - Known hot table → `skill tasks plan analyze-table-perf --param table=<table>`
41
+ - Whole-environment scan `report --section perf` `guide slow-query`
42
+
43
+ `report --section perf` already runs the slow-query, index-usage, and cache-hit diagnostics —
44
+ afterwards add only the `@diag/*` it does not cover (`missing-indexes`, `locks`, `connections`,
45
+ `table-sizes`). Once you have a specific slow statement, `explain --analyze "<SQL>"` shows its plan.
46
+
47
+ **On failure:** pass `--recovery` to `query` / `q` / `insert` / `update` / `delete` /
48
+ `export` / `schema` / `inspect`. The command emits a `RecoveryEnvelope` to stdout and saves
49
+ it to `.dbcli/last-recovery.json`; then `dbcli recover` inspects it and `dbcli recover --apply`
50
+ runs the saved plan under risk gating. Multi-turn `--next`, connection branching, and the
51
+ post-apply verify probe are documented in reference.md §Recovery Cookbook.
52
+
53
+ When reporting a check's outcome use the vocabulary `verified` (evidence matched) /
54
+ `not_verified` (check ran and contradicted) / `indeterminate` (ran but ambiguous) /
55
+ `blocked` (could not run due to config, permission, schema, placeholder, or safety gate).
66
56
 
67
57
  Prefer `--format json` for agent-friendly output.
68
58
 
69
59
  ## Agent Task Packs
70
60
 
71
- When the user asks for a database workflow (e.g. "diagnose this slow query", "audit
72
- permissions", "review long-running operations"), prefer published task templates
73
- over inventing steps from memory.
61
+ When the user asks for a database workflow ("diagnose this slow query", "audit
62
+ permissions", "review long-running operations"), **prefer published task templates over
63
+ inventing steps from memory.**
74
64
 
75
65
  ```bash
76
66
  dbcli skill tasks list --format json # discover
@@ -78,45 +68,35 @@ dbcli skill tasks show <task> # inspect
78
68
  dbcli skill tasks plan <task> --param key=value --format json # generate plan
79
69
  ```
80
70
 
81
- The plan output is an ordered list of dbcli commands with rationale and risk
82
- labels. Execute them one at a time — task plans do **not** override blacklist,
83
- schema, dry-run, or confirmation requirements.
84
-
85
- Builtin packs: `diagnose-slow-query` and **(v1.23)** `analyze-table-perf` — a
86
- read-only `plan-only` pack taking a required `table` parameter that walks
87
- `blacklist list` `schema <table> --format json` → `guide index-usage`. `dbcli
88
- inspect` suggests `analyze-table-perf` automatically for the hottest table in
89
- recent audit activity. Additional read-only packs: `audit-permissions`,
90
- `safe-backfill`, `schema-drift-review`, `connection-health` run
91
- `dbcli skill tasks list` for the full set.
92
-
93
- Review & verification packs: `pr-database-review` (assess a PR's changed queries,
94
- migrations and blacklist risk), `migration-review` (capture pre-change schema and
95
- preview DDL), `safe-backfill-verify` (backfill planning with a read-back `assert`),
96
- and `slow-endpoint-investigation` (chain `proxy analyze` → `explain` →
97
- `guide missing-index-for`). All are read-only `plan-only` — pick the pack matching the
98
- user's situation before improvising, and run any index/DDL proposal through
99
- `migration-review` before writing.
71
+ The plan is an ordered list of dbcli commands with rationale and risk labels. Execute them
72
+ one at a time — task plans do **not** override blacklist, schema, dry-run, or confirmation
73
+ requirements.
74
+
75
+ Builtin packs: `diagnose-slow-query` (targets a specific SQL), `analyze-table-perf` (targets
76
+ a specific table; `dbcli inspect` auto-suggests it for the hottest table in recent audit
77
+ activity), `audit-permissions`, `safe-backfill`, `schema-drift-review`, `connection-health`.
78
+ Review/verify packs: `pr-database-review`, `migration-review`, `safe-backfill-verify`,
79
+ `slow-endpoint-investigation`. All are read-only `plan-only` — pick the pack matching the
80
+ situation, and run any index/DDL proposal through `migration-review` before writing.
100
81
 
101
82
  Tasks live under `assets/tasks/` (builtin), `.dbcli-shared/tasks/` (shared), and
102
83
  `.dbcli/tasks/` (local override).
103
84
 
104
85
  ## Developer workflows
105
86
 
106
- Use these workflows when database impact is implicit in a development task. Keep
107
- the normal dbcli safety rules: prefer `--format json`, run `blacklist list`
108
- before touching sensitive data, confirm names with `schema`, dry-run writes, and
109
- use `--recovery` / `recover` after failures.
110
-
111
- | Situation | Use dbcli for | Minimum safe path |
112
- | --- | --- | --- |
113
- | DB-backed feature | Map product/code terms to real objects before editing code. | `inspect --for-agent` -> `blacklist list` -> `schema <object>` -> `queries suggest <intent>` |
114
- | 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 |
115
- | 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>` |
116
- | 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. |
117
- | 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. |
118
- | 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`. |
119
- | Environment validation | Check config shape and connectivity without leaking secrets. | `status --format json` -> `doctor --format json` -> `inspect --for-agent --no-connect --format json`. |
87
+ Use these workflows when database impact is implicit in a development task. The safety baseline
88
+ in **How to use dbcli** still applies.
89
+
90
+ | Situation | Minimum safe path |
91
+ | --- | --- |
92
+ | DB-backed feature | `blacklist list` `schema <object>` `queries suggest <intent>` |
93
+ | DB report / dashboard request | `blacklist list` → `queries search <keywords>` / `queries suggest <intent>` → `queries show @<name>` → `q @<name> --ui` or `--format html` |
94
+ | Application data bug | `audit tail --for-agent --n 10` `blacklist list` `schema <object>` narrow query |
95
+ | ORM or migration work | `schema --format json` `diff --snapshot <name>` `migrate add-index`/`add-column` (preview SQL) → `diff --against <snapshot>` |
96
+ | PR database review | Review changed persistence paths, then propose concrete `schema` / `plan` / `dry-run` / `report` / `guide` commands per material claim. |
97
+ | Slow endpoint or query | `report --section perf` task pack `analyze-table-perf` `guide missing-index-for "<query>"`; use `proxy analyze` when logs exist. |
98
+ | Safe data backfill | `blacklist list` `schema <object>` count/scope query `update --dry-run` read-back or snippet `--verify`. |
99
+ | Environment validation | `status --format json` `doctor --format json` `inspect --for-agent --no-connect`. |
120
100
 
121
101
  Copy-paste command anchors:
122
102
 
@@ -125,86 +105,49 @@ dbcli inspect --for-agent --format json
125
105
  dbcli blacklist list --format json
126
106
  dbcli schema <object> --format json
127
107
  dbcli queries suggest <intent> --format json
108
+ dbcli queries search <report keywords> --format json
109
+ dbcli queries show @<name> --format json
110
+ dbcli q @<name> --param k=v --ui
111
+ dbcli q @<name> --param k=v --format html > report.html
112
+ dbcli export "<SQL>" --format html --output report.html
128
113
  dbcli audit tail --for-agent --n 10
129
- dbcli schema --format json
130
114
  dbcli diff --snapshot <name>
131
- dbcli migrate add-index <table>
132
- dbcli diff --against <snapshot>
133
115
  dbcli report --section perf --format json
134
116
  dbcli skill tasks plan analyze-table-perf --param table=<table> --format json
135
117
  dbcli guide missing-index-for "<query>" --format json
136
- dbcli proxy analyze --format json
137
- dbcli query "<count/scope query>" --format json
138
118
  dbcli update <object> --where "<bounded predicate>" --set '<json>' --dry-run --format json
139
- dbcli status --format json
140
- dbcli doctor --format json
141
119
  dbcli inspect --for-agent --no-connect --format json
142
120
  ```
143
121
 
144
- Developer workflow guardrails:
122
+ Guardrails:
145
123
 
146
- - Never invent table, collection, key, index, or field names. Confirm them with
147
- `schema` before writing code that depends on them.
148
- - Separate database facts from application-code inference. Report which dbcli
149
- output shaped the code or review conclusion.
150
- - For writes and backfills, include scope count, dry-run preview, execution
151
- command, and read-back or snippet verification.
124
+ - Never invent table, collection, key, index, or field names. Confirm with `schema`.
125
+ - Separate database facts from application-code inference. Report which dbcli output shaped the conclusion.
126
+ - For writes and backfills, include scope count, dry-run preview, execution command, and read-back.
152
127
  - Do not create indexes directly from a performance suggestion; turn them into reviewed migrations.
153
128
  - Do not print credentials, copied connection strings, or blacklisted values.
154
- - To persist result evidence for a read-back assertion, run `assert ... --write-verification-artifact --verification-subject <kind:name>` (kinds: `recovery`, `task-pack`, `assertion`, `migration`, `backfill`, `manual`).
155
- - Inspect result evidence (read-only): `dbcli verification summary --format json`
156
- (also `verification list` / `verification show <id>`). Reclaim old artifacts with
157
- `dbcli verification prune --older-than 30d` (dry-run; add `--execute --force` to delete).
158
- - `tasks plan safe-backfill-verify` when the user needs a plan only.
159
- - `verify safe-backfill` — before a real safe backfill (preflight) and after it
160
- (`--after-write`) when durable evidence is required. Never executes the write.
161
- - `tasks plan migration-review` — when the user needs a migration plan only (plan output, no DDL executed).
162
- - `verify migration` — preflight a schema migration (analyze DDL, run guards) and after the migration is applied externally (`--after-write`) to record evidence. Never executes DDL.
163
- - `verify rollback --kind <ddl|dml>` — verify that a reverting change restored the prior state: preflight analyzes the reverting `ALTER TABLE` (`--kind ddl`) or `UPDATE` (`--kind dml`) via `--statement`, and `--after-write` records evidence after you apply it externally. Never executes the statement.
164
- - `verification show <id>` — cite the final artifact.
165
-
166
- 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).
167
-
168
- ## Audit Log usage
169
-
170
- Use the audit log when you need cross-session history or forensics on what dbcli
171
- has done on this database, rather than re-querying live DB state from scratch.
172
-
173
- **Scenario 1 — Session handoff (picking up where another agent left off):**
174
-
175
- ```bash
176
- dbcli audit tail --for-agent --n 10 # last 10 entries as JSON envelope
177
- dbcli audit tail --all --for-agent --n 20 # cross-connection merged view (D4)
178
- ```
129
+ - Durable evidence: `assert --write-verification-artifact --verification-subject <kind:name>`;
130
+ inspect with `verification summary` / `list` / `show <id>`. The `verify safe-backfill` /
131
+ `migration` / `rollback --kind <ddl|dml>` / `constraint --check <fk|not-null|unique|custom>`
132
+ family runs preflight + `--after-write` checks and **never executes the write**. Full flags
133
+ and the per-command blocks are in reference.md.
179
134
 
180
- Returns an agent-facing JSON envelope with `session_id` / `engine` / `command` /
181
- `target` / `success` per entry. Metadata-only by design — never raw SQL bodies,
182
- `--param` values, or result cell contents (D3 lock).
135
+ ## Audit log
183
136
 
184
- **Scenario 2 Forensics (reconstructing a failure):**
137
+ Use the audit log for cross-session history or failure forensics instead of re-querying
138
+ live DB state.
185
139
 
186
140
  ```bash
187
- dbcli recover --format json # inspect audit_recent embed + recovery_ref
188
- dbcli audit show <id-prefix> # full entry by id prefix (>=4 chars)
189
- dbcli audit show --recovery-ref <envelope-id> # find entry that emitted an envelope
141
+ dbcli audit tail --for-agent --n 10 # last N entries (JSON envelope, metadata-only)
142
+ dbcli audit show <id-prefix> # full entry by id prefix (4 chars)
143
+ dbcli audit show --recovery-ref <env-id> # find the entry that emitted an envelope
190
144
  ```
191
145
 
192
- The `inspect` / `guide` / `recover` / `recover --apply` agent JSON output embeds
193
- `audit_recent: AuditEntryBrief[]` (last 5 entries) a fresh session has immediate
194
- history context. The envelope's `audit_ref` and the audit entry's `recovery_ref`
195
- point at each other; agents can pivot either direction.
196
-
197
- Bi-directional `recovery_ref` / `audit_ref` linkage is wired on every command
198
- that accepts `--recovery`: `query`, `inspect`, `insert`, `update`, `delete`,
199
- `export`, `q`, and `schema`. Agents can pivot from an envelope to its audit
200
- entry via `audit tail --recovery-ref <id>`.
201
-
202
- Audit entries are written to `.dbcli/audit/<connection>.jsonl` with rotation at
203
- ~10 MB or 1000 entries. `audit.enabled = false` in `.dbcli` opts out (default ON
204
- since v1.20.0). For flag reference see [`reference.md`](./reference.md) §audit.
205
- For end-to-end recovery walkthroughs (per-code scenarios, `--next` multi-turn,
206
- envelope ⇄ audit pivot, risk-gate cheat sheet) see
207
- [`reference.md`](./reference.md) §Recovery Cookbook.
146
+ The `inspect` / `guide` / `recover` agent JSON embeds `audit_recent` (last 5 entries) — a
147
+ fresh session has immediate history. An envelope's `audit_ref` and an audit entry's
148
+ `recovery_ref` point at each other, so you can pivot either way. Audit is on by default
149
+ (`audit.enabled = false` to opt out); entries are metadata-only (never SQL bodies, `--param`
150
+ values, or result cells) and rotate at ~10 MB / 1000 entries. Full flags: reference.md §audit.
208
151
 
209
152
  ## Quick start
210
153
 
@@ -235,12 +178,12 @@ or `doctor` / `status` reports a missing or invalid config, follow this flow.
235
178
  2. **Where do credentials live?**
236
179
  - Already in a `.env` (`DATABASE_URL` or `DB_HOST` / `DB_PORT` / `DB_USER` /
237
180
  `DB_PASSWORD` / `DB_NAME` | `DB_DATABASE`) → `init` parses it automatically.
238
- - Need to keep secrets out of `.dbcli` (CI/CD, multi-env) → `--use-env-refs`
239
- plus `--env-host` / `--env-port` / `--env-user` / `--env-password` / `--env-database`.
181
+ - Need to keep secrets out of `.dbcli` (CI/CD, multi-env) → `--use-env-refs` (see below).
240
182
  - Plain values are acceptable → pass `--host` / `--port` / `--user` /
241
183
  `--password` / `--name` (and `--system`).
242
184
  3. **What permission tier?** Default to the **lowest** that satisfies the task:
243
- `query-only` → `read-write` → `data-admin` → `admin`. Set with `--permission`.
185
+ `query-only` → `read-write` → `data-admin` → `admin`. Set with `--permission`
186
+ (defaults to `query-only`).
244
187
  4. **Verify, never assume.** After init: `dbcli status` (system + permission +
245
188
  blacklist summary, no creds) and `dbcli doctor --format json` (env, config
246
189
  shape, connectivity, schema-cache age, Mongo SRV path).
@@ -280,25 +223,38 @@ dbcli init --conn-name staging --env-file .env.staging --permission query-only
280
223
  dbcli init --conn-name prod --env-file .env.production --use-env-refs --skip-test
281
224
  dbcli use --list # show all, * marks default
282
225
  dbcli use prod # switch default
283
- dbcli query --use staging "SELECT 1" # one-shot override
226
+ dbcli query --use staging "SELECT 1" # one-shot override on any subcommand
284
227
  dbcli init --rename staging:stg # rename
285
228
  dbcli init --remove stg # remove
286
229
  ```
287
230
 
288
- Per-connection schema cache lives at `.dbcli/schemas/<connection>/`. Run
289
- `dbcli schema --use <name>` once per connection before `schema <table>` —
290
- otherwise the cache may serve another connection's columns.
231
+ Each named connection has its own schema cache at `.dbcli/schemas/<connection>/`. Run
232
+ `dbcli schema --use <name>` once per connection **before** `schema <table>` — otherwise the
233
+ cache may serve another connection's columns. `schema --refresh` / `--reset` manage the cache
234
+ (reference.md). `--skip-test` skips the init-time TCP connection test; it is implied
235
+ automatically when `--use-env-refs` is set (the `$env` refs have no value to connect with yet).
236
+ `--system` is optional for v2 — without it the engine is inferred from `--env-file` / `.env`
237
+ (`DATABASE_URL` scheme), defaulting to `postgresql`.
291
238
 
292
239
  ### env-refs (keep secrets out of `.dbcli`)
293
240
 
241
+ Store credentials as `{ "$env": "VAR" }` references resolved at runtime, never plaintext:
242
+
294
243
  ```bash
295
- dbcli init --use-env-refs \
296
- --env-host DB_HOST --env-port DB_PORT \
297
- --env-user DB_USER --env-password DB_PASSWORD --env-database DB_NAME
244
+ # Default key names: DB_HOST / DB_PORT / DB_USER / DB_PASSWORD / DB_DATABASE
245
+ dbcli init --use-env-refs
246
+
247
+ # Non-default key names — name each one explicitly (required in CI):
248
+ dbcli init --conn-name prod --env-file .env.production --use-env-refs --skip-test \
249
+ --env-host PROD_DB_HOST --env-port PROD_DB_PORT \
250
+ --env-user PROD_DB_USER --env-password PROD_DB_PASSWORD --env-database PROD_DB_NAME
298
251
  ```
299
252
 
300
- Stored as `{ "$env": "DB_HOST" }` etc. and resolved at runtime. Pair with
301
- `--env-file <path>` (v2) when each connection has its own env file.
253
+ In an **interactive terminal**, omitting the `--env-*` flags prompts for each key name
254
+ (defaults above) you can type a non-default name like `PROD_DB_PASSWORD` and it is stored
255
+ as a `$env` ref. In a **non-interactive / CI** run you **must** pass all five `--env-*`
256
+ flags; otherwise `init` exits with an error — it never silently falls back to plaintext.
257
+ `--env-file <path>` is the path to the env file, independent of the `$env` key names.
302
258
 
303
259
  ### Common gotchas
304
260
 
@@ -329,7 +285,7 @@ Full flags and edge cases: see [reference.md](reference.md) `init` section.
329
285
  | `q` | query-only+ | Run a saved snippet by `@name` with `--param k=v`. Supports `--verify` to run assertions. |
330
286
  | `queries` | n/a | Manage saved snippets: `list` / `show` / `search` / `suggest` / `new` / `edit` / `check` / `delete` / `rename` / `copy` / `import` / `export`. |
331
287
  | `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`. |
332
- | `delete` | data-admin+ | SQL or MongoDB only. `--where` required; `--dry-run` first. Supports `--recovery`. |
288
+ | `delete` | data-admin+ | SQL or MongoDB; Redis has a basic implementation (see Redis section). `--where` required; `--dry-run` first. Supports `--recovery`. |
333
289
  | `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`. |
334
290
  | `blacklist` | n/a | `list` / `table` / `column` subcommands redact sensitive data from query results. |
335
291
  | `check` | query-only+ | SQL only (best on MySQL/MariaDB). |
@@ -337,10 +293,10 @@ Full flags and edge cases: see [reference.md](reference.md) `init` section.
337
293
  | `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`. |
338
294
  | `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>`. |
339
295
  | `verification` | n/a | Inspect and manage local verification artifacts. `list` / `show <id-or-path>` / `summary` are read-only; `prune` is dry-run by default and deletes only with `--execute --force`. Reads `<cwd>/.dbcli/verification/`; no DB connection, no audit writes. |
340
- | `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`. |
296
+ | `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`, `--slow-ms` (default `1000`), `--redact none\|literals`. 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) — errors out if no events exist yet. |
341
297
  | `status` | query-only+ | Safe JSON/text summary (no credentials). |
342
298
  | `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`. |
343
- | `report` | query-only+ | Diagnostic report (health / capacity / perf) built from `@diag/*` snippets. `--section`, `--brief`, `--for-agent`, `--no-connect`. |
299
+ | `report` | query-only+ | Diagnostic report built from `@diag/*` snippets. `--section <health\|capacity\|perf>` (comma-separated to combine), `--brief`, `--for-agent`, `--no-connect`. |
344
300
  | `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`). |
345
301
  | `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. |
346
302
  | `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. |
@@ -348,11 +304,27 @@ Full flags and edge cases: see [reference.md](reference.md) `init` section.
348
304
  | `completion` | n/a | bash / zsh / fish scripts. |
349
305
  | `upgrade` | n/a | Self-update from npm; 24h-cached version hints on every command. |
350
306
  | `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). |
351
- | `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. |
307
+ | `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 an LLM prompt-context payload (for injecting into another LLM, not needed for normal operation). |
352
308
  | `migrate` | admin | SQL only. **DDL; dry-run by default** — needs `--execute`. |
353
309
 
354
- `--use <name>` on any subcommand targets a v2 connection without changing the default.
355
- `--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.
310
+ `--use <name>` on any subcommand (including `status` / `doctor`) targets a v2 connection
311
+ without changing the default. `--recovery` is honoured by `query`, `q`, `insert`, `update`,
312
+ `delete`, `export`, `schema`, and `inspect` (see **On failure** above).
313
+
314
+ **Write & query flag semantics** (SQL/Mongo `insert`/`update`):
315
+
316
+ - `--set` (update) / `--data` (insert) take a **JSON object string**, not a SQL fragment:
317
+ `dbcli update users --where "id=42" --set '{"email":"new@example.com"}'`. For MongoDB, a
318
+ JSON without `$` operators is auto-wrapped as `$set`; explicit operators pass through.
319
+ `insert --data` can also read the object from stdin.
320
+ - `--where` (SQL) accepts only `col=val` or `col1=val1 AND col2=val2` — **not** full SQL
321
+ (no `>=`, `!=`, `LIKE`, `OR`). MongoDB `--where` takes a full JSON filter
322
+ (`'{"status":"pending"}'`), falling back to `col=val` when it is not valid JSON.
323
+ - `--dry-run` prints the parameterized SQL (with `$1` / `?` placeholders, not real values)
324
+ and `rows_affected: 0`; proceed once `status:"success"` and the SQL shape matches the
325
+ intended `--where` / `--set`. MongoDB prints a shell-style preview.
326
+ - `--recovery` is recommended for automated agent pipelines (enables `dbcli recover --apply`
327
+ after a failure); optional for one-off manual writes.
356
328
 
357
329
  ## Permission levels
358
330
 
@@ -363,170 +335,120 @@ Full flags and edge cases: see [reference.md](reference.md) `init` section.
363
335
  | data-admin | + DELETE (DML, no DDL) |
364
336
  | admin | + DDL via `migrate` and destructive ops |
365
337
 
366
- ## Multi-connection (v2)
367
-
368
- - Each named connection has its own schema dir: `.dbcli/schemas/<connection>/`.
369
- - Run `dbcli schema --use <name>` once per connection before `schema <table>` — otherwise the cache may return another connection's columns.
370
- - `schema --refresh` / `--reset` manage the cache; see reference.md.
371
-
372
338
  ## MongoDB
373
339
 
374
- - JSON filter object (`find`) or JSON array (`aggregate`); SQL is rejected. `--collection <name>` is required on `query`.
375
- - **Supported:** `init`, `list`, `schema` (sampled), `query`, `insert`, `update`, `delete`, `export`, `q` (saved queries), `status`, `use`, `shell`, `doctor`, `upgrade`, `completion`.
376
- - **Not supported:** `diff`, `migrate`, `check`.
377
- - 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.
378
- - **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`.
379
- - **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]`.
380
- - **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.
381
- - See reference.md MongoDB section for full syntax and examples.
340
+ - `query` takes a JSON filter object (`find`) or array (`aggregate`); SQL is rejected.
341
+ `--collection <name>` is required on `query`.
342
+ - **Supported:** `init`, `list`, `schema` (sampled), `query`, `insert`, `update`, `delete`,
343
+ `export`, `q`, `status`, `use`, `shell`, `doctor`. **Not supported:** `diff`, `migrate`, `check`.
344
+ - Schema is **sampled** by `$sample` (default 100 docs, max 1000; `--sample-method natural`
345
+ uses `find().limit()`). Columns surface as dot-paths (e.g. `profile.tokens.access`) with
346
+ `presence` (0..1) and `redacted` flags.
347
+ - Writes: `--set` / `--data` JSON is auto-wrapped as `$set` when no `$` operator is present;
348
+ explicit operators (`$set`/`$inc`/`$push`/…) pass through. Nested blacklist accepts dotted
349
+ paths (`profile.email`) and trailing wildcards (`profile.tokens.*`). Saved snippets end in
350
+ `.mongodb.sql` (frontmatter `engine: mongodb`, `operation: find|aggregate`). Full
351
+ write-planner tiers and syntax: reference.md MongoDB section.
382
352
 
383
353
  ## Redis
384
354
 
385
- - Command-style execution; `query` runs a whitelisted Redis command (e.g. `GET`, `HSET`, `DEL`).
386
- - **Supported:** `init`, `list` (keys via SCAN), `schema <key>` (type / TTL / size / sample), `query`, `shell`, `status`, `use`, `doctor`, `upgrade`, `completion`.
387
- - **Not supported:** `schema` full scan, `insert`, `update`, `delete`, `export`, `check`, `diff`, `migrate`, `q`.
388
- Use `query "DEL <key>"` etc. for writes they go through the same permission gate.
389
- - Permission tiers map to commands: read commands → `query-only`; mutators (`SET`, `HSET`, ...) → `read-write`; `DEL` / `UNLINK` → `data-admin`.
390
- - `database` field is the logical DB index (default `0`); `list` returns ≤ 100 000 keys via SCAN.
391
- - **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.
392
- - **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.
393
- - **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**.
394
- - **Shell:** `dbcli shell` on a Redis connection opens a single-line REPL (history, tab completion of commands + key prefixes, `.no-limit on/off`).
395
- - See reference.md Redis section.
355
+ - `query` runs a single **whitelisted** Redis command (e.g. `GET`, `SET`, `HSET`, `DEL`).
356
+ The full whitelist and the per-command permission tier are defined in reference.md.
357
+ - **Supported:** `init`, `list` (keys via SCAN), `schema <key>` (type / TTL / size / sample),
358
+ `query`, `q` (saved snippets**read-only commands only**), `delete` (basic implementation:
359
+ `DEL` / `HDEL` / `LREM` / `SREM` / `ZREM`, needs `data-admin`; `query "DEL <key>"` also
360
+ works), `shell`, `status`, `use`, `doctor`. **Not supported:** `schema` full scan,
361
+ `insert`, `update`, `check`, `diff`, `migrate`.
362
+ - **Permission tiers:** reads (`GET`/`HGET`/`SCAN`/…) `query-only`; mutators
363
+ (`SET`/`HSET`/`INCR`/`EXPIRE`/`SETEX`/`RENAME`/…) `read-write`; `DEL`/`UNLINK`/`HDEL`/`XDEL`
364
+ `data-admin`. A command not in the whitelist is refused.
365
+ - **No `--dry-run` for Redis `query`** — write safety comes from the permission gate and key
366
+ blacklist (matching reads/writes are rejected). To preview a delete, use `delete <key> --dry-run`.
367
+ - `database` is the logical DB index (default `0`). `dbcli blacklist add 'secrets:*'`
368
+ registers a key glob; an optional `redis.mask` block masks values on read. Size guards
369
+ (SCAN/HGETALL truncation, `--no-limit` to bypass) and masking details: reference.md Redis section.
396
370
 
397
371
  ## Elasticsearch
398
372
 
399
- - DSL (JSON body) or Lucene query string; `--collection <index>` is required on `query`.
400
- - **Supported:** `init`, `list` (indices with doc count), `schema [index]` (flattened mapping), `query`, `export` (v1.22), `shell` (v1.22), `status`, `use`, `doctor`, `upgrade`, `completion`.
401
- - **Not supported:** `insert`, `update`, `delete`, `check`, `diff`, `migrate`, `q`.
402
- Writes are not exposed via dedicated subcommands yet — use `query` if the cluster allows or external tools.
403
- - **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.
404
- - **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.
405
- - Query-only mode caps at 1000 hits; `--no-limit` is bounded at 10 000.
406
- - Schema flattens nested fields (`a.b.c`) and surfaces `.fields` multi-fields.
407
- - See reference.md Elasticsearch section.
373
+ - `query` takes a DSL (JSON body) or Lucene query string; `--collection <index>` is required.
374
+ - **Supported:** `init`, `list` (indices with doc count), `schema [index]` (flattened mapping),
375
+ `query`, `export` (v1.22), `shell` (v1.22), `status`, `use`, `doctor`. **Not supported:**
376
+ `insert`, `update`, `delete`, `check`, `diff`, `migrate`.
377
+ - `export` takes a search DSL with `--index <index>`, or an index name as the query to scroll
378
+ the whole index via `match_all`. Query-only caps at 1000 hits; `--no-limit` is bounded at 10 000.
379
+ - Schema flattens nested fields (`a.b.c`) and surfaces `.fields` multi-fields. `shell` opens a
380
+ Kibana Dev Tools-style REPL. Full syntax and examples: reference.md Elasticsearch section.
408
381
 
409
382
  ## Saved queries
410
383
 
411
- Run reusable parameterised SELECT snippets stored in your repo.
384
+ Run reusable parameterised snippets stored in your repo.
412
385
 
413
386
  | Step | Command |
414
387
  |------|---------|
415
- | 1. Discover | `dbcli queries list` |
388
+ | 1. Discover | `dbcli queries list` (or `queries search <keywords>` / `queries suggest <intent>`) |
416
389
  | 2. Inspect | `dbcli queries show @<name>` |
417
- | 3. Run | `dbcli q @<name> --param k=v` |
418
-
419
- ### When you don't know which query to run
390
+ | 3. Run | `dbcli q @<name> --param k=v` (blacklist always enforced) |
420
391
 
421
- 1. `dbcli queries search <keywords>` — natural keywords, fuzzy ranked
422
- 2. `dbcli queries suggest <intent>` — browse a category
423
- Common intents: perf.slow-query, perf.cache-hit, capacity.size,
424
- safety.connections, monitor.cluster-health
425
- 3. Once you find one: `dbcli q @<name>` (blacklist always enforced)
392
+ Common intents: `perf.slow-query`, `perf.cache-hit`, `capacity.size`, `safety.connections`,
393
+ `monitor.cluster-health`.
426
394
 
427
- Snippets resolve from three layers, **local > shared > builtin** (local wins):
428
- - `builtin` bundled with dbcli (e.g. `@diag/*`); read-only at runtime
429
- - `.dbcli-shared/queries/` committed, team-shared
430
- - `.dbcli/queries/` gitignored, personal override
395
+ Snippets resolve **local > shared > builtin** (local wins): `builtin` (bundled `@diag/*`,
396
+ read-only) / `.dbcli-shared/queries/` (team) / `.dbcli/queries/` (personal). Manage local
397
+ snippets with `queries new | edit | delete | rename | copy | import | export`. Each `.sql`
398
+ file declares YAML frontmatter inside `-- ---` blocks (name, description, engine, params, tags,
399
+ optional `intent`, optional `visual`).
431
400
 
432
- Manage local snippets with `queries new | edit | delete | rename | copy | import | export`
433
- (see reference.md). Use `copy` / `import` to fork a builtin or shared snippet into the
434
- local layer for editing.
435
-
436
- Each `.sql` file may declare YAML frontmatter inside `-- ---` blocks
437
- (name, description, engine, params, tags, optional `intent`, optional `visual`).
438
- The `visual:` block drives the interactive dashboard (see "Interactive HTML dashboard"
439
- below). See `dbcli queries show @<name> --format json` for the machine-readable contract.
440
-
441
- ### Engine-specific bodies
442
-
443
- Each snippet's body format is determined by the `engine` frontmatter field:
401
+ Body format by `engine`:
444
402
 
445
403
  | Engine | Body format | Notes |
446
404
  |-------------------|------------------------|-------|
447
405
  | postgres / mysql | Single SELECT or WITH | `:name` → driver bind (`$1` / `?`) |
448
406
  | elasticsearch | JSON DSL | `:name` → JSON-aware substitution; `index:` field required |
449
- | redis | Single Redis command | `:name` → raw text; only read commands allowed |
407
+ | redis | Single Redis command | `:name` → raw text; **only read commands allowed** |
450
408
 
451
409
  Mixed-family `engine` arrays (e.g. `[postgres, elasticsearch]`) are rejected at parse time.
452
410
 
453
411
  ### Built-in diagnostic snippets
454
412
 
455
- dbcli ships ready-made diagnostic queries. Run with `dbcli q @diag/<topic>`:
413
+ Run with `dbcli q @diag/<topic>` (engine variant auto-picked by the active connection):
456
414
 
457
415
  | key | purpose |
458
416
  |-------------------------|------------------------------------------|
459
417
  | `@diag/connections` | active sessions |
460
- | `@diag/long-running` | queries above `min_seconds` (default 30) |
418
+ | `@diag/long-running` | queries above `min_seconds` (`--param min_seconds=N`, default 30) |
461
419
  | `@diag/table-sizes` | table data/index size with row counts |
462
420
  | `@diag/index-usage` | indexes by scan count |
463
421
  | `@diag/missing-indexes` | tables dominated by sequential scans |
464
422
  | `@diag/locks` | lock-wait chains |
465
423
  | `@diag/db-size` | database size summary |
466
424
  | `@diag/cache-hit` | buffer cache hit ratios |
467
- | `@diag/es-cluster-health` | document counts per index (ES connections) |
468
- | `@diag/redis-key-stats` | sample SCAN over keyspace (Redis connections) |
469
-
470
- Engine variants are picked automatically based on the active connection.
471
- Override any of them by placing a same-named file under `.dbcli-shared/queries/`
472
- or `.dbcli/queries/`.
425
+ | `@diag/es-cluster-health` | document counts per index (ES) |
426
+ | `@diag/redis-key-stats` | sample SCAN over keyspace (Redis) |
473
427
 
474
428
  ## Interactive HTML dashboard
475
429
 
476
- `query`, `q`, and `export` can render results as a standalone, self-contained HTML
477
- report powered by a bundled React + Recharts template (`assets/ui-template.html`,
478
- injected via a hardened `window.__DBCLI_PAYLOAD__ = {...}` block — `<` is escaped
479
- to neutralise `</script>` payloads).
430
+ `query`, `q`, and `export` can render results as a standalone, self-contained HTML report
431
+ (bundled React + Recharts template).
480
432
 
481
433
  ```bash
482
- # Open in browser (writes to a temp file, then `open`/`xdg-open`/`start`)
483
- dbcli query "SELECT day, dau FROM dau_daily" --ui
484
- dbcli q @analytics/revenue --param days=30 --ui
485
-
486
- # Pipe HTML to stdout (CI artifacts, email, static hosting)
487
- dbcli query "SELECT * FROM orders" --format html > orders.html
488
-
489
- # Export to a file (interchangeable with json/jsonl/csv)
434
+ dbcli query "SELECT day, dau FROM dau_daily" --ui # open in browser
435
+ dbcli q @analytics/revenue --param days=30 --ui # snippet metadata + charts/KPIs
436
+ dbcli q @analytics/revenue --param days=30 --format html > report.html
437
+ dbcli query "SELECT * FROM orders" --format html > out.html # pipe HTML to stdout
490
438
  dbcli export "SELECT * FROM orders" --format html --output orders.html
491
439
  ```
492
440
 
493
- `--ui` implies `--format html` and opens the file; `--format html` alone prints to
494
- stdout. Blacklist redaction is applied **before** rendering the dashboard never
495
- sees masked columns.
496
-
497
- ### Snippet `visual:` block
498
-
499
- To get KPIs and charts (rather than just a sortable table), add a `visual:` block
500
- to the snippet's frontmatter. Column names must exist in the result row.
501
-
502
- ```sql
503
- -- ---
504
- -- name: Revenue Trend
505
- -- engine: postgres
506
- -- params:
507
- -- days: { type: int, default: 30 }
508
- -- visual:
509
- -- title: Revenue (last :days days)
510
- -- kpis:
511
- -- - { label: Total Revenue, value_column: total_revenue, format: currency }
512
- -- - { label: Orders, value_column: order_count, format: number }
513
- -- - { label: Conversion, value_column: conv_rate, format: percent }
514
- -- charts:
515
- -- - { type: line, title: Daily Revenue, x: day, y: [revenue] }
516
- -- - { type: bar, title: By Channel, x: channel, y: [revenue, refunds] }
517
- -- ---
518
- SELECT ...
519
- ```
520
-
521
- - `kpis[].format`: `currency` / `number` / `percent` (omit for raw value).
522
- - `charts[].type`: `line` / `bar` / `area` / `pie` / `scatter`.
523
- - Raw `query` invocations (no snippet) render a sortable/filterable table only —
524
- there is no `visual:` to attach.
441
+ `--ui` implies `--format html` and opens the file; `--format html` alone prints to stdout.
442
+ When a saved snippet exists, prefer `q @<name> --ui` / `q @<name> --format html` because snippet
443
+ metadata can drive titles, KPI cards, and charts. Blacklist redaction is applied **before**
444
+ rendering. To get KPIs and charts instead of a plain table, add a `visual:` block (`title`,
445
+ `kpis[]`, `charts[]`) to the snippet frontmatter — see reference.md for the full `visual:`
446
+ schema. Raw `query` / `export` invocations render a sortable table only.
525
447
 
526
448
  ## Common workflows
527
449
 
528
450
  - **Debug odd state:** `schema` → `check` → `query` with tight `WHERE` → follow FKs from schema JSON. Evidence over theory.
529
- - **After INSERT/UPDATE:** `--dry-run` → run → `query` read-back; explain mismatches via triggers, defaults, or blacklist.
451
+ - **After INSERT/UPDATE:** follow the write sequence in **How to use dbcli** (`--dry-run` → run → `query` read-back); explain mismatches via triggers, defaults, or blacklist.
530
452
  - **Migrations:** `diff --snapshot` → `migrate` (dry-run → `--execute`) → `diff --against` → `check` affected tables. DROP requires `--force`.
531
453
  - **Health / growth:** `check --all` (huge tables skipped unless `--include-large`); consult schema `sizeCategory` before ad-hoc queries.
532
454
  - **Codegen from live DB:** `schema --format json` to drive an ORM; cross-check once with `dbcli query`.