@carllee1983/dbcli 1.37.1 → 1.38.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.
- package/.cursor/rules/dbcli.mdc +192 -281
- package/.cursor/skills/dbcli/reference.md +68 -0
- package/.github/skills/dbcli/SKILL.md +192 -281
- package/.github/skills/dbcli/reference.md +68 -0
- package/CHANGELOG.md +16 -0
- package/assets/SKILL.md +192 -281
- package/assets/SKILL.zh-TW.md +211 -331
- package/assets/reference.md +68 -0
- package/dist/cli.mjs +506 -24
- package/dist/core.mjs +1 -1
- package/package.json +1 -1
- package/plugins/dbcli-agent/skills/dbcli/SKILL.md +192 -281
- package/plugins/dbcli-agent/skills/dbcli/reference.md +68 -0
- package/skills/dbcli/SKILL.md +192 -281
- package/skills/dbcli/reference.md +68 -0
package/skills/dbcli/SKILL.md
CHANGED
|
@@ -12,65 +12,54 @@ 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
|
-
##
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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 baseline — apply 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
|
+
| Setting up a connection | see **Connection setup** |
|
|
34
|
+
| Anything else | run commands manually; consult the **Developer workflows** cheat-sheet |
|
|
35
|
+
|
|
36
|
+
Slow-query diagnosis has three canonical paths (pick by what you already know):
|
|
37
|
+
|
|
38
|
+
- Known slow SQL → `skill tasks plan diagnose-slow-query --param query="<SQL>"` → `guide missing-index-for "<SQL>"`
|
|
39
|
+
- Known hot table → `skill tasks plan analyze-table-perf --param table=<table>`
|
|
40
|
+
- Whole-environment scan → `report --section perf` → `guide slow-query`
|
|
41
|
+
|
|
42
|
+
`report --section perf` already runs the slow-query, index-usage, and cache-hit diagnostics —
|
|
43
|
+
afterwards add only the `@diag/*` it does not cover (`missing-indexes`, `locks`, `connections`,
|
|
44
|
+
`table-sizes`). Once you have a specific slow statement, `explain --analyze "<SQL>"` shows its plan.
|
|
45
|
+
|
|
46
|
+
**On failure:** pass `--recovery` to `query` / `q` / `insert` / `update` / `delete` /
|
|
47
|
+
`export` / `schema` / `inspect`. The command emits a `RecoveryEnvelope` to stdout and saves
|
|
48
|
+
it to `.dbcli/last-recovery.json`; then `dbcli recover` inspects it and `dbcli recover --apply`
|
|
49
|
+
runs the saved plan under risk gating. Multi-turn `--next`, connection branching, and the
|
|
50
|
+
post-apply verify probe are documented in reference.md §Recovery Cookbook.
|
|
51
|
+
|
|
52
|
+
When reporting a check's outcome use the vocabulary `verified` (evidence matched) /
|
|
53
|
+
`not_verified` (check ran and contradicted) / `indeterminate` (ran but ambiguous) /
|
|
54
|
+
`blocked` (could not run due to config, permission, schema, placeholder, or safety gate).
|
|
66
55
|
|
|
67
56
|
Prefer `--format json` for agent-friendly output.
|
|
68
57
|
|
|
69
58
|
## Agent Task Packs
|
|
70
59
|
|
|
71
|
-
When the user asks for a database workflow (
|
|
72
|
-
permissions", "review long-running operations"), prefer published task templates
|
|
73
|
-
|
|
60
|
+
When the user asks for a database workflow ("diagnose this slow query", "audit
|
|
61
|
+
permissions", "review long-running operations"), **prefer published task templates over
|
|
62
|
+
inventing steps from memory.**
|
|
74
63
|
|
|
75
64
|
```bash
|
|
76
65
|
dbcli skill tasks list --format json # discover
|
|
@@ -78,45 +67,34 @@ dbcli skill tasks show <task> # inspect
|
|
|
78
67
|
dbcli skill tasks plan <task> --param key=value --format json # generate plan
|
|
79
68
|
```
|
|
80
69
|
|
|
81
|
-
The plan
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
Builtin packs: `diagnose-slow-query`
|
|
86
|
-
|
|
87
|
-
`
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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.
|
|
70
|
+
The plan is an ordered list of dbcli commands with rationale and risk labels. Execute them
|
|
71
|
+
one at a time — task plans do **not** override blacklist, schema, dry-run, or confirmation
|
|
72
|
+
requirements.
|
|
73
|
+
|
|
74
|
+
Builtin packs: `diagnose-slow-query` (targets a specific SQL), `analyze-table-perf` (targets
|
|
75
|
+
a specific table; `dbcli inspect` auto-suggests it for the hottest table in recent audit
|
|
76
|
+
activity), `audit-permissions`, `safe-backfill`, `schema-drift-review`, `connection-health`.
|
|
77
|
+
Review/verify packs: `pr-database-review`, `migration-review`, `safe-backfill-verify`,
|
|
78
|
+
`slow-endpoint-investigation`. All are read-only `plan-only` — pick the pack matching the
|
|
79
|
+
situation, and run any index/DDL proposal through `migration-review` before writing.
|
|
100
80
|
|
|
101
81
|
Tasks live under `assets/tasks/` (builtin), `.dbcli-shared/tasks/` (shared), and
|
|
102
82
|
`.dbcli/tasks/` (local override).
|
|
103
83
|
|
|
104
84
|
## Developer workflows
|
|
105
85
|
|
|
106
|
-
Use these workflows when database impact is implicit in a development task.
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
|
112
|
-
|
|
|
113
|
-
|
|
|
114
|
-
|
|
|
115
|
-
|
|
|
116
|
-
|
|
|
117
|
-
|
|
|
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`. |
|
|
86
|
+
Use these workflows when database impact is implicit in a development task. The safety baseline
|
|
87
|
+
in **How to use dbcli** still applies.
|
|
88
|
+
|
|
89
|
+
| Situation | Minimum safe path |
|
|
90
|
+
| --- | --- |
|
|
91
|
+
| DB-backed feature | `blacklist list` → `schema <object>` → `queries suggest <intent>` |
|
|
92
|
+
| Application data bug | `audit tail --for-agent --n 10` → `blacklist list` → `schema <object>` → narrow query |
|
|
93
|
+
| ORM or migration work | `schema --format json` → `diff --snapshot <name>` → `migrate add-index`/`add-column` (preview SQL) → `diff --against <snapshot>` |
|
|
94
|
+
| PR database review | Review changed persistence paths, then propose concrete `schema` / `plan` / `dry-run` / `report` / `guide` commands per material claim. |
|
|
95
|
+
| Slow endpoint or query | `report --section perf` → task pack `analyze-table-perf` → `guide missing-index-for "<query>"`; use `proxy analyze` when logs exist. |
|
|
96
|
+
| Safe data backfill | `blacklist list` → `schema <object>` → count/scope query → `update … --dry-run` → read-back or snippet `--verify`. |
|
|
97
|
+
| Environment validation | `status --format json` → `doctor --format json` → `inspect --for-agent --no-connect`. |
|
|
120
98
|
|
|
121
99
|
Copy-paste command anchors:
|
|
122
100
|
|
|
@@ -126,85 +104,43 @@ dbcli blacklist list --format json
|
|
|
126
104
|
dbcli schema <object> --format json
|
|
127
105
|
dbcli queries suggest <intent> --format json
|
|
128
106
|
dbcli audit tail --for-agent --n 10
|
|
129
|
-
dbcli schema --format json
|
|
130
107
|
dbcli diff --snapshot <name>
|
|
131
|
-
dbcli migrate add-index <table>
|
|
132
|
-
dbcli diff --against <snapshot>
|
|
133
108
|
dbcli report --section perf --format json
|
|
134
109
|
dbcli skill tasks plan analyze-table-perf --param table=<table> --format json
|
|
135
110
|
dbcli guide missing-index-for "<query>" --format json
|
|
136
|
-
dbcli proxy analyze --format json
|
|
137
|
-
dbcli query "<count/scope query>" --format json
|
|
138
111
|
dbcli update <object> --where "<bounded predicate>" --set '<json>' --dry-run --format json
|
|
139
|
-
dbcli status --format json
|
|
140
|
-
dbcli doctor --format json
|
|
141
112
|
dbcli inspect --for-agent --no-connect --format json
|
|
142
113
|
```
|
|
143
114
|
|
|
144
|
-
|
|
115
|
+
Guardrails:
|
|
145
116
|
|
|
146
|
-
- Never invent table, collection, key, index, or field names. Confirm
|
|
147
|
-
|
|
148
|
-
-
|
|
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.
|
|
117
|
+
- Never invent table, collection, key, index, or field names. Confirm with `schema`.
|
|
118
|
+
- Separate database facts from application-code inference. Report which dbcli output shaped the conclusion.
|
|
119
|
+
- For writes and backfills, include scope count, dry-run preview, execution command, and read-back.
|
|
152
120
|
- Do not create indexes directly from a performance suggestion; turn them into reviewed migrations.
|
|
153
121
|
- Do not print credentials, copied connection strings, or blacklisted values.
|
|
154
|
-
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
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
|
-
```
|
|
122
|
+
- Durable evidence: `assert … --write-verification-artifact --verification-subject <kind:name>`;
|
|
123
|
+
inspect with `verification summary` / `list` / `show <id>`. The `verify safe-backfill` /
|
|
124
|
+
`migration` / `rollback --kind <ddl|dml>` / `constraint --check <fk|not-null|unique|custom>`
|
|
125
|
+
family runs preflight + `--after-write` checks and **never executes the write**. Full flags
|
|
126
|
+
and the per-command blocks are in reference.md.
|
|
179
127
|
|
|
180
|
-
|
|
181
|
-
`target` / `success` per entry. Metadata-only by design — never raw SQL bodies,
|
|
182
|
-
`--param` values, or result cell contents (D3 lock).
|
|
128
|
+
## Audit log
|
|
183
129
|
|
|
184
|
-
|
|
130
|
+
Use the audit log for cross-session history or failure forensics instead of re-querying
|
|
131
|
+
live DB state.
|
|
185
132
|
|
|
186
133
|
```bash
|
|
187
|
-
dbcli
|
|
188
|
-
dbcli audit show <id-prefix>
|
|
189
|
-
dbcli audit show --recovery-ref <
|
|
134
|
+
dbcli audit tail --for-agent --n 10 # last N entries (JSON envelope, metadata-only)
|
|
135
|
+
dbcli audit show <id-prefix> # full entry by id prefix (≥4 chars)
|
|
136
|
+
dbcli audit show --recovery-ref <env-id> # find the entry that emitted an envelope
|
|
190
137
|
```
|
|
191
138
|
|
|
192
|
-
The `inspect` / `guide` / `recover`
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
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.
|
|
139
|
+
The `inspect` / `guide` / `recover` agent JSON embeds `audit_recent` (last 5 entries) — a
|
|
140
|
+
fresh session has immediate history. An envelope's `audit_ref` and an audit entry's
|
|
141
|
+
`recovery_ref` point at each other, so you can pivot either way. Audit is on by default
|
|
142
|
+
(`audit.enabled = false` to opt out); entries are metadata-only (never SQL bodies, `--param`
|
|
143
|
+
values, or result cells) and rotate at ~10 MB / 1000 entries. Full flags: reference.md §audit.
|
|
208
144
|
|
|
209
145
|
## Quick start
|
|
210
146
|
|
|
@@ -235,12 +171,12 @@ or `doctor` / `status` reports a missing or invalid config, follow this flow.
|
|
|
235
171
|
2. **Where do credentials live?**
|
|
236
172
|
- Already in a `.env` (`DATABASE_URL` or `DB_HOST` / `DB_PORT` / `DB_USER` /
|
|
237
173
|
`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`.
|
|
174
|
+
- Need to keep secrets out of `.dbcli` (CI/CD, multi-env) → `--use-env-refs` (see below).
|
|
240
175
|
- Plain values are acceptable → pass `--host` / `--port` / `--user` /
|
|
241
176
|
`--password` / `--name` (and `--system`).
|
|
242
177
|
3. **What permission tier?** Default to the **lowest** that satisfies the task:
|
|
243
|
-
`query-only` → `read-write` → `data-admin` → `admin`. Set with `--permission
|
|
178
|
+
`query-only` → `read-write` → `data-admin` → `admin`. Set with `--permission`
|
|
179
|
+
(defaults to `query-only`).
|
|
244
180
|
4. **Verify, never assume.** After init: `dbcli status` (system + permission +
|
|
245
181
|
blacklist summary, no creds) and `dbcli doctor --format json` (env, config
|
|
246
182
|
shape, connectivity, schema-cache age, Mongo SRV path).
|
|
@@ -280,25 +216,38 @@ dbcli init --conn-name staging --env-file .env.staging --permission query-only
|
|
|
280
216
|
dbcli init --conn-name prod --env-file .env.production --use-env-refs --skip-test
|
|
281
217
|
dbcli use --list # show all, * marks default
|
|
282
218
|
dbcli use prod # switch default
|
|
283
|
-
dbcli query --use staging "SELECT 1" # one-shot override
|
|
219
|
+
dbcli query --use staging "SELECT 1" # one-shot override on any subcommand
|
|
284
220
|
dbcli init --rename staging:stg # rename
|
|
285
221
|
dbcli init --remove stg # remove
|
|
286
222
|
```
|
|
287
223
|
|
|
288
|
-
|
|
289
|
-
`dbcli schema --use <name>` once per connection before `schema <table>` —
|
|
290
|
-
|
|
224
|
+
Each named connection has its own schema cache at `.dbcli/schemas/<connection>/`. Run
|
|
225
|
+
`dbcli schema --use <name>` once per connection **before** `schema <table>` — otherwise the
|
|
226
|
+
cache may serve another connection's columns. `schema --refresh` / `--reset` manage the cache
|
|
227
|
+
(reference.md). `--skip-test` skips the init-time TCP connection test; it is implied
|
|
228
|
+
automatically when `--use-env-refs` is set (the `$env` refs have no value to connect with yet).
|
|
229
|
+
`--system` is optional for v2 — without it the engine is inferred from `--env-file` / `.env`
|
|
230
|
+
(`DATABASE_URL` scheme), defaulting to `postgresql`.
|
|
291
231
|
|
|
292
232
|
### env-refs (keep secrets out of `.dbcli`)
|
|
293
233
|
|
|
234
|
+
Store credentials as `{ "$env": "VAR" }` references resolved at runtime, never plaintext:
|
|
235
|
+
|
|
294
236
|
```bash
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
237
|
+
# Default key names: DB_HOST / DB_PORT / DB_USER / DB_PASSWORD / DB_DATABASE
|
|
238
|
+
dbcli init --use-env-refs
|
|
239
|
+
|
|
240
|
+
# Non-default key names — name each one explicitly (required in CI):
|
|
241
|
+
dbcli init --conn-name prod --env-file .env.production --use-env-refs --skip-test \
|
|
242
|
+
--env-host PROD_DB_HOST --env-port PROD_DB_PORT \
|
|
243
|
+
--env-user PROD_DB_USER --env-password PROD_DB_PASSWORD --env-database PROD_DB_NAME
|
|
298
244
|
```
|
|
299
245
|
|
|
300
|
-
|
|
301
|
-
|
|
246
|
+
In an **interactive terminal**, omitting the `--env-*` flags prompts for each key name
|
|
247
|
+
(defaults above) — you can type a non-default name like `PROD_DB_PASSWORD` and it is stored
|
|
248
|
+
as a `$env` ref. In a **non-interactive / CI** run you **must** pass all five `--env-*`
|
|
249
|
+
flags; otherwise `init` exits with an error — it never silently falls back to plaintext.
|
|
250
|
+
`--env-file <path>` is the path to the env file, independent of the `$env` key names.
|
|
302
251
|
|
|
303
252
|
### Common gotchas
|
|
304
253
|
|
|
@@ -329,7 +278,7 @@ Full flags and edge cases: see [reference.md](reference.md) `init` section.
|
|
|
329
278
|
| `q` | query-only+ | Run a saved snippet by `@name` with `--param k=v`. Supports `--verify` to run assertions. |
|
|
330
279
|
| `queries` | n/a | Manage saved snippets: `list` / `show` / `search` / `suggest` / `new` / `edit` / `check` / `delete` / `rename` / `copy` / `import` / `export`. |
|
|
331
280
|
| `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
|
|
281
|
+
| `delete` | data-admin+ | SQL or MongoDB; Redis has a basic implementation (see Redis section). `--where` required; `--dry-run` first. Supports `--recovery`. |
|
|
333
282
|
| `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
283
|
| `blacklist` | n/a | `list` / `table` / `column` subcommands redact sensitive data from query results. |
|
|
335
284
|
| `check` | query-only+ | SQL only (best on MySQL/MariaDB). |
|
|
@@ -337,10 +286,10 @@ Full flags and edge cases: see [reference.md](reference.md) `init` section.
|
|
|
337
286
|
| `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
287
|
| `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
288
|
| `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
|
|
289
|
+
| `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
290
|
| `status` | query-only+ | Safe JSON/text summary (no credentials). |
|
|
342
291
|
| `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
|
|
292
|
+
| `report` | query-only+ | Diagnostic report built from `@diag/*` snippets. `--section <health\|capacity\|perf>` (comma-separated to combine), `--brief`, `--for-agent`, `--no-connect`. |
|
|
344
293
|
| `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
294
|
| `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
295
|
| `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 +297,27 @@ Full flags and edge cases: see [reference.md](reference.md) `init` section.
|
|
|
348
297
|
| `completion` | n/a | bash / zsh / fish scripts. |
|
|
349
298
|
| `upgrade` | n/a | Self-update from npm; 24h-cached version hints on every command. |
|
|
350
299
|
| `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
|
|
300
|
+
| `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
301
|
| `migrate` | admin | SQL only. **DDL; dry-run by default** — needs `--execute`. |
|
|
353
302
|
|
|
354
|
-
`--use <name>` on any subcommand targets a v2 connection
|
|
355
|
-
`--recovery` is honoured by `query`, `q`, `insert`, `update`,
|
|
303
|
+
`--use <name>` on any subcommand (including `status` / `doctor`) targets a v2 connection
|
|
304
|
+
without changing the default. `--recovery` is honoured by `query`, `q`, `insert`, `update`,
|
|
305
|
+
`delete`, `export`, `schema`, and `inspect` (see **On failure** above).
|
|
306
|
+
|
|
307
|
+
**Write & query flag semantics** (SQL/Mongo `insert`/`update`):
|
|
308
|
+
|
|
309
|
+
- `--set` (update) / `--data` (insert) take a **JSON object string**, not a SQL fragment:
|
|
310
|
+
`dbcli update users --where "id=42" --set '{"email":"new@example.com"}'`. For MongoDB, a
|
|
311
|
+
JSON without `$` operators is auto-wrapped as `$set`; explicit operators pass through.
|
|
312
|
+
`insert --data` can also read the object from stdin.
|
|
313
|
+
- `--where` (SQL) accepts only `col=val` or `col1=val1 AND col2=val2` — **not** full SQL
|
|
314
|
+
(no `>=`, `!=`, `LIKE`, `OR`). MongoDB `--where` takes a full JSON filter
|
|
315
|
+
(`'{"status":"pending"}'`), falling back to `col=val` when it is not valid JSON.
|
|
316
|
+
- `--dry-run` prints the parameterized SQL (with `$1` / `?` placeholders, not real values)
|
|
317
|
+
and `rows_affected: 0`; proceed once `status:"success"` and the SQL shape matches the
|
|
318
|
+
intended `--where` / `--set`. MongoDB prints a shell-style preview.
|
|
319
|
+
- `--recovery` is recommended for automated agent pipelines (enables `dbcli recover --apply`
|
|
320
|
+
after a failure); optional for one-off manual writes.
|
|
356
321
|
|
|
357
322
|
## Permission levels
|
|
358
323
|
|
|
@@ -363,170 +328,116 @@ Full flags and edge cases: see [reference.md](reference.md) `init` section.
|
|
|
363
328
|
| data-admin | + DELETE (DML, no DDL) |
|
|
364
329
|
| admin | + DDL via `migrate` and destructive ops |
|
|
365
330
|
|
|
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
331
|
## MongoDB
|
|
373
332
|
|
|
374
|
-
- JSON filter object (`find`) or
|
|
375
|
-
|
|
376
|
-
- **
|
|
377
|
-
|
|
378
|
-
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
-
|
|
333
|
+
- `query` takes a JSON filter object (`find`) or array (`aggregate`); SQL is rejected.
|
|
334
|
+
`--collection <name>` is required on `query`.
|
|
335
|
+
- **Supported:** `init`, `list`, `schema` (sampled), `query`, `insert`, `update`, `delete`,
|
|
336
|
+
`export`, `q`, `status`, `use`, `shell`, `doctor`. **Not supported:** `diff`, `migrate`, `check`.
|
|
337
|
+
- Schema is **sampled** by `$sample` (default 100 docs, max 1000; `--sample-method natural`
|
|
338
|
+
uses `find().limit()`). Columns surface as dot-paths (e.g. `profile.tokens.access`) with
|
|
339
|
+
`presence` (0..1) and `redacted` flags.
|
|
340
|
+
- Writes: `--set` / `--data` JSON is auto-wrapped as `$set` when no `$` operator is present;
|
|
341
|
+
explicit operators (`$set`/`$inc`/`$push`/…) pass through. Nested blacklist accepts dotted
|
|
342
|
+
paths (`profile.email`) and trailing wildcards (`profile.tokens.*`). Saved snippets end in
|
|
343
|
+
`.mongodb.sql` (frontmatter `engine: mongodb`, `operation: find|aggregate`). Full
|
|
344
|
+
write-planner tiers and syntax: reference.md MongoDB section.
|
|
382
345
|
|
|
383
346
|
## Redis
|
|
384
347
|
|
|
385
|
-
-
|
|
386
|
-
|
|
387
|
-
- **
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
- **
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
-
|
|
348
|
+
- `query` runs a single **whitelisted** Redis command (e.g. `GET`, `SET`, `HSET`, `DEL`).
|
|
349
|
+
The full whitelist and the per-command permission tier are defined in reference.md.
|
|
350
|
+
- **Supported:** `init`, `list` (keys via SCAN), `schema <key>` (type / TTL / size / sample),
|
|
351
|
+
`query`, `q` (saved snippets — **read-only commands only**), `delete` (basic implementation:
|
|
352
|
+
`DEL` / `HDEL` / `LREM` / `SREM` / `ZREM`, needs `data-admin`; `query "DEL <key>"` also
|
|
353
|
+
works), `shell`, `status`, `use`, `doctor`. **Not supported:** `schema` full scan,
|
|
354
|
+
`insert`, `update`, `check`, `diff`, `migrate`.
|
|
355
|
+
- **Permission tiers:** reads (`GET`/`HGET`/`SCAN`/…) → `query-only`; mutators
|
|
356
|
+
(`SET`/`HSET`/`INCR`/`EXPIRE`/`SETEX`/`RENAME`/…) → `read-write`; `DEL`/`UNLINK`/`HDEL`/`XDEL`
|
|
357
|
+
→ `data-admin`. A command not in the whitelist is refused.
|
|
358
|
+
- **No `--dry-run` for Redis `query`** — write safety comes from the permission gate and key
|
|
359
|
+
blacklist (matching reads/writes are rejected). To preview a delete, use `delete <key> --dry-run`.
|
|
360
|
+
- `database` is the logical DB index (default `0`). `dbcli blacklist add 'secrets:*'`
|
|
361
|
+
registers a key glob; an optional `redis.mask` block masks values on read. Size guards
|
|
362
|
+
(SCAN/HGETALL truncation, `--no-limit` to bypass) and masking details: reference.md Redis section.
|
|
396
363
|
|
|
397
364
|
## Elasticsearch
|
|
398
365
|
|
|
399
|
-
- DSL (JSON body) or Lucene query string; `--collection <index>` is required
|
|
400
|
-
- **Supported:** `init`, `list` (indices with doc count), `schema [index]` (flattened mapping),
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
-
|
|
404
|
-
|
|
405
|
-
-
|
|
406
|
-
|
|
407
|
-
- See reference.md Elasticsearch section.
|
|
366
|
+
- `query` takes a DSL (JSON body) or Lucene query string; `--collection <index>` is required.
|
|
367
|
+
- **Supported:** `init`, `list` (indices with doc count), `schema [index]` (flattened mapping),
|
|
368
|
+
`query`, `export` (v1.22), `shell` (v1.22), `status`, `use`, `doctor`. **Not supported:**
|
|
369
|
+
`insert`, `update`, `delete`, `check`, `diff`, `migrate`.
|
|
370
|
+
- `export` takes a search DSL with `--index <index>`, or an index name as the query to scroll
|
|
371
|
+
the whole index via `match_all`. Query-only caps at 1000 hits; `--no-limit` is bounded at 10 000.
|
|
372
|
+
- Schema flattens nested fields (`a.b.c`) and surfaces `.fields` multi-fields. `shell` opens a
|
|
373
|
+
Kibana Dev Tools-style REPL. Full syntax and examples: reference.md Elasticsearch section.
|
|
408
374
|
|
|
409
375
|
## Saved queries
|
|
410
376
|
|
|
411
|
-
Run reusable parameterised
|
|
377
|
+
Run reusable parameterised snippets stored in your repo.
|
|
412
378
|
|
|
413
379
|
| Step | Command |
|
|
414
380
|
|------|---------|
|
|
415
|
-
| 1. Discover | `dbcli queries list` |
|
|
381
|
+
| 1. Discover | `dbcli queries list` (or `queries search <keywords>` / `queries suggest <intent>`) |
|
|
416
382
|
| 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
|
|
383
|
+
| 3. Run | `dbcli q @<name> --param k=v` (blacklist always enforced) |
|
|
420
384
|
|
|
421
|
-
|
|
422
|
-
|
|
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)
|
|
385
|
+
Common intents: `perf.slow-query`, `perf.cache-hit`, `capacity.size`, `safety.connections`,
|
|
386
|
+
`monitor.cluster-health`.
|
|
426
387
|
|
|
427
|
-
Snippets resolve
|
|
428
|
-
-
|
|
429
|
-
|
|
430
|
-
|
|
388
|
+
Snippets resolve **local > shared > builtin** (local wins): `builtin` (bundled `@diag/*`,
|
|
389
|
+
read-only) / `.dbcli-shared/queries/` (team) / `.dbcli/queries/` (personal). Manage local
|
|
390
|
+
snippets with `queries new | edit | delete | rename | copy | import | export`. Each `.sql`
|
|
391
|
+
file declares YAML frontmatter inside `-- ---` blocks (name, description, engine, params, tags,
|
|
392
|
+
optional `intent`, optional `visual`).
|
|
431
393
|
|
|
432
|
-
|
|
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:
|
|
394
|
+
Body format by `engine`:
|
|
444
395
|
|
|
445
396
|
| Engine | Body format | Notes |
|
|
446
397
|
|-------------------|------------------------|-------|
|
|
447
398
|
| postgres / mysql | Single SELECT or WITH | `:name` → driver bind (`$1` / `?`) |
|
|
448
399
|
| elasticsearch | JSON DSL | `:name` → JSON-aware substitution; `index:` field required |
|
|
449
|
-
| redis | Single Redis command | `:name` → raw text; only read commands allowed |
|
|
400
|
+
| redis | Single Redis command | `:name` → raw text; **only read commands allowed** |
|
|
450
401
|
|
|
451
402
|
Mixed-family `engine` arrays (e.g. `[postgres, elasticsearch]`) are rejected at parse time.
|
|
452
403
|
|
|
453
404
|
### Built-in diagnostic snippets
|
|
454
405
|
|
|
455
|
-
|
|
406
|
+
Run with `dbcli q @diag/<topic>` (engine variant auto-picked by the active connection):
|
|
456
407
|
|
|
457
408
|
| key | purpose |
|
|
458
409
|
|-------------------------|------------------------------------------|
|
|
459
410
|
| `@diag/connections` | active sessions |
|
|
460
|
-
| `@diag/long-running` | queries above `min_seconds` (default 30) |
|
|
411
|
+
| `@diag/long-running` | queries above `min_seconds` (`--param min_seconds=N`, default 30) |
|
|
461
412
|
| `@diag/table-sizes` | table data/index size with row counts |
|
|
462
413
|
| `@diag/index-usage` | indexes by scan count |
|
|
463
414
|
| `@diag/missing-indexes` | tables dominated by sequential scans |
|
|
464
415
|
| `@diag/locks` | lock-wait chains |
|
|
465
416
|
| `@diag/db-size` | database size summary |
|
|
466
417
|
| `@diag/cache-hit` | buffer cache hit ratios |
|
|
467
|
-
| `@diag/es-cluster-health` | document counts per index (ES
|
|
468
|
-
| `@diag/redis-key-stats` | sample SCAN over keyspace (Redis
|
|
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/`.
|
|
418
|
+
| `@diag/es-cluster-health` | document counts per index (ES) |
|
|
419
|
+
| `@diag/redis-key-stats` | sample SCAN over keyspace (Redis) |
|
|
473
420
|
|
|
474
421
|
## Interactive HTML dashboard
|
|
475
422
|
|
|
476
|
-
`query`, `q`, and `export` can render results as a standalone, self-contained HTML
|
|
477
|
-
|
|
478
|
-
injected via a hardened `window.__DBCLI_PAYLOAD__ = {...}` block — `<` is escaped
|
|
479
|
-
to neutralise `</script>` payloads).
|
|
423
|
+
`query`, `q`, and `export` can render results as a standalone, self-contained HTML report
|
|
424
|
+
(bundled React + Recharts template).
|
|
480
425
|
|
|
481
426
|
```bash
|
|
482
|
-
|
|
483
|
-
dbcli query "SELECT
|
|
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)
|
|
427
|
+
dbcli query "SELECT day, dau FROM dau_daily" --ui # open in browser
|
|
428
|
+
dbcli query "SELECT * FROM orders" --format html > out.html # pipe HTML to stdout
|
|
490
429
|
dbcli export "SELECT * FROM orders" --format html --output orders.html
|
|
491
430
|
```
|
|
492
431
|
|
|
493
|
-
`--ui` implies `--format html` and opens the file; `--format html` alone prints to
|
|
494
|
-
|
|
495
|
-
|
|
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.
|
|
432
|
+
`--ui` implies `--format html` and opens the file; `--format html` alone prints to stdout.
|
|
433
|
+
Blacklist redaction is applied **before** rendering. To get KPIs and charts instead of a plain
|
|
434
|
+
table, add a `visual:` block (`title`, `kpis[]`, `charts[]`) to the snippet frontmatter — see
|
|
435
|
+
reference.md for the full `visual:` schema. Raw `query` invocations render a sortable table only.
|
|
525
436
|
|
|
526
437
|
## Common workflows
|
|
527
438
|
|
|
528
439
|
- **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.
|
|
440
|
+
- **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
441
|
- **Migrations:** `diff --snapshot` → `migrate` (dry-run → `--execute`) → `diff --against` → `check` affected tables. DROP requires `--force`.
|
|
531
442
|
- **Health / growth:** `check --all` (huge tables skipped unless `--include-large`); consult schema `sizeCategory` before ad-hoc queries.
|
|
532
443
|
- **Codegen from live DB:** `schema --format json` to drive an ORM; cross-check once with `dbcli query`.
|