db-driver
v0.1.5
Published
Database CLI tool with web-based configuration
Downloads
773
Maintainers
Readme
db-driver
让 AI Agent 安全使用 MySQL / PostgreSQL 的 CLI 工具 — 通过
~/.agents/skills/db-driverskill 一键安装。npm 包
db-driver· CLI 命令db-driver· 本地配置加密存储
为什么需要它
让 AI 直接拼 SQL 是有风险的:
- 注释断字
U/**/PDATE绕过简单正则检测 - 存储过程
CALL proc()可以做任何事 - 一句写错的 SQL 改坏了生产数据
db-driver 用 AST 解析器(node-sql-parser)做 SQL 权限校验,配 JSON 输出 给 AI Agent 用,最少上下文、最高可控。
30 秒上手
# 1. 安装
npm install -g db-driver
# 2. 给 AI 配置一个 DB 连接(只读账号更安全)
db-driver config --dbId my-app \
--type mysql --host 127.0.0.1 --port 3306 \
--user reader --password secret --database mydb
# 3. 让 AI 自动装上 skill
db-driver install
# 4. AI 开始查询
db-driver schema my-app
db-driver execute my-app "SELECT * FROM users LIMIT 5" --json给 AI Agent 用:skill 工作流
db-driver install 会把 skill/SKILL.md 写入 ~/.agents/skills/db-driver/。之后任何支持 skills 的 Agent 工具(Claude Code、本地 IDE agent 等)都能自动发现并学会这套命令。
AI 拿到任务时的标准流程:
db-driver list→ 知道有哪些 dbId 可用db-driver schema <dbId>→ 列出表名(轻量,不爆上下文)db-driver schema <dbId> --table <name>→ 找具体表的字段 + 索引db-driver sample <dbId> <table>/count <dbId> <table>→ 看样本 / 统计db-driver execute <dbId> "<SQL>" --json→ 跑查询- 需要改表结构?→
db-driver execute <dbId> "<DDL>"(需要ddl权限)
给 AI 的最佳实践:
- 永远加
--json— Agent 解析 JSON 比解析表格稳 - 永远带
--limit— 默认 50 行,防爆炸 - 不确定时先 schema — 别瞎写列名/表名
- 写操作前先 count — 确认影响范围
权限模型
核心设计:每个连接保存时绑定 4 个权限位,执行 SQL 前做权限校验。
| 权限位 | 默认值 | 允许的 SQL 类型 |
|--------|--------|----------------|
| dmlQuery | ✅ true | SELECT / SHOW / DESCRIBE / EXPLAIN |
| dmlUpdate | ❌ false | INSERT / UPDATE / REPLACE / MERGE |
| dmlDelete | ❌ false | DELETE |
| ddl | ❌ false | CREATE / ALTER / DROP / TRUNCATE / RENAME 等 |
任何 SQL 执行前都会走这个流程:
SQL 文本
↓
node-sql-parser 解析为 AST
↓
解析失败?→ ❌ 拒绝(防注释断字 / 条件注释等绕过)
↓
AST 类型 → 映射到 4 个权限位之一
↓
权限位开启?→ ✅ 执行
权限位关闭?→ ❌ 拒绝并打印「<操作> 已被禁用」能挡住什么
| 攻击 | 拦截方式 |
|------|----------|
| UPDATE users SET ... | AST 识别为 update + dmlUpdate 未开 |
| U/**/PDATE users ... | 注释断字 → parser 失败 → 拒绝 |
| /*! UPDATE */ users ... | MySQL 条件注释 → parser 失败 → 拒绝 |
| CALL dangerous_proc() | AST 识别为 call → 要求 ddl 权限 |
| LOAD DATA INFILE ... | AST 识别为 load → 要求 ddl 权限 |
| PREPARE stmt FROM '...' | AST 识别为 prepare → 要求 ddl 权限 |
| 多语句 SELECT 1; DROP TABLE x | parser 返回多条语句 → 拒绝 |
| 语法错误 / 解析失败 | 一律 dangerous → 拒绝 |
挡不住什么(必须靠「最小权限 DB 账号」兜底)
- 数据库触发器:SELECT 自动触发 INSERT/UPDATE
- 用
root/superuser账号 → 任何工具都拦不住直接 psql/mysql 连 - AI 改其它通道(直接 psql、SSH、Web 面板)
👉 终极建议:用最小权限的 DB 账号配置 db-driver
-- MySQL 只读账号示例
CREATE USER 'reader'@'%' IDENTIFIED BY 'xxx';
GRANT SELECT ON mydb.* TO 'reader'@'%';
-- 写权限账号(谨慎)
CREATE USER 'writer'@'%' IDENTIFIED BY 'yyy';
GRANT SELECT, INSERT, UPDATE ON mydb.* TO 'writer'@'%';把 reader 配进 db-driver 给日常查询,需要写时再单独配 writer。
配置详解
两种方式,二选一:
方式 A:命令行 flags(适合脚本)
db-driver config \
--dbId my-app \
--type mysql \
--host 127.0.0.1 --port 3306 \
--user root --password secret \
--database app \
--dml-query --dml-update --ddl \
--test # 保存前先 ping必填:--dbId --type --host --user --password --database
可选:--port(按类型默认)、权限开关、--test、--schema(PG)、--description
PostgreSQL 多 schema 支持
PG 一个 catalog 内有多个 schema(如 public、tenant_1)。db-driver 默认按 public 处理:
db-driver config --dbId my-app \
--type postgres --host ... --database mydb \
--schema tenant_1 # 默认 public,可指定
--description "生产 - 租户1" # 可选,便于区分多套环境schema 命令支持临时覆盖:
db-driver schema my-app --schema tenant_1
db-driver schema my-app --schema tenant_1 --table orders方式 B:网页控制台(适合人)
db-driver console浏览器打开 http://127.0.0.1:7842,可视化增删改连接配置、勾选权限、查看表结构、编辑 SQL 用法笔记、测试连接等。Ctrl+C 退出。
配置存储格式(加密)
连接配置用 AES-256-GCM 加密二进制存储,master key 由 OS keyring 托管(Windows DPAPI / macOS Keychain / Linux Secret Service)。
- 不存在明文 JSON,密码字段不被机器单独抽取
- 配置文件不公开具体路径
- 系统重装 / 换用户后 keyring 中的 key 会丢失,配置需重新 config(设计如此:密钥不跨机器迁移)
- 没有手动编辑入口;统一通过
db-driver config(CLI)或db-driver console(网页)修改
// 配置内容示例(实际是加密二进制)—— 仅供理解结构
{
"version": 1,
"connections": [
{
"dbId": "my-app",
"type": "mysql",
"host": "127.0.0.1",
"port": 3306,
"user": "reader",
"password": "...",
"database": "mydb",
"schema": null,
"description": null,
"permissions": {
"dmlQuery": true,
"dmlUpdate": false,
"dmlDelete": false,
"ddl": false
},
"createdAt": "2026-09-19T...",
"updatedAt": "2026-09-19T..."
}
]
}schema(PG 专用,可选)、description(连接描述,可选)是向后兼容的扩展字段,旧配置文件读取时缺省等同于未设置。
命令一览
连接管理
| 命令 | 何时用 |
|------|--------|
| db-driver console [--port N] | 打开网页控制台(同时管理连接配置 + SQL 用法笔记,默认 7842 端口) |
| db-driver config --dbId x --type ... | 命令行快速保存连接(适合脚本) |
| db-driver console | 打开网页控制台(同时管理连接配置 + SQL 用法笔记) |
| db-driver list | 列出所有 dbId |
| db-driver show <dbId> | 看连接详情(密码默认隐藏,--reveal-password 显示明文) |
| db-driver test <dbId> | 测试连通性 |
| db-driver remove <dbId> --yes | 删除连接 |
| db-driver export <file> [--passphrase <pwd>] | 导出所有连接到文件(passphrase 留空 = 明文 JSON;≥8 位 = 加密 .exp) |
| db-driver import <file> [--passphrase <pwd>] [--replace] | 从文件导入连接(同名 dbId 默认跳过,--replace 覆盖) |
数据浏览
| 命令 | 何时用 |
|------|--------|
| db-driver schema <dbId> | 列表名(第一步必走) |
| db-driver schema <dbId> --table <t> | 看字段 + 索引 + 注释 |
| db-driver schema <dbId> --table <t> --show-partitions | 同时输出 MySQL 分区子表信息 |
| db-driver schema <dbId> --search <p> | 按表名模糊过滤 |
| db-driver schema <dbId> --schema <s> | PG 临时切换 schema(覆盖配置默认) |
| db-driver schema <dbId> --limit N --offset M | 列表分页(total/offset/limit 都在输出里) |
| db-driver sample <dbId> <table> | 样本数据(默认 10 行) |
| db-driver count <dbId> <table> | 行数 |
| db-driver execute <dbId> "<SQL>" --json | 跑查询(带 JSON 输出) |
| db-driver explain <dbId> "<SQL>" | 执行计划(不执行) |
| db-driver explain <dbId> "<SQL>" --analyze | 真正执行并返回耗时 |
用法笔记(明文 Markdown,一条笔记可关联多个 dbId)
| 命令 | 何时用 |
|------|--------|
| db-driver usage list | 列出(默认只显示标题 + 首行预览) |
| db-driver usage list --dbId a,b | 过滤(逗号分隔,OR 匹配) |
| db-driver usage list --search <kw> | 关键词搜索(title / dbIds / content) |
| db-driver usage list --limit N --offset M | 翻页 |
| db-driver usage detail <index> | 查看某条完整 Markdown |
| db-driver usage save --dbId a,b --title "..." --content "..." | 新增(多 dbId 逗号分隔) |
| db-driver usage save --dbId a --title "..." --content-file ./note.md | 从文件读内容 |
| db-driver usage save --dbId a --title "..." --content-file - | 从 stdin 读 |
| db-driver usage update <index> --title/--content/--dbIds | 更新(AI 友好,字段可省略) |
| db-driver usage update <index> --content-file ./new.md | 从文件读新内容 |
| db-driver usage bind --add prd | 批量给所有笔记加 prd 关联 |
| db-driver usage bind --remove staging | 批量给所有笔记删 staging 关联 |
| db-driver usage bind --entries 1,2,3 --add a | 只给指定序号加 |
| db-driver usage rm <index> | 删除 |
| db-driver usage clear [--dbId <id>] --yes | 清空(可指定 dbId) |
安装 / 自更新
| 命令 | 何时用 |
|------|--------|
| db-driver install | 把 skill 装到 ~/.agents/skills/db-driver/ |
| db-driver update | 从 npm 自更新(拒绝源码 link 模式) |
| db-driver update --check | 仅检查是否有新版 |
通用选项
--json— 所有查询类命令都支持,AI 解析用--limit N—execute/sample限制返回行数(默认 50 / 10);schema/usage list列表分页--offset M—schema/usage list列表分页(与 --limit 配合翻页)--where <expr>—sample/count附加 WHERE 条件
错误信息本地化
所有 DB 错误自动翻译为中文,格式 中文提示(原始错误消息),便于排查:
MySQL 错误码
| 错误码 | 翻译 | |--------|------| | 1044 | 访问被拒绝:当前用户无权访问该数据库 | | 1045 | 访问被拒绝:用户名或密码错误 | | 1049 | 数据库不存在 | | 1054 | 未知列 | | 1062 | 唯一键冲突(重复插入) | | 1064 | SQL 语法错误 | | 1141 / 1142 | 权限不足 | | 1146 | 表不存在 | | 1205 | 锁等待超时 | | 1213 | 死锁,请重试 | | 2002 | 无法连接到数据库主机(连接被拒绝) | | 2003 | 无法连接到数据库主机(端口不可达) | | 2013 | 连接丢失(网络问题或查询超时) | | ECONNREFUSED | 连接被拒绝:检查 host/port 是否正确,数据库服务是否启动 |
PostgreSQL SQLSTATE
| SQLSTATE | 翻译 | |----------|------| | 08000 / 08001 / 08003 / 08006 | 连接异常/失败 | | 23502 | 非空约束违反 | | 23503 | 外键约束违反 | | 23505 | 唯一键冲突(重复插入) | | 28P01 | 身份验证失败:用户名或密码错误 | | 3D000 | 数据库(catalog)不存在 | | 40P01 | 死锁,请重试 | | 42501 | 权限不足 | | 42601 | SQL 语法错误 | | 42703 | 列不存在 | | 42P01 | 表或视图不存在 | | 55P03 | 锁等待超时,请稍后重试 |
故障排查
| 现象 | 排查 |
|------|------|
| 命令不存在 | npm install -g db-driver 没跑 / PATH 不对 |
| 连接不存在 | db-driver list 看可用 dbId |
| 权限被拒("已被禁用") | db-driver show <dbId> 看实际权限位;错误消息附带 SELECT=... UPDATE=... DELETE=... DDL=...;手动用 db-driver config 调整(不要让 AI 自动调) |
| SELECT 报权限不足但理应通过 | 错误消息会附带当前权限,确认 dmlQuery=true;可能 SQL 被 AST 识别成其他类型(用 --json + node-sql-parser 排查) |
| 表/列不存在 | db-driver schema <dbId> --search <keyword> |
| PG schema 找不到表 | db-driver show <dbId> 确认 schema 字段;可用 --schema 临时切换 |
| 列表太多想翻页 | schema / usage list 加 --limit N --offset M |
| 想看 MySQL 分区子表 | schema <dbId> --table <t> --show-partitions |
| 无法解析 SQL | 含注释断字/条件注释,已被拒绝(设计如此) |
| 笔记想批量加 dbId | usage bind --add <dbId>(一次性应用到所有笔记) |
| 笔记想单条改 dbId/title | usage update <index> --title ... --dbIds a,b(AI 友好,非阻塞) |
| 进程卡住 | MySQL/PG 连接池问题;db-driver update 拉到最新版试试;npm run dev:stop 清理残留 |
AI Agent 协作红线
如果由 AI Agent 在调用本工具:
- 禁止自行提升权限 —— 权限被拒时不要自动跑
db-driver config加新权限 - 提权必须用户明确同意 —— 只有用户亲口说"开 XX 权限"才能给新的 config 命令
- 失败立即停下并报告 —— 不要尝试第二条路径蒙混
- 不要直接编辑配置文件 —— 让用户自己用
db-driver config
完整版见 skill/SKILL.md(AI Agent 实际加载的入口)。
开发
git clone https://github.com/668mt/db-driver.git
cd db-driver
npm install
npm run build # 编译到 dist/
npm link # 全局链接 → db-driver 命令可用修改代码后必跑:
npm run build # 编译
db-driver install # 同步 skill(命令改了必跑)完整规范见 AGENTS.md。
发布
# 改版本 + 编译 + 发布
npm run release:patch # 0.1.0 → 0.1.1
# 或 minor / major
# 推送代码 + tag
git push --follow-tags发布后用户用 db-driver update 升级。
架构
db-driver/
├── src/
│ ├── cli.ts # commander 入口
│ ├── commands/ # 每个子命令一个文件
│ ├── db/
│ │ ├── mysql.ts # MySQL 驱动 (mysql2/promise)
│ │ ├── postgres.ts # PostgreSQL 驱动 (pg.Client)
│ │ ├── pool.ts # 进程内连接池(30s TTL)
│ │ ├── permissions.ts # AST 解析 + 权限校验
│ │ ├── types.ts # DbConnectionConfig 等共享类型
│ │ └── index.ts # createDriver 工厂
│ ├── store/
│ │ ├── configStore.ts # AES-256-GCM 加密连接配置
│ │ └── usageStore.ts # SQLite 存储用法笔记
│ ├── utils/
│ │ ├── paths.ts # 配置 / skill 路径
│ │ ├── crypto.ts # AES-256-GCM 加解密
│ │ ├── ident.ts # 表名/列名引用
│ │ └── errors.ts # 错误码中文翻译
│ └── web/ # db-driver console 的本地网页(React + Vite)
│ ├── server.ts # 本地 HTTP 服务(连接 + 用法 API)
│ └── src/ # React 组件
├── skill/SKILL.md # AI Agent 看到的入口
└── AGENTS.md # 架构与规范许可
MIT
