作者注本文深入解析 ECC 项目的 Rules 体系展示如何通过模块化规则引擎统一团队的编码规范和安全标准。项目开源地址github.com/affaan-m/ECC摘要在团队协作中**“代码风格不一致和安全漏洞反复出现”**是两大顽疾。ECCEverything Claude Code项目的 Rules 系统通过多语言、分层级的规则引擎为 AI 编码助手植入了永不遗忘的编码宪法。本文系统介绍 Rules 的目录架构、编写规范、选择性安装策略以及如何在 Python、TypeScript、Go、Rust 等 12 语言项目中落地。文章提供完整的 Rules 管理和验证工具代码。关键词Rules、编码规范、多语言、安全策略、AI 编码助手一、为什么需要 Rules1.1 团队开发的巴别塔困境场景你的团队有 5 名后端工程师分别习惯不同的编码风格工程师 A函数名用 camelCase注释写英文工程师 B函数名用 snake_case注释写中文工程师 C喜欢大文件2000 行认为集中好管理工程师 D喜欢小文件200 行认为模块化更清晰工程师 E经常忘记处理错误代码里满是try-except: pass当 AI 助手面对这样风格迥异的代码库时它会困惑“我该用哪种风格”Rules 的作用就是在 AI 助手加载项目时第一时间注入团队的统一规范让 AI 从第一行代码开始就遵循标准。1.2 Rules vs 传统 Lint 工具维度ESLint/Black/gofmtECC Rules执行时机CI 阶段事后检查编码阶段事前约束检查范围语法和格式架构、安全、风格、流程反馈对象开发者看报告AI 助手直接遵守可定制性配置文件自然语言描述覆盖深度表层规则深层最佳实践关键洞察Lint 工具告诉你哪里错了Rules 告诉 AI应该怎么做。二、Rules 目录架构2.1 多语言分层设计ECC 的 Rules 采用**“通用层 语言专属层”**的架构rules/ ├── common/ # 通用规则所有项目 │ ├── security.md # 安全规范 │ ├── coding-style.md # 编码风格 │ ├── testing.md # 测试要求 │ ├── git-workflow.md # Git 工作流 │ ├── performance.md # 性能优化 │ └── agents.md # 智能体使用指南 ├── typescript/ # TypeScript 专属 │ ├── naming.md │ ├── types.md │ └── react.md ├── python/ # Python 专属 │ ├── pep8.md │ ├── django.md │ └── async.md ├── golang/ # Go 专属 │ ├── idioms.md │ └── error-handling.md ├── java/ # Java 专属 ├── rust/ # Rust 专属 ├── kotlin/ # Kotlin 专属 ├── cpp/ # C 专属 ├── dart/ # Dart/Flutter 专属 └── ...共覆盖 12 语言2.2 选择性安装策略ECC 支持按需安装只加载项目需要的规则# 安装通用规则必装cp-Rrules/common ~/.claude/rules/# 根据技术栈安装专属规则cp-Rrules/python ~/.claude/rules/# Python 项目cp-Rrules/typescript ~/.claude/rules/# TypeScript 项目cp-Rrules/golang ~/.claude/rules/# Go 项目# 不要安装不需要的语言规则避免污染上下文⚠️ 注意事项手动复制规则时请复制整个语言目录如rules/python而非目录内的单个文件。这样可以保证相对路径引用正常。2.3 规则优先级当多个 Rules 文件同时生效时优先级如下用户级规则~/.claude/rules/项目级规则project/.claude/rules/会话级规则动态注入图 1规则优先级 —— 越靠近当前会话的规则优先级越高可以覆盖上层规则三、Rules 文件编写规范3.1 通用规则模板# 规则名称 适用范围[全部语言 / Python / TypeScript] 优先级[must / should / may] 违反后果[build-failure / warning / note] ## 规则正文 用清晰的指令描述要求 1. **必须**使用参数化查询禁止字符串拼接 SQL 2. **应该**将函数控制在 50 行以内 3. **可以**使用类型别名简化复杂类型 ## 原理说明 解释为什么这条规则存在帮助 AI 理解上下文 - 参数化查询可以防止 SQL 注入攻击 - 小函数更容易测试和维护 ## 示例 ### ✅ 正确 python # 参数化查询 cursor.execute(SELECT * FROM users WHERE id %s, (user_id,))❌ 错误# 字符串拼接 —— 存在注入风险cursor.execute(fSELECT * FROM users WHERE id {user_id})例外情况如果存在合理的例外明确说明内部工具脚本可以放宽函数长度限制迁移旧代码时允许逐步重构### 3.2 ECC 核心安全规则详解 markdown # 安全规范rules/common/security.md ## 提交前必检清单 - [ ] **无硬编码密钥**API Key、密码、Token - [ ] **所有用户输入已验证** - [ ] **SQL 注入防护**使用参数化查询 - [ ] **XSS 防护**HTML 已净化 - [ ] **CSRF 保护**已启用 - [ ] **认证/授权**已验证 - [ ] **所有端点有速率限制** - [ ] **错误信息不泄露敏感数据** ## 密钥管理 **严禁**硬编码任何密钥。使用环境变量或密钥管理器。 启动时验证所需密钥发现泄露立即轮换。 python # ✅ 正确从环境变量读取 import os API_KEY os.environ.get(API_KEY) if not API_KEY: raise ValueError(API_KEY 环境变量未设置) # ❌ 错误硬编码密钥 API_KEY sk-live-abc123输入验证在系统边界验证所有用户输入使用模式验证快速失败。# ✅ 正确模式验证frompydanticimportBaseModel,validatorclassUserCreate(BaseModel):email:strage:intvalidator(age)defage_must_be_positive(cls,v):ifv0:raiseValueError(年龄必须为正数)returnv# ❌ 错误无验证defcreate_user(data:dict):db.users.insert(data)# 危险发现安全问题时的处理流程STOP—— 立即停止当前工作调用 security-reviewer 智能体修复关键问题轮换暴露的密钥审查代码库中的同类问题### 3.3 编码风格规则 markdown # 编码风格rules/common/coding-style.md ## 不可变性原则CRITICAL **始终创建新对象绝不修改现有对象。** python # ✅ 正确返回新对象 def update_user(user: dict, name: str) - dict: return {**user, name: name} # ❌ 错误修改传入对象 def update_user_bad(user: dict, name: str) - None: user[name] name # 副作用文件组织多小文件优于少大文件典型文件 200-400 行最大不超过 800 行按功能/领域组织而非按类型高内聚、低耦合函数规范函数不超过 50 行嵌套不超过 4 层使用描述性命名单一职责错误处理每层都要有错误处理UI 代码提供用户友好的消息服务端记录详细上下文绝不静默吞掉错误# ❌ 错误静默吞掉异常try:process_data()except:pass# ✅ 正确记录并转换importlogging loggerlogging.getLogger(__name__)try:process_data()exceptValueErrorase:logger.error(f数据处理失败:{e},exc_infoTrue)raiseUserFriendlyError(数据格式不正确请检查输入)--- ## 四、实战Python Rules 验证工具 python #!/usr/bin/env python3 ECC Rules 验证器 —— 检查代码是否符合规则要求 功能 1. 扫描代码中的规则违反项 2. 检查硬编码密钥 3. 验证函数长度 4. 检测 SQL 注入风险 import ast import re from pathlib import Path from typing import List, Dict, Optional from dataclasses import dataclass import logging logging.basicConfig(levellogging.INFO) logger logging.getLogger(__name__) dataclass class RuleViolation: 规则违反项 rule: str file: str line: int message: str severity: str # critical, warning, info class RulesChecker: 规则检查器 模拟 AI 助手遵循 Rules 的过程 # 硬编码密钥的模式 SECRET_PATTERNS [ rapi[_-]?key\s*\s*[\]\w[\], rpassword\s*\s*[\][^\][\], rsecret\s*\s*[\]\w[\], rtoken\s*\s*[\]\w[\], raws_access_key_id\s*\s*[\]\w[\], ] # SQL 注入风险模式 SQL_INJECTION_PATTERNS [ rexecute\s*\(\s*f[\], rexecute\s*\(\s*[\].*\{.*\}[\], r\.format\s*\(.*\), r%\s*\w.*execute, ] def __init__(self, rules_path: Optional[str] None): 初始化检查器 Args: rules_path: Rules 目录路径 self.rules_path Path(rules_path) if rules_path else None self.violations: List[RuleViolation] [] def check_file(self, file_path: str) - List[RuleViolation]: 检查单个文件 Args: file_path: Python 文件路径 Returns: 违反项列表 self.violations [] path Path(file_path) if not path.exists(): logger.error(f文件不存在: {path}) return self.violations try: content path.read_text(encodingutf-8) except Exception as e: logger.error(f读取失败: {e}) return self.violations # 运行各项检查 self._check_hardcoded_secrets(path, content) self._check_sql_injection(path, content) self._check_function_length(path, content) self._check_empty_except(path, content) self._check_mutable_defaults(path, content) return self.violations def _check_hardcoded_secrets(self, path: Path, content: str) - None: 检查硬编码密钥 lines content.split(\n) for i, line in enumerate(lines, 1): for pattern in self.SECRET_PATTERNS: if re.search(pattern, line, re.IGNORECASE): # 排除环境变量读取的误报 if os.environ in line or os.getenv in line: continue self.violations.append(RuleViolation( rulesecurity/no-hardcoded-secrets, filestr(path), linei, messagef疑似硬编码密钥: {line.strip()[:60]}, severitycritical )) def _check_sql_injection(self, path: Path, content: str) - None: 检查 SQL 注入风险 lines content.split(\n) for i, line in enumerate(lines, 1): # 检查 f-string SQL if re.search(rexecute\s*\(\s*f[\], line): self.violations.append(RuleViolation( rulesecurity/no-sql-injection, filestr(path), linei, message使用 f-string 拼接 SQL 存在注入风险, severitycritical )) # 检查 .format SQL elif re.search(r[\].*%.*[\].*%.*\w, line): if execute in line or query in line: self.violations.append(RuleViolation( rulesecurity/no-sql-injection, filestr(path), linei, message使用 % 格式化 SQL 存在注入风险, severitywarning )) def _check_function_length(self, path: Path, content: str) - None: 检查函数长度 try: tree ast.parse(content) except SyntaxError: return for node in ast.walk(tree): if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): func_lines node.end_lineno - node.lineno 1 if func_lines 50: self.violations.append(RuleViolation( rulestyle/function-too-long, filestr(path), linenode.lineno, messagef函数 {node.name} 有 {func_lines} 行建议拆分为 50 行, severitywarning )) def _check_empty_except(self, path: Path, content: str) - None: 检查空的 except 块 try: tree ast.parse(content) except SyntaxError: return for node in ast.walk(tree): if isinstance(node, ast.ExceptHandler): # 检查 except 块是否为空或只有 pass body node.body if len(body) 1 and isinstance(body[0], ast.Pass): self.violations.append(RuleViolation( rulestyle/no-empty-except, filestr(path), linenode.lineno, message空的 except: pass 会静默吞掉所有异常, severitywarning )) def _check_mutable_defaults(self, path: Path, content: str) - None: 检查可变默认参数 try: tree ast.parse(content) except SyntaxError: return for node in ast.walk(tree): if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): for default in node.args.defaults node.args.kw_defaults: if isinstance(default, (ast.List, ast.Dict)): self.violations.append(RuleViolation( rulestyle/no-mutable-defaults, filestr(path), linenode.lineno, messagef函数 {node.name} 使用可变对象作为默认参数, severitywarning )) def check_directory(self, dir_path: str) - List[RuleViolation]: 递归检查目录中的所有 Python 文件 Args: dir_path: 目录路径 Returns: 所有违反项 all_violations [] path Path(dir_path) for py_file in path.rglob(*.py): # 跳过虚拟环境和依赖 if any(part.startswith(.) or part in (venv, __pycache__) for part in py_file.parts): continue violations self.check_file(str(py_file)) all_violations.extend(violations) return all_violations def print_report(self, violations: List[RuleViolation]) - None: 打印检查报告 critical [v for v in violations if v.severity critical] warnings [v for v in violations if v.severity warning] print( * 60) print( ECC Rules 检查报告) print( * 60) print(f 严重: {len(critical)} | 警告: {len(warnings)}) if critical: print(\n ❌ 严重问题:) for v in critical[:10]: # 最多显示 10 个 print(f {v.file}:{v.line} [{v.rule}]) print(f {v.message}) if warnings: print(\n ⚠️ 警告:) for v in warnings[:10]: print(f {v.file}:{v.line} [{v.rule}]) print(f {v.message}) if not violations: print(\n ✅ 未发现问题代码符合规范) # 使用示例 if __name__ __main__: # 创建测试代码 test_code # test_sample.py import os API_KEY sk-live-abc123 # 硬编码密钥 def get_users(user_id): cursor.execute(fSELECT * FROM users WHERE id {user_id}) # SQL 注入 def very_long_function(): x 1 x 2 # ... 重复 60 行 ... return x def bad_function(data[]): # 可变默认参数 try: process() except: pass # 空 except # 写入临时文件 test_path Path(/tmp/test_sample.py) test_path.write_text(test_code, encodingutf-8) # 检查 checker RulesChecker() violations checker.check_file(str(test_path)) checker.print_report(violations)五、Rules 的选择性安装与版本管理5.1 安装配置文件示例{install:{modules:[common,python,security],exclude:[typescript,golang]},rules:{enforced:[security,coding-style],advisory:[performance,testing]}}5.2 团队规则更新流程规则变更需求本地编辑 rules/自验证提交 PR团队评审合并到 main同步到 ~/.claude/rules/AI 助手自动加载新规则图 2团队规则更新流程 —— 确保规则变更经过评审并同步到所有开发者六、总结Rules 是 AI 编码助手的**“宪法”**——它定义了不可逾越的底线和应该追求的高线。规则类别核心价值实施建议Security守住安全底线所有项目必须安装Coding Style统一代码面貌按团队偏好定制Testing保障质量设定覆盖率红线Performance追求效率作为建议性规则参考资料ECC Rules 目录https://github.com/affaan-m/ECC/tree/main/rulesPython PEP8 规范Google TypeScript Style GuideGo Code Review CommentsOWASP Top 10安全规则参考本文完。你的团队有编码宪法了吗