@carllee1983/dbcli 1.41.0 → 1.43.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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,55 @@ All notable changes to dbcli are documented here.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.43.0] - 2026-08-02 - Agent Core、查詢完整性與跨平台修復
9
+
10
+ ### Added
11
+
12
+ - **穩定的 `./agent-core` 子路徑匯出。** 以五個 runtime functions(env 載入、env reference、連線選取、名稱解析、lookahead 截斷)與三個型別形成 agent CLI 共用的 semver interface;`./core` 仍是 dbcli 專用介面。建置同時產出 ESM 與型別宣告,CI purity gate 禁止資料庫、adapter 或 CLI framework 相依滲入。
13
+ - **欄位投影 `--fields`。** SQL 與 MongoDB 通用;`--fields a,b` 取用、`--fields=-raw_response` 排除,兩種形式不可混用。MongoDB 會把 `projection`(find)或 `$project`(aggregate)下推給 driver,未明確指定時不回傳 `_id`。黑名單欄位不會因為被 `--fields` 點名而洩漏。
14
+ - **欄位值截斷 `--truncate`。** table 輸出預設在 120 個 Unicode code point 截斷並標記 `…(+N chars)`,以 code point 計數所以不會切壞中文與 emoji;`--no-truncate` 可關閉。`--format json` / `csv` 會拒絕此旗標而非靜默忽略。
15
+ - **從檔案或 stdin 讀查詢 `-f, --query-file`。** `-f -` 讀 stdin,可用 heredoc 傳含 `$regex`、巢狀日期物件的 MongoDB pipeline,完全避開 shell 引號問題。同時給檔案與位置參數會明確報錯。
16
+ - **單次連線指定。** 新增 `DBCLI_CONNECTION` 環境變數,`query` / `list` / `schema` / `export` / `check` 也接受子指令層級的 `--use`。優先序為 `--use` > `DBCLI_CONNECTION` > 儲存的預設值,兩者都不會改寫 `.dbcli/config.json`,因此平行執行不會互相污染。
17
+ - **唯讀多連線扇出 `--use a,b`。** 同一查詢對多個連線執行,JSON 回傳 `results` 陣列並逐一標示 `ok` / `error`,table 則分段標註連線名。單一連線失敗不會取消其他連線。彙總 exit code:全成功 `0`、部分失敗 `2`、全失敗或執行前拒絕 `1`。寫入語句、`--recovery`、`--ui` 與 CSV/HTML 輸出在扇出下一律拒絕。
18
+
19
+ ### Changed
20
+
21
+ - **HTML dashboard 明示不完整與遮蔽結果。** `query`、`q` 與 HTML export 會把既有的截斷與 security metadata 傳入 dashboard;在 KPI、圖表與 raw table 之前顯示醒目提示,避免使用不完整資料得出結論。
22
+ - **截斷改為出現在結果本身。** dbcli 擁有的 row cap 會多取一列前瞻,因此能區分「剛好 N 筆」與「被砍到 N 筆」:table footer 顯示 `Rows: N (truncated; limit N)`、`--format json` 帶 `metadata.truncated` 與 `metadata.limit_applied`、CSV 附加 `# truncated; limit N` 註解行。`dbcli q` 的 snippet size guard 同樣依此回報,不再讓整數列數被誤讀為全集。
23
+ - **`dbcli export` 撞到 auto-limit 改為 fail closed。** 匯出檔沒有地方記錄資料被丟掉(jsonl 是一行一筆、MongoDB `--format json` 是裸陣列),stderr 警告又會在重導向後消失,因此改為 exit `1` 且不寫檔,要求以 `--no-limit` 或 `--limit N` 明確表態。Elasticsearch 匯出的 1000 筆上限同此處理。
24
+ - **CLI 錯誤輸出收斂。** 連線類錯誤在所有指令路徑都會被頂層 handler 攔截並格式化,stderr 首行即為人類可讀訊息,不再由 Bun 印出打包後的 code frame 與未解碼的中文跳脫序列。stack 改掛在 `-v` / `-vv` 之下,預設不輸出。
25
+
26
+ ### Fixed
27
+
28
+ - **MySQL 8 schema introspection 相容預設 `ONLY_FULL_GROUP_BY`。** 外鍵查詢現在完整分組 referenced table,不再讓 `dbcli schema <table>` 在原廠預設設定下失敗。
29
+ - **已分類的連線錯誤不再被巢狀 adapter catch 重包。** `mapError` 直接保留既有 `ConnectionError` 的 identity、code、message 與 hints,消除 `Connection failed: Connection failed:` 重複前綴與分類退化。
30
+ - **stdout 管線與 Windows CI 修復。** redirected stdout 以完整同步寫入避免 64KB 截斷;測試 filesystem 與換行處理改為跨平台實作,Windows matrix 恢復全綠。
31
+ - **發布依賴安全更新。** 將 PostCSS 鎖定至 `8.5.25`、`brace-expansion` 鎖定至 `5.0.9`,清除 release gate 回報的 3 個 high-severity advisories;並統一 Prettier 格式,讓完整 9 階段發布檢查恢復全綠。
32
+ - **`--no-limit` 過去被靜默忽略。** Commander 會把 `--no-limit` 折進 `limit` 屬性(設為 `false`)而不會產生 `noLimit`,但 `query` / `q` / `export` 都讀 `options.noLimit`,導致這個旗標自始無效——`query` 仍套用 1000 筆上限,`q` 仍包 size guard。CLI 邊界現在會把 Commander 的否定形式轉回指令實際讀取的形狀。
33
+ - **`dbcli export` 的 SQL 路徑忽略 `--limit` 與 `--no-limit`。** 該分支未把選項傳給 QueryExecutor,任何 `--limit N` 都不生效。
34
+ - **`-v` / `-vv` 的 stack 開關過去對 `q` / `insert` / `update` / `delete` 無效。** 這四個指令自行輸出在地化訊息、繞過共用的錯誤呈現層,因此 verbose 對它們不會多印任何東西。改為共用同一個呈現函式:措辭維持不變,但 verbose 下會補上 stack。
35
+ - **Redis 的 size-guard warning 在 `query` 被丟棄。** adapter 早已算出 `REDIS_SIZE_TRUNCATE` / `REDIS_SIZE_REWRITE` / `REDIS_BLACKLIST_FILTERED`,但 `query` 分支完全沒讀 `result.warnings`——文件卻聲稱結果會帶 `warnings[]`。現在每則 warning 都會印到 stderr,且被裁切的回覆會回報 `truncated` / `limit_applied`,與其他引擎一致。
36
+ - **`--query-file -` 在互動式終端會無提示空等。** 改為立即拒絕並說明需要 piped input,與 repo 中其他 stdin 消費端(`insert`、`shell`、`audit`)既有的 TTY 檢查一致。
37
+ - **單一連線 (v1) 設定會靜默忽略 `--use` / `DBCLI_CONNECTION`。** v1 沒有具名連線可選,過去卻照樣執行那唯一的連線,讓使用者以為切換成功——正是 issue #7 要避免的情境。現在會明確報錯並指出升級為 v2 的方式。
38
+ - **skill assets 與 reference 補齊。** `assets/SKILL.md`、`SKILL.zh-TW.md` 與 `reference.md` 新增查詢工作流程旗標章節;`reference.md` 原本記載「MongoDB 不套用 auto-limit」與實際行為不符,已更正為套用於 filter 與未自帶 `$limit` 的 pipeline。
39
+
40
+ ## [1.42.0] - 2026-07-20 - Drizzle Snapshot 與 ORM DDL 工作流擴充
41
+
42
+ ### Added
43
+
44
+ - **Drizzle Kit snapshot 可直接用於 ORM drift 比對。** `dbcli diff --against-orm` 新增 Drizzle snapshot 格式偵測與 `NormalizedSchema` adapter,支援 PostgreSQL v7 snapshot 的 table、column、primary key、unique constraint、index 與 foreign key metadata。
45
+ - **TypeORM/Sequelize DDL alias。** `--orm-format typeorm`、`typeorm-ddl`、`sequelize` 與 `sequelize-ddl` 可直接走既有 DDL adapter;自動忽略 `typeorm_metadata` 與 `SequelizeMeta` bookkeeping table,並補上 source-file 使用者的可執行匯出/比對指引。
46
+
47
+ ### Changed
48
+
49
+ - **ORM drift 文件完整同步。** 英文/繁體中文的 Markdown 與 HTML 使用者文件、skill assets、各平台 plugin 副本及 reference 已補上 Drizzle snapshot、TypeORM/Sequelize DDL 的格式、限制與操作範例。
50
+ - **跨平台發版 metadata 對齊。** npm package、Codex/Claude/Cursor plugin、packaged Codex plugin 與 Gemini extension 統一為 `1.42.0`。
51
+
52
+ ### Fixed
53
+
54
+ - **不支援的 ORM 輸入改為 fail closed。** Drizzle snapshot 會拒絕不支援的版本/dialect、generated/identity/enum/composite primary key 等結構,以及無法無損轉換的 column default;TypeORM/Sequelize source file 則回報完整的匯出 DDL recipe,不再被 JSON/DDL fallback 誤解析。
55
+ - **Qualified ignore identity 保留完整。** ORM drift 的 ignore 比對不再把 schema-qualified identity 降成 bare table name,避免同名 table 跨 schema 時被錯誤忽略;ORM DDL alias 也會正確沿用 DDL 輸入處理與 bookkeeping ignore。
56
+
8
57
  ## [1.41.0] - 2026-07-19 - ORM Drift 比對與無損 Schema Identity
9
58
 
10
59
  ### Added
package/README.dev.md CHANGED
@@ -42,7 +42,7 @@ Before running `npm publish`:
42
42
  ```bash
43
43
  npm pack --dry-run
44
44
  ```
45
- Expect **`dist/`** (at least `cli.mjs`), **`assets/`** (e.g. `SKILL.md`, `reference.md` for `dbcli skill`), **`README.md`**, **`CHANGELOG.md`**, **`LICENSE`**, and **`package.json`**. There must be **no** `src/`, `tests/`, or `node_modules/`. The listing may also include other root `README*.md` files (npm can still pack them even when `files` is set); dev-only readmes are listed in **`.npmignore`** — re-check with dry-run if you add or remove docs.
45
+ Expect **`dist/`** (including `cli.mjs`, `core.mjs` / `core.d.ts`, and `agent-core.mjs` / `agent-core.d.ts`), **`assets/`** (e.g. `SKILL.md`, `reference.md` for `dbcli skill`), **`README.md`**, **`CHANGELOG.md`**, **`LICENSE`**, and **`package.json`**. There must be **no** `src/`, `tests/`, or `node_modules/`. The listing may also include other root `README*.md` files (npm can still pack them even when `files` is set); dev-only readmes are listed in **`.npmignore`** — re-check with dry-run if you add or remove docs.
46
46
 
47
47
  5. **Check package size:**
48
48
  ```bash
package/README.md CHANGED
@@ -149,8 +149,9 @@ dbcli export "SELECT * FROM users" --format html --output report.html
149
149
  `dbcli` can render query results as fully interactive, standalone HTML dashboards. These reports are powered by React + Recharts and are zero-dependency — the entire application and data are inlined into a single HTML file.
150
150
 
151
151
  - **`--ui` flag**: Automatically generates a temporary report and opens it in your default browser.
152
- - **`visual:` block**: Snippet frontmatter can define KPIs and charts (Line, Bar, Area, Pie, Scatter) to drive the dashboard.
152
+ - **`visual:` block**: Snippet frontmatter can define KPIs and charts (Line, Bar, Area, Pie) to drive the dashboard.
153
153
  - **Security**: Result sets are redacted by the blacklist before injection, and data is safely escaped for HTML.
154
+ - **Completeness warnings**: Truncation and security metadata are shown before KPIs, charts, and the raw table so incomplete or masked data is never presented as a complete result.
154
155
 
155
156
  ### Recovery & Guided Remediation
156
157
 
@@ -291,7 +292,7 @@ dbcli init --rename staging:production
291
292
 
292
293
  ### Using a Specific Connection Temporarily
293
294
 
294
- You can use the `--use <name>` global flag to execute any command against a specific connection without changing the default.
295
+ You can use the `--use <name>` global flag, the supported command-level form, or `DBCLI_CONNECTION` to execute against a specific connection without changing the default. Selection precedence is explicit `--use`, then `DBCLI_CONNECTION`, then the configured default. A selector is rejected for legacy v1 single-connection configuration instead of being silently ignored.
295
296
 
296
297
  ```bash
297
298
  # Query the production database once
@@ -299,8 +300,21 @@ dbcli query "SELECT count(*) FROM users" --use prod
299
300
 
300
301
  # Check staging table health
301
302
  dbcli check users --use staging
303
+
304
+ # Select one connection for this process
305
+ DBCLI_CONNECTION=prod dbcli query "SELECT count(*) FROM users"
302
306
  ```
303
307
 
308
+ `query`, `schema`, `list`, `export`, and `check` accept the command-level `--use` form shown above. Other commands use the global form before the subcommand.
309
+
310
+ For read-only comparisons, an explicit comma-separated `--use` fans one query out to multiple named connections:
311
+
312
+ ```bash
313
+ dbcli query --use primary,staging "SELECT count(*) FROM users" --format json
314
+ ```
315
+
316
+ SQL fan-out permits `SELECT`, `SHOW`, `DESCRIBE`, and `EXPLAIN`; MongoDB permits filters and read-only pipelines; Elasticsearch permits search. Redis, writes, `--recovery`, `--ui`, CSV, and HTML are rejected. Connections run independently: JSON returns an ordered `results` array, table output labels each section, and one failure does not cancel the others. Exit codes are `0` for all success, `2` for mixed outcomes, and `1` for all failures or a preflight rejection. `DBCLI_CONNECTION` always names one literal connection and never enables fan-out.
317
+
304
318
  ---
305
319
 
306
320
 
@@ -453,24 +467,33 @@ dbcli schema
453
467
 
454
468
  ---
455
469
 
456
- #### `dbcli query "SQL"`
470
+ #### `dbcli query [query]`
457
471
 
458
- Execute SQL query and return results.
472
+ Execute a SQL statement, MongoDB filter/pipeline, allow-listed Redis command, or Elasticsearch DSL/Lucene query and return results.
459
473
 
460
474
  **Usage:**
461
475
  ```bash
462
476
  dbcli query "SELECT * FROM users"
477
+ dbcli query --query-file ./queries/active-users.sql
463
478
  ```
464
479
 
465
480
  **Options:**
466
- - `--format json|table|csv` — Output format (default: table)
481
+ - `--format json|table|csv|html` — Output format (default: table)
482
+ - `--ui` — Render HTML to a temporary file and open it in the system browser
467
483
  - `--limit <number>` — Cap rows (overrides the automatic limit in query-only mode)
468
484
  - `--no-limit` — Disable the automatic 1000-row cap in query-only mode
485
+ - `-f, --query-file <path>` — Read a UTF-8 query from a file; use `-` for piped stdin
486
+ - `--fields <list>` — Include `a,b` or exclude `-a,-b` fields from SQL/MongoDB results
487
+ - `--truncate <number>` — Set the table cell limit in Unicode code points (default: 120)
488
+ - `--no-truncate` — Show complete table cells
469
489
 
470
490
  **Behavior:**
471
491
  - Enforces permission-based restrictions (Query-only mode blocks INSERT/UPDATE/DELETE)
472
- - Auto-limits results to 1000 rows in Query-only mode (notification shown), unless `--no-limit` or `--limit` applies
473
- - Returns structured results with metadata (row count, execution time)
492
+ - Requires exactly one query source: positional text, `--query-file <path>`, or piped stdin through `--query-file -`
493
+ - Auto-limits results to 1000 rows in Query-only mode, unless `--no-limit` or `--limit` applies
494
+ - Uses a one-row lookahead for dbcli-owned limits. Truncated tables say so in the footer, JSON returns `metadata.truncated` and `metadata.limit_applied`, and CSV appends a truncation comment
495
+ - Applies `--fields` after SQL execution and pushes it into MongoDB find/pipeline operations. Blacklist masking remains authoritative
496
+ - Truncates table cells only; JSON and CSV rows remain lossless. Explicit truncation flags with JSON, CSV, HTML, or `--ui` are rejected
474
497
  - To write CSV/JSON to a file, use shell redirection or the `export` command
475
498
 
476
499
  **Examples:**
@@ -489,6 +512,17 @@ dbcli query "SELECT * FROM products" --format json | jq '.data[] | .name'
489
512
 
490
513
  # Large result sets (paginate with LIMIT/OFFSET)
491
514
  dbcli query "SELECT * FROM users LIMIT 100 OFFSET 0"
515
+
516
+ # Multiline SQL from stdin
517
+ dbcli query --query-file - <<'SQL'
518
+ SELECT id, email
519
+ FROM users
520
+ WHERE status = 'active';
521
+ SQL
522
+
523
+ # Include or exclude fields (use = when the value starts with a hyphen)
524
+ dbcli query "SELECT * FROM users" --fields id,email,status
525
+ dbcli query "SELECT * FROM users" --fields=-password_hash,-raw_payload
492
526
  ```
493
527
 
494
528
  ---
@@ -598,9 +632,12 @@ dbcli export "SELECT * FROM users" --format json --output users.json
598
632
  **Options:**
599
633
  - `--format json|csv` — Output format
600
634
  - `--output file` — Write to file (default: stdout for piping)
635
+ - `--limit <number>` — Deliberately accept a bounded export
636
+ - `--no-limit` — Export the complete result
601
637
 
602
638
  **Behavior:**
603
- - Query-only permission limited to 1000 rows per export
639
+ - Query-only mode still applies its automatic 1000-row limit, but reaching it fails closed with exit code `1` and writes no partial file
640
+ - Re-run with `--no-limit` for the complete export or `--limit N` to accept a cap explicitly
604
641
  - Generates RFC 4180 compliant CSV
605
642
  - Creates well-formed JSON arrays
606
643
 
@@ -754,19 +791,24 @@ dbcli check --all --checks nulls,duplicates --format json
754
791
 
755
792
  #### `dbcli diff`
756
793
 
757
- Save a schema snapshot or compare the live database to a previous snapshot (tables, columns, indexes).
794
+ Save a schema snapshot, compare the live database to a previous snapshot, or compare an ORM definition with the local SQL schema cache. ORM drift is cache-only: it does not connect, refresh the cache, or execute proposals.
758
795
 
759
796
  **Usage:**
760
797
  ```bash
761
798
  dbcli diff --snapshot ./schema-before.json
762
799
  dbcli diff --against ./schema-before.json
763
800
  dbcli diff --against ./schema-before.json --format table
801
+ dbcli diff --against-orm prisma/schema.prisma --format json
802
+ dbcli diff --against-orm drizzle/meta/0001_snapshot.json --orm-format drizzle --format table
803
+ dbcli diff --against-orm schema.sql --orm-format typeorm --format table
764
804
  ```
765
805
 
766
806
  **Options:**
767
807
  - `--snapshot <path>` — Write the current schema to a JSON file
768
808
  - `--against <path>` — Diff live schema vs. the saved snapshot
769
- - `--format json|table`Output format (default: `json`)
809
+ - `--against-orm <path>`Compare Prisma, Drizzle snapshot, TypeORM/Sequelize DDL, raw DDL, or normalized JSON with the cached SQL schema
810
+ - `--orm-format prisma|drizzle|typeorm|sequelize|ddl|json` — Override ORM input detection
811
+ - `--format json|table|markdown` — Output format (default: `json`)
770
812
  - `--config <path>` — Config path (default: `.dbcli`)
771
813
 
772
814
  ---
@@ -983,6 +1025,12 @@ dbcli migrate drop-enum status --execute --force
983
1025
 
984
1026
  ## Query Risk Planning
985
1027
 
1028
+ Use `lint` for read-only static advice about SQL anti-patterns and optional rewrite drafts. It accepts inline SQL, saved queries, files, globs, and bulk input; it never connects or applies a rewrite:
1029
+
1030
+ ```bash
1031
+ dbcli lint "SELECT * FROM users WHERE LOWER(email) = 'a@example.com'" --format json
1032
+ ```
1033
+
986
1034
  Use `plan` to inspect SQL safety before execution. It reads local dbcli config, permissions, blacklist rules, and cached schema metadata only; it does not connect to the database.
987
1035
 
988
1036
  ```bash
@@ -1596,6 +1644,20 @@ chmod +x dist/cli.mjs
1596
1644
 
1597
1645
  ## Development
1598
1646
 
1647
+ Package consumers building agent CLIs can import the semver-stable, database-independent interface from `@carllee1983/dbcli/agent-core`:
1648
+
1649
+ ```ts
1650
+ import {
1651
+ loadEnvFile,
1652
+ parseConnectionNames,
1653
+ resolveConnectionSelector,
1654
+ resolveEnvRef,
1655
+ trimAppliedLimit,
1656
+ } from '@carllee1983/dbcli/agent-core'
1657
+ ```
1658
+
1659
+ The broader `@carllee1983/dbcli/core` interface remains dbcli-specific. CLI option factories, config-storage binding, and connection-string parsing are intentionally outside `agent-core`.
1660
+
1599
1661
  ```bash
1600
1662
  bun test # full test suite (Bun test runner)
1601
1663
  bun run typecheck # TypeScript compile-time validation
package/README.zh-TW.md CHANGED
@@ -134,8 +134,9 @@ dbcli export "SELECT * FROM users" --format html --output report.html
134
134
  `dbcli` 可將查詢結果算繪為完全互動、獨立的 HTML 儀表板。這些報表由 React + Recharts 驅動且具備「零依賴」特性 — 整個應用程式與資料皆被內嵌於單一 HTML 檔案中。
135
135
 
136
136
  - **`--ui` 旗標**:自動產生暫時性報表並在預設瀏覽器中開啟。
137
- - **`visual:` 區塊**:可在查詢片段的 frontmatter 中定義 KPI 與圖表 (Line, Bar, Area, Pie, Scatter)。
137
+ - **`visual:` 區塊**:可在查詢片段的 frontmatter 中定義 KPI 與圖表 (Line, Bar, Area, Pie)。
138
138
  - **安全性**:資料在注入前會先經過黑名單過濾,且針對 HTML 進行了安全跳脫處理。
139
+ - **完整性警示**:KPI、圖表與 raw table 之前會先顯示截斷與 security metadata,避免把不完整或已遮蔽的資料誤認為完整結果。
139
140
 
140
141
  ---
141
142
 
@@ -189,14 +190,25 @@ dbcli init --rename staging:production # 更名(格式:舊名:新名)
189
190
 
190
191
  ### 臨時指定連線(不改預設)
191
192
 
192
- 任何子指令皆可加全域 **`--use <名稱>`**,僅本次使用該連線:
193
+ 可使用全域 **`--use <名稱>`**、支援的指令層級寫法或 `DBCLI_CONNECTION`,僅本次使用指定連線而不改預設。選擇優先序為明確的 `--use`、`DBCLI_CONNECTION`、最後才是設定檔預設連線。舊版 v1 單連線設定沒有具名連線可選,因此 selector 會被明確拒絕,不會遭到靜默忽略。
193
194
 
194
195
  ```bash
195
196
  dbcli query "SELECT count(*) FROM users" --use prod
196
197
  dbcli check users --use staging
197
198
  dbcli list --use prod
199
+ DBCLI_CONNECTION=prod dbcli query "SELECT count(*) FROM users"
198
200
  ```
199
201
 
202
+ `query`、`schema`、`list`、`export`、`check` 支援上面的指令層級 `--use`;其他指令請將全域 selector 放在子指令之前。
203
+
204
+ 若要比較多個環境,可透過明確的逗號分隔 `--use`,將同一個唯讀 query 扇出至多個具名連線:
205
+
206
+ ```bash
207
+ dbcli query --use primary,staging "SELECT count(*) FROM users" --format json
208
+ ```
209
+
210
+ SQL fan-out 允許 `SELECT`、`SHOW`、`DESCRIBE`、`EXPLAIN`;MongoDB 允許 filter 與唯讀 pipeline;Elasticsearch 允許 search。Redis、寫入、`--recovery`、`--ui`、CSV 與 HTML 都會被拒絕。各連線獨立執行:JSON 依序回傳 `results` array,table 為每個連線標示區段,單一失敗不會取消其他連線。全部成功 exit `0`、混合結果 exit `2`、全部失敗或 preflight 拒絕 exit `1`。`DBCLI_CONNECTION` 永遠代表單一完整連線名稱,不會啟用 fan-out。
211
+
200
212
  若同時需要自訂設定路徑,可與 **`--config <路徑>`** 併用(仍指向含 `config.json` 的 `.dbcli` 目錄)。
201
213
 
202
214
  ---
@@ -351,24 +363,33 @@ dbcli schema
351
363
 
352
364
  ---
353
365
 
354
- #### `dbcli query "SQL"`
366
+ #### `dbcli query [query]`
355
367
 
356
- 執行 SQL 查詢並回傳結果。
368
+ 執行 SQL statement、MongoDB filter/pipeline、allow-listed Redis command 或 Elasticsearch DSL/Lucene query 並回傳結果。
357
369
 
358
370
  **用法:**
359
371
  ```bash
360
372
  dbcli query "SELECT * FROM users"
373
+ dbcli query --query-file ./queries/active-users.sql
361
374
  ```
362
375
 
363
376
  **選項:**
364
- - `--format json|table|csv` — 輸出格式(預設:table)
377
+ - `--format json|table|csv|html` — 輸出格式(預設:table)
378
+ - `--ui` — 將 HTML 算繪至暫存檔並在系統瀏覽器開啟
365
379
  - `--limit <數字>` — 限制列數(覆寫 query-only 下的自動上限)
366
380
  - `--no-limit` — 在 query-only 模式下關閉自動 1000 列上限
381
+ - `-f, --query-file <路徑>` — 從 UTF-8 檔案讀取 query;以 `-` 讀取 piped stdin
382
+ - `--fields <清單>` — 在 SQL/MongoDB 結果中納入 `a,b` 或排除 `-a,-b` 欄位
383
+ - `--truncate <數字>` — 設定 table cell 的 Unicode code point 上限(預設 120)
384
+ - `--no-truncate` — 顯示完整 table cell
367
385
 
368
386
  **行為:**
369
387
  - 依權限限制操作(Query-only 會阻擋 INSERT/UPDATE/DELETE)
370
- - Query-only 模式預設自動限制最多 1000 列(並顯示提示),除非使用 `--no-limit` `--limit`
371
- - 回傳含中繼資料的結構化結果(列數、執行時間等)
388
+ - 必須且只能指定一種 query 來源:positional 文字、`--query-file <路徑>`,或透過 `--query-file -` 傳入 piped stdin
389
+ - Query-only 模式預設自動限制最多 1000 列,除非使用 `--no-limit` 或 `--limit`
390
+ - dbcli 自己套用上限時會多取一列 lookahead;截斷的 table footer 會明示,JSON 回傳 `metadata.truncated` 與 `metadata.limit_applied`,CSV 則附加截斷註解
391
+ - SQL 執行後套用 `--fields`,MongoDB 則下推至 find/pipeline;blacklist masking 仍是最終權限邊界
392
+ - 只截斷 table cell;JSON 與 CSV rows 維持無損。JSON、CSV、HTML 或 `--ui` 若明確給定截斷旗標會被拒絕
372
393
  - 若要將 CSV/JSON 寫入檔案,請用 shell 重新導向或 `export` 指令
373
394
 
374
395
  **範例:**
@@ -387,6 +408,17 @@ dbcli query "SELECT * FROM products" --format json | jq '.data[] | .name'
387
408
 
388
409
  # 大量結果(以 LIMIT/OFFSET 分頁)
389
410
  dbcli query "SELECT * FROM users LIMIT 100 OFFSET 0"
411
+
412
+ # 從 stdin 傳入多行 SQL
413
+ dbcli query --query-file - <<'SQL'
414
+ SELECT id, email
415
+ FROM users
416
+ WHERE status = 'active';
417
+ SQL
418
+
419
+ # 納入或排除欄位(值以 hyphen 開頭時使用 =)
420
+ dbcli query "SELECT * FROM users" --fields id,email,status
421
+ dbcli query "SELECT * FROM users" --fields=-password_hash,-raw_payload
390
422
  ```
391
423
 
392
424
  ---
@@ -496,9 +528,12 @@ dbcli export "SELECT * FROM users" --format json --output users.json
496
528
  **選項:**
497
529
  - `--format json|csv` — 輸出格式
498
530
  - `--output file` — 寫入檔案(預設 stdout 供管道使用)
531
+ - `--limit <數字>` — 明確接受有界匯出
532
+ - `--no-limit` — 匯出完整結果
499
533
 
500
534
  **行為:**
501
- - Query-only 權限下每次匯出最多 1000
535
+ - Query-only 模式仍會套用自動 1000 列上限,但真的撞到上限時會 fail closed,以 exit code `1` 結束且不寫入不完整檔案
536
+ - 使用 `--no-limit` 匯出完整結果,或用 `--limit N` 明確接受上限
502
537
  - 產生符合 RFC 4180 的 CSV
503
538
  - 產生結構良好的 JSON 陣列
504
539
 
@@ -652,19 +687,24 @@ dbcli check --all --checks nulls,duplicates --format json
652
687
 
653
688
  #### `dbcli diff`
654
689
 
655
- 儲存 schema 快照,或將目前資料庫與先前快照比對(表、欄位、索引)。
690
+ 儲存 schema 快照、將目前資料庫與先前快照比對,或把 ORM 定義與本地 SQL schema cache 比對。ORM drift 只讀 cache:不連線、不更新 cache,也不執行提案。
656
691
 
657
692
  **用法:**
658
693
  ```bash
659
694
  dbcli diff --snapshot ./schema-before.json
660
695
  dbcli diff --against ./schema-before.json
661
696
  dbcli diff --against ./schema-before.json --format table
697
+ dbcli diff --against-orm prisma/schema.prisma --format json
698
+ dbcli diff --against-orm drizzle/meta/0001_snapshot.json --orm-format drizzle --format table
699
+ dbcli diff --against-orm schema.sql --orm-format typeorm --format table
662
700
  ```
663
701
 
664
702
  **選項:**
665
703
  - `--snapshot <path>` — 將目前 schema 寫入 JSON 檔
666
704
  - `--against <path>` — 與已存快照比對差異
667
- - `--format json|table`輸出格式(預設:`json`)
705
+ - `--against-orm <path>`將 Prisma、Drizzle snapshot、TypeORM/Sequelize DDL、raw DDL 或 normalized JSON 與 SQL schema cache 比對
706
+ - `--orm-format prisma|drizzle|typeorm|sequelize|ddl|json` — 覆寫 ORM 輸入格式偵測
707
+ - `--format json|table|markdown` — 輸出格式(預設:`json`)
668
708
  - `--config <path>` — 設定路徑(預設:`.dbcli`)
669
709
 
670
710
  ---
@@ -881,6 +921,12 @@ dbcli migrate drop-enum status --execute --force
881
921
 
882
922
  ## 查詢風險規劃
883
923
 
924
+ 使用 `lint` 對 SQL anti-pattern 與可選 rewrite draft 做唯讀靜態分析。支援 inline SQL、saved query、檔案、glob 與 bulk input;不會連線,也不會套用 rewrite:
925
+
926
+ ```bash
927
+ dbcli lint "SELECT * FROM users WHERE LOWER(email) = 'a@example.com'" --format json
928
+ ```
929
+
884
930
  使用 `plan` 在執行前檢查 SQL 安全性。它只讀取本機 dbcli 設定、權限、黑名單規則與已快取的 schema metadata;不會連線到資料庫。
885
931
 
886
932
  ```bash
@@ -1481,6 +1527,20 @@ chmod +x dist/cli.mjs
1481
1527
 
1482
1528
  ## 開發
1483
1529
 
1530
+ 開發 agent CLI 的套件使用者,可從 `@carllee1983/dbcli/agent-core` 匯入遵循 semver、與資料庫無關的穩定介面:
1531
+
1532
+ ```ts
1533
+ import {
1534
+ loadEnvFile,
1535
+ parseConnectionNames,
1536
+ resolveConnectionSelector,
1537
+ resolveEnvRef,
1538
+ trimAppliedLimit,
1539
+ } from '@carllee1983/dbcli/agent-core'
1540
+ ```
1541
+
1542
+ 較廣的 `@carllee1983/dbcli/core` 仍是 dbcli 專用介面。CLI option factory、config storage binding 與連線字串解析刻意不納入 `agent-core`。
1543
+
1484
1544
  ```bash
1485
1545
  bun test # 完整測試(Bun test runner)
1486
1546
  bun run test:unit # 僅單元與 core 測試
package/assets/SKILL.md CHANGED
@@ -239,8 +239,10 @@ dbcli init --system elasticsearch \
239
239
  dbcli init --conn-name staging --env-file .env.staging --permission query-only
240
240
  dbcli init --conn-name prod --env-file .env.production --use-env-refs --skip-test
241
241
  dbcli use --list # show all, * marks default
242
- dbcli use prod # switch default
242
+ dbcli use prod # switch default (persists — avoid for one-off queries)
243
243
  dbcli query --use staging "SELECT 1" # one-shot override on any subcommand
244
+ DBCLI_CONNECTION=staging dbcli query "SELECT 1" # one-shot via env; parallel-safe
245
+ dbcli --use staging,prod query "SELECT count(*) FROM users" # read-only fan-out
244
246
  dbcli init --rename staging:stg # rename
245
247
  dbcli init --remove stg # remove
246
248
  ```
@@ -296,7 +298,7 @@ Full flags and edge cases: see [reference.md](reference.md) `init` section.
296
298
  | `use` | n/a | Show/switch default named connection (v2 only). |
297
299
  | `list` | query-only+ | Tables (SQL), collections (MongoDB), keys (Redis), or indices (Elasticsearch). |
298
300
  | `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`. |
299
- | `query` | query-only+ | SQL, Mongo JSON (`--collection`), Redis command, or ES DSL/Lucene (`--collection`). `--format table\|json\|csv\|html`, `--ui` to open the interactive dashboard in a browser. Supports `--recovery`. |
301
+ | `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. `--fields` (projection), `--truncate` (cell width), `-f/--query-file` (read query from file or stdin), `--use a,b` (read-only fan-out). Supports `--recovery`. See **Query workflow flags**. |
300
302
  | `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`. |
301
303
  | `lint` | n/a | Static SQL anti-pattern advisor (no DB connection). 9 rules incl. schema-aware implicit-cast / NOT IN-nullable checks via the layered `.dbcli/schemas/` cache; global `--use <conn>` selects a named cache. Findings carry rewrite drafts + guarded `explain` verify commands (`--analyze` only for proven read-only SQL) — report-only, never executes. `--format text\|json\|markdown`, `--min-severity`, `--no-schema`, `--bulk`. Supports `--recovery`. |
302
304
  | `plan` | n/a | Static SQL risk analyzer (`--format text\|json`); classifies a statement without connecting to the database. |
@@ -304,10 +306,10 @@ Full flags and edge cases: see [reference.md](reference.md) `init` section.
304
306
  | `queries` | n/a | Manage saved snippets: `list` / `show` / `search` / `suggest` / `new` / `edit` / `check` / `delete` / `rename` / `copy` / `import` / `export`. |
305
307
  | `insert` / `update` | read-write+ | SQL or MongoDB only. JSON `--data` / `--set`; `--where` required on `update`; `--dry-run` first. Redis writes go through `query`. Supports `--recovery`. |
306
308
  | `delete` | data-admin+ | SQL or MongoDB; Redis has a basic implementation (see Redis section). `--where` required; `--dry-run` first. Supports `--recovery`. |
307
- | `export` | query-only+ | SQL, MongoDB, or **(v1.22)** Elasticsearch (DSL `--index` or whole-index scroll). Query → `--format json\|jsonl\|csv\|html` file or stdout. `html` emits a standalone interactive dashboard. Supports `--recovery`. |
309
+ | `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. **Fails closed rather than truncating silently**: if the auto-limit would drop rows, the export errors out and you must pass `--no-limit` or `--limit N`. Supports `--recovery`. |
308
310
  | `blacklist` | n/a | `list` / `table` / `column` subcommands redact sensitive data from query results. |
309
311
  | `check` | query-only+ | SQL only (best on MySQL/MariaDB). |
310
- | `diff` | query-only+ | SQL only. Save/compare schema snapshots. **(P1b)** `--against-orm <path>` compares a Prisma schema / DDL file / normalized JSON against the local schema cache (no DB connection): categorized drift (`missing_in_db` = error, `missing_in_orm` = warn, `mismatch` per tolerance table, `unmanaged`) with dry-run `migrate` proposals; exit 1 on error-level drift. `--orm-format prisma\|ddl\|json`, `--ignore <globs>`, `--format json\|table\|markdown`. |
312
+ | `diff` | query-only+ | SQL only. Save/compare schema snapshots. **(P1b)** `--against-orm <path>` compares a Prisma schema / DDL file / normalized JSON against the local schema cache (no DB connection): categorized drift (`missing_in_db` = error, `missing_in_orm` = warn, `mismatch` per tolerance table, `unmanaged`) with dry-run `migrate` proposals; exit 1 on error-level drift. `--orm-format prisma\|ddl\|json\|drizzle\|typeorm\|sequelize`, `--ignore <globs>`, `--format json\|table\|markdown`. Drizzle: point at `drizzle/meta/<NNNN>_snapshot.json` (run `drizzle-kit generate` first; `.ts` sources are rejected with a hint). TypeORM/Sequelize: feed tool-generated DDL (`schema:log` / a schema-only dump); source files are rejected with the exact generation command to run. |
311
313
  | `snapshot` | query-only+ | **(v1.25)** SQL only. Capture a result fingerprint (`rowCount` + per-column null/distinct/min/max/sum + order-independent checksum). `--out` (default `.dbcli/snapshots/snap-<ts>.json`), `--rows`, `--stdout`, `--format`, `--no-limit`. Baseline for `assert --against`. |
312
314
  | `assert` | query-only+ | **(v1.25)** SQL only. Verify an invariant; exit 1 on failure unless `--no-fail`. `--expect "rows>0\|value==X\|col:c not null\|unique\|between a and b\|>= n"`, `--vs <query> --compare rows\|value` (reconcile), `--against <snapshot> --tolerance <pct>`. |
313
315
  | `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. |
@@ -325,8 +327,9 @@ Full flags and edge cases: see [reference.md](reference.md) `init` section.
325
327
  | `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). |
326
328
  | `migrate` | admin | SQL only. **DDL; dry-run by default** — needs `--execute`. |
327
329
 
328
- `--use <name>` on any subcommand (including `status` / `doctor`) targets a v2 connection
329
- without changing the default. `--recovery` is honoured by `query`, `q`, `insert`, `update`,
330
+ Use root-level `dbcli --use <name> <command>` for any command; `query`, `schema`, `list`,
331
+ `export`, and `check` also accept command-level `--use`. Both target a v2 connection without
332
+ changing the default. `--recovery` is honoured by `query`, `q`, `insert`, `update`,
330
333
  `delete`, `export`, `schema`, `inspect`, `lint`, and `diff --against-orm` (see **On failure** above).
331
334
 
332
335
  **Write & query flag semantics** (SQL/Mongo `insert`/`update`):
@@ -344,6 +347,27 @@ without changing the default. `--recovery` is honoured by `query`, `q`, `insert`
344
347
  - `--recovery` is recommended for automated agent pipelines (enables `dbcli recover --apply`
345
348
  after a failure); optional for one-off manual writes.
346
349
 
350
+ ## Query workflow flags
351
+
352
+ These exist so you do not have to pipe output through `head` / `jq` / `python3`
353
+ to make it usable. Reach for them instead of post-processing.
354
+
355
+ | Need | Flag | Notes |
356
+ |------|------|-------|
357
+ | Only some columns | `--fields sn,bet,created_at` | SQL and MongoDB. Mongo pushes a real `projection` / `$project` to the driver; `_id` is dropped unless you ask for it. A field the result lacks comes back as `null`, so verify spellings with `schema` before reading meaning into an all-null column. |
358
+ | Everything except a huge column | `--fields=-raw_response` | Exclusion form. Include and exclude cannot be mixed. |
359
+ | One field is a giant JSON blob | `--truncate 120` | Table output truncates cells at 120 chars **by default** and marks them `…(+3412 chars)`. `--no-truncate` disables it. Explicit truncation flags are rejected on JSON, CSV, HTML, and `--ui` output. |
360
+ | Query has quotes / newlines / `$regex` | `-f pipeline.json` or `-f -` | Reads the query from a file or stdin; use a heredoc for Mongo pipelines. Passing both a file and positional query text is an error, never a silent pick. `-f -` needs piped input — it refuses an interactive terminal rather than hanging. |
361
+ | Same query across connections | `--use hub-prod,site-a` | Read-only fan-out. Per-connection results, one failure does not cancel the others. Exit `0` all-ok, `2` mixed, `1` all-failed. Rejects writes, `--recovery`, `--ui`, CSV/HTML. |
362
+ | Pick a connection for one call | `DBCLI_CONNECTION=hub-prod dbcli query …` | Env var, or `--use` on the subcommand. Priority: `--use` > `DBCLI_CONNECTION` > saved default. Neither writes the default back to disk, so parallel shells never fight. Requires a v2 config — a single-connection (v1) project rejects both rather than silently running its only connection. **Do not** use `dbcli use <name>` just to switch for one query. |
363
+
364
+ **Truncation is reported, never implied.** When the query-only auto-limit trims a
365
+ result, the table footer reads `Rows: 1000 (truncated; limit 1000)`, `--format json`
366
+ carries `metadata.truncated` / `metadata.limit_applied`, and CSV appends a `#`
367
+ comment. `Rows: 1000` with no marker means exactly 1000 rows exist — do not infer
368
+ truncation from a round number. This applies to `query` and to `q` snippets
369
+ (whose own 1000-row guard reports the same way). `export` refuses to truncate at all. Redis replies trimmed by the size guard report the same way, and each size-guard warning is printed on stderr.
370
+
347
371
  ## Permission levels
348
372
 
349
373
  | Level | Allowed |
@@ -192,8 +192,10 @@ dbcli init --system elasticsearch \
192
192
  dbcli init --conn-name staging --env-file .env.staging --permission query-only
193
193
  dbcli init --conn-name prod --env-file .env.production --use-env-refs --skip-test
194
194
  dbcli use --list # show all, * marks default
195
- dbcli use prod # switch default
195
+ dbcli use prod # switch default(會持久化 — 單次查詢別用)
196
196
  dbcli query --use staging "SELECT 1" # one-shot override on any subcommand
197
+ DBCLI_CONNECTION=staging dbcli query "SELECT 1" # 單次指定,env 版;平行安全
198
+ dbcli --use staging,prod query "SELECT count(*) FROM users" # 唯讀扇出
197
199
  dbcli init --rename staging:stg # rename
198
200
  dbcli init --remove stg # remove
199
201
  ```
@@ -234,7 +236,7 @@ dbcli init --conn-name prod --env-file .env.production --use-env-refs --skip-tes
234
236
  | `use` | n/a | 顯示 / 切換預設命名連線(僅 v2)。 |
235
237
  | `list` | query-only+ | 資料表(SQL)、collections(MongoDB)、keys(Redis)或 indices(Elasticsearch)。 |
236
238
  | `schema` | query-only+ | SQL:單表或全掃描存入 `.dbcli/schemas/`。MongoDB:sampled。ES:flattened mapping。Redis:僅單一 key(type / TTL / size)。支援 `--recovery`。 |
237
- | `query` | query-only+ | SQL、Mongo JSON(`--collection`)、Redis 指令、ES DSL / Lucene(`--collection`)。`--format table\|json\|csv\|html`、`--ui` 開啟瀏覽器互動式 dashboard。支援 `--recovery`。 |
239
+ | `query` | query-only+ | SQL、Mongo JSON(`--collection`)、Redis 指令、ES DSL / Lucene(`--collection`)。`--format table\|json\|csv\|html`、`--ui` 開啟瀏覽器互動式 dashboard。`--fields`(欄位投影)、`--truncate`(欄位值寬度)、`-f/--query-file`(從檔案或 stdin 讀查詢)、`--use a,b`(唯讀扇出)。支援 `--recovery`。見 **查詢工作流程旗標**。 |
238
240
  | `explain` | query-only+ | **(v1.23)** 唯讀查詢計畫並附註解。僅 SQL。單一查詢、`@saved-query`、`@file.sql` 或 `--bulk @glob/*`。`--analyze`(EXPLAIN ANALYZE / MariaDB ANALYZE SELECT)、`--format markdown\|json\|table`。 |
239
241
  | `lint` | n/a | 靜態 SQL 反模式顧問(不連線 DB)。共 9 條規則,包含透過分層 `.dbcli/schemas/` 快取進行的 schema-aware implicit-cast / NOT IN-nullable 檢查;全域 `--use <conn>` 會選擇命名連線的快取。Finding 可附 rewrite 草稿與受保護的 `explain` 驗證指令;只有已證明唯讀的 SQL 才會加上 `--analyze`,且只回報、絕不執行。`--format text\|json\|markdown`、`--min-severity`、`--no-schema`、`--bulk`。支援 `--recovery`。 |
240
242
  | `plan` | n/a | 靜態 SQL 風險分析器(`--format text\|json`);不連線即可分類語句。 |
@@ -242,10 +244,10 @@ dbcli init --conn-name prod --env-file .env.production --use-env-refs --skip-tes
242
244
  | `queries` | n/a | 管理已儲存 snippet:`list` / `show` / `search` / `suggest` / `new` / `edit` / `check` / `delete` / `rename` / `copy` / `import` / `export`。 |
243
245
  | `insert` / `update` | read-write+ | 僅 SQL 與 MongoDB。JSON `--data` / `--set`;`update` 必填 `--where`;先 `--dry-run`。Redis 寫入透過 `query`。支援 `--recovery`。 |
244
246
  | `delete` | data-admin+ | 僅 SQL 與 MongoDB;Redis 有基本實作(見 Redis 段落)。必填 `--where`;先 `--dry-run`。支援 `--recovery`。 |
245
- | `export` | query-only+ | SQL、MongoDB 或 **(v1.22)** Elasticsearch(DSL `--index` 或全 index scroll)。Query → `--format json\|jsonl\|csv\|html` 檔案或 stdout。`html` 輸出獨立可互動 dashboard。支援 `--recovery`。 |
247
+ | `export` | query-only+ | SQL、MongoDB 或 **(v1.22)** Elasticsearch(DSL `--index` 或全 index scroll)。Query → `--format json\|jsonl\|csv\|html` 檔案或 stdout。`html` 輸出獨立可互動 dashboard。**寧可失敗也不靜默截斷**:若 auto-limit 會砍掉資料列,匯出直接報錯,必須改用 `--no-limit` 或 `--limit N`。支援 `--recovery`。 |
246
248
  | `blacklist` | n/a | `list` / `table` / `column` 子指令,從查詢結果中遮蔽敏感資料。 |
247
249
  | `check` | query-only+ | 僅 SQL(在 MySQL / MariaDB 最佳)。 |
248
- | `diff` | query-only+ | 僅 SQL。儲存 / 比較 schema snapshot。**(P1b)** `--against-orm <path>` 會將 Prisma schema / DDL 檔 / normalized JSON 與本地 schema cache 比對(不連線 DB):分類為 `missing_in_db`(error)、`missing_in_orm`(warn)、依 tolerance 表判定的 `mismatch`、以及 `unmanaged`,並提供 dry-run `migrate` 提案;出現 error-level drift 時 exit 1。`--orm-format prisma\|ddl\|json`、`--ignore <globs>`、`--format json\|table\|markdown`。 |
250
+ | `diff` | query-only+ | 僅 SQL。儲存 / 比較 schema snapshot。**(P1b)** `--against-orm <path>` 會將 Prisma schema / DDL 檔 / normalized JSON 與本地 schema cache 比對(不連線 DB):分類為 `missing_in_db`(error)、`missing_in_orm`(warn)、依 tolerance 表判定的 `mismatch`、以及 `unmanaged`,並提供 dry-run `migrate` 提案;出現 error-level drift 時 exit 1。`--orm-format prisma\|ddl\|json\|drizzle\|typeorm\|sequelize`、`--ignore <globs>`、`--format json\|table\|markdown`。Drizzle:請指向 `drizzle/meta/<NNNN>_snapshot.json`(先執行 `drizzle-kit generate`;`.ts` source 會被拒絕並顯示提示)。TypeORM/Sequelize:傳入工具產生的 DDL(`schema:log` / schema-only dump);source file 會被拒絕,並顯示要執行的精確產生指令。 |
249
251
  | `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` 的基準。 |
250
252
  | `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>`。 |
251
253
  | `verification` | n/a | 檢視與管理本機驗證 artifact。`list` / `show <id-or-path>` / `summary` 為唯讀;`prune` 預設 dry-run,僅在 `--execute --force` 時刪除。讀取 `<cwd>/.dbcli/verification/`;不需 DB 連線,不寫入 audit log。 |
@@ -263,7 +265,7 @@ dbcli init --conn-name prod --env-file .env.production --use-env-refs --skip-tes
263
265
  | `skill` | n/a | 產出 / 安裝 AI skill 文件(`--install <claude\|gemini\|antigravity\|copilot\|cursor\|codex\|windsurf>`);`skill tasks list/show/plan` 提供 Agent Task Packs;`skill context` 提供 LLM 提示詞脈絡載荷(用於注入其他 LLM,正常操作不需要)。 |
264
266
  | `migrate` | admin | 僅 SQL。**DDL;預設 dry-run** — 需 `--execute`。 |
265
267
 
266
- 任何子指令上的 `--use <name>` 可在不改變預設值的情況下,把目標切到 v2 連線。`--recovery` 被 `query`、`q`、`insert`、`update`、`delete`、`export`、`schema`、`inspect`、`lint` 與 `diff --against-orm` 支援(見上方**失敗時**)。
268
+ 任何指令都可使用 root 層級的 `dbcli --use <name> <command>`;`query`、`schema`、`list`、`export`、`check` 也接受指令層級的 `--use`。兩種寫法都只把本次目標切到 v2 連線,不改變預設值。`--recovery` 被 `query`、`q`、`insert`、`update`、`delete`、`export`、`schema`、`inspect`、`lint` 與 `diff --against-orm` 支援(見上方**失敗時**)。
267
269
 
268
270
  **寫入與查詢旗標語意**(SQL / Mongo `insert`/`update`):
269
271
 
@@ -272,6 +274,27 @@ dbcli init --conn-name prod --env-file .env.production --use-env-refs --skip-tes
272
274
  - `--dry-run` 輸出參數化 SQL(使用 `$1` / `?` 佔位符,非真實值)與 `rows_affected: 0`;確認 `status:"success"` 且 SQL 形狀符合預期的 `--where` / `--set` 後再執行。MongoDB 輸出 shell 風格預覽。
273
275
  - `--recovery` 建議用於自動化 agent pipeline(讓失敗後可執行 `dbcli recover --apply`);手動一次性寫入可選用。
274
276
 
277
+ ## 查詢工作流程旗標 (Query workflow flags)
278
+
279
+ 這些旗標的存在,就是為了讓你不必再把輸出 pipe 給 `head` / `jq` / `python3`
280
+ 才能用。優先用它們,不要事後加工。
281
+
282
+ | 需求 | 旗標 | 說明 |
283
+ |------|------|------|
284
+ | 只要某幾個欄位 | `--fields sn,bet,created_at` | SQL 與 MongoDB 皆可。Mongo 會把真正的 `projection` / `$project` 下推給 driver;除非明確指定,否則不回傳 `_id`。結果中不存在的欄位會回傳 `null`,所以看到整欄 null 時先用 `schema` 核對欄位名。 |
285
+ | 除了某個巨大欄位以外都要 | `--fields=-raw_response` | 排除形式。include 與 exclude 不能混用。 |
286
+ | 某欄位是一大包 JSON | `--truncate 120` | table 輸出**預設**就在 120 字截斷,並標記 `…(+3412 chars)`。`--no-truncate` 可關閉。JSON、CSV、HTML 與 `--ui` 輸出會拒絕明確的截斷旗標。 |
287
+ | 查詢含引號 / 換行 / `$regex` | `-f pipeline.json` 或 `-f -` | 從檔案或 stdin 讀查詢;Mongo pipeline 建議用 heredoc。同時給檔案與位置參數會直接報錯,不會靜默擇一。`-f -` 需要 piped input——遇到互動式終端會直接拒絕而不是空等。 |
288
+ | 同一查詢跨多個連線 | `--use hub-prod,site-a` | 唯讀扇出。各連線各自出結果,其中一個失敗不會取消其他。exit `0` 全成功、`2` 部分失敗、`1` 全失敗。拒絕寫入、`--recovery`、`--ui`、CSV/HTML。 |
289
+ | 單次指定連線 | `DBCLI_CONNECTION=hub-prod dbcli query …` | 環境變數,或在子指令上加 `--use`。優先序:`--use` > `DBCLI_CONNECTION` > 已存的預設值。兩者都不會把預設值寫回磁碟,所以平行的 shell 不會互相干擾。需要 v2 設定——單一連線 (v1) 專案會直接拒絕,而不是靜默改跑那唯一的連線。**不要**為了單次查詢去跑 `dbcli use <name>`。 |
290
+
291
+ **截斷一律明說,絕不靠推測。** query-only 的 auto-limit 砍掉結果時,table footer
292
+ 會顯示 `Rows: 1000 (truncated; limit 1000)`,`--format json` 會帶
293
+ `metadata.truncated` / `metadata.limit_applied`,CSV 則附加 `#` 註解行。
294
+ `Rows: 1000` 沒有標記就代表資料**剛好**是 1000 筆——不要因為數字是整數就推論它被截斷。
295
+ `query` 與 `q` snippet(其自身的 1000 筆 guard 也用同樣方式回報)皆適用。
296
+ `export` 則是根本拒絕截斷。Redis 被 size guard 裁切的回覆同樣依此回報,每則 size-guard warning 也會印到 stderr。
297
+
275
298
  ## 權限等級 (Permission levels)
276
299
 
277
300
  | Level | Allowed |