@carllee1983/dbcli 1.44.1 → 1.45.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dbcli-agent",
3
- "version": "1.44.1",
3
+ "version": "1.45.0",
4
4
  "description": "Database CLI skill and command reference for AI agents.",
5
5
  "contextFileName": "AGENTS.md"
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@carllee1983/dbcli",
3
- "version": "1.44.1",
3
+ "version": "1.45.0",
4
4
  "description": "Database CLI for AI agents",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -73,6 +73,7 @@
73
73
  "test:integration": "bun test tests/integration",
74
74
  "test:docker": "docker compose -f docker-compose.test.yml up -d --wait && bun test tests/integration/adapters; docker compose -f docker-compose.test.yml down",
75
75
  "docs:check": "bun run scripts/check-user-docs.ts",
76
+ "contract:check": "bun run scripts/check-cli-contract.ts",
76
77
  "skill:check": "bun run scripts/check-skill-parity.ts",
77
78
  "platform:check": "bun run scripts/check-platform-parity.ts",
78
79
  "agent-core:check": "bun run scripts/check-agent-core-purity.ts",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dbcli-agent",
3
- "version": "1.44.1",
3
+ "version": "1.45.0",
4
4
  "description": "Database CLI skill and command reference for AI agents",
5
5
  "author": {
6
6
  "name": "Carl Lee",
@@ -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.
@@ -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
 
@@ -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.
@@ -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