Build a new Python CLI named sql-agent-cli that runs safe, read-only SQL queries against local or remote databases and emits deterministic, agent-friendly output.
The tool should follow the same broad product pattern as similar agent-first CLIs such as confluence-fetch:
- local single-file execution via
uv run ./sql_agent_cli.py ...using PEP 723 inline script metadata - packaged execution via
uvx sql-agent-cli ... - agent-first stdout/stderr behavior with stable output contracts
Primary audience:
- agentic coding tools such as Codex CLI and Claude Code
Secondary audience:
- humans running ad hoc database inspection commands directly in a terminal
License:
- MIT
Release status:
- 0.14.0 adds guided setup, saved credentials, and read-only readiness checks while the public contracts are stabilized for 1.0.
- The documented CLI, config, JSON, stdout/stderr, and exit-code behavior in this spec is the intended 1.0 public contract.
- The primary happy path is
sql-agent-cli "SELECT ..."against a configured default target. - The tool supports named targets so multiple databases can be queried safely from one CLI.
- V1 supports MySQL, MariaDB, PostgreSQL, and SQLite.
- The internal design leaves room for SQL Server later without redesigning the config model.
- The tool is strictly read-only in v1.
- Stdout contains payload only. Diagnostics, warnings, progress, and errors go to stderr only.
- The default output is optimized for agents, not for humans staring at a terminal.
- The project is publishable so
uvx sql-agent-cli --helpworks. - The repo also keeps a root-level
sql_agent_cli.pywrapper foruv run.
- Write queries in v1.
- Interactive TUI behavior.
- Backward compatibility with
sql-query.py. - Cross-database joins or fan-out queries in a single invocation.
- Full database administration features.
sql-agent-cli
sql-agent-cli/
pyproject.toml
README.md
sql_agent_cli.py
spec.md
src/
sql_agent/
__init__.py
cli.py
config.py
models.py
validation.py
render.py
engines/
__init__.py
base.py
mysql.py
postgres.py
sqlite.py
- Publishable Python package via
pyproject.toml. - Console script entry point exposed as
sql-agent-cli. - Root-level
sql_agent_cli.pywrapper with PEP 723 metadata for local script execution. - The wrapper delegates into packaged implementation instead of duplicating the application logic.
Recommended implementation dependencies:
PyMySQL[rsa]for MySQL and MariaDBpsycopg[binary]for PostgreSQL- standard-library
sqlite3for SQLite sqlglotfor parser-backed SQL validation
Rationale:
- these choices are compatible with the
uvxpackaging and execution model PyMySQL[rsa]avoids common MySQL authentication friction while remaining easy to shippsycopg[binary]avoids common system-library installation issues for PostgreSQLsqlglotprovides token-aware, dialect-aware SQL parsing suitable for read-only validation
sql_agent_cli.py must include inline script metadata similar to:
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "...",
# ]
# ///Notes:
- The wrapper may add
src/tosys.pathduring local development. - The package itself still uses
pyproject.tomlmetadata foruv buildanduv publish.
- MySQL
- MariaDB
- PostgreSQL
- SQLite
The target/config model must be engine-neutral enough that SQL Server can be added later without changing the user-facing target structure.
That means:
- targets are named records with an explicit
engine - shared concepts such as host, port, database name, SSL mode, and read-only behavior live in common models where practical
- engine-specific fields may exist where required
- Payload output goes to stdout only.
- Diagnostics, warnings, progress, and errors go to stderr only.
- Resolution rules must be deterministic and documented in
--help. - The default output must be structured enough for agents to consume reliably.
- Read-only safety must be enforced before any query is executed.
- Missing target or credential context must fail fast with corrective error text.
Primary happy path:
sql-agent-cli "SELECT ..."
Named target:
sql-agent-cli --target reporting "SELECT ..."
Explicit query flag:
sql-agent-cli --target reporting --query "SELECT ..."
SQL file:
sql-agent-cli --target reporting --sql-file query.sql
Stdin:
Get-Content query.sql | sql-agent-cli --target reporting
V1 should support exactly one query source per invocation:
- positional query text
--query SQL--sql-file PATH- stdin when no positional query and no query flag/file were provided
If more than one query source is supplied, fail with a usage error.
Resolution order:
--target NAME- an explicit
--enginebuilds an ephemeral target without merging[defaults].target [defaults].target- fail with a clear error if no target is available
The tool should also support one-off execution without config by allowing connection details on the CLI.
Examples:
sql-agent-cli --engine mysql --host db.example.com --database app --user paul "SELECT ..."
sql-agent-cli --engine postgres --host db.example.com --database app --user paul --password-stdin "SELECT ..."
sql-agent-cli --engine sqlite --path C:\data\app.db "SELECT ..."
Behavior:
- CLI connection flags can define a full ephemeral target for the current run.
- CLI connection flags override the selected config target field-by-field.
- If no target is specified and no default target exists, a complete ephemeral CLI target is allowed.
- If the resulting target is incomplete, fail with a clear validation error before attempting a connection.
- If
--engineis supplied without--target, start from an ephemeral target rather than the configured default target.
V1 should avoid password-as-argument by default.
Recommended supported methods:
- native engine credential resolution
--password-stdin- optional
--prompt-passwordfor human use
V1 should not require --password as a normal CLI argument.
sql-agent-cli "SELECT ..."
sql-agent-cli --target NAME "SELECT ..."
sql-agent-cli --about
sql-agent-cli config show
sql-agent-cli config check [--target NAME | --all] [--format text|json]
sql-agent-cli config set-default-target NAME
sql-agent-cli config add-target NAME [options]
sql-agent-cli config remove-target NAME
sql-agent-cli config init-native-auth --engine postgres [--target NAME]
sql-agent-cli config init-native-auth --engine mysql [--target NAME]
sql-agent-cli targets
sql-agent-cli skill install [--force] [--skills-dir PATH]
sql-agent-cli skill status [--format text|json] [--skills-dir PATH]
sql-agent-cli skill remove [--force] [--skills-dir PATH]
sql-agent-cli install-skill
sql-agent-cli remove-skill
Compatibility requirement:
- none
uvx sql-agent-cli skill install installs or updates the managed $sql-agent-cli skill at ~/.agents/skills/sql-agent-cli/SKILL.md. install-skill remains an alias. All skill commands support --skills-dir PATH for explicit custom locations and --format text|json. Installation and removal retain their default deterministic JSON results. Status defaults to text.
One canonical renderer supplies the existing name, description, instructions, and examples. The skill continues using uvx sql-agent-cli with the default-target happy path, read-only boundary, least-privilege roles, structured output, native credentials, TLS behavior, and one-time config check troubleshooting. Generation uses UTF-8 without a BOM, LF line endings, and a trailing newline.
Management state lives under the supported YAML metadata mapping. managed-by is sql-agent-cli. managed-version is a quoted string exactly matching sql_agent.__version__, the runtime version reported by the CLI. managed-content-sha256 is a quoted sha256: value followed by 64 lowercase hexadecimal characters. There is no top-level version or sidecar. Existing unrelated supported template metadata is preserved.
The hash covers the entire normalized UTF-8 file with only the hash field's value replaced by "". Verification uses the installed file's original formatting, without YAML reserialization or comparison with the current bundled hash. CRLF and CR normalize to LF. The hash detects modifications and is not a signature.
Query and informational CLI runs, including help, version, about, and rendering, synchronize only an existing managed skill in the standard location. Configuration, targets, and skill-management commands skip this check. Setup explicitly installs the skill after database verification. PEP 440 comparison determines whether the installed version is older, equal, or newer. Equal and newer versions are never automatically replaced. A pristine older version is updated. An older skill with a missing, malformed, or mismatched hash is preserved with a stderr recommendation to run uvx sql-agent-cli skill install --force.
The legacy <!-- managed-by: sql-agent-cli --> marker remains recognized unless parsed metadata names a different manager. Unversioned legacy skills are treated as version 0. Missing or malformed managed versions trigger a fresh replacement before hash checks. Newly generated skills use only front matter management metadata.
Explicit installation creates missing skills and updates pristine older skills. Current skills are unchanged. Altered or unverifiable managed skills with valid versions require --force. Force installation still refuses unmanaged content and never downgrades newer versions. Unexpected directories and unrelated files are preserved.
Automatic synchronization uses installed-distribution metadata to exclude editable and local source builds, including PEP 610 local file: sources. Installed wheels remain eligible, including local wheel artifacts. Unidentified runtime sources skip synchronization. Explicit installation still works from local builds. Custom locations require explicit updates. The feature never queries an index, refreshes uv's cache, or updates the CLI.
skill status is read-only. Its text and JSON output report the selected path, installation and management state, runtime and installed versions, version comparison, integrity, runtime source, automatic eligibility and skip reason, and an applicable force-install recommendation.
Replacement writes and flushes a temporary file in the target directory, closes it, revalidates the installed state, and uses atomic replacement. Failures clean up temporary files and never affect the primary command's exit status. Notices use stderr exclusively. Updates affect future agent skill loading and may not change a running agent session.
skill remove and its remove-skill alias remove managed SKILL.md files, including legacy skills. Existing --force removal of unmanaged content remains supported. Removal preserves unrelated files and removes the skill directory only when empty. A missing skill directory returns the existing not_installed JSON result.
V1 must execute exactly one SQL statement per invocation.
Required behavior:
- allow a single trailing semicolon and strip it before validation
- reject multiple statements
- reject empty input
Rationale:
- agents frequently emit a harmless trailing semicolon
- stacked statements materially increase risk and complexity
Implementation requirement:
- validation should be token-aware or parser-backed rather than a simple regex-only keyword scan
Recommended implementation:
- use
sqlglotwith the selected engine dialect and require exactly one parsed statement
V1 should allow only read-oriented statements.
Required allowlist:
SELECTWITH ... SELECTSHOWDESCRIBEandDESCEXPLAIN
Engine-specific notes:
- SQLite may also allow read-only
PRAGMAstatements if they are explicitly validated as non-mutating. USEmust not be allowed. Target selection belongs to CLI/config, not SQL text.- Stored procedures, dynamic SQL, and administrative commands must not be allowed.
The validator should reject statements containing or invoking mutating or administrative behavior, including but not limited to:
INSERTUPDATEDELETEREPLACEMERGEUPSERTDROPALTERCREATETRUNCATEGRANTREVOKELOCKUNLOCKCALLEXECPREPAREDEALLOCATESETLOAD_FILEINTO OUTFILEINTO DUMPFILE- sleep/benchmark-style functions
Validation must happen before a database connection is attempted where practical.
Validation requirements:
- comments must not confuse statement classification
- quoted strings and identifiers must not be treated as executable keywords
- semicolons inside quoted literals must not be treated as statement separators
- CTE-based
WITH ... SELECTqueries must be accepted when they remain read-only - parse failures should return a clear validation error instead of falling through to execution
Where the underlying driver/database supports a true read-only connection mode, the tool should enable it.
Examples:
- SQLite connections must be opened in read-only mode.
- PostgreSQL connections must set
default_transaction_read_only=onfor the session. - MySQL/MariaDB connections must run
SET SESSION TRANSACTION READ ONLYbefore user SQL. - Integration tests must bypass parser validation and prove that PostgreSQL and MySQL reject a write at the session layer.
- These controls are defense in depth. Targets should use dedicated database identities with only the required read and metadata privileges.
- Stored functions, extensions, temporary objects, server configuration, and privileged database roles can weaken assumptions made from SQL text alone.
V1 should support:
jsonmarkdowntablecsv
Default output format:
json
Rationale:
- JSON is the best default for agents because it can carry structured metadata, truncation status, and stable field names.
Recommended top-level structure:
{
"target": {
"name": "default",
"engine": "mysql",
"database": "app",
"host": "db.example.com"
},
"query": {
"input": "SELECT id, name FROM users",
"normalized": "SELECT id, name FROM users",
"statement_type": "select"
},
"result": {
"columns": ["id", "name"],
"rows": [
[1, "Alice"],
[2, "Bob"]
],
"returned_row_count": 2,
"truncated": false
}
}The top-level target, query, and result objects and the documented fields above are stable public fields. Compatible releases may add fields, but must not remove or reinterpret existing fields without a major version change. The payload includes:
- resolved target metadata with secrets omitted
- normalized query text
- column names
- rows
- returned row count
- truncation indicator
Serialization requirements:
- datetimes and dates should be emitted as ISO 8601 strings
- decimals should be emitted as strings to avoid silent precision loss
- bytes/blob values should be emitted as base64 strings or explicit placeholders; the choice should be documented and stable
NULLshould become JSONnull- UUID-like values may be emitted as strings
Row count semantics:
- use
returned_row_countfor the number of rows actually present in the payload - use
truncatedto indicate whether rows were omitted due tomax_rows - do not claim a
total_row_countunless the tool actually computed it
markdownshould render a stable prompt-friendly table plus a short metadata header.tableshould optimize for terminal readability.csvshould emit raw CSV payload only, with no explanatory text on stdout.
- Successful query payloads are written to stdout.
- Diagnostics and errors are written to stderr.
- Failed normal queries do not emit partial stdout payloads.
setupandconfig check --format jsonemit diagnostic reports even on failure. Runtime failures return 1. Missing or invalid input returns 2.
Use a single user config file at:
~/.sql-agent-cli/config.toml
The default target should be an alias, not a duplicated block of connection data.
Recommended shape:
[defaults]
target = "dev"
format = "json"
max_rows = 200
connect_timeout_seconds = 8
query_timeout_seconds = 15
[targets.dev]
engine = "mysql"
host = "az-mysql-pub-sona-asia1-dev.mysql.database.azure.com"
port = 3306
database = "asiadev_2794"
user = "paul"
ssl_mode = "required"
[targets.reporting]
engine = "postgres"
host = "db.example.com"
port = 5432
database = "app"
user = "report_reader"
[targets.local_sqlite]
engine = "sqlite"
path = "C:/data/app.db"This is the preferred approach because:
[defaults].targetclearly selects the default target- all connection details live in exactly one place
- renaming or editing a target does not require syncing duplicated settings
sql-agent-cli setup [RESOURCE] verifies a database, saves its named target, and installs the managed skill in ~/.agents/skills/sql-agent-cli/SKILL.md. No agent-specific copy or link is created. Existing skill integrity, unmanaged-content, and newer-version protections remain unchanged.
RESOURCE is a password-free PostgreSQL, MySQL, or MariaDB URL, or an existing SQLite path. Network setup resolves identity from the resource, explicit connection flags, the selected target, and native connection sources before asking for missing fields. The first target is named default unless specified. Adding a named target preserves an existing default. SQLite paths are saved absolutely.
Setup accepts --target, existing connection flags, --auth auto|native|managed, --auth-file, --service, --unix-socket, --ssl-ca, --replace-password, --non-interactive, --config, --credentials-file, and --format json|text. Text is the default. Automation can select JSON explicitly with --format json. Interactive input requires terminal stdin and stderr. Password input uses asterisk masking and no history. Prompts, progress, and errors go to stderr. Non-interactive setup never reads stdin or prompts.
Verification uses one read-only session for a constant query and a bounded catalog query. It reports authentication, session mode, catalog visibility, and transport identity. No application rows or write probes are used. Table access, absence of write privileges, future validity, and access from another execution environment remain unverified. SQLite WAL sidecars and server audit events can still occur.
Verification failures preserve existing local state. Success saves configuration and entered credentials before installing the skill. Skill failures report the saved database configuration separately. Repeated setup preserves unrelated targets, unknown configuration fields, comments, and credentials. Optimistic snapshot checks prevent overwriting concurrent configuration edits.
Ordinary configuration contains no managed passwords. Entered setup passwords are stored in a separate credentials.toml beside the selected configuration file. Files use normal inherited permissions and the process umask. No keyring or custom restrictive ACL is required. Native PostgreSQL password-file rules still apply to native files.
Credentials have opaque identifiers and bind to the engine, host, port, database, login, socket, and service. Replacements are verified, staged under new identifiers, and selected by an atomic configuration update. Failed saves clean up the staged entry. Unused older entries are removed after a successful switch. A process crash can leave an unused entry.
Passwords never appear in command arguments, public configuration, prompts in agent chat, or diagnostics. Driver exceptions are classified without echoing raw messages. Environment secrets are never persisted. Short-lived tokens are acquired and refreshed externally.
Configuration path precedence is --config, SQL_AGENT_CLI_CONFIG, then ~/.sql-agent-cli/config.toml. Credential path precedence is --credentials-file, SQL_AGENT_CLI_CREDENTIALS_FILE, then credentials.toml beside the selected config. Paths must differ.
Recommended target fields:
Shared fields:
enginedatabaseuserhostportssl_modemax_rowsconnect_timeout_secondsquery_timeout_seconds
SQLite-specific fields:
path
Notes:
ssl_modeshould default to secure behavior where relevant.- SQLite ignores network-only fields.
- The implementation may allow additional engine-specific fields later.
- Engine-specific credential hints may be stored in config, but raw passwords should not be the preferred v1 path.
PostgreSQL retains libpq authentication, including PGPASSFILE, PGPASSWORD, PGSERVICE, and PGSERVICEFILE. Missing connection fields may come from the selected service or PG environment. Password-file hints follow libpq's Windows APPDATA location and Unix ~/.pgpass location. Service discovery checks the user file or PGSERVICEFILE and an explicit PGSYSCONFDIR.
MySQL and MariaDB retain client option files. A target can select an auth_file. Otherwise the existing APPDATA/MySQL/.my.cnf and ~/.my.cnf search order remains. Connection fields, including native port and socket, are resolved before built-in defaults. mysql_config_editor login paths remain unsupported.
--password-stdin and --prompt-password remain supported for queries and single-target checks. Offline checks and --all reject password-input flags. Native authentication is also available through --auth native when a saved credential should be bypassed.
Required behavior:
- new network targets created by setup default to
ssl_mode = "verify-full" - existing targets retain their mode and direct legacy connections default to
required - support a per-target config value for
ssl_mode - support a shared user-facing
ssl_modemodel ofverify-full,required,preferred, ordisabled - map the shared
ssl_modevalues onto engine-specific driver options internally - support an explicit CLI
--ssl-mode {verify-full,required,preferred,disabled}override - support a CLI
--insecureshorthand that means--ssl-mode preferred - support an explicit less-secure override when needed, such as
--ssl-mode disabled --insecureshould not modify config permanentlyrequiredmust fail if encrypted transport is not negotiatedpreferredattempts TLS but permits a plaintext fallbackdisabledprohibits TLSrequiredguarantees transport encryption without guaranteeing server identityverify-fullrequires certificate and hostname verification for TCP connections.ssl_caselects a private CA file
Rationale:
- SSL behavior is a target attribute, but
--insecureis a useful temporary override for troubleshooting
Recommended commands:
sql-agent-cli config show
sql-agent-cli config check [--target NAME | --all] [--format text|json]
sql-agent-cli config set-default-target NAME
sql-agent-cli config add-target NAME --engine mysql --host HOST --port 3306 --database DB --user USER
sql-agent-cli config add-target NAME --engine postgres --host HOST --port 5432 --database DB --user USER
sql-agent-cli config add-target NAME --engine sqlite --path PATH
sql-agent-cli config remove-target NAME
sql-agent-cli config init-native-auth --engine postgres [--target NAME]
sql-agent-cli config init-native-auth --engine mysql [--target NAME]
Behavior requirements:
config showdisplays the effective defaults and configured targets with credential sources described but secrets redactedconfig showshould indicate whether each target is complete enough to runconfig checkdefaults to the configured default target,--target NAMEchecks one named target, and--allis required to contact every configured targetconfig checkuses the setup verifier without saving files or synchronizing skills. It supports --offline, source diagnostics, text, and JSON outputconfig check --allcontinues after individual failures and returns exit code1if any selected target fails- normal queries do not require a successful preflight check
- config-writing commands create the file if it does not exist
- only documented config fields are supported; unknown fields are ignored on read and may be removed when a config-writing command rewrites the file
V1 should help users bootstrap native credential files without requiring them to remember the exact file format.
Recommended command:
sql-agent-cli config init-native-auth --engine postgres [--target NAME]
sql-agent-cli config init-native-auth --engine mysql [--target NAME]
Recommended behavior:
- create the standard file only if it does not already exist, unless an explicit overwrite flag is later added
- write a commented template with placeholders and brief inline instructions
- print the exact path written and the next step for the user
- never auto-fill or persist secrets unless the user explicitly supplied them for that purpose
- for PostgreSQL, set restrictive file permissions where required and warn if that cannot be done
- if the file already exists, do not modify it silently; print a clear message instead
- when
--target NAMEis supplied, prefill non-secret fields such as host, port, database, and user from the selected target where those fields are relevant
PostgreSQL helper requirements:
- seed a
.pgpasstemplate in the preferred platform-specific user location - include the expected
hostname:port:database:username:passwordrecord shape - explain that PostgreSQL expects restrictive permissions on the file
- when
--target NAMEis supplied, prefill host, port, database, and user from the target and leave password blank
MySQL helper requirements:
- seed a
~/.my.cnftemplate or platform-appropriate user option file - include a minimal
[client]example section with host, user, password, and optional port - note that the file stores plaintext secrets and should be protected with filesystem permissions
- when
--target NAMEis supplied, prefill host, port, and user from the target and leave password blank
Platform-specific path rules:
- on Windows, PostgreSQL lookup and template helpers should support both
%APPDATA%\postgresql\pgpass.confand~/.pgpass - on Windows, MySQL lookup and template helpers should support both
%APPDATA%\MySQL\.my.cnfand~/.my.cnfif practical - when both locations exist, prefer the explicit native platform path first, then the
~/fallback - when seeding a new file, prefer the native platform path unless the user later requests an explicit path override
Rationale:
- this reduces setup friction without inventing a proprietary credential format
- it keeps the tool aligned with native client conventions
- it avoids requiring users to search for file syntax documentation during setup
Recommended precedence:
- explicit CLI connection flags such as
--host,--database,--user,--path,--engine,--max-rows,--connect-timeout-seconds,--query-timeout-seconds,--insecure - selected target from
--target NAME - default target named by
[defaults].target - global defaults from
[defaults]for non-connection behavior such as output format and row limits
Password precedence is explicit --password-stdin or --prompt-password, then SQL_AGENT_CLI_PASSWORD, then PostgreSQL PGPASSWORD, then the referenced managed credential, then native driver authentication. Explicit native mode skips the managed file. Unavailable referenced credentials fail without silently changing sources. Explicit environment input can bypass an unavailable file.
Connection fields use explicit CLI values, then selected target fields, then native fields, then built-in defaults. Target selection uses --target, then a one-off --engine, then SQL_AGENT_CLI_TARGET, then the configured default.
Only one query source may be provided. If more than one is supplied, fail.
Accepted sources:
- positional query
--query--sql-file- stdin
--format[defaults].format- built-in default
json
V1 should enforce sensible default guardrails, overridable by config or CLI.
Recommended defaults:
max_rows = 200connect_timeout_seconds = 8query_timeout_seconds = 15
Behavior:
- results are truncated to
max_rows - truncation is reflected in output metadata
- timeout failures return a stable non-zero exit code and a concise stderr error
Public contract:
0success1runtime, connection, driver, or query execution failure2usage or validation error
Starting with 1.0.0, semantic versioning applies to the documented command line, config schema, JSON fields, stdout/stderr behavior, and exit codes.
- patch releases contain compatible fixes and security updates
- minor releases may add backward-compatible commands, options, config fields, and JSON fields
- intended incompatible changes require a major release
- when practical, deprecated interfaces should warn for at least one minor release before removal
- urgent security fixes may require faster changes and must be called out explicitly in release notes
Requirements:
- use a mature driver with TLS support
- support host, port, database, and user
- apply secure SSL defaults unless
--insecureis used - support native option-file based credential resolution where practical
- do not document or guarantee
MYSQL_PWDas a public credential source
Requirements:
- use a mature driver that aligns with libpq-style connection behavior where practical
- support host, port, database, and user
- support standard PostgreSQL credential conventions such as
.pgpass - support secure SSL defaults unless explicitly overridden
- map shared
ssl_modevalues onto PostgreSQL driver-specific SSL settings internally
Requirements:
- accept a filesystem path instead of host/port/database
- open the database in read-only mode where possible
- document any platform-specific path handling in
--help
The project should include a release workflow suitable for public PyPI publishing.
Release expectations:
uv build --no-sources- publish via
uv publishor a GitHub Actions workflow - prefer PyPI Trusted Publishing over long-lived API tokens
- run no-network tests on supported Python versions
- run opt-in integration tests against real PostgreSQL and MySQL service containers before building release artifacts
The README should include:
- quick start for the default target model
- one-off CLI-only connection examples
- config file examples for MySQL, PostgreSQL, and SQLite
- examples showing
.pgpass, MySQL option files,config init-native-auth --target NAME, and--password-stdin - a clear statement that v1 is read-only by design
config checktroubleshooting and--aboutmetadata examples
These are intentionally out of scope for initial v1 unless implementation is unexpectedly cheap:
- SQL Server support
- OS keychain-backed credential storage
- write-enabled mode
- connection profile inheritance
- schema introspection commands beyond what the query interface already allows
- MySQL login-path support via
.mylogin.cnf