@carllee1983/dbcli 1.31.0 → 1.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/.agents/plugins/marketplace.json +21 -0
  2. package/.claude-plugin/plugin.json +9 -0
  3. package/.codex-plugin/plugin.json +41 -0
  4. package/.cursor/rules/dbcli.mdc +541 -0
  5. package/.cursor/skills/dbcli/SKILL.md +106 -0
  6. package/.cursor/skills/dbcli/reference.md +2232 -0
  7. package/.cursor-plugin/plugin.json +36 -0
  8. package/.github/skills/dbcli/SKILL.md +541 -0
  9. package/.github/skills/dbcli/reference.md +2232 -0
  10. package/CHANGELOG.md +81 -0
  11. package/README.md +38 -1
  12. package/README.zh-TW.md +37 -1
  13. package/assets/SKILL.md +86 -2
  14. package/assets/SKILL.zh-TW.md +71 -3
  15. package/assets/reference.md +286 -1
  16. package/assets/tasks/audit-permissions.md +35 -0
  17. package/assets/tasks/connection-health.md +37 -0
  18. package/assets/tasks/migration-review.md +41 -0
  19. package/assets/tasks/pr-database-review.md +38 -0
  20. package/assets/tasks/safe-backfill-verify.md +63 -0
  21. package/assets/tasks/safe-backfill.md +42 -0
  22. package/assets/tasks/schema-drift-review.md +37 -0
  23. package/assets/tasks/slow-endpoint-investigation.md +40 -0
  24. package/dist/cli.mjs +55833 -63508
  25. package/dist/core.mjs +1 -1
  26. package/gemini-extension.json +6 -0
  27. package/package.json +18 -5
  28. package/plugins/dbcli-agent/.codex-plugin/plugin.json +40 -0
  29. package/plugins/dbcli-agent/INSTALL.md +241 -0
  30. package/plugins/dbcli-agent/README.md +89 -0
  31. package/plugins/dbcli-agent/scripts/install-dbcli.sh +15 -0
  32. package/plugins/dbcli-agent/scripts/install-skills.sh +83 -0
  33. package/plugins/dbcli-agent/skills/dbcli/SKILL.md +541 -0
  34. package/plugins/dbcli-agent/skills/dbcli/reference.md +2232 -0
  35. package/skills/dbcli/SKILL.md +541 -0
  36. package/skills/dbcli/reference.md +2232 -0
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "dbcli-agent",
3
+ "interface": {
4
+ "displayName": "dbcli Agent"
5
+ },
6
+ "plugins": [
7
+ {
8
+ "name": "dbcli-agent",
9
+ "source": {
10
+ "source": "url",
11
+ "url": "https://github.com/CarlLee1983/dbcli.git",
12
+ "ref": "main"
13
+ },
14
+ "policy": {
15
+ "installation": "AVAILABLE",
16
+ "authentication": "ON_INSTALL"
17
+ },
18
+ "category": "Productivity"
19
+ }
20
+ ]
21
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "dbcli-agent",
3
+ "version": "1.37.0",
4
+ "description": "Database CLI skill and command reference for AI agents.",
5
+ "author": {
6
+ "name": "Carl Lee",
7
+ "url": "https://github.com/CarlLee1983"
8
+ }
9
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "dbcli-agent",
3
+ "version": "1.37.0",
4
+ "description": "Database CLI skill and command reference for AI agents",
5
+ "author": {
6
+ "name": "Carl Lee",
7
+ "url": "https://github.com/CarlLee1983"
8
+ },
9
+ "homepage": "https://github.com/CarlLee1983/dbcli",
10
+ "repository": "https://github.com/CarlLee1983/dbcli",
11
+ "license": "MIT",
12
+ "keywords": [
13
+ "database",
14
+ "cli",
15
+ "ai-agent",
16
+ "postgresql",
17
+ "mysql",
18
+ "mongodb",
19
+ "redis",
20
+ "elasticsearch"
21
+ ],
22
+ "skills": "./skills/",
23
+ "interface": {
24
+ "displayName": "dbcli Agent",
25
+ "shortDescription": "Use dbcli safely from Codex.",
26
+ "longDescription": "Installs the dbcli agent skill and reference guide so Codex can inspect schemas, query databases, respect blacklist boundaries, and recover from database errors through the dbcli command workflow.",
27
+ "developerName": "Carl Lee",
28
+ "category": "Productivity",
29
+ "capabilities": [
30
+ "Database",
31
+ "Local CLI",
32
+ "Agent Skill"
33
+ ],
34
+ "websiteURL": "https://github.com/CarlLee1983/dbcli",
35
+ "defaultPrompt": [
36
+ "Inspect my database with dbcli.",
37
+ "Show schema safely with dbcli.",
38
+ "Diagnose a dbcli query failure."
39
+ ]
40
+ }
41
+ }
@@ -0,0 +1,541 @@
1
+ ---
2
+ name: dbcli
3
+ description: Database CLI for AI agents with permission-based access control. Use to set up new connections, query, inspect schemas, insert/update/delete, export results, and blacklist sensitive columns/tables. Supports MySQL, PostgreSQL, MariaDB, MongoDB, Redis, and Elasticsearch with multiple named connections per project and custom env files. Trigger when configuring a database connection (`.dbcli` / `.env`), choosing between v1 single and v2 multi-connection layouts, picking auth modes (URI, env refs, Cloud ID, API key), running SQL / MongoDB JSON / Redis commands / Elasticsearch DSL, exploring table/collection/key/index structures, switching database environments, protecting sensitive data from AI access, or performing automated recovery and guided remediation after command failures. For exhaustive flags and examples, read the sibling `reference.md`.
4
+ ---
5
+
6
+ # dbcli
7
+
8
+ Database CLI for AI agents with permission-based access control.
9
+
10
+ If the `dbcli` executable is not available in `PATH`, use
11
+ `bunx @carllee1983/dbcli <command>` as the command prefix. This is the expected
12
+ fallback for Codex plugin installs where the skill is installed by the plugin but
13
+ the CLI package has not been installed globally.
14
+
15
+ ## AI agent workflow (follow in order)
16
+
17
+ 0. `dbcli skill context --format xml` — LLM prompt context payload: serializes connection metadata, schema caches, and saved queries into a compressed XML/JSON structure for prompt injection.
18
+ 1. `dbcli inspect --for-agent` — bounded snapshot: connection, permission, blacklist, objects, snippets, suggested next commands.
19
+ 2. `dbcli report --format json` — diagnostic report (health/capacity/perf) using built-in snippets.
20
+ 3. `dbcli guide <goal> --format json` — deterministic next-command plan for a fixed goal (`slow-query`, `capacity`, `health`, `index-usage`, `permissions`, `schema-overview`). Use `dbcli guide --list` to see goals.
21
+ 4. `dbcli recovery --code <CODE>` — look up structured recovery commands for a known error code (e.g. `CONN_REFUSED`, `PERMISSION_DENIED`, `SNIPPET_NOT_FOUND`). Pass `--recovery` to `dbcli query` / `dbcli q` to have failures emit a `RecoveryEnvelope` directly. In v1.16.0 the `--recovery` flag is also accepted by `dbcli insert`, `dbcli update`, `dbcli delete`, `dbcli export`, `dbcli schema`, and `dbcli inspect` (which also gained `--require-schema-cache` for the `SCHEMA_CACHE_MISSING` path).
22
+ - **v1.17.0** `dbcli recover` reads the auto-saved envelope (`.dbcli/last-recovery.json`) written by any prior `--recovery` failure. Inspect it (Markdown by default) or pass `--apply` to execute the saved plan under risk gating.
23
+ - **v1.17.0** `dbcli recover --apply` runs `risk=readonly` and `risk=dry-run` steps by default. Open the gate one tier with `--allow-write=readonly-cmd` (run local-side writes such as `blacklist remove`) or `--allow-write=write-cmd` (also run steps that mutate the connected database). Pass `--from <file>` to read an explicit envelope instead of the auto-saved one. Use `--format json` for an aggregated machine-readable result.
24
+ - Exit codes: `0` ok, `1` step failed, `2` envelope missing/malformed, `3` every step skipped (open `--allow-write` or fix interactive/placeholder).
25
+ - GuideStep optional fields agents should respect:
26
+ - `interactive: true` — step requires a TTY (`dbcli init` family). `dbcli recover --apply` skips with `skipped:interactive`.
27
+ - `dbWrite: true` — step mutates the connected database. Gates the highest risk tier; reserved for future write-side recovery steps.
28
+ - `placeholders: ['<token>', ...]` — agent must replace these tokens before `--apply` will execute. Skipped with `skipped:placeholder`.
29
+ - **v1.17.0 P4 Verification.** After `--apply` finishes the main plan, dbcli runs **one extra read-only step** (`envelope.verify`) to probe whether the original failure is gone. The output gains `verifyResult` (the executed step) and `verifyStatus`:
30
+ - `passed` — verifier exited 0 and (where applicable) the expected JSON shape was found.
31
+ - `failed` — verifier exited non-zero or timed out.
32
+ - `indeterminate` — verifier exited 0 but the heuristic could not confirm the fix (JSON parse failure, missing field, gate skip).
33
+ Verify is **only run when** `finalStatus === 'ok'`. Pass `--no-verify` to skip it. Heuristic is intentionally cheap; agents should still re-run their own check against the original failing operation when correctness matters.
34
+
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.
66
+
67
+ Prefer `--format json` for agent-friendly output.
68
+
69
+ ## Agent Task Packs
70
+
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.
74
+
75
+ ```bash
76
+ dbcli skill tasks list --format json # discover
77
+ dbcli skill tasks show <task> # inspect
78
+ dbcli skill tasks plan <task> --param key=value --format json # generate plan
79
+ ```
80
+
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.
100
+
101
+ Tasks live under `assets/tasks/` (builtin), `.dbcli-shared/tasks/` (shared), and
102
+ `.dbcli/tasks/` (local override).
103
+
104
+ ## Developer workflows
105
+
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`. |
120
+
121
+ Copy-paste command anchors:
122
+
123
+ ```bash
124
+ dbcli inspect --for-agent --format json
125
+ dbcli blacklist list --format json
126
+ dbcli schema <object> --format json
127
+ dbcli queries suggest <intent> --format json
128
+ dbcli audit tail --for-agent --n 10
129
+ dbcli schema --format json
130
+ dbcli diff --snapshot <name>
131
+ dbcli migrate add-index <table>
132
+ dbcli diff --against <snapshot>
133
+ dbcli report --section perf --format json
134
+ dbcli skill tasks plan analyze-table-perf --param table=<table> --format json
135
+ dbcli guide missing-index-for "<query>" --format json
136
+ dbcli proxy analyze --format json
137
+ dbcli query "<count/scope query>" --format json
138
+ dbcli update <object> --where "<bounded predicate>" --set '<json>' --dry-run --format json
139
+ dbcli status --format json
140
+ dbcli doctor --format json
141
+ dbcli inspect --for-agent --no-connect --format json
142
+ ```
143
+
144
+ Developer workflow guardrails:
145
+
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.
152
+ - Do not create indexes directly from a performance suggestion; turn them into reviewed migrations.
153
+ - 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
+ - `verification show <id>` — cite the final artifact.
164
+
165
+ 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).
166
+
167
+ ## Audit Log usage
168
+
169
+ Use the audit log when you need cross-session history or forensics on what dbcli
170
+ has done on this database, rather than re-querying live DB state from scratch.
171
+
172
+ **Scenario 1 — Session handoff (picking up where another agent left off):**
173
+
174
+ ```bash
175
+ dbcli audit tail --for-agent --n 10 # last 10 entries as JSON envelope
176
+ dbcli audit tail --all --for-agent --n 20 # cross-connection merged view (D4)
177
+ ```
178
+
179
+ Returns an agent-facing JSON envelope with `session_id` / `engine` / `command` /
180
+ `target` / `success` per entry. Metadata-only by design — never raw SQL bodies,
181
+ `--param` values, or result cell contents (D3 lock).
182
+
183
+ **Scenario 2 — Forensics (reconstructing a failure):**
184
+
185
+ ```bash
186
+ dbcli recover --format json # inspect audit_recent embed + recovery_ref
187
+ dbcli audit show <id-prefix> # full entry by id prefix (>=4 chars)
188
+ dbcli audit show --recovery-ref <envelope-id> # find entry that emitted an envelope
189
+ ```
190
+
191
+ The `inspect` / `guide` / `recover` / `recover --apply` agent JSON output embeds
192
+ `audit_recent: AuditEntryBrief[]` (last 5 entries) — a fresh session has immediate
193
+ history context. The envelope's `audit_ref` and the audit entry's `recovery_ref`
194
+ point at each other; agents can pivot either direction.
195
+
196
+ Bi-directional `recovery_ref` / `audit_ref` linkage is wired on every command
197
+ that accepts `--recovery`: `query`, `inspect`, `insert`, `update`, `delete`,
198
+ `export`, `q`, and `schema`. Agents can pivot from an envelope to its audit
199
+ entry via `audit tail --recovery-ref <id>`.
200
+
201
+ Audit entries are written to `.dbcli/audit/<connection>.jsonl` with rotation at
202
+ ~10 MB or 1000 entries. `audit.enabled = false` in `.dbcli` opts out (default ON
203
+ since v1.20.0). For flag reference see [`reference.md`](./reference.md) §audit.
204
+ For end-to-end recovery walkthroughs (per-code scenarios, `--next` multi-turn,
205
+ envelope ⇄ audit pivot, risk-gate cheat sheet) see
206
+ [`reference.md`](./reference.md) §Recovery Cookbook.
207
+
208
+ ## Quick start
209
+
210
+ ```bash
211
+ dbcli init # Create .dbcli config (parses .env automatically)
212
+ dbcli schema # Scan all tables → .dbcli/schemas/
213
+ dbcli query "SELECT * FROM users" # Execute SQL (auto LIMIT 1000)
214
+ ```
215
+
216
+ If `.dbcli` does not yet exist, route through **Connection setup** below before
217
+ touching `schema` / `query`.
218
+
219
+ ## Connection setup (helping the user wire up a database)
220
+
221
+ When the user asks "how do I connect to X?", "set up dbcli for our staging DB",
222
+ or `doctor` / `status` reports a missing or invalid config, follow this flow.
223
+
224
+ > **Default to guiding, not running.** `init` writes credentials to disk. Only
225
+ > execute it for the user with explicit permission and confirmed values.
226
+ > If a `.dbcli` already contains `{"$env": "..."}` references, **do not** rerun
227
+ > `init` to "fill them in" — the env-ref form is intentional for CI/multi-env.
228
+
229
+ ### Decision tree (ask before writing)
230
+
231
+ 1. **One DB or many environments?** One → v1 (single connection). Multiple
232
+ environments / tenants / replicas → v2 (`--conn-name <name>`, optionally
233
+ `--env-file <path>` per connection).
234
+ 2. **Where do credentials live?**
235
+ - Already in a `.env` (`DATABASE_URL` or `DB_HOST` / `DB_PORT` / `DB_USER` /
236
+ `DB_PASSWORD` / `DB_NAME` | `DB_DATABASE`) → `init` parses it automatically.
237
+ - Need to keep secrets out of `.dbcli` (CI/CD, multi-env) → `--use-env-refs`
238
+ plus `--env-host` / `--env-port` / `--env-user` / `--env-password` / `--env-database`.
239
+ - Plain values are acceptable → pass `--host` / `--port` / `--user` /
240
+ `--password` / `--name` (and `--system`).
241
+ 3. **What permission tier?** Default to the **lowest** that satisfies the task:
242
+ `query-only` → `read-write` → `data-admin` → `admin`. Set with `--permission`.
243
+ 4. **Verify, never assume.** After init: `dbcli status` (system + permission +
244
+ blacklist summary, no creds) and `dbcli doctor --format json` (env, config
245
+ shape, connectivity, schema-cache age, Mongo SRV path).
246
+
247
+ ### Per-engine essentials
248
+
249
+ ```bash
250
+ # PostgreSQL / MySQL / MariaDB (v1, plain values)
251
+ dbcli init --system postgresql --host localhost --port 5432 \
252
+ --user app --password '<secret>' --name appdb --permission query-only
253
+
254
+ # Reuse an existing .env (DATABASE_URL=postgresql://user:pw@host:5432/db)
255
+ dbcli init # parses .env in cwd
256
+
257
+ # MongoDB — full URI (Atlas / replica sets / authSource)
258
+ dbcli init --system mongodb \
259
+ --uri "mongodb+srv://user:pw@cluster.example.mongodb.net/mydb?authSource=admin"
260
+ # MongoDB — discrete params (no auth = omit --user/--password)
261
+ dbcli init --system mongodb --host localhost --port 27017 --name mydb
262
+
263
+ # Redis — `--name` is the LOGICAL DB INDEX ("0".."15"), not a database name
264
+ dbcli init --system redis --host localhost --port 6379 --password '<secret>' --name 0
265
+
266
+ # Elasticsearch — basic auth, Cloud ID, or API key
267
+ dbcli init --system elasticsearch --host localhost --port 9200 \
268
+ --user elastic --password '<secret>'
269
+ dbcli init --system elasticsearch \
270
+ --cloud-id "myCluster:dXMtZWFzdC0xLmF3..." --api-key "<base64>"
271
+ # Multi-node / custom CA / self-signed: edit `.dbcli` directly to add
272
+ # `nodes: [...]`, `protocol: https`, `caPath`, `rejectUnauthorized: false`.
273
+ ```
274
+
275
+ ### Multi-connection (v2)
276
+
277
+ ```bash
278
+ dbcli init --conn-name staging --env-file .env.staging --permission query-only
279
+ dbcli init --conn-name prod --env-file .env.production --use-env-refs --skip-test
280
+ dbcli use --list # show all, * marks default
281
+ dbcli use prod # switch default
282
+ dbcli query --use staging "SELECT 1" # one-shot override
283
+ dbcli init --rename staging:stg # rename
284
+ dbcli init --remove stg # remove
285
+ ```
286
+
287
+ Per-connection schema cache lives at `.dbcli/schemas/<connection>/`. Run
288
+ `dbcli schema --use <name>` once per connection before `schema <table>` —
289
+ otherwise the cache may serve another connection's columns.
290
+
291
+ ### env-refs (keep secrets out of `.dbcli`)
292
+
293
+ ```bash
294
+ dbcli init --use-env-refs \
295
+ --env-host DB_HOST --env-port DB_PORT \
296
+ --env-user DB_USER --env-password DB_PASSWORD --env-database DB_NAME
297
+ ```
298
+
299
+ Stored as `{ "$env": "DB_HOST" }` etc. and resolved at runtime. Pair with
300
+ `--env-file <path>` (v2) when each connection has its own env file.
301
+
302
+ ### Common gotchas
303
+
304
+ - **MongoDB `mongodb+srv://`** — `dbcli doctor` reports whether SRV resolves
305
+ natively or via the DoH fallback; useful when the runtime restricts DNS.
306
+ - **MySQL/Postgres password with `@` `:` `/`** — when using `DATABASE_URL`,
307
+ percent-encode (`@` → `%40`); discrete `--password` flags do not need encoding.
308
+ - **Redis `--name`** — accepts only the logical DB index string; non-numeric
309
+ values are rejected.
310
+ - **Elasticsearch TLS** — `caPath` and `rejectUnauthorized` are not exposed as
311
+ flags; edit `.dbcli` after `init` to add them.
312
+ - **Re-running `init`** — refuses to overwrite without `--force`; never use
313
+ `--force` to "fix" a config full of `{ "$env": "..." }` refs.
314
+
315
+ Full flags and edge cases: see [reference.md](reference.md) `init` section.
316
+
317
+ ## Command overview
318
+
319
+ | Command | Min permission | Summary |
320
+ |---------|-----------------|---------|
321
+ | `init` | n/a | Create `.dbcli` (v1 single or v2 multi via `--conn-name` / `--env-file`). **Usually run by the human** — do NOT re-run to strip `{"$env"}` references; that format is intentional. |
322
+ | `use` | n/a | Show/switch default named connection (v2 only). |
323
+ | `list` | query-only+ | Tables (SQL), collections (MongoDB), keys (Redis), or indices (Elasticsearch). |
324
+ | `schema` | query-only+ | SQL: per-table or full scan into `.dbcli/schemas/`. MongoDB: sampled. ES: flattened mapping. Redis: per-key only (type/TTL/size). Supports `--recovery`. |
325
+ | `query` | query-only+ | SQL, Mongo JSON (`--collection`), Redis command, or ES DSL/Lucene (`--collection`). `--format table\|json\|csv\|html`, `--ui` to open the interactive dashboard in a browser. Supports `--recovery`. |
326
+ | `explain` | query-only+ | **(v1.23)** Read-only query plan with annotations. SQL only. Single query, `@saved-query`, `@file.sql`, or `--bulk @glob/*`. `--analyze` (EXPLAIN ANALYZE / MariaDB ANALYZE SELECT), `--format markdown\|json\|table`. |
327
+ | `plan` | n/a | Static SQL risk analyzer (`--format text\|json`); classifies a statement without connecting to the database. |
328
+ | `q` | query-only+ | Run a saved snippet by `@name` with `--param k=v`. Supports `--verify` to run assertions. |
329
+ | `queries` | n/a | Manage saved snippets: `list` / `show` / `search` / `suggest` / `new` / `edit` / `check` / `delete` / `rename` / `copy` / `import` / `export`. |
330
+ | `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`. |
331
+ | `delete` | data-admin+ | SQL or MongoDB only. `--where` required; `--dry-run` first. Supports `--recovery`. |
332
+ | `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`. |
333
+ | `blacklist` | n/a | `list` / `table` / `column` subcommands redact sensitive data from query results. |
334
+ | `check` | query-only+ | SQL only (best on MySQL/MariaDB). |
335
+ | `diff` | query-only+ | SQL only. Save/compare schema snapshots. |
336
+ | `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`. |
337
+ | `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>`. |
338
+ | `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. |
339
+ | `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`. |
340
+ | `status` | query-only+ | Safe JSON/text summary (no credentials). |
341
+ | `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`. |
342
+ | `report` | query-only+ | Diagnostic report (health / capacity / perf) built from `@diag/*` snippets. `--section`, `--brief`, `--for-agent`, `--no-connect`. |
343
+ | `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`). |
344
+ | `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. |
345
+ | `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. |
346
+ | `doctor` | n/a | Environment, config, connection, SRV diagnostics (Mongo), schema cache age. |
347
+ | `completion` | n/a | bash / zsh / fish scripts. |
348
+ | `upgrade` | n/a | Self-update from npm; 24h-cached version hints on every command. |
349
+ | `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). |
350
+ | `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. |
351
+ | `migrate` | admin | SQL only. **DDL; dry-run by default** — needs `--execute`. |
352
+
353
+ `--use <name>` on any subcommand targets a v2 connection without changing the default.
354
+ `--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.
355
+
356
+ ## Permission levels
357
+
358
+ | Level | Allowed |
359
+ |-------|---------|
360
+ | query-only | SELECT, list, schema, export |
361
+ | read-write | + INSERT, UPDATE |
362
+ | data-admin | + DELETE (DML, no DDL) |
363
+ | admin | + DDL via `migrate` and destructive ops |
364
+
365
+ ## Multi-connection (v2)
366
+
367
+ - Each named connection has its own schema dir: `.dbcli/schemas/<connection>/`.
368
+ - Run `dbcli schema --use <name>` once per connection before `schema <table>` — otherwise the cache may return another connection's columns.
369
+ - `schema --refresh` / `--reset` manage the cache; see reference.md.
370
+
371
+ ## MongoDB
372
+
373
+ - JSON filter object (`find`) or JSON array (`aggregate`); SQL is rejected. `--collection <name>` is required on `query`.
374
+ - **Supported:** `init`, `list`, `schema` (sampled), `query`, `insert`, `update`, `delete`, `export`, `q` (saved queries), `status`, `use`, `shell`, `doctor`, `upgrade`, `completion`.
375
+ - **Not supported:** `diff`, `migrate`, `check`.
376
+ - 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.
377
+ - **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`.
378
+ - **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]`.
379
+ - **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.
380
+ - See reference.md MongoDB section for full syntax and examples.
381
+
382
+ ## Redis
383
+
384
+ - Command-style execution; `query` runs a whitelisted Redis command (e.g. `GET`, `HSET`, `DEL`).
385
+ - **Supported:** `init`, `list` (keys via SCAN), `schema <key>` (type / TTL / size / sample), `query`, `shell`, `status`, `use`, `doctor`, `upgrade`, `completion`.
386
+ - **Not supported:** `schema` full scan, `insert`, `update`, `delete`, `export`, `check`, `diff`, `migrate`, `q`.
387
+ Use `query "DEL <key>"` etc. for writes — they go through the same permission gate.
388
+ - Permission tiers map to commands: read commands → `query-only`; mutators (`SET`, `HSET`, ...) → `read-write`; `DEL` / `UNLINK` → `data-admin`.
389
+ - `database` field is the logical DB index (default `0`); `list` returns ≤ 100 000 keys via SCAN.
390
+ - **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.
391
+ - **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.
392
+ - **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**.
393
+ - **Shell:** `dbcli shell` on a Redis connection opens a single-line REPL (history, tab completion of commands + key prefixes, `.no-limit on/off`).
394
+ - See reference.md Redis section.
395
+
396
+ ## Elasticsearch
397
+
398
+ - DSL (JSON body) or Lucene query string; `--collection <index>` is required on `query`.
399
+ - **Supported:** `init`, `list` (indices with doc count), `schema [index]` (flattened mapping), `query`, `export` (v1.22), `shell` (v1.22), `status`, `use`, `doctor`, `upgrade`, `completion`.
400
+ - **Not supported:** `insert`, `update`, `delete`, `check`, `diff`, `migrate`, `q`.
401
+ Writes are not exposed via dedicated subcommands yet — use `query` if the cluster allows or external tools.
402
+ - **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.
403
+ - **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.
404
+ - Query-only mode caps at 1000 hits; `--no-limit` is bounded at 10 000.
405
+ - Schema flattens nested fields (`a.b.c`) and surfaces `.fields` multi-fields.
406
+ - See reference.md Elasticsearch section.
407
+
408
+ ## Saved queries
409
+
410
+ Run reusable parameterised SELECT snippets stored in your repo.
411
+
412
+ | Step | Command |
413
+ |------|---------|
414
+ | 1. Discover | `dbcli queries list` |
415
+ | 2. Inspect | `dbcli queries show @<name>` |
416
+ | 3. Run | `dbcli q @<name> --param k=v` |
417
+
418
+ ### When you don't know which query to run
419
+
420
+ 1. `dbcli queries search <keywords>` — natural keywords, fuzzy ranked
421
+ 2. `dbcli queries suggest <intent>` — browse a category
422
+ Common intents: perf.slow-query, perf.cache-hit, capacity.size,
423
+ safety.connections, monitor.cluster-health
424
+ 3. Once you find one: `dbcli q @<name>` (blacklist always enforced)
425
+
426
+ Snippets resolve from three layers, **local > shared > builtin** (local wins):
427
+ - `builtin` — bundled with dbcli (e.g. `@diag/*`); read-only at runtime
428
+ - `.dbcli-shared/queries/` — committed, team-shared
429
+ - `.dbcli/queries/` — gitignored, personal override
430
+
431
+ Manage local snippets with `queries new | edit | delete | rename | copy | import | export`
432
+ (see reference.md). Use `copy` / `import` to fork a builtin or shared snippet into the
433
+ local layer for editing.
434
+
435
+ Each `.sql` file may declare YAML frontmatter inside `-- ---` blocks
436
+ (name, description, engine, params, tags, optional `intent`, optional `visual`).
437
+ The `visual:` block drives the interactive dashboard (see "Interactive HTML dashboard"
438
+ below). See `dbcli queries show @<name> --format json` for the machine-readable contract.
439
+
440
+ ### Engine-specific bodies
441
+
442
+ Each snippet's body format is determined by the `engine` frontmatter field:
443
+
444
+ | Engine | Body format | Notes |
445
+ |-------------------|------------------------|-------|
446
+ | postgres / mysql | Single SELECT or WITH | `:name` → driver bind (`$1` / `?`) |
447
+ | elasticsearch | JSON DSL | `:name` → JSON-aware substitution; `index:` field required |
448
+ | redis | Single Redis command | `:name` → raw text; only read commands allowed |
449
+
450
+ Mixed-family `engine` arrays (e.g. `[postgres, elasticsearch]`) are rejected at parse time.
451
+
452
+ ### Built-in diagnostic snippets
453
+
454
+ dbcli ships ready-made diagnostic queries. Run with `dbcli q @diag/<topic>`:
455
+
456
+ | key | purpose |
457
+ |-------------------------|------------------------------------------|
458
+ | `@diag/connections` | active sessions |
459
+ | `@diag/long-running` | queries above `min_seconds` (default 30) |
460
+ | `@diag/table-sizes` | table data/index size with row counts |
461
+ | `@diag/index-usage` | indexes by scan count |
462
+ | `@diag/missing-indexes` | tables dominated by sequential scans |
463
+ | `@diag/locks` | lock-wait chains |
464
+ | `@diag/db-size` | database size summary |
465
+ | `@diag/cache-hit` | buffer cache hit ratios |
466
+ | `@diag/es-cluster-health` | document counts per index (ES connections) |
467
+ | `@diag/redis-key-stats` | sample SCAN over keyspace (Redis connections) |
468
+
469
+ Engine variants are picked automatically based on the active connection.
470
+ Override any of them by placing a same-named file under `.dbcli-shared/queries/`
471
+ or `.dbcli/queries/`.
472
+
473
+ ## Interactive HTML dashboard
474
+
475
+ `query`, `q`, and `export` can render results as a standalone, self-contained HTML
476
+ report powered by a bundled React + Recharts template (`assets/ui-template.html`,
477
+ injected via a hardened `window.__DBCLI_PAYLOAD__ = {...}` block — `<` is escaped
478
+ to neutralise `</script>` payloads).
479
+
480
+ ```bash
481
+ # Open in browser (writes to a temp file, then `open`/`xdg-open`/`start`)
482
+ dbcli query "SELECT day, dau FROM dau_daily" --ui
483
+ dbcli q @analytics/revenue --param days=30 --ui
484
+
485
+ # Pipe HTML to stdout (CI artifacts, email, static hosting)
486
+ dbcli query "SELECT * FROM orders" --format html > orders.html
487
+
488
+ # Export to a file (interchangeable with json/jsonl/csv)
489
+ dbcli export "SELECT * FROM orders" --format html --output orders.html
490
+ ```
491
+
492
+ `--ui` implies `--format html` and opens the file; `--format html` alone prints to
493
+ stdout. Blacklist redaction is applied **before** rendering — the dashboard never
494
+ sees masked columns.
495
+
496
+ ### Snippet `visual:` block
497
+
498
+ To get KPIs and charts (rather than just a sortable table), add a `visual:` block
499
+ to the snippet's frontmatter. Column names must exist in the result row.
500
+
501
+ ```sql
502
+ -- ---
503
+ -- name: Revenue Trend
504
+ -- engine: postgres
505
+ -- params:
506
+ -- days: { type: int, default: 30 }
507
+ -- visual:
508
+ -- title: Revenue (last :days days)
509
+ -- kpis:
510
+ -- - { label: Total Revenue, value_column: total_revenue, format: currency }
511
+ -- - { label: Orders, value_column: order_count, format: number }
512
+ -- - { label: Conversion, value_column: conv_rate, format: percent }
513
+ -- charts:
514
+ -- - { type: line, title: Daily Revenue, x: day, y: [revenue] }
515
+ -- - { type: bar, title: By Channel, x: channel, y: [revenue, refunds] }
516
+ -- ---
517
+ SELECT ...
518
+ ```
519
+
520
+ - `kpis[].format`: `currency` / `number` / `percent` (omit for raw value).
521
+ - `charts[].type`: `line` / `bar` / `area` / `pie` / `scatter`.
522
+ - Raw `query` invocations (no snippet) render a sortable/filterable table only —
523
+ there is no `visual:` to attach.
524
+
525
+ ## Common workflows
526
+
527
+ - **Debug odd state:** `schema` → `check` → `query` with tight `WHERE` → follow FKs from schema JSON. Evidence over theory.
528
+ - **After INSERT/UPDATE:** `--dry-run` → run → `query` read-back; explain mismatches via triggers, defaults, or blacklist.
529
+ - **Migrations:** `diff --snapshot` → `migrate` (dry-run → `--execute`) → `diff --against` → `check` affected tables. DROP requires `--force`.
530
+ - **Health / growth:** `check --all` (huge tables skipped unless `--include-large`); consult schema `sizeCategory` before ad-hoc queries.
531
+ - **Codegen from live DB:** `schema --format json` to drive an ORM; cross-check once with `dbcli query`.
532
+ - **Integration truth:** `query` before → run app → `query` after. Unit-test mocks are not a substitute.
533
+ - **Natural language requests** (e.g. "update order to shipped"): pick `query` vs DML, map terms → columns via `schema` (and enum values in data), respect blacklist and `sizeCategory`, **always `--dry-run` writes first**.
534
+
535
+ ## Notes
536
+
537
+ - Query-only mode auto-appends `LIMIT 1000`; add `--no-limit` for `information_schema` or statements that break with `LIMIT`.
538
+ - Blacklisted tables and columns are redacted from query output.
539
+ - `schema` reports `estimatedRowCount` and `sizeCategory` (small / medium / large / huge). For large/huge tables add `WHERE` or `LIMIT` — bands in reference.md.
540
+ - `doctor` on `mongodb+srv://` reports whether SRV resolves natively or through the DoH fallback — useful when the runtime restricts DNS.
541
+ - **Global flags:** `--config <path>`, `--use <name>`, `-v` / `-vv` / `-q`, `--no-color` (also honours `NO_COLOR`).