内容
# 哨兵
**适用于 AI 编程代理的完全本地验证层。** 哨兵可以与任何兼容 MCP 的代理(Claude Code、Cursor、Copilot、OpenCode 等)连接,并允许它自我检查自己的工作成果 —— 差异是否真正完成了任务、引用的代码是否存在、是否泄露了秘密、是否与代码库的风格匹配 —— 在人类看到之前。所有操作都在您的机器上运行:无需云后端,无需遥测,无需账户。
[](LICENSE)
## 快速入门
```bash
# 需要 Node.js 24+(哨兵使用 Node.js 内置的 SQLite — 无需编译)
npm install -g sentinel-verify
cd your-project
sentinel init # 创建本地的 .sentinel/ 数据文件夹
# 连接您的代理 — 一个命令,无需编辑配置:
sentinel connect claude-code # 或:cursor,antigravity
```
就这样。您的代理现在有四个可以调用的验证工具。在代理模式下,哨兵不需要 **任何 API 密钥和本地模型** — 请参见下面的两种模式。
## 连接代理
**推荐:`sentinel connect <agent>`** — 在项目根目录中运行它,并写入正确的 MCP 条目(绝对路径,项目根目录通过 `SENTINEL_PROJECT_ROOT` 固定),安全地与已经配置的任何 MCP 服务器合并。不会触及格式错误的配置文件 — 而是出现错误。
| 代理 | 命令 | 它写入的配置 |
|---|---|---|
| Claude Code | `sentinel connect claude-code` | `<project>/.mcp.json` |
| Cursor | `sentinel connect cursor` | `<project>/.cursor/mcp.json` |
| Antigravity | `sentinel connect antigravity` | `~/.gemini/antigravity/mcp_config.json`(全局 — 固定到运行的项目) |
`sentinel connect --list` 在终端中显示此表格。连接后,重启/重新加载代理,以便它获取新的服务器。随时重新运行 `connect`(例如,在更新 Node.js 或 Sentinel 之后)— 它会刷新条目。支持新代理是 `src/cli/commands/connect.ts` 中的 `AGENTS` 表中的一个条目 — 欢迎 PR。
<details>
<summary><strong>手动设置(适用于上述未列出的代理)</strong></summary>
任何 MCP 客户端都可以使用 — 配置它以启动 `sentinel mcp` 作为 stdio 服务器。对于通过 JSON 配置的客户端:
```json
{
"mcpServers": {
"sentinel": {
"command": "sentinel",
"args": ["mcp"],
"env": { "SENTINEL_PROJECT_ROOT": "/absolute/path/to/your-project" }
}
}
}
```
如果代理在启动服务器时不使用您的 shell 的 PATH,请使用 `sentinel` 二进制文件的绝对路径(使用 `which sentinel` 查找)或 `node /path/to/dist/cli/index.js` 作为命令。Claude Code 用户可以等效地运行 `claude mcp add sentinel -e SENTINEL_PROJECT_ROOT="$(pwd)" -- sentinel mcp`。
</details>
**哨兵如何找到您的项目:** 一些 MCP 客户端从意外的当前工作目录(甚至 `/`)启动服务器,因此哨兵防御性地解析项目根目录,按以下顺序:`SENTINEL_PROJECT_ROOT` 环境变量 → 一个合理的启动目录 → MCP 客户端声明的工作区根目录(协议的 `roots` 能力)。如果这些都不起作用,工具调用会失败,并显示清晰的消息,而不是写入错误的位置。`sentinel connect` 为您设置环境变量,这就是为什么它是推荐的路径。
可选附加功能:
```bash
sentinel install-hook # 在 git 预提交时阻止不良提交
sentinel dashboard # 验证历史记录的本地 Web UI
```
## 四项检查
| 工具 | 它回答的问题 |
|---|---|
| `verify_task_match` | 差异是否**功能性地**完成了声明的任务 — 而不仅仅是表面上? |
| `check_hallucination` | 差异引用的包、文件和符号是否真正**存在**?(针对 `package.json`、`node_modules` 和实际文件系统进行验证) |
| `check_security` | 是否有泄露的秘密(AWS/GitHub/Slack/Stripe/... 密钥、私钥、连接字符串 — 检测并**屏蔽**),`eval`、Shell 注入、禁用的 TLS、硬编码凭证? |
| `check_style_consistency` | 差异是否以该项目已经**存在**的方式编写代码?(缩进、引号、分号、命名、模块样式 — 从实际文件中测量) |
每项检查都结合了**确定性证据**(文件系统检查、模式规则、样式测量 — 权威)和**模型判断**(适用于规则无法证明的内容)。每项结果都存储在 `.sentinel/sentinel.db` 中。
## 两种模式,一个重要理念
**代理模式(MCP)** — 当 AI 代理调用哨兵的工具时,哨兵**不**运行自己的模型。调用的代理已经是一个强大的、已经付费的模型;第二个较弱的判断会增加成本和噪音。相反,每个工具返回结构化的**证据** — 确定性发现、测量的样式配置文件、项目规则 — 以及告诉代理如何判断的指令。无需任何:无需密钥,无需 Ollama。
**独立模式(CLI)** — 在终端中自行运行检查时,没有代理来判断,因此哨兵使用自己的模型层:**默认情况下免费的本地 Ollama**(推荐模型:`ollama pull qwen2.5-coder`),或您自己的 Anthropic API 密钥(如果您设置了一个)。
```bash
git diff | sentinel test-security # 独立检查,本地判断
git diff | sentinel test-hallucination
git diff | sentinel test-style
sentinel test-verify --task "Add rate limiting" --diff-file change.diff
```
所有 `test-*` 命令在发现问题时退出状态非零,因此它们可以组合到脚本中。
| | 代理模式(MCP) | 独立模式(CLI) |
|---|---|---|
| 谁来判断 | 调用代理 | 哨兵的配置模型 |
| 要求 | 无 | Ollama 运行,**或** `ANTHROPIC_API_KEY` |
| 结果 | 证据 + 判断指令 | 最终裁决(退出代码) |
独立设置:`SENTINEL_PROVIDER`(`ollama`/`anthropic`; 默认自动 — 如果设置了 Anthropic 密钥,则为 Anthropic,否则为 Ollama),`SENTINEL_MODEL`(模型覆盖),`OLLAMA_HOST`,`ANTHROPIC_API_KEY`(环境变量或项目根目录中 git 忽略的 `.env`)。
## 预提交钩子
```bash
sentinel install-hook # sentinel uninstall-hook 删除
```
每次 `git commit` 检查**暂存**的差异 — 默认情况下为 `check_security`。发现问题会阻止提交,并附有打印的摘要;可以使用 `git commit --no-verify` 跳过一次提交。**失败关闭:** 如果模型层不可用,提交将被阻止,并附有设置说明 — 损坏的设置永远不会静默地通过提交。安装拒绝覆盖哨兵未创建的钩子,卸载拒绝删除它。
## 本地仪表盘
```bash
sentinel dashboard # http://127.0.0.1:4747 (--port 修改)
```
总数、每个工具的标记率和完整的历史记录,带有点击展开的详细信息,从一个自包含的页面提供,该页面绑定到 `127.0.0.1` — 无外部资产,无分析。存储前会屏蔽秘密,因此仪表盘永远不会显示一个。
## 配置:`.sentinelrc`(可选)
默认情况下无需配置。在项目根目录中,可选的 `.sentinelrc`(JSON,严格验证 — 拼写错误会大声失败)添加了团队标准:
```json
{
"context": "使用 GSAP 进行动画的 React + TypeScript SPA。仅限现代浏览器。",
"style": { "indent": 2, "quotes": "single", "semicolons": "always", "naming": "camelCase", "moduleStyle": "esm" },
"tools": { "check_style_consistency": false },
"rules": [
"永远不要建议 React 类组件 — 仅限函数组件和钩子。",
"在讨论之前不要添加新的 npm 依赖项。"
],
"hook": { "tools": ["check_security", "check_hallucination"] }
}
```
| 字段 | 影响 |
|---|---|
| `context` | 提供给所有模型提示的自由文本项目描述(最大 2000 个字符)。 |
| `style` | 惯例覆盖**替换**推断 — 甚至在全新项目中也强制执行。`indent` 可以是 `"tabs"` 或空格数。 |
| `tools` | 禁用任何工具:它会使 MCP 服务器和 CLI 命令打印跳过通知。 |
| `rules` | 普通语言策略(最大 20 × 500 个字符),模型层会标记违反这些策略的内容。短小精悍的效果最好。 |
| `hook.tools` | 预提交钩子运行的内容(默认 `["check_security"]`; `verify_task_match` 不能在钩子中运行)。 |
## 显示您已覆盖
在您的项目中集成哨兵?将徽章添加到您的 README 中:
```markdown
[](https://www.npmjs.com/package/sentinel-verify)
```
[](https://www.npmjs.com/package/sentinel-verify)
## 设计原则
- **100% 本地** — 无哨兵拥有的后端,无遥测;除了您自己的可选 API 调用到您自己的提供商外,任何内容都不会离开您的机器。
- **默认免费** — 代理模式根本不需要模型;独立模式在本地 Ollama 上运行。
- **确定性优先** — 文件系统检查、模式规则和测量是权威的;模型判断填补空白,永远不会覆盖它们。
- **与代理无关** — 普通 MCP;不锁定到任何供应商。
## 语言覆盖
`check_hallucination` 和 `check_style_consistency` 的确定性部分涵盖 JavaScript/TypeScript;`check_security` 的规则涵盖 Node、Python、Go 和 Shell 模式。其他语言获得每种工具的模型判断部分。
## 贡献
欢迎提出问题和 PR。代码库故意设计得小而易读:`src/verify/` 包含四个工具加上共享的差异/组合逻辑,`src/providers/` 包含模型层(Ollama、Anthropic — 欢迎 OpenAI 提供商的贡献),`src/mcp/` 包含服务器,`src/cli/` 包含命令,`src/dashboard/` 包含 UI。保持依赖项最小(目前为三个),保持秘密屏蔽,并保持所有内容本地。许可为 MIT。