beemann/claudeguard

GitHub: beemann/claudeguard

ClaudeGuard 是一个基于 Claude Code 的只读式合并前策略检查工具,用版本化规则集对 diff 做出 PASS/WARN/FAIL 判定,帮助团队在代码合并前自动发现策略违规。

Stars: 0 | Forks: 0

# ClaudeGuard [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) ## 它是什么 ClaudeGuard 是一个**门卫,而不是修复工具**。它针对每一次改动只回答一个问题—— *“这个 diff 是否违反了我们的策略?”*——并将决定权留给人类。 它刻意**复用宿主 agent 的现有引擎**(git、diff 读取、推理),而不是重新构建一个 LLM 客户端、diff 分析器或补丁应用器。ClaudeGuard 唯一拥有的是**以数据形式呈现的策略**:一个包含纯 Markdown 规则的文件夹,每条规则都带有一个小型的 frontmatter 契约,以及描述失败表现及其原因的、人类可读的正文。 这种设计带来了三个值得提前说明的后果: - **关注点分离。** 一个同时*发现*并*修复*违规的组件会有动力去过度标记以显得有用。而纯粹的 gate 不会。 - **杜绝未审查的合并。** 如果在合并前夕作为一个自动修复器在 PR 上运行,它会篡改人类刚刚审查过的 diff。ClaudeGuard 只负责报告;采取行动由你决定。 - **确定性与可审计性。** 输出是一个判定表加上一个可解析的 JSON 区块——可 diff、可审查,并且可以映射到 CI 的退出代码。 ## 0.2.0 的新特性 **更强大、更具确定性的核心。** ClaudeGuard 是构建在非确定性引擎之上的确定性 gate;0.2.0 版本将确定性推向了规则层面: - **确定性的 `detect`/`exempt`。** 规则可以在其 frontmatter 中携带 regex 列表。候选项的检测因此变得可复现——真正的命中不会被悄悄漏掉——而模型只对这些候选项进行*裁决*。已应用于 `no-secrets`、`no-conflict-markers`、`no-any`;其他规则保持仅靠人工判断。 - **可测试的规则。** 固定测试数据 + `scripts/test-rules.{sh,ps1}` 断言所有 `detect`/`exempt` 模式,**无需 LLM 和 API key**,因此确定性层可以免费进行回归测试。 - **稳健的判定。** 该 skill 以运行器直接读取的 `claudeguard-verdict:` 行结束——不再需要从普通文本中费力提取判定结果。 **0.1.0 实现了一步安装:** Claude Code 插件 + marketplace,一个 `claudeguard-init` 引导 skill,一个适用于任何 repo 或 CI 的独立脚本 `scripts/install.{sh,ps1}`,以及引擎/策略分离(通用的 `_core` 随引擎发布;你的 `house` 规则和配置存在于你的 repo 中)。 完整说明请查阅 [CHANGELOG](CHANGELOG.md)。 ## 安装 采用 ClaudeGuard 有两种方式,它们共享一个设计——一个通用的**引擎**(gate skill、`_core` 规则、运行器脚本)加上按项目定制的**策略**(`rulesets/house/`、`claudeguard.config.json`、CI 工作流)。 ### 作为 Claude Code 插件 ``` /plugin marketplace add beemann/claudeguard /plugin install claudeguard@claudeguard ``` 你将立即在每个项目中获得两个 skill:`claudeguard`(gate)和 `claudeguard-init`(引导)。要将 gate 脚手架搭建到当前 repo 中,请询问: 引擎会通过 `/plugin update` 进行更新。作为插件运行时,gate 会从插件中读取其 `_core` 规则,并从项目中读取你的 `house` 规则。 ### 独立模式(任何 repo / CI) 将引擎和策略模板 vendor 到你的 repo 中,自包含且无插件依赖——非常适合 CI: ``` # POSIX scripts/install.sh /path/to/your/repo ``` ``` # PowerShell ./scripts/install.ps1 -Target C:\path\to\your\repo ``` 安装程序是幂等的:它每次运行都会刷新引擎文件,并且绝不会覆盖你的策略(`rulesets/house/`、`claudeguard.config.json`、现有的工作流)。请参阅[分叉到你的项目](#forking-into-your-project)以了解它具体部署了哪些内容。 ## 为什么 静态 linter 只能发现语法错误;它们无法发现*策略*违规。“我们所有的东西都要通过 Docker 运行”、“没有批准不得进行破坏性迁移”、“每个新路由都必须声明其认证姿态”、“没有度量就不要优化”——这些都是团队契约,通常存放在一个在审查时没人会重新阅读的 `CLAUDE.md` 中。ClaudeGuard 将这些契约转化为可执行的规则,并在成本最低的时机强制执行它们:**在合并之前**。 ## 工作原理 该流程定义在 [`SKILL.md`](SKILL.md) 中,分五个步骤运行: 1. **解析 diff。** 默认基准是 `origin/main`(使用 merge-base,因此只判断分支自身的提交);可按项目或按运行覆盖。 2. **解析规则集。** 从引擎的 `_core`(作为插件安装时位于 `${CLAUDE_PLUGIN_ROOT}/rulesets/_core/`)和项目的 `rulesets/` 中读取每个 `*.md` 文件,按 `id` 去重(项目副本优先,以便 repo 可以覆盖内置规则),遵循 `claudeguard.config.json`(启用/禁用、严重性覆盖),并且只保留其 `applies_to` glob 至少匹配到一个更改文件的规则。 3. **冒烟检查(强制性,防伪造)。** 对于每条保留的规则,说明它*实际*适用于多少个已更改的文件。匹配零个文件的规则将被丢弃——gate 绝不会为了证明某条规则的用处而捏造违规。 4. **评估。** 仅判断已添加/修改(`+`)的行。声明了 `detect` 模式的规则会获得**确定性候选项检测**(regex 找到命中项;模型仅根据规则的豁免项对它们进行裁决);没有 `detect` 的规则则直接由模型判断。每次违规都必须引用具体的证据:一个文件、尽可能精确的行号,以及违规的确切行内容。 5. **判定。** 如果有任何违规是 `high`/`critical` 则为 `FAIL`;`medium`/`low` 则为 `WARN`;如果干净则为 `PASS`。阈值可通过 `block_on` 配置(默认为 `high`)。 ## 输出 ClaudeGuard 会输出一个人类可读的表格,其后跟着一个机器可读的 JSON 区块: ``` ClaudeGuard verdict: FAIL Base: origin/main · Files scanned: 7 · Rulesets active: 5 | Severity | Rule | File | Line | Why | |----------|-------------|-----------------|------|------------------------------| | high | docker-only | scripts/dev.ps1 | 12 | `npm run dev` invoked on host | | medium | no-any | src/api/user.ts | 44 | `: any` on request body | ``` ``` { "verdict": "FAIL", "base": "origin/main", "files_scanned": 7, "rulesets_active": ["docker-only", "no-any", "..."], "violations": [ { "rule": "docker-only", "severity": "high", "file": "scripts/dev.ps1", "line": 12, "evidence": "+ npm run dev", "why": "Command invoked on host instead of `docker compose exec app …`.", "suggestion": "docker compose exec app npm run dev" } ], "block_on": "high" } ``` CI 运行器将判定结果映射到退出代码:`PASS`/`WARN` → `0`,`FAIL` → `1`。 ## 规则集 规则分为两个层级发布: | 层级 | 文件夹 | 意图 | |------|--------|--------| | **Core** | `rulesets/_core/` | 通用、与供应商无关、无争议——可直接采用。 | | **House** | `rulesets/house/` | 你团队的偏好规则——可在分叉时替换。 | 内置规则: | 规则 | 层级 | 严重性 | 触发条件 | |------|------|----------|----------| | `no-secrets` | core | critical | 凭证/key/token 字面量(提供商前缀、PEM 区块、密钥赋值)。 | | `no-conflict-markers` | core | high | 被提交到受跟踪文件中且未解决的 git 冲突标记。 | | `docker-only` | house | high | 项目工具运行在宿主机上而不是容器内(shell 脚本和任务运行器)。 | | `no-destructive-db` | house | critical | 未受保护的 `DROP`/`TRUNCATE`/`DELETE … ` 且没有 `WHERE` 等。 | | `security-routes` | house | high | 没有可见认证、验证或注入姿态的新路由/处理程序。 | | `no-any` | house | medium | `any`、`as any`、`@ts-ignore` 和其他 TypeScript 逃生舱。 | | `measurement-first` | house | medium | 声称要*优化*某项内容但没有基准/度量的更改。 | ## 用法 ### 作为 Claude Code skill 将此 repo 的内容放在 Claude Code 能够发现 skill 的位置(例如你项目中的 `.claude/skills/claudeguard/`),然后询问: ### 本地运行器 ``` # PowerShell ./scripts/check.ps1 -BaseRef origin/main ``` ``` # POSIX scripts/check.sh origin/main ``` 需要在 `PATH` 中有 `git`、`claude` CLI,并在环境变量中设置 `ANTHROPIC_API_KEY`。空的 diff 会直接判定为 `PASS`。 ### CI (GitHub Actions) [`.github/workflows/claudeguard.yml`](.github/workflows/claudeguard.yml) 会对拉取请求进行拦截,将判定结果作为 PR 评论和作业摘要发布,并在出现 high/critical 违规时阻止合并。添加一个仓库 secret `ANTHROPIC_API_KEY` 即可激活它。 ## 配置 将 [`claudeguard.config.example.json`](claudeguard.config.example.json) 复制到 `claudeguard.config.json` 并按项目进行编辑: ``` { "base": "origin/main", "block_on": "high", "rules": { "no-secrets": { "enabled": true }, "docker-only": { "enabled": true, "severity": "critical" } } } ``` - `base` — 用于进行 diff 对比的默认参考分支。 - `block_on` — 产生 `FAIL` 的最低严重性(`low`|`medium`|`high`|`critical`)。 - `rules..enabled` — 在不删除规则的情况下将其关闭。 - `rules..severity` — 覆盖规则内置的严重性。 ## 编写规则 将一个 `*.md` 文件放入 `rulesets/_core/`(通用)或 `rulesets/house/`(团队特定)。无需更改任何代码——流程会自动识别它。 ``` --- id: no-todo-without-ticket severity: low applies_to: - "**/*.ts" - "**/*.py" enabled: true detect: # optional: deterministic candidate detection (ERE) - 'TODO|FIXME' exempt: # optional: suppress candidates that cite a ticket - '[A-Z]+-[0-9]+|#[0-9]+' --- # 没有 tracking ticket 就没有 TODO **FAIL** when the diff adds a `TODO`/`FIXME` with no issue reference. Trip on added lines matching `TODO`/`FIXME` not followed by a ticket id (e.g. `JIRA-123`, `#456`). **Why:** untracked TODOs are debt that never gets scheduled. **Suggestion:** link a ticket, or do the work now. ``` **确定性检测(可选)。** 规则可以携带 `detect`(和 `exempt`)regex 列表。检测随后会*确定性地*运行:当更改的行匹配到 `detect` 模式且不匹配任何 `exempt` 模式时,它就是一个候选项,模型仅根据规则主体对这些候选项进行*裁决*。这使得召回率可复现——真正的命中不会被漏报——这也是模式规则(`no-secrets`、`no-conflict-markers`、`no-any`)应具备的正确形态。没有 `detect` 的规则将像以前一样完全由模型进行判断。 **测试你的模式。** 添加 `fixtures//should-fail.txt` 和 `should-pass.txt`,然后运行 `scripts/test-rules.sh`(或 `.ps1`)。它会**无需 LLM 和 API key** 就断言所有针对这些固定数据的 `detect`/`exempt` 模式,因此确定性层可以免费进行回归测试。 保持 `_core` 规则毫无争议;任何有争议的内容都属于 `house/`。每一条规则主体都应当用通俗的语言说明,**什么样子的情况算 `FAIL`**,**为什么**它很重要,以及一个**建议**——并且应当依赖于 diff 中可见的证据。 ## 分叉到你的项目 最快的途径是使用[独立安装程序](#standalone-any-repo--ci)或 `claudeguard-init` skill——两者都会完整部署以下所有内容。在底层,它会: 1. 将引擎复制到你的 repo 中:gate skill → `.claude/skills/claudeguard/SKILL.md`、`rulesets/_core/`、`scripts/check.*`,以及工作流(如果不存在)。 2. 仅在它们不存在时,才会植入 `rulesets/house/` 和 `claudeguard.config.json`——你的策略永远不会被覆盖。 然后将其变成你自己的专属配置: 3. 用你团队的规则替换 `rulesets/house/`;保留 `rulesets/_core/`。 4. 根据你的技术栈调整 `applies_to` glob 和触发模式(例如 Bun 对比 npm,Drizzle 对比 Prisma,Hono 对比 Express)。 5. 在 `claudeguard.config.json` 中将 `base` 设置为你的集成分支。 ## 设计原则与非目标 - **绝不编辑、暂存或提交。** 这是一个 gate,而不是修复工具。 - **绝不为了使规则看起来有用而捏造违规。** 无效规则 → 直接丢弃。 - **基于证据。** 每一个违规都会引用确切的增加行。 - **宁缺毋滥。** 一个错误的 `FAIL` 比漏报一个 `LOW` 更快失去信任。 - **确定性输出**,以便报告的 diff 保持可审查性。 ## 许可证 [MIT](LICENSE) © 2026 Beeman
标签:AI合规, AI编程, Cutter, Homebrew安装, Libemu, 云安全监控, 代码审查, 开发辅助, 开源框架, 持续集成, 网络安全研究, 防御加固, 静态分析