◆

vft-rules:Claude Code 插件级规则注入与自动检查

2026-09-19 02:000

为什么需要它

想让 Claude 写代码时「一定」遵守团队规范,只写说明文字是不够的:

手段什么时候生效能保证遵守吗
CLAUDE.md / .claude/rules/会话开始或读到匹配文件时加载不能,模型可能遗漏
skill描述命中时加载不能
钩子 + 检查脚本每次读写文件时由 Claude Code 自动执行能,违规会被退回修改

另外,插件不能直接提供 .claude/rules/:官方只加载项目和用户目录下的规则文件,插件根目录的 CLAUDE.md 也不会被当作项目上下文。插件能带的是 skill、agent、钩子等。

vft-rules 用钩子把两件事都做了:

  1. 读写文件前注入规范:文件路径命中规则的 paths 时,把规则正文注入给模型,效果等同 .claude/rules/。
  2. 写完文件后自动检查:运行规则声明的检查项,error 级违规直接退回,模型必须修复后才能继续。

装一次插件,所有项目都生效;规则跟着插件升级,改一处各处同步。

工作流程

Claude 读/改 xxx.vue
  → PreToolUse:inject.mjs 匹配 rules/*.md 的 paths
      命中且本会话没注入过 → 注入规则正文
  → 工具执行(写入文件)
  → PostToolUse:check.mjs 运行规则里的 checks
      有 error → 退回模型修复
      只有 warn → 提示,不阻断
上下文压缩 / clear
  → SessionStart:reset.mjs 清注入记录,下次命中重新注入

三个脚本都在 plugins/vft-kit/scripts/rules/,任何内部异常都会静默放行,不会卡住会话。

内置规则:vue-sfc

适用于 **/*.vue,内容覆盖 <script setup>、模板、TSX 渲染函数、响应式副作用和样式。其中能用文本规则可靠判断的条目会自动检查:

检查项级别说明
no-with-defaultserrorVue ≥ 3.5 用 props 解构声明默认值,不用 withDefaults(按项目实际安装的 vue 版本判断,低版本自动跳过)
no-v-if-with-v-forerror同一元素不能同时写 v-if 和 v-for
tsx-no-quoted-directiveerrorTSX 里 v-auth="'a:b'" 多了一层引号,指令收到的是带引号的字符串
v-for-needs-keywarnv-for 必须带 :key
tsx-no-kebab-componentwarnTSX 里 <el-button> 这类小写组件标签不会被自动导入解析

语义类规范(比如「条件判断别漏 .value」「SSR 顶层别碰 window」)只注入说明,由模型遵守。

内置规则:style-layout

适用于 **/*.vue 和 css / scss / sass / less / styl 样式文件,主要解决还原 MasterGo 等设计稿时,模型按图层坐标把整页写成绝对定位的问题:

  • 文档流优先:块级元素自然排列,横向排列与对齐用 flex;设计稿的「自动布局」直接翻译成 flex 属性。position: absolute 只用于角标、浮层、遮罩、装饰层等脱离文档流的元素。
  • 居中按顺序选:flex 居中 → 定宽块 margin: 0 auto → 脱离文档流的元素用 left: 50% + transform: translate(-50%, -50%)。不用按设计稿算出来的 left: 137px 做「看起来居中」。
  • 先看 Vue 版本:Vue 2 项目通常要兼容旧 WebView,不用 CSS Grid,flex 的 gap 也慎用(iOS < 14.5、Chrome < 84 不支持)。Vue 3 项目不受这一条限制。
检查项级别说明
vue2-no-griderror项目安装的 vue 主版本 < 3 时,不能出现 display: grid / inline-grid / -ms-grid 和任何 grid-* 属性(含 grid-gap、grid-column-gap、grid-auto-*、grid 简写)。检查 .vue 的 <style> 块、样式文件,以及模板里的 style / :style(含 gridTemplateColumns 驼峰写法)。scss/less 变量 $grid-gap 和类名 .grid-item 不算。非 Vue 项目或 Vue 3 自动跳过
vue2-flex-gapwarnVue 2 项目里,同一规则块同时写了 display: flex 和 gap / row-gap / column-gap 时提示改用 margin
absolute-hardcoded-layoutwarn同一文件里「position: absolute + 上下、左右两个方向都写死非零长度」的规则块达到 3 个时提示。left: 50% 的居中写法、单个角标不计入;兼容 scss/less 嵌套

确认项目只跑在新内核上时,可以在 .claude/vft-rules.json 里把 vue2-no-grid、vue2-flex-gap 设为 off。

这两项只拦 Claude 的写入。想让人手写的样式也被拦下,在项目 .stylelintrc 的 rules 里加:

'property-disallowed-list': ['/^grid/'],
'declaration-property-value-disallowed-list': { display: ['/grid/'] },

内置规则:package-json

适用于 **/package.json,要求依赖一律写精确版本号,不写 ^1.3.5、~4.17.21、>=1.0.0、* 这类范围。范围版本在重装、换机器、CI 构建或锁文件丢失时会装到不同的小版本,老项目容易因此构建失败。

检查项级别说明
pin-exact-versionerror检查 dependencies、devDependencies、optionalDependencies。提示里给出 node_modules 中实际安装的版本,按它改,不要只删掉 ^(那等于降到范围下限)。workspace:*、catalog:、file:、git 地址、URL 放行;npm: 别名要写精确版本;peerDependencies 描述兼容范围,不检查

安装时加 -E(pnpm add -E xxx),或在项目 .npmrc 写 save-exact=true,就不用装完再手改。对外发布、需要保留范围版本的库,在 .claude/vft-rules.json 里把 pin-exact-version 设为 off。

项目继承与私有规则

在项目根目录建 .claude/ 下的这几个文件。钩子从被操作的文件一路向上查找,所有层级由外到内合并:monorepo 根放一份对全仓生效,子项目再放一份继续追加或覆盖(disable 取并集,检查级别内层覆盖外层,checks.mjs 同名内层覆盖)。

.claude/vft-rules.json        # 关闭规则、调整检查级别
.claude/vft-rules/*.md        # 私有规则
.claude/vft-rules/checks.mjs  # 私有自动检查

继承内置规则并追加

frontmatter 写 extends: vue-sfc,项目正文会追加到内置规范后面,checks 合并:

---
name: my-vue
extends: vue-sfc
checks:
  - no-v-loading
---
- 加载态用 v-spin,不用 v-loading。
- 列表页用 useCrudPage + <crud-page>。

不写 extends 且与内置规则同名时,整条替换;名字不同就是新增规则,可以匹配任意文件类型:

---
name: my-api
paths:
  - 'src/apis/**/*.ts'
checks:
  - no-axios-direct
---
- 接口统一走 request 封装,不直接用 axios。

私有自动检查

checks.mjs 默认导出一个对象,键是检查 id,同名会覆盖内置检查:

export default {
  'no-v-loading': {
    level: 'error', // error 阻断 / warn 提示
    // src: 文件全文;blocks: .vue 文件切好的 template/scripts(其他文件为 null)
    run: ({ src }) => {
      const i = src.search(/\sv-loading[\s=>]/);
      return i < 0 ? [] : [{ line: src.slice(0, i).split('\n').length, message: '加载态用 v-spin' }];
    },
  },
};

关闭与调整级别

{
  "disable": ["vue-sfc"],
  "checks": { "v-for-needs-key": "off", "tsx-no-kebab-component": "error" }
}

在 Codex 或命令行里用

钩子只在 Claude Code 里自动运行。Codex 或手动检查时直接调用同一份脚本:

# 检查文件,有 error 时退出码为 1,可接进 lint-staged / CI
node "$VFT_PLUGIN_ROOT/scripts/rules/check.mjs" src/**/*.vue

# 查看某个文件适用的规则正文
node "$VFT_PLUGIN_ROOT/scripts/rules/inject.mjs" src/App.vue

踩坑与说明

  • zsh 传文件列表:check.mjs $files 在 zsh 里不会按行拆分,整串会当成一个参数,结果显示「没有发现问题」。用 find ... -print0 | xargs -0 node check.mjs。
  • 会话去重:同一会话里一条规则只注入一次,记录存放在 CLAUDE_PLUGIN_DATA(没有时用系统临时目录)。上下文压缩后会自动重新注入。
  • 修改插件规则后:需要升级插件版本并刷新插件缓存(见 plugin-refresh),新会话才会读到新规则。项目内 .claude/vft-rules/ 的改动即时生效。
  • 自测:改完规则模块跑 node plugins/vft-kit/scripts/rules/selftest.mjs。
💬留言板0

还没有留言,来发表第一条吧~

PAGE LOAD / LIVEvft-rules:Claude Code 插件级规则注入与自动检查加载中