编辑
2026-07-07
AI
00
请注意,本文编写于 47 天前,最后修改于 46 天前,其中某些信息可能已经过时。

目录

hooks
实践

hooks

中文名为钩子,实际常用于代码某些执行阶段触发某些逻辑,如结尾触发检测或测试,使得代码编译正常。

安全防线、质量守卫、审计日志,全部由 Hooks 在“幕后”自动完成,高频用于自动化或安全控制;

cursor中hooks配置:https://cursor.com/cn/docs/hooks claude code: https://code.claude.com/docs/en/hooks-guide

实践

针对vue3代码:高频用于eslint 运行没问题后再给到执行,可以有效降低AI带来的语法等问题。

配置:Cursor Hook(钩子),用来在 AI Agent 每次“结束回答”时自动做一次 ESLint 检查

文件位置:.cursor/hooks.json

js
{ "version": 1, "hooks": { "stop": [ { "command": "node .cursor/hooks/local-lint-check.mjs", "timeout": 300, "loop_limit": 3 } ] } }

相关信息

含义:

stop:事件类型。当 Agent 一轮任务“停止/完成”时触发(也就是 AI 觉得自己干完活、准备把结果交给你之前)。 command:触发时运行的命令,这里就是执行那个 .mjs 脚本。 timeout: 300:脚本最多跑 300 秒,超时就中断。 loop_limit: 3:最关键的一点——如果 hook 让 Agent 继续修(返回了 followup_message),最多循环 3 次,防止无限循环。

.cursor/hooks/local-lint-check.mjs

js
#!/usr/bin/env node /** * Cursor stop hook: lint changed src files with the same ESLint rules as `npm run local` * (vite-plugin-eslint in config/vite.config.dev.ts). */ import { spawnSync } from 'node:child_process' import { readFileSync } from 'node:fs' const MAX_OUTPUT_CHARS = 8000 const LINTABLE_FILE = /\.(vue|ts|tsx|js|jsx)$/i function readHookInput() { try { const raw = readFileSync(0, 'utf8') return raw ? JSON.parse(raw) : {} } catch { return {} } } function runGit(args) { const result = spawnSync('git', args, { cwd: process.cwd(), encoding: 'utf8', shell: process.platform === 'win32', }) return (result.stdout || '').split(/\r?\n/).filter(Boolean) } function getChangedLintableFiles() { const files = new Set() for (const file of runGit(['diff', '--name-only', 'HEAD', '--', 'src/'])) { if (LINTABLE_FILE.test(file)) files.add(file) } for (const file of runGit(['diff', '--cached', '--name-only', 'HEAD', '--', 'src/'])) { if (LINTABLE_FILE.test(file)) files.add(file) } for (const file of runGit(['ls-files', '--others', '--exclude-standard', 'src/'])) { if (LINTABLE_FILE.test(file)) files.add(file) } return [...files] } function runEslint(files) { const npx = process.platform === 'win32' ? 'npx.cmd' : 'npx' const result = spawnSync( npx, ['eslint', ...files, '--max-warnings', '0', '--format', 'stylish'], { cwd: process.cwd(), encoding: 'utf8', shell: process.platform === 'win32', env: process.env, } ) const output = [result.stdout, result.stderr].filter(Boolean).join('\n').trim() return { ok: result.status === 0, output, exitCode: result.status ?? 1, } } function emit(result) { process.stdout.write(`${JSON.stringify(result)}\n`) } const input = readHookInput() if (input.status === 'aborted') { emit({}) process.exit(0) } const changedFiles = getChangedLintableFiles() if (changedFiles.length === 0) { emit({}) process.exit(0) } const { ok, output, exitCode } = runEslint(changedFiles) if (ok) { emit({}) process.exit(0) } const truncated = output.length > MAX_OUTPUT_CHARS ? `${output.slice(0, MAX_OUTPUT_CHARS)}\n...(输出已截断)` : output const fileList = changedFiles.map((f) => `- ${f}`).join('\n') emit({ followup_message: `本地 Lint 检查未通过(规则与 npm run local 开发服一致)。请修复以下问题: 检查文件: ${fileList} \`\`\` ${truncated || `eslint 退出码 ${exitCode}`} \`\`\` 可本地复现:npx eslint ${changedFiles.join(' ')}`, }) process.exit(0)

代码每次跑完,都会自动触发eslint check 使得:

相关信息

每当 AI 觉得自己写完代码要收工时,自动对它改过的前端文件跑一遍 ESLint。过了就放行;没过就把报错自动丢回给 AI 让它继续修,最多重试 3 次。 相当于给 Agent 装了一道“交作业前的自动质检关卡”,保证它给你的代码不会有 lint 错误

js
已修复 Prettier 格式问题:将「复用HEX」表单项和 a-option 的多行属性合并为单行。npx eslint 现已通过(exit code 0)。
js
已修复 detail.vue 中的 2Prettier 格式问题: 第 117 行:将 a-button 的多行属性合并为单行 第 726 行:将三元表达式合并为单行 对上述两个文件的 ESLint 检查已通过。
js
已修复:将 fetchReuseHexCandidates 及其依赖的 isPersonalUploadedHex、sortReuseHexOptions 提前到 resetImportState 之前定义,消除 no-use-before-define 报错。 上述 3 个文件的 ESLint 检查均已通过。

本文作者:lixf6

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!