@carllee1983/dbcli 1.44.1 → 1.45.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/README.zh-TW.md CHANGED
@@ -172,6 +172,18 @@ dbcli init --conn-name staging --env-file .env.staging
172
172
  dbcli init --conn-name prod --env-file .env.production --use-env-refs
173
173
  ```
174
174
 
175
+ 若要讓多個專案共用連線,請使用 user-global scope。它會把 v2 registry 儲存在 `~/.config/dbcli/config.json`,且不會修改目前專案的 `.dbcli` binding:
176
+
177
+ ```bash
178
+ dbcli --global init --conn-name shared --system postgresql --host db.example.com \
179
+ --port 5432 --user app --password '<secret>' --name appdb \
180
+ --skip-test --no-interactive --force
181
+ dbcli --global use --list --format json
182
+ dbcli --global query "SELECT 1"
183
+ ```
184
+
185
+ Root 層級的 `--global` 必須放在指令之前。未帶它時,指令仍會使用專案設定。
186
+
175
187
  每一條具名連線可以設定不同的 **`--permission`**(例如正式環境只給 `query-only`)。現在專案內的 `.dbcli` 主要扮演**綁定 + 快取層**;真正的連線設定會存到使用者家目錄下的 `~/.config/dbcli/projects/<project-id>/`,避免敏感設定留在工作區。
176
188
 
177
189
  ### 管理連線(`use` / 移除 / 更名)
@@ -969,6 +981,7 @@ dbcli plan "SELECT id FROM users WHERE id = 1 LIMIT 1" --format json
969
981
  | 旗標 | 說明 |
970
982
  |------|------|
971
983
  | `--config <path>` | `.dbcli` 設定檔路徑(預設:`.dbcli`) |
984
+ | `--global` | 使用 `~/.config/dbcli/config.json` 的 user-global registry |
972
985
  | `--use <connection>` | 僅本次指令使用具名的 v2 連線(不變更預設連線) |
973
986
  | `-v, --verbose` | 提高詳細度(`-v` 詳細、`-vv` 除錯) |
974
987
  | `-q, --quiet` | 抑制非必要輸出 |
package/assets/SKILL.md CHANGED
@@ -21,6 +21,20 @@ the CLI package has not been installed globally.
21
21
  3. All writes: `--dry-run` (SQL/Mongo) → run → `query` read-back to confirm. Redis
22
22
  `query` has **no `--dry-run`** (see **Redis**); Elasticsearch is **read-only**.
23
23
 
24
+ **Environment and mutation boundary:** In v2, inspect `dbcli use --list --format json`
25
+ before selecting a named connection. A connection labelled `environment: "production"`
26
+ must be explicitly selected; it is never silently used through the saved default. To
27
+ persist a production default, a human must repeat the exact name with
28
+ `--confirm-production`. When `DBCLI_AGENT_MODE=1`, configuration, permission, and
29
+ credential mutations are blocked unconditionally. Run human/admin changes in a separate
30
+ process with agent mode disabled; do not treat a same-process environment variable as
31
+ approval. Trusted config writes maintain an integrity record and secure file modes where
32
+ supported, and agent reads fail closed on missing, replaced, non-regular, or tampered
33
+ records. Agent mode refuses legacy single-file `.dbcli` configs until a human/admin
34
+ migration to V2 home storage. For a same-user hostile process, a host can set
35
+ `DBCLI_CONFIG_INTEGRITY_ANCHOR_DIR` to a protected or read-only directory containing
36
+ detached digests.
37
+
24
38
  **`update` / `delete` `--where` is equality-only (SQL).** It accepts **only** `col=val` or
25
39
  `col1=v1 AND col2=v2`. A comparison / pattern operator (`>`, `>=`, `<`, `!=`, `LIKE`, `IN`)
26
40
  is a **parse error**; worse, `OR` is **silently swallowed into the value** — `a=1 OR b=2`
@@ -238,7 +252,7 @@ dbcli init --system elasticsearch \
238
252
  ```bash
239
253
  dbcli init --conn-name staging --env-file .env.staging --permission query-only
240
254
  dbcli init --conn-name prod --env-file .env.production --use-env-refs --skip-test
241
- dbcli use --list # show all, * marks default
255
+ dbcli use --list --format json # safe identity inventory: name/env/permission/server/database
242
256
  dbcli use prod # switch default (persists — avoid for one-off queries)
243
257
  dbcli query --use staging "SELECT 1" # one-shot override on any subcommand
244
258
  DBCLI_CONNECTION=staging dbcli query "SELECT 1" # one-shot via env; parallel-safe
@@ -247,6 +261,18 @@ dbcli init --rename staging:stg # rename
247
261
  dbcli init --remove stg # remove
248
262
  ```
249
263
 
264
+ For a connection shared across projects, use the explicit root-level `--global` scope. It stores a v2 registry at `~/.config/dbcli/config.json`; it does not create or modify a project binding:
265
+
266
+ ```bash
267
+ dbcli --global init --conn-name shared --system postgresql --host db.example.com \
268
+ --port 5432 --user app --password '<secret>' --name appdb \
269
+ --skip-test --no-interactive --force
270
+ dbcli --global use --list --format json
271
+ dbcli --global query "SELECT 1"
272
+ ```
273
+
274
+ `--global` must appear before the command. Without it, commands continue to use the current project's `.dbcli` binding; global and project registries are independent.
275
+
250
276
  Each named connection has its own schema cache at `.dbcli/schemas/<connection>/`. Run
251
277
  `dbcli schema --use <name>` once per connection **before** `schema <table>` — otherwise the
252
278
  cache may serve another connection's columns. `schema --refresh` / `--reset` manage the cache
@@ -313,6 +339,7 @@ Full flags and edge cases: see [reference.md](reference.md) `init` section.
313
339
  | `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`. |
314
340
  | `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>`. |
315
341
  | `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. |
342
+ | `backfill artifact` | n/a | Build a bounded, reviewable source-to-SQL backfill artifact from JSON. Includes source/target identity, blacklist/schema preflight, read-back verification, and rollback hints; dry-run only and never executes writes. |
316
343
  | `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. |
317
344
  | `status` | query-only+ | Safe JSON/text summary (no credentials). |
318
345
  | `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`. |
@@ -320,7 +347,7 @@ Full flags and edge cases: see [reference.md](reference.md) `init` section.
320
347
  | `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`). |
321
348
  | `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. |
322
349
  | `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. |
323
- | `doctor` | n/a | Environment, config, connection, SRV diagnostics (Mongo), schema cache age. |
350
+ | `doctor` | n/a | Environment/runtime identity, config, connection, SRV diagnostics (Mongo), schema cache age. `--format json --remediation` emits candidate-only blacklist/schema/bounded-sample plans (SQL: `dbcli plan` → human-confirmed bounded `dbcli query`; MongoDB/Elasticsearch: `dbcli schema` preflight → human-confirmed bounded query); it never applies them. |
324
351
  | `completion` | n/a | bash / zsh / fish scripts. |
325
352
  | `upgrade` | n/a | Self-update from npm; 24h-cached version hints on every command. |
326
353
  | `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). |
@@ -509,4 +536,4 @@ schema. Raw `query` / `export` invocations render a sortable table only.
509
536
  - Blacklisted tables and columns are redacted from query output.
510
537
  - `schema` reports `estimatedRowCount` and `sizeCategory` (small / medium / large / huge). For large/huge tables add `WHERE` or `LIMIT` — bands in reference.md.
511
538
  - `doctor` on `mongodb+srv://` reports whether SRV resolves natively or through the DoH fallback — useful when the runtime restricts DNS.
512
- - **Global flags:** `--config <path>`, `--use <name>`, `-v` / `-vv` / `-q`, `--no-color` (also honours `NO_COLOR`).
539
+ - **Global flags:** `--version`, `--config <path>`, `--global`, `--use <name>`, `-v` / `--verbose` / `-vv`, `-q` / `--quiet`, `--no-color` (also honours `NO_COLOR`). Root-level flags must precede the command unless the command explicitly declares a command-level option.
@@ -18,6 +18,16 @@ description: Database CLI for AI agents with permission-based access control. Us
18
18
  3. 所有寫入:`--dry-run`(SQL / Mongo)→ 實際執行 → `query` 回讀確認。Redis 的 `query`
19
19
  **沒有 `--dry-run`**(見 **Redis** 節);Elasticsearch 為**唯讀**。
20
20
 
21
+ **環境與變更邊界:** 在 v2 中,選取具名連線前先執行 `dbcli use --list --format json`。
22
+ 標示 `environment: "production"` 的連線不得透過儲存的預設值靜默選取,必須明確指定;若要
23
+ 持久化 production 預設值,人類需以 `--confirm-production` 重複完全相同的名稱。當
24
+ `DBCLI_AGENT_MODE=1` 時,設定、權限與憑證變更一律封鎖。人類/管理員變更必須在關閉 agent
25
+ mode 的獨立 process 執行;不要把同一 process 的環境變數當作核准。受信任設定寫入會維護
26
+ integrity record,並在支援時設定安全檔案權限;agent 讀取遇到缺失、替換、非一般檔案或竄改的
27
+ record 時會 fail closed;agent mode 在完成 human/admin 遷移到 V2 home storage 前也會拒絕
28
+ legacy 單檔 `.dbcli`。若要防護同一 OS 使用者的惡意 process,host 可將
29
+ `DBCLI_CONFIG_INTEGRITY_ANCHOR_DIR` 設為受保護或唯讀掛載的 detached digest 目錄。
30
+
21
31
  **`update` / `delete` 的 `--where` 僅支援等式(SQL)。** 只接受 `col=val` 或
22
32
  `col1=v1 AND col2=v2`。比較 / 模式運算子(`>`、`>=`、`<`、`!=`、`LIKE`、`IN`)會直接
23
33
  **報錯**;更危險的是,`OR` 會被**靜默當成值的一部分** — `a=1 OR b=2` 會被解析成
@@ -191,7 +201,7 @@ dbcli init --system elasticsearch \
191
201
  ```bash
192
202
  dbcli init --conn-name staging --env-file .env.staging --permission query-only
193
203
  dbcli init --conn-name prod --env-file .env.production --use-env-refs --skip-test
194
- dbcli use --list # show all, * marks default
204
+ dbcli use --list --format json # 安全列出 name/env/permission/server/database
195
205
  dbcli use prod # switch default(會持久化 — 單次查詢別用)
196
206
  dbcli query --use staging "SELECT 1" # one-shot override on any subcommand
197
207
  DBCLI_CONNECTION=staging dbcli query "SELECT 1" # 單次指定,env 版;平行安全
@@ -200,6 +210,18 @@ dbcli init --rename staging:stg # rename
200
210
  dbcli init --remove stg # remove
201
211
  ```
202
212
 
213
+ 若要讓多個專案共用連線,請使用明確的 root-level `--global` scope。它會把 v2 registry 儲存在 `~/.config/dbcli/config.json`,不會建立或修改專案 binding:
214
+
215
+ ```bash
216
+ dbcli --global init --conn-name shared --system postgresql --host db.example.com \
217
+ --port 5432 --user app --password '<secret>' --name appdb \
218
+ --skip-test --no-interactive --force
219
+ dbcli --global use --list --format json
220
+ dbcli --global query "SELECT 1"
221
+ ```
222
+
223
+ `--global` 必須放在指令之前。未帶它時,指令仍使用目前專案的 `.dbcli` binding;全域與專案 registry 彼此獨立。
224
+
203
225
  每個命名連線的 schema cache 存於 `.dbcli/schemas/<connection>/`。在 `schema <table>` 前,每個連線都先跑一次 `dbcli schema --use <name>` — 否則 cache 可能回傳到別的連線欄位。`schema --refresh` / `--reset` 管理 cache(reference.md)。`--skip-test` 跳過 init 時的 TCP 連線測試;使用 `--use-env-refs` 時會自動隱含(`$env` refs 尚無值可連線)。`--system` 在 v2 中為選填 — 若省略,引擎會從 `--env-file` / `.env`(`DATABASE_URL` scheme)推斷,預設為 `postgresql`。
204
226
 
205
227
  ### env-refs(把機密排除在 `.dbcli` 之外)
@@ -251,6 +273,7 @@ dbcli init --conn-name prod --env-file .env.production --use-env-refs --skip-tes
251
273
  | `snapshot` | query-only+ | **(v1.25)** 僅 SQL。擷取結果指紋(`rowCount` + 每欄 null/distinct/min/max/sum + 順序無關 checksum)。`--out`(預設 `.dbcli/snapshots/snap-<ts>.json`)、`--rows`、`--stdout`、`--format`、`--no-limit`。作為 `assert --against` 的基準。 |
252
274
  | `assert` | query-only+ | **(v1.25)** 僅 SQL。驗證不變量;失敗時 exit 1,除非 `--no-fail`。`--expect "rows>0\|value==X\|col:c not null\|unique\|between a and b\|>= n"`、`--vs <query> --compare rows\|value`(對帳)、`--against <snapshot> --tolerance <pct>`。 |
253
275
  | `verification` | n/a | 檢視與管理本機驗證 artifact。`list` / `show <id-or-path>` / `summary` 為唯讀;`prune` 預設 dry-run,僅在 `--execute --force` 時刪除。讀取 `<cwd>/.dbcli/verification/`;不需 DB 連線,不寫入 audit log。 |
276
+ | `backfill artifact` | n/a | 將受限 JSON source catalog 產生可檢閱的 source-to-SQL 回填 artifact,包含 source/target identity、blacklist/schema preflight、read-back 驗證與 rollback hint;只產生 dry-run,絕不執行寫入。 |
254
277
  | `proxy` | n/a | **(v1.26)** 僅 MySQL/MariaDB/PostgreSQL。本地端開發觀測代理 — 中繼應用程式流量至真實資料庫,並將查詢 / 延遲 / 位元組 / 錯誤事件附加到 `.dbcli/proxy/events.jsonl`。子指令:`mysql` \| `mariadb` \| `postgresql`。`--listen`、`--target`、`--events`、`--slow-ms`(預設 `1000`)、`--redact none\|literals`。僅作觀測。**(v1.27)** `proxy analyze` 離線彙整事件 log 為 JSON / 文字報表(summary、byFingerprint 含 suggestedCommands、slowest、errors、hotTables、N+1)— 若無事件則報錯。 |
255
278
  | `status` | query-only+ | 安全 JSON / 文字摘要(不含憑證)。 |
256
279
  | `inspect` | query-only+ | 唯讀脈絡快照(連線、權限、blacklist、物件、snippets、建議指令,以及 **(v1.23)** 人類可讀 `hints`)。`--for-agent` / `--brief` / `--no-connect` / `--require-schema-cache`。支援 `--recovery`。 |
@@ -258,7 +281,7 @@ dbcli init --conn-name prod --env-file .env.production --use-env-refs --skip-tes
258
281
  | `guide` | query-only+ | 針對固定目標產出確定性下一步指令計畫(`slow-query`、`capacity`、`health`、`index-usage`、`permissions`、`schema-overview`)。`--list` 列舉所有目標。**(v1.23)** `guide missing-index-for <query>` 為單一 SELECT 建議複合索引(`--format yaml\|json\|markdown`、`--min-confidence`)。 |
259
282
  | `recovery` | n/a | 對已知錯誤代碼查詢結構化 `RecoveryEnvelope`(`--code <CODE>` 或 `--list`)。獨立合成器;不需真實失敗。 |
260
283
  | `recover` | n/a | 檢視(預設)或 `--apply` 執行 `.dbcli/last-recovery.json` 中自動儲存的復原計畫。`--allow-write=readonly-cmd\|write-cmd`、`--no-verify`、`--from <file>`、`--next --after-step <n> --result <json\|@file>` 多輪逐步執行。 |
261
- | `doctor` | n/a | 環境、設定、連線、SRV 診斷(Mongo)、schema cache 年齡。 |
284
+ | `doctor` | n/a | 環境/runtime identity、設定、連線、SRV 診斷(Mongo)、schema cache 年齡。`--format json --remediation` 僅輸出 blacklist/schema/bounded-sample 候選計畫(SQL:`dbcli plan` → 人工確認後的 bounded `dbcli query`;MongoDB/Elasticsearch:先以 `dbcli schema` 預檢,再由人工確認 bounded query),不會套用。 |
262
285
  | `completion` | n/a | bash / zsh / fish 腳本。 |
263
286
  | `upgrade` | n/a | 從 npm 自我更新;每個指令都帶 24h 快取的版本提示。 |
264
287
  | `shell` | (與 query 同) | 互動式 REPL。SQL 引擎、MongoDB 與 Redis(單行;`.no-limit on/off`)。**(v1.22)** Elasticsearch 開啟 Kibana Dev Tools 風格的 REPL(`<METHOD> /<path>` + 可選 JSON body,空白行送出)。 |
@@ -403,4 +426,4 @@ dbcli export "SELECT * FROM orders" --format html --output orders.html
403
426
  - 被 blacklist 的 table / column 會從查詢輸出中遮蔽。
404
427
  - `schema` 回報 `estimatedRowCount` 與 `sizeCategory`(small / medium / large / huge)。大 / 巨大表要加 `WHERE` 或 `LIMIT` — 分界值見 reference.md。
405
428
  - 對 `mongodb+srv://` 連線,`doctor` 會回報 SRV 是用原生解析或走 DoH fallback — 在執行環境限制 DNS 時很有用。
406
- - **全域旗標:** `--config <path>`、`--use <name>`、`-v` / `-vv` / `-q`、`--no-color`(也尊重 `NO_COLOR`)。
429
+ - **全域旗標:** `--version`、`--config <path>`、`--global`、`--use <name>`、`-v` / `--verbose` / `-vv`、`-q` / `--quiet`、`--no-color`(也尊重 `NO_COLOR`)。除非指令明確宣告 command-level 選項,否則 root-level 旗標必須放在指令之前。
@@ -4,6 +4,22 @@ Companion to [SKILL.md](SKILL.md). Exhaustive flags, copy-paste examples, `shell
4
4
 
5
5
  For cross-engine support status, see `docs/feature-matrix.md` in the repository.
6
6
 
7
+ ## Global options and placement
8
+
9
+ These options are available on the root `dbcli` command. Root-level options must
10
+ appear before the command path (for example, `dbcli --use prod status`). A
11
+ command-level option is only valid after the command that declares it.
12
+
13
+ | Option | Purpose |
14
+ |---|---|
15
+ | `--version` | Print the installed dbcli version. |
16
+ | `--no-color` | Disable colored output. |
17
+ | `-v, --verbose` | Increase logging verbosity; repeat for debug output. |
18
+ | `-q, --quiet` | Suppress non-essential output. |
19
+ | `--config <path>` | Select the `.dbcli` configuration path. |
20
+ | `--global` | Select the user-global registry at `~/.config/dbcli/config.json` instead of the current project's `.dbcli` config. Place it before the command path. |
21
+ | `--use <connection>` | Select a named connection for this invocation; place it before the command path unless that command explicitly lists a command-level `--use`. |
22
+
7
23
  ## Commands
8
24
 
9
25
  ### init
@@ -34,10 +50,18 @@ dbcli init --conn-name staging --env-file .env.staging # Named connection with
34
50
  dbcli init --conn-name prod --env-file .env.production --use-env-refs --skip-test
35
51
  dbcli init --remove staging # Remove a named connection
36
52
  dbcli init --rename staging:production # Rename a connection
53
+
54
+ # User-global registry (shared by projects; --global must precede the command)
55
+ dbcli --global init --conn-name shared --system postgresql --host db.example.com \
56
+ --port 5432 --user app --password '<secret>' --name appdb \
57
+ --skip-test --no-interactive --force
58
+ dbcli --global use --list
37
59
  ```
38
60
 
39
61
  **Key options:** `--system`, `--permission`, `--use-env-refs`, `--skip-test`, `--no-interactive`, `--force`, `--conn-name <name>`, `--env-file <path>`, `--remove <name>`, `--rename <old:new>`
40
62
 
63
+ **Environment-reference options:** `--env-host <var>`, `--env-port <var>`, `--env-user <var>`, `--env-password <var>`, `--env-database <var>`
64
+
41
65
  **MongoDB-specific options:** `--uri <uri>` (full connection URI), `--auth-source <db>` (auth database, default: `admin` when user/password set)
42
66
 
43
67
  **Elasticsearch-specific options:** `--cloud-id <id>` (Elastic Cloud), `--api-key <key>` (ApiKey auth). Other ES fields (`nodes[]`, `protocol`, `caPath`, `rejectUnauthorized`) can be edited directly in `.dbcli`.
@@ -46,6 +70,8 @@ dbcli init --rename staging:production # Rename a connection
46
70
 
47
71
  **Multi-connection:** Using `--conn-name` or `--env-file` creates a v2 config with named connections. Each connection can have its own env file and permission level. Existing v1 configs are automatically imported as the `default` connection when upgrading.
48
72
 
73
+ Use root-level `--global` with `init`, `use`, `status`, `query`, or any other command to read or mutate the user-global v2 registry at `~/.config/dbcli/config.json`. Without it, the current project binding remains the source of truth. The global registry uses the same private file mode and integrity record as project home storage.
74
+
49
75
  > **AI agent note on `--use-env-refs`:** If an existing `.dbcli` config contains `{"$env": "DB_HOST"}` style references, the connection values are read from environment variables at runtime. Do NOT re-run `init` to replace these references with actual values — the env-ref format is intentional for CI/CD and multi-environment setups.
50
76
 
51
77
  ### use
@@ -56,8 +82,20 @@ Switch or display the default database connection (v2 multi-connection config).
56
82
  dbcli use # Show current default connection
57
83
  dbcli use staging # Switch default to 'staging'
58
84
  dbcli use --list # List all connections (* marks default)
85
+ dbcli use --list --format json # Credential-free connection identity inventory
59
86
  ```
60
87
 
88
+ Each v2 named connection may include an optional non-secret `environment` label
89
+ (for example, `"environment": "production"`). JSON output is an object with a
90
+ `connections` array. Each item contains `name`, `environment` (a string or
91
+ `null`),
92
+ `permission`, `system`, `server` (`host` and `port`), `database`, and `isDefault`.
93
+ Environment-backed server and database fields are `null`; URI-only MongoDB and
94
+ Cloud ID-only Elasticsearch connections also return `null` instead of default
95
+ placeholders. It deliberately excludes user names, passwords, URIs, Cloud IDs,
96
+ API keys, and env variable names.
97
+ Misspelled selectors suggest nearby configured connection names.
98
+
61
99
  Any command can also use `--use <name>` to temporarily select a connection without changing the default:
62
100
 
63
101
  ```bash
@@ -67,6 +105,18 @@ dbcli list --use prod
67
105
 
68
106
  **Requires v2 config** (created with `dbcli init --conn-name`).
69
107
 
108
+ **Options:** `--list`, `--format <text|json>`, `--confirm-production <name>` (required when explicitly selecting a production connection as the default).
109
+
110
+ ### Agent configuration trust boundary
111
+
112
+ When `DBCLI_AGENT_MODE=1`, configuration, permission, and credential mutations
113
+ are rejected. Agent reads require the V2 directory config and its integrity
114
+ record; missing, replaced, non-regular, or tampered records fail closed. Legacy
115
+ single-file `.dbcli` configs must be migrated by a human/admin process with
116
+ agent mode disabled. A host that needs protection from a same-user hostile
117
+ process can set `DBCLI_CONFIG_INTEGRITY_ANCHOR_DIR` to a protected or read-only
118
+ directory; trusted writes publish detached digests there.
119
+
70
120
  ### list
71
121
 
72
122
  List all tables (SQL), collections (MongoDB), keys (Redis), or indices (Elasticsearch).
@@ -746,6 +796,7 @@ Manage sensitive data blacklist to prevent AI access to restricted tables/column
746
796
 
747
797
  ```bash
748
798
  dbcli blacklist list # Show current blacklist
799
+ dbcli blacklist list --format json # Stable machine-readable result
749
800
  dbcli blacklist table add payments # Block entire table
750
801
  dbcli blacklist table remove payments # Unblock table
751
802
  dbcli blacklist column add users.password # Block specific column
@@ -754,6 +805,11 @@ dbcli blacklist column remove users.password
754
805
 
755
806
  **Subcommands:** `list`, `table add <name>`, `table remove <name>`, `column add <table.column>`, `column remove <table.column>`
756
807
 
808
+ **`list` options:** `--config <path>`, `--format <text|json>` (default: `text`). JSON writes one
809
+ document to stdout: `{ "tables": string[], "columns": Record<string, string[]>, "warnings":
810
+ [{ "collection", "raw", "reason" }] }`. Invalid MongoDB blacklist patterns appear in `warnings`;
811
+ the JSON result is otherwise free of human headings and diagnostics.
812
+
757
813
  ### check
758
814
 
759
815
  Run data health checks on tables.
@@ -1079,7 +1135,7 @@ dbcli proxy mysql --listen 127.0.0.1:3307 --target 127.0.0.1:3306
1079
1135
  dbcli proxy postgresql --listen 127.0.0.1:5434 --target 127.0.0.1:5432
1080
1136
  dbcli proxy mysql --slow-ms 500 --redact literals # redact SQL literals in events
1081
1137
  dbcli proxy mariadb --events ./logs/proxy.jsonl # custom event file
1082
- dbcli proxy postgresql --use prod # infer target from named connection
1138
+ dbcli --use prod proxy postgresql # infer target from named connection
1083
1139
 
1084
1140
  dbcli proxy analyze # analyze .dbcli/proxy/events.jsonl (JSON)
1085
1141
  dbcli proxy analyze --format text --top 10 # human-readable top-10 view
@@ -1489,6 +1545,7 @@ Audit entries are metadata-only by design — never raw SQL bodies, `--param` va
1489
1545
  | `--all` | Merge entries across all connections; output is an envelope array `[{ connection, entry }, ...]` (D-39). | off (current connection only) |
1490
1546
  | `--for-agent` | Shortcut for `--format json --brief`. Single-connection JSON is a flat array; `--all` JSON is an envelope array. | off |
1491
1547
  | `--brief` | Drop large redaction fields from the entry; keep `ts / command / target / success` (D-33). | off |
1548
+ | `--no-brief` | Disable brief mode when a higher-level default enables it. | off |
1492
1549
  | `--format <fmt>` | `table` \| `json`. | `table` |
1493
1550
 
1494
1551
  Reader behavior (D-41): tail merges `<conn>.jsonl.1` (rotated segment, if present) and `<conn>.jsonl`, sorts by `ts` ascending, then takes the last `--n` entries — so `--n 1000` can span a fresh rotation boundary.
@@ -1506,6 +1563,7 @@ Examples:
1506
1563
  | `<id-prefix>` | Positional. UUID or prefix ≥ 4 characters; ambiguous prefix exits 1 with disambiguation hint; prefix < 4 chars exits 1. | — |
1507
1564
  | `--recovery-ref <id>` | Find the audit entry whose `recovery_ref` field matches this id (exact, not prefix). Mutually exclusive with positional `<id-prefix>` (D-38). | — |
1508
1565
  | `--all` | Search across all connections. Output is an envelope `{ connection, entry }` (single-hit also envelope, for shape stability — D-36). | off |
1566
+ | `--no-brief` | Disable brief mode when a higher-level default enables it. | off |
1509
1567
  | `--format <fmt>` | `table` \| `json`. | `table` |
1510
1568
 
1511
1569
  Examples:
@@ -1532,6 +1590,7 @@ Examples:
1532
1590
  | Flag | Purpose | Default |
1533
1591
  |---|---|---|
1534
1592
  | `--format <fmt>` | `table` \| `json`. | `table` |
1593
+ | `--no-brief` | Disable brief mode when a higher-level default enables it. | off |
1535
1594
 
1536
1595
  Output reports: writer enabled/disabled, last write result, file-lock state, rotation cap usage (`max_bytes` / `max_entries`). When `audit.enabled = false` (D1 opt-out), `tail` / `show` / `health` still exit 0 and print `Audit is disabled (audit.enabled = false in .dbcli). Use 'dbcli audit health' for details.` (E note).
1537
1596
 
@@ -1919,6 +1978,39 @@ includes `storageDir`, `dryRun`, `cutoff`, `criteria`, `protected`, `candidates`
1919
1978
 
1920
1979
  **Permission:** n/a
1921
1980
 
1981
+ ### backfill
1982
+
1983
+ Generate a bounded, reviewable source-to-SQL backfill artifact. The command is
1984
+ strictly dry-run: it reads a local JSON source catalog, records non-secret
1985
+ source/target connection identity, and never opens a database connection or
1986
+ executes generated SQL.
1987
+
1988
+ ```bash
1989
+ dbcli backfill artifact \
1990
+ --source ./backfill.json \
1991
+ --source-use staging \
1992
+ --target-use production
1993
+ dbcli backfill artifact --source ./backfill.json \
1994
+ --source-use staging --target-use production --stdout
1995
+ dbcli backfill artifact --source ./backfill.json \
1996
+ --source-use staging --target-use production --out .dbcli/backfills/review.json
1997
+ ```
1998
+
1999
+ The source catalog must contain `table`, non-empty `keyColumns`, `rows`, a
2000
+ read-only `verifyQuery`, and `expect`; no more than 1,000 rows are accepted.
2001
+ Identifiers are validated and row values are limited to JSON scalars. The
2002
+ target connection must be PostgreSQL, MySQL, or MariaDB (the source identity
2003
+ may describe another engine); target selectors in generated commands are
2004
+ shell-quoted. The artifact includes a SHA-256 source fingerprint, generated parameterized
2005
+ `UPDATE` statements with per-statement `plan` commands, blacklist/schema
2006
+ preflight commands, a `verify safe-backfill` read-back command, identity
2007
+ differences, and a rollback hint. `execution.mode` is always `dry-run` and
2008
+ `requiresHumanConfirmation` is always true; applying SQL is a separate,
2009
+ explicit human-reviewed workflow.
2010
+
2011
+ **Options:** `--source <path>` (required), `--source-use <name>` (required),
2012
+ `--target-use <name>` (required), `--stdout`, `--out <path>`
2013
+
1922
2014
  ### doctor
1923
2015
 
1924
2016
  Run diagnostic checks on environment, configuration, connection, and data.
@@ -1936,7 +2028,13 @@ dbcli doctor --format json # JSON output for AI agents
1936
2028
  > **MongoDB SRV diagnostics:** When the active connection uses `mongodb+srv://`, `doctor` reports whether the current runtime can resolve SRV records directly or only through the DNS-over-HTTPS fallback used by dbcli. This helps spot execution-environment DNS restrictions even when Compass can connect.
1937
2029
 
1938
2030
  **Exit code:** 0 if all pass or warnings only, 1 if any error
1939
- **Options:** `--format <text|json>`
2031
+ **Options:** `--format <text|json>`, `--remediation`
2032
+
2033
+ With `--format json --remediation`, large-table warnings include one bounded
2034
+ sample candidate per table. SQL candidates first run `dbcli plan` for a `LIMIT
2035
+ 100` read; MongoDB and Elasticsearch candidates first run `dbcli schema` as a
2036
+ preflight. Each then offers a matching bounded `dbcli query` as the
2037
+ human-confirmed apply step; doctor never runs either command automatically.
1940
2038
 
1941
2039
  ### completion
1942
2040
 
@@ -57,15 +57,26 @@ function trimAppliedLimit(rows, limit) {
57
57
  };
58
58
  }
59
59
  // src/agent-core/connection-selector.ts
60
+ function normalizeSelector(value, source) {
61
+ if (value === undefined)
62
+ return;
63
+ const normalized = value.trim();
64
+ if (normalized === "") {
65
+ throw new Error(`${source} connection selector cannot be empty`);
66
+ }
67
+ return normalized;
68
+ }
60
69
  function resolveConnectionSelector(inputs) {
61
- if (inputs.root !== undefined && inputs.command !== undefined && inputs.root !== inputs.command) {
62
- throw new Error(`Conflicting connection selectors: root value '${inputs.root}' does not match command value '${inputs.command}'`);
70
+ const root = normalizeSelector(inputs.root, "Root");
71
+ const command = normalizeSelector(inputs.command, "Command");
72
+ if (root !== undefined && command !== undefined && root !== command) {
73
+ throw new Error(`Conflicting connection selectors: root value '${root}' does not match command value '${command}'`);
63
74
  }
64
- const explicit = inputs.command ?? inputs.root;
75
+ const explicit = command ?? root;
65
76
  if (explicit !== undefined)
66
77
  return explicit;
67
78
  const environment = inputs.environment?.trim();
68
- return environment ? environment : undefined;
79
+ return environment || undefined;
69
80
  }
70
81
  function parseConnectionNames(selector) {
71
82
  const names = selector.split(",").map((name) => name.trim());