一行命令,让 AI 从此懂你项目的规范
上篇 一份 AGENTS.md,让 AI 代码规范率从 60% 飙升到 95% 教你手写 AGENTS.md,这篇教你自动生成。一行命令,5 秒搞定,AI 从此懂你项目的规范。
一、痛点:AI 写代码为什么老"不对味"?
你有没有这种体验:
- AI 给你用了
moment.js,但你项目早就切到dayjs了 - AI 生成的组件用了内联样式,但你团队用的是 CSS Modules
- AI 不知道你的项目有
useModel全局状态管理,每次都给你useState+ prop drilling - AI 不知道你们的 API 请求都封装在
src/services/里,直接给你裸写fetch
核心问题:AI 不知道你项目的规范。
解法:给 AI 一份项目规范配置,让它在写代码前先"读规则"。
但手动写这份配置?太累了。我写了个脚本,一行命令,5 秒搞定。
二、效果预览
执行前:
你的项目/
├── src/
├── package.json
└── ...(普通前端项目)
执行精简版脚本后(本文附带):
你的项目/
├── AGENTS.md ← 项目 AI 规范(~130 行,可操作)
├── AGENTS.local.md ← 个人偏好(AI 只读,不入仓库)
├── DESIGN.md ← 视觉设计规范(~35 行,自动生成)
└── ...
执行完整版脚本后(文末私信获取):
你的项目/
├── .agents/
│ ├── generation-spec.md ← 代码生成模板(组件/Hook/Service)
│ └── logs/corrections.md ← AI 错误修正记录(半自动进化)
├── AGENTS.md ← 项目 AI 规范(增强版,~200 行)
├── AGENTS.local.md ← 个人偏好(不入仓库)
├── DESIGN.md ← 视觉设计规范(完整版,~70 行)
└── ...
精简版生成 AGENTS.md + AGENTS.local.md + DESIGN.md 三个文件,AI 编程助手会自动读取。之后你再让它写代码,它就知道——用 Less 不用 Tailwind,组件放 src/components/,API 走 src/services/,构建命令是 yarn serve 而非 npm start,路径别名是 @/*,主色是 #1677ff,间距用 8px 网格。不用你每次都提醒了。还内置 3 个 AI 指令(分析项目规范 / CR 代码 / 生成变量名),开箱即用。
完整版多了代码模板(组件/Hook/Service 模板)、半自动进化(错误自动记录 + Never 规则自动升级)、6~8 个 AI 指令、命名规范、导入顺序、安全规范等,适合需要精细管控的团队。
三、实操步骤(3 分钟)
Step 1:创建初始化脚本
把下面这段脚本保存为 init-agents.sh,放到你项目根目录:
#!/bin/bash
# AGENTS.md + DESIGN.md 自动生成器(精简版 v4)
# 读取 package.json + tsconfig + prettierrc,自动识别技术栈,生成 AI 规范文件
# 产出:AGENTS.md(~130 行)+ AGENTS.local.md + DESIGN.md(~35 行)
# 策略:AGENTS.md / DESIGN.md 默认覆盖,AGENTS.local.md 存在则跳过
PROJECT_DIR=$(pwd)
PKG="$PROJECT_DIR/package.json"
if [ ! -f "$PKG" ]; then
echo "❌ 未找到 package.json,请在项目根目录执行"
exit 1
fi
# ── 读取项目名 ──
PROJECT_NAME=$(cat "$PKG" | grep '"name"' | head -1 | sed 's/.*: *"\(.*\)".*/\1/' | sed 's/@.*\///')
echo "📦 项目: $PROJECT_NAME"
# ── 技术栈检测(含 Monorepo 兜底)──
DEPS=$(cat "$PKG" | tr -d '\n')
FRAMEWORK="Unknown"
UI_LIB="无"
CSS_SCHEME="CSS"
CSS_IMPORT=""
PKG_MGR="npm"
LANG="JavaScript"
IS_MONOREPO="false"
# Monorepo 检测:如果根 package.json 检测不到框架,扫描子包
detect_from_deps() {
local D="$1"
echo "$D" | grep -q '"react"' && FRAMEWORK="React" || true
echo "$D" | grep -q '"vue"' && FRAMEWORK="Vue" || true
echo "$D" | grep -q '"next"' && FRAMEWORK="Next.js" || true
echo "$D" | grep -q '"nuxt"' && FRAMEWORK="Nuxt" || true
echo "$D" | grep -q '"@angular/core"' && FRAMEWORK="Angular" || true
echo "$D" | grep -q '"svelte"' && FRAMEWORK="Svelte" || true
echo "$D" | grep -q '"@ali/ppx"\|"umi"\|"@umijs"' && FRAMEWORK="$FRAMEWORK + Umi" || true
echo "$D" | grep -q '"antd"\|"@ant-design"' && UI_LIB="Ant Design" || true
echo "$D" | grep -q '"element-plus"' && UI_LIB="Element Plus" || true
echo "$D" | grep -q '"element-ui"' && UI_LIB="Element UI" || true
echo "$D" | grep -q '"@arco-design"' && UI_LIB="Arco Design" || true
echo "$D" | grep -q '"@douyinfe/semi-ui"' && UI_LIB="Semi Design" || true
echo "$D" | grep -q '"vant"' && UI_LIB="Vant" || true
echo "$D" | grep -q '"@mui/material"\|"@material-ui"' && UI_LIB="Material UI" || true
echo "$D" | grep -q '"less"' && CSS_SCHEME="Less + CSS Modules" && CSS_IMPORT="import styles from './index.less'" || true
echo "$D" | grep -q '"sass"\|"node-sass"' && CSS_SCHEME="Sass/SCSS" && CSS_IMPORT="import styles from './index.module.scss'" || true
echo "$D" | grep -q '"tailwindcss"' && CSS_SCHEME="Tailwind CSS" && CSS_IMPORT="" || true
(echo "$D" | grep -q '"styled-components"' || echo "$D" | grep -q '"@emotion/') && CSS_SCHEME="CSS-in-JS" && CSS_IMPORT="" || true
}
# 先从根 package.json 检测
detect_from_deps "$DEPS"
# 如果框架仍为 Unknown,尝试 Monorepo 子包扫描
if [ "$FRAMEWORK" = "Unknown" ] || [ "$FRAMEWORK" = "Unknown + Umi" ]; then
# 检测是否为 Monorepo
if [ -f "$PROJECT_DIR/lerna.json" ] || [ -f "$PROJECT_DIR/pnpm-workspace.yaml" ] || echo "$DEPS" | grep -q '"workspaces"'; then
IS_MONOREPO="true"
echo "📦 检测到 Monorepo 结构,扫描子包..."
for SUB_PKG in "$PROJECT_DIR"/packages/*/package.json "$PROJECT_DIR"/apps/*/package.json; do
[ -f "$SUB_PKG" ] || continue
SUB_DEPS=$(cat "$SUB_PKG" | tr -d '\n')
detect_from_deps "$SUB_DEPS"
[ "$FRAMEWORK" != "Unknown" ] && [ "$FRAMEWORK" != "Unknown + Umi" ] && break
done
fi
fi
# 版本号
FRAMEWORK_VERSION=$(cat "$PKG" | grep -E '"react"|"vue"|"@angular/core"' | head -1 | grep -oE '[0-9]+' | head -1 2>/dev/null)
[ -n "$FRAMEWORK_VERSION" ] && [ "$FRAMEWORK" != "Unknown" ] && FRAMEWORK="$FRAMEWORK $FRAMEWORK_VERSION"
# 包管理器
[ -f "$PROJECT_DIR/yarn.lock" ] || [ -f "$PROJECT_DIR/.yarnrc" ] || [ -f "$PROJECT_DIR/.yarnrc.yml" ] && PKG_MGR="yarn"
[ -f "$PROJECT_DIR/pnpm-lock.yaml" ] && PKG_MGR="pnpm"
[ -f "$PROJECT_DIR/bun.lockb" ] && PKG_MGR="bun"
# TypeScript
(echo "$DEPS" | grep -q '"typescript"' || [ -f "$PROJECT_DIR/tsconfig.json" ]) && LANG="TypeScript" || true
# UI 库主色(用于 DESIGN.md)
PRIMARY_COLOR="#1677ff"
BORDER_RADIUS="6"
case "$UI_LIB" in
"Ant Design") PRIMARY_COLOR="#1677ff"; BORDER_RADIUS="6" ;;
"Element Plus"|"Element UI") PRIMARY_COLOR="#409EFF"; BORDER_RADIUS="4" ;;
"Arco Design") PRIMARY_COLOR="#165DFF"; BORDER_RADIUS="4" ;;
"Semi Design") PRIMARY_COLOR="#0077FA"; BORDER_RADIUS="6" ;;
"Vant") PRIMARY_COLOR="#1989fa"; BORDER_RADIUS="4" ;;
"Material UI") PRIMARY_COLOR="#1976d2"; BORDER_RADIUS="4" ;;
esac
echo "🔍 检测结果: $FRAMEWORK | $UI_LIB | $CSS_SCHEME | $PKG_MGR | $LANG"
[ "$IS_MONOREPO" = "true" ] && echo " 📦 Monorepo: 是"
# ── 读取 scripts(构建命令)──
CMD_DEV=$(cat "$PKG" | grep -oE '"(dev|serve|start)"\s*:\s*"[^"]*"' | head -1 | sed 's/.*: *"\(.*\)"/\1/' 2>/dev/null)
CMD_BUILD=$(cat "$PKG" | grep -oE '"build"\s*:\s*"[^"]*"' | head -1 | sed 's/.*: *"\(.*\)"/\1/' 2>/dev/null)
CMD_LINT=$(cat "$PKG" | grep -oE '"lint"\s*:\s*"[^"]*"' | head -1 | sed 's/.*: *"\(.*\)"/\1/' 2>/dev/null)
CMD_DEV_KEY=$(cat "$PKG" | grep -oE '"(dev|serve|start)"' | head -1 | tr -d '"' 2>/dev/null || echo "dev")
[ -z "$CMD_DEV_KEY" ] && CMD_DEV_KEY="dev"
# ── 读取路径别名(tsconfig.json)──
ALIAS_LINES=""
if [ -f "$PROJECT_DIR/tsconfig.json" ]; then
ALIAS_AT=$(cat "$PROJECT_DIR/tsconfig.json" | grep -oE '"@/\*"' 2>/dev/null)
[ -n "$ALIAS_AT" ] && ALIAS_LINES="- \`@/*\` → \`src/*\`"
ALIAS_ATAT=$(cat "$PROJECT_DIR/tsconfig.json" | grep -oE '"@@/\*"' 2>/dev/null)
[ -n "$ALIAS_ATAT" ] && ALIAS_LINES="$ALIAS_LINES\n- \`@@/*\` → \`src/.umi/*\`"
fi
# ── 读取 Prettier 配置 ──
PRETTIER_SUMMARY=""
for PFILE in .prettierrc .prettierrc.json .prettierrc.js .prettierrc.yml; do
if [ -f "$PROJECT_DIR/$PFILE" ]; then
HAS_SINGLE=$(cat "$PROJECT_DIR/$PFILE" | grep -i "singleQuote.*true\|single_quote" 2>/dev/null)
HAS_SEMI=$(cat "$PROJECT_DIR/$PFILE" | grep -i '"semi".*false' 2>/dev/null)
HAS_TRAILING=$(cat "$PROJECT_DIR/$PFILE" | grep -i "trailingComma\|trailing" 2>/dev/null)
PRETTIER_SUMMARY=""
[ -n "$HAS_SINGLE" ] && PRETTIER_SUMMARY="单引号"
[ -n "$HAS_SEMI" ] && PRETTIER_SUMMARY="$PRETTIER_SUMMARY、无分号"
[ -n "$HAS_TRAILING" ] && PRETTIER_SUMMARY="$PRETTIER_SUMMARY、尾随逗号"
[ -n "$PRETTIER_SUMMARY" ] && PRETTIER_SUMMARY="Prettier:$PRETTIER_SUMMARY"
break
fi
done
# ── 目录结构扫描 ──
SRC_DIR="src"
[ -d "$PROJECT_DIR/app" ] && SRC_DIR="app"
DIR_STRUCTURE="$SRC_DIR/\n"
[ -d "$PROJECT_DIR/$SRC_DIR/components" ] && DIR_STRUCTURE="${DIR_STRUCTURE}├── components/ # 通用组件\n"
[ -d "$PROJECT_DIR/$SRC_DIR/pages" ] || [ -d "$PROJECT_DIR/$SRC_DIR/views" ] && DIR_STRUCTURE="${DIR_STRUCTURE}├── pages/ # 页面组件\n"
[ -d "$PROJECT_DIR/$SRC_DIR/hooks" ] && DIR_STRUCTURE="${DIR_STRUCTURE}├── hooks/ # 自定义 Hooks\n"
[ -d "$PROJECT_DIR/$SRC_DIR/services" ] || [ -d "$PROJECT_DIR/$SRC_DIR/api" ] && DIR_STRUCTURE="${DIR_STRUCTURE}├── services/ # API 请求封装\n"
[ -d "$PROJECT_DIR/$SRC_DIR/models" ] && DIR_STRUCTURE="${DIR_STRUCTURE}├── models/ # 状态模型\n"
[ -d "$PROJECT_DIR/$SRC_DIR/stores" ] || [ -d "$PROJECT_DIR/$SRC_DIR/store" ] && DIR_STRUCTURE="${DIR_STRUCTURE}├── stores/ # 状态仓库\n"
[ -d "$PROJECT_DIR/$SRC_DIR/utils" ] && DIR_STRUCTURE="${DIR_STRUCTURE}├── utils/ # 工具函数\n"
[ -d "$PROJECT_DIR/$SRC_DIR/constants" ] && DIR_STRUCTURE="${DIR_STRUCTURE}├── constants/ # 常量定义\n"
[ -d "$PROJECT_DIR/$SRC_DIR/typings" ] || [ -d "$PROJECT_DIR/$SRC_DIR/types" ] && DIR_STRUCTURE="${DIR_STRUCTURE}└── typings/ # 类型定义\n"
# ── 自动生成目录判断 ──
AUTO_GEN_DIRS=""
[ -d "$PROJECT_DIR/$SRC_DIR/.umi" ] && AUTO_GEN_DIRS="- \`Never\` edit files under \`${SRC_DIR}/.umi/\` or \`${SRC_DIR}/.umi-production/\` — 框架自动生成"
[ -d "$PROJECT_DIR/.next" ] && AUTO_GEN_DIRS="- \`Never\` edit files under \`.next/\` — 框架自动生成"
[ -d "$PROJECT_DIR/.nuxt" ] && AUTO_GEN_DIRS="- \`Never\` edit files under \`.nuxt/\` — 框架自动生成"
[ -d "$PROJECT_DIR/.angular" ] && AUTO_GEN_DIRS="- \`Never\` edit files under \`.angular/\` — 框架缓存目录"
# ── 组件风格(React vs Vue vs 通用)──
if echo "$FRAMEWORK" | grep -q "React\|Next"; then
COMP_STYLE="**组件(React)**
- 命名:PascalCase,文件名 \`index.tsx\`
- 使用 \`interface\` 定义 Props 类型,组件使用 \`React.FC<Props>\` 或函数声明
- 导出:\`export default Component\`"
elif echo "$FRAMEWORK" | grep -q "Vue\|Nuxt"; then
COMP_STYLE="**组件(Vue)**
- 命名:PascalCase,单文件组件 \`.vue\`
- 使用 \`defineProps<T>()\` 定义 Props 类型
- 使用 Composition API + \`<script setup>\`"
elif echo "$FRAMEWORK" | grep -q "Angular"; then
COMP_STYLE="**组件(Angular)**
- 命名:kebab-case,每个组件包含 \`.component.ts\` + \`.component.html\` + \`.component.scss\`
- 使用 \`@Input()\` / \`@Output()\` 定义组件接口
- 使用 standalone components(推荐)"
else
COMP_STYLE="**组件**
- 命名:PascalCase
- 使用明确的类型定义
- 导出:\`export default Component\`"
fi
# ── 生成 AGENTS.md(默认覆盖)──
[ -f "$PROJECT_DIR/AGENTS.md" ] && echo " ♻️ AGENTS.md 已存在,更新覆盖"
cat > "$PROJECT_DIR/AGENTS.md" << EOF
# AGENTS.md
- 本项目为 ${FRAMEWORK} + ${LANG} 前端应用
- 包管理器:\`${PKG_MGR}\`
- 样式方案:${CSS_SCHEME}
- UI 组件库:${UI_LIB}
$([ -n "$PRETTIER_SUMMARY" ] && echo "- ${PRETTIER_SUMMARY}")
## Project Structure
\`\`\`
$(echo -e "$DIR_STRUCTURE")\`\`\`
${AUTO_GEN_DIRS}
- \`Never\` edit \`dist/\` or \`build/\` — 构建产物目录
## Build & Dev Commands
\`\`\`bash
# 开发
${PKG_MGR} ${CMD_DEV_KEY}$([ -n "$CMD_DEV" ] && echo " # ${CMD_DEV}")
# 构建
${PKG_MGR} build$([ -n "$CMD_BUILD" ] && echo " # ${CMD_BUILD}")
$([ -n "$CMD_LINT" ] && echo "
# 代码格式化
${PKG_MGR} lint # ${CMD_LINT}")
\`\`\`
- 测试框架暂未配置,如需添加测试请先与用户确认方案
$([ -n "$ALIAS_LINES" ] && echo "
## Path Aliases
$(echo -e "$ALIAS_LINES")")
## Coding Style & Naming
${COMP_STYLE}
$([ -n "$CSS_IMPORT" ] && echo "
**样式**
\`\`\`tsx
${CSS_IMPORT}
\`\`\`")
**命名规范**
- 组件目录:PascalCase(如 \`CopyButton/\`)
- Hook 函数:\`useXxx\`(如 \`useAuth\`)
- 常量:\`UPPER_SNAKE_CASE\`(如 \`MAX_RETRY_COUNT\`)
- CSS 类名:kebab-case(如 \`copy-button\`)
- 工具函数 / 变量:camelCase(如 \`formatDate\`)
- 类型 / 接口:PascalCase(如 \`IUserInfo\` 或 \`UserInfo\`)
**导入顺序**
\`\`\`ts
// 1. 框架核心(React / Vue)
// 2. UI 组件库(antd / element-plus)
// 3. 第三方工具(lodash / dayjs)
// 4. 路径别名(@/ 开头)
// 5. 相对路径导入
// 6. 样式文件(放最后)
\`\`\`
## Commit & Git Convention
**Commit Message**
- 遵循 Conventional Commits 规范
- 格式:\`type(scope): description\`
- 类型:feat / fix / docs / style / refactor / test / chore
**提交前**
- lint-staged 会自动运行格式化和 lint 检查
- \`Never\` 使用 \`git stash\` — 会影响其他 Agent 的工作区
- \`Never\` 切换分支 — 只在当前分支工作
- 只 commit 自己修改的文件
## Component & API Conventions
**组件开发**
- 新建组件在 \`${SRC_DIR}/components/\` 下创建 PascalCase 目录
- 目录结构:入口文件 + 样式文件(如 \`index.tsx\` + \`index.less\`)
- 复杂组件可添加 \`types.ts\` 集中定义类型
**API 开发**
- 新增 API 在 \`${SRC_DIR}/services/\` 对应业务模块下添加
- 类型定义放在 \`${SRC_DIR}/typings/\` 或服务模块同级 \`typings.d.ts\`
## Never Rules
- \`Never\` 使用 \`any\` 类型 — 必须定义明确的类型
- \`Never\` 使用内联样式(\`style={{ }}\`),除非需要动态计算
$(echo "$CSS_SCHEME" | grep -q "Less\|Sass" && echo "- \`Never\` 使用硬编码颜色值 — 使用主题变量")
- \`Never\` 在组件中直接调用 fetch/axios — 使用 \`${SRC_DIR}/services/\` 封装
- \`Never\` 在列表渲染中省略 \`key\` 属性
- \`Never\` 修改 \`node_modules/\` 或构建产物目录
- \`Never\` 在渲染路径中执行耗时操作(如 \`new Date()\`、大循环)
- \`Never\` 提交 lock 文件 — 除非明确要求安装新依赖
- \`Never\` 在代码中硬编码敏感信息(密钥、token、AK/SK)
- \`Never\` 修改框架自动生成的目录
- \`Never\` 在 \`useEffect\` / \`watch\` 中遗漏依赖项或清理函数
- \`Never\` 在全局作用域中抛出未捕获的异步错误
- \`Never\` 使用 \`git stash\` 或切换分支 — 多 Agent 并发安全
- \`Never\` 跳过 TypeScript 类型检查(\`@ts-ignore\` / \`@ts-nocheck\`)
- \`Never\` 在 \`catch\` 块中吞掉错误不做任何处理
## Multi-Agent Safety
- 禁止 \`git stash\`、禁止切换分支
- 只 commit 自己修改的文件
- 修改全局配置文件前先与用户确认
- 安装 / 删除依赖前先与用户确认
## Quick Commands(AI 指令)
以下指令可直接对 AI 说,AI 会按照本文件的规范执行:
| 指令 | 说明 |
|------|------|
| \`分析项目规范\` | 扫描源码,学习项目的隐性编码习惯,产出规范总结 |
| \`CR 代码\` | 自动 Review 暂存区代码,检查 Never 规则,生成 Conventional Commits 格式的 commit 信息 |
| \`生成变量名\` | 根据上下文 + 社区约定推荐命名(变量 / 函数 / 组件 / CSS 类名) |
## Error Handling
- 异步操作必须有 try-catch 或 .catch() 兜底
- 用户可见的错误需要友好提示,不暴露技术细节
- API 错误统一在 \`${SRC_DIR}/services/\` 的请求封装中处理
- 组件级错误使用 ErrorBoundary 捕获(React)或 onErrorCaptured(Vue)
EOF
echo " ✅ AGENTS.md 已生成"
# ── 生成 AGENTS.local.md(个人偏好,存在则跳过)──
if [ -f "$PROJECT_DIR/AGENTS.local.md" ]; then
echo " ~ AGENTS.local.md 已存在,跳过(个人偏好不覆盖)"
else
cat > "$PROJECT_DIR/AGENTS.local.md" << 'LOCALEOF'
# AGENTS.local.md — 个人偏好配置
> 此文件仅供 AI 只读参考,不入仓库(已加入 .gitignore)。
> AI 不可修改此文件,仅人工编辑。
## 个人偏好
- 代码注释语言:中文
- 变量命名倾向:语义化长命名 > 简短缩写
- Commit message 语言:中文描述
- 响应风格:简洁直接
LOCALEOF
echo " ✅ AGENTS.local.md 已生成"
# 添加到 .gitignore
if [ -f "$PROJECT_DIR/.gitignore" ]; then
if ! grep -q "AGENTS.local.md" "$PROJECT_DIR/.gitignore"; then
echo "" >> "$PROJECT_DIR/.gitignore"
echo "# AI 个人偏好(不入仓库)" >> "$PROJECT_DIR/.gitignore"
echo "AGENTS.local.md" >> "$PROJECT_DIR/.gitignore"
echo " 📝 已添加到 .gitignore"
fi
fi
fi
# ── 生成 DESIGN.md(默认覆盖)──
[ -f "$PROJECT_DIR/DESIGN.md" ] && echo " ♻️ DESIGN.md 已存在,更新覆盖"
cat > "$PROJECT_DIR/DESIGN.md" << EOF
# DESIGN.md — 视觉设计规范
> AI 生成 UI 代码时参考此文件,确保视觉一致性。
## Design Tokens
| Token | 值 | 说明 |
|-------|-----|------|
| 主色 | \`${PRIMARY_COLOR}\` | 按钮、链接、高亮 |
| 成功色 | \`#52c41a\` | 成功状态、完成提示 |
| 警告色 | \`#faad14\` | 警告状态、注意提示 |
| 错误色 | \`#ff4d4f\` | 错误状态、删除操作 |
| 圆角 | \`${BORDER_RADIUS}px\` | 卡片、按钮、输入框 |
| 间距基数 | \`8px\` | 所有间距为 8 的倍数(8/16/24/32) |
| 字体 | 系统默认 | -apple-system, BlinkMacSystemFont, 'Segoe UI' |
| 正文字号 | \`14px\` | 行高 \`22px\`(1.57 倍) |
| 标题字号 | \`20px / 16px / 14px\` | h1 / h2 / h3 |
## 设计原则
- 遵循 ${UI_LIB} 默认主题,不硬编码颜色和间距
- 使用组件库内置的 Design Token / CSS 变量
- 间距使用 8px 网格系统(\`8 / 16 / 24 / 32 / 48\`)
- 响应式断点:移动端 \`< 768px\` / 平板 \`768-1024px\` / 桌面 \`> 1024px\`
- 动画时长:微交互 \`150ms\`,过渡 \`300ms\`,复杂动画 \`500ms\`
- 阴影层级:卡片 \`0 1px 2px rgba(0,0,0,0.06)\`,弹窗 \`0 4px 12px rgba(0,0,0,0.08)\`
- 文字颜色:主文本 \`rgba(0,0,0,0.88)\`,辅助文本 \`rgba(0,0,0,0.65)\`,禁用文本 \`rgba(0,0,0,0.25)\`
## 图标 & 插图
- 图标尺寸:\`16px\`(行内)/ \`24px\`(操作栏)/ \`48px\`(空状态)
- 使用 ${UI_LIB} 内置图标库,不引入额外图标包(除非确认)
- 空状态插图使用组件库默认,不自定义 SVG
EOF
echo " ✅ DESIGN.md 已生成"
echo ""
echo "🎉 完成!已生成 AGENTS.md + AGENTS.local.md + DESIGN.md"
echo " AI 编程助手现在能读懂你的项目规范了。"
Step 2:执行
chmod +x init-agents.sh && bash init-agents.sh
5 秒搞定 ✅
四、脚本都做了什么?(逐步解析)
🔍 智能检测(含 Monorepo 兜底)
脚本会自动扫描 package.json、tsconfig.json、.prettierrc,输出类似这样的结果:
📦 项目: imp-data-agent
🔍 检测结果: React 19 + Umi | Ant Design | Less + CSS Modules | yarn | TypeScript
原理:从多个配置文件中提取信息,用 grep 匹配关键词:
| 检测项 | 来源 | 识别方式 |
|---|---|---|
| 框架 | package.json | react / vue / next / nuxt / angular / svelte / umi |
| UI 库 | package.json | antd / element-plus / @arco-design / semi / vant / @mui |
| 样式方案 | package.json | less / sass / tailwindcss / styled-components |
| 包管理器 | lock 文件 | yarn.lock / pnpm-lock.yaml / bun.lockb |
| 构建命令 | package.json scripts | 读取 dev/serve/start/build/lint |
| 路径别名 | tsconfig.json | 读取 paths 字段(@/* → src/*) |
| Prettier | .prettierrc | 读取单引号/分号/尾逗号配置 |
| 目录结构 | 文件系统 | 扫描 src/ 下实际存在的目录 |
| Monorepo | lerna.json / pnpm-workspace.yaml / workspaces | 根包检测失败时自动扫描 packages/*/package.json |
Monorepo 兜底:这个功能是我自己踩坑后加的。一开始在 Lerna Monorepo 项目里跑,根 package.json 只有工具链依赖(比如 lerna、turbo),根本检测不到框架。所以加了个兜底逻辑——如果根包检测失败,就自动扫描子包。
📄 生成 AGENTS.md(~130 行)
检测完后,脚本用结果填充 AGENTS.md 模板。精简版生成的内容包括 10 个章节:
| 章节 | 内容 | 行数 |
|---|---|---|
| 技术栈声明 | 框架 + 版本 + 语言 + UI 库 + 样式 + Prettier | ~7 行 |
| Project Structure | 动态扫描 src/ 下实际存在的目录 | ~15 行 |
| Build & Dev Commands | 从 scripts 读取,不再硬编码 | ~12 行 |
| Coding Style & Naming | 组件风格自适应 + 6 条命名 + 6 层导入顺序 | ~25 行 |
| Commit & Git Convention | Conventional Commits + lint-staged + git 禁止操作 | ~12 行 |
| Component & API Conventions | 组件目录规则 + API 放置规则 | ~10 行 |
| Never Rules | 14 条禁止规则 | ~16 行 |
| Multi-Agent Safety | 并发安全规则 | ~5 行 |
| Quick Commands | 3 个 AI 指令(分析规范 / CR 代码 / 生成命名) | ~10 行 |
| Error Handling | 错误处理约定(try-catch / ErrorBoundary) | ~6 行 |
🎨 生成 DESIGN.md(~35 行)
基于检测到的 UI 库,自动适配设计 Token:
| UI 库 | 主色 | 圆角 |
|---|---|---|
| Ant Design | #1677ff | 6px |
| Element | #409EFF | 4px |
| Arco Design | #165DFF | 4px |
| Semi Design | #0077FA | 6px |
| Vant | #1989fa | 4px |
| Material UI | #1976d2 | 4px |
还包含间距系统(8px 网格)、字体、响应式断点等基础设计规范。
文件已存在?跳过。不会覆盖你手动调整过的内容。
🚀 完整版额外能力(私信获取)
精简版生成 AGENTS.md + DESIGN.md 两个文件。完整版额外做这些:
| 文件 | 作用 |
|---|---|
AGENTS.local.md | 个人偏好(不入仓库) |
.agents/generation-spec.md | 代码生成模板(组件/Hook/Service 模板) |
.agents/logs/corrections.md | AI 错误修正记录(半自动进化用) |
| AGENTS.md 增强 | 多检测状态管理/Hooks 库/Node 版本 + 命名规范 + 导入顺序 + 安全规范 + 进化声明 |
| DESIGN.md 增强 | CSS 变量示例 + 暗色模式 + 动画时长 |
五、增量安全:重复执行不会炸
# 第一次跑:生成文件
bash init-agents.sh
# 手抖又跑了一次:
bash init-agents.sh
# 输出:♻️ AGENTS.md 已存在,更新覆盖
脚本默认增量覆盖——AGENTS.md 和 DESIGN.md 每次执行都会用最新检测结果重新生成,保证内容始终和项目实际情况一致。AGENTS.local.md 是个人偏好文件,存在则跳过不覆盖。坦白讲,这个设计我纠结过——要不要全跳过?后来想想,覆盖其实更安全,毕竟技术栈可能迭代,你不希望 AI 还在用旧配置。
六、团队使用流程
管理员(执行一次)
cd your-project
bash init-agents.sh
git add AGENTS.md DESIGN.md
git commit -m "chore: 初始化项目 AI 规范(AGENTS.md + DESIGN.md)"
git push
团队成员(零操作)
git pull
# 自动生效 ✅ AI 已经知道你们的项目规范了
AGENTS.md 入了仓库,所有成员(包括 AI)都能读到——不需要额外安装任何东西。
七、实战对比:初始化前 vs 后
场景:写一个"复制按钮"组件
初始化前(AI 不懂规范):
// ❌ 用了 any
// ❌ 内联样式
// ❌ 没用 CSS Modules
// ❌ 没放对目录
export default function CopyBtn({ text }: any) {
return <button style={{color: 'blue'}} onClick={() => navigator.clipboard.writeText(text)}>Copy</button>
}
初始化后(AI 懂规范):
// ✅ 正确的目录:src/components/CopyButton/index.tsx
// ✅ interface 定义 Props
// ✅ CSS Modules
// ✅ 正确的导出方式
import React, { useCallback } from 'react'
import { message } from 'antd'
import styles from './index.less'
interface CopyButtonProps {
text: string
onSuccess?: () => void
}
const CopyButton: React.FC<CopyButtonProps> = ({ text, onSuccess }) => {
const handleCopy = useCallback(async () => {
await navigator.clipboard.writeText(text)
message.success('已复制')
onSuccess?.()
}, [text, onSuccess])
return (
<button className={styles['copy-button']} onClick={handleCopy}>
复制
</button>
)
}
export default CopyButton
差距:一个是"AI 写的代码",一个是"像团队成员写的代码"。说白了,你想想,AI 本来就不知道你项目的这些规矩,你指望它凭空猜对?
七点五、生成的 AGENTS.md 不准确怎么办?
脚本是通用检测,不可能百分百匹配你项目的全部细节。三种应对策略:
1. 直接用(80% 场景够了)
脚本生成的 AGENTS.md 覆盖了技术栈、目录结构、基础 Never 规则——对 AI 来说已经比"什么都没有"强 10 倍。大多数场景不需要改。
2. 手动微调(5 分钟)
打开 AGENTS.md,找到不对的地方直接改。常见要调的:
- 构建命令不对(如
yarn serve而不是yarn dev) - 漏了某个路径别名(如
@@/*→src/.umi/*) - 项目有特殊禁止项(如不允许用某个库)
3. 让 AI 帮你精修
你:帮我检查 AGENTS.md,结合项目实际代码看看有没有不准确的地方
AI 会对比你的实际代码和 AGENTS.md 的声明,把不一致的地方标出来。确认后一键修复。
💡 记住:AGENTS.md 是活的文档,随时可以改。脚本只是帮你生成初始版本,后续维护靠你(或 AI)。
八、进阶:让 AI 学会你的潜规则
AGENTS.md 管的是显性规范——"组件用 PascalCase"、"不准用 any"。但每个项目还有一堆没写下来的规矩,比如你们的 Model 命名是 Chat.index 这种"模块.子模块"格式,或者 SSE 统一用回调式 + MessageAccumulator 模式。
这些靠初始化脚本搞不定。但你可以让 AI 扫描你的源码自己学:
你:分析项目规范
AI 会从以下维度逐一扫描你的代码:
| 维度 | 分析内容 |
|---|---|
| 技术栈识别 | 框架版本、构建工具、核心依赖 |
| 代码风格 | 组件声明方式、函数 vs 箭头、export 风格 |
| 命名规范 | 文件/目录/变量/常量/CSS 类名的命名模式 |
| 导入顺序 | import 分组和排列习惯 |
| 注释风格 | JSDoc / 行内注释 / 注释语言(中文/英文) |
| Git 规范 | Commit message 格式、scope 命名 |
| 状态管理 | Model / Store 的组织方式和命名 |
| 请求封装 | API 调用模式、错误处理方式 |
| 团队隐性规范 | 只有"老员工才知道"的潜规则(如特殊目录约定、封装模式) |
它会把这些规则整理出来,生成一份 knowledge/best-practices.md。之后写代码就连"只有老员工才知道"的规矩也能遵守了。说实话,这个功能是我自己用的时候才发现威力——它能挖出很多我自己都没意识到的编码习惯。
八点五、搭配社区工具使用
AGENTS.md 管的是 AI 编程助手,社区工具管的是人。两者不冲突,互相补位:
| 工具 | 管谁 | 管什么 |
|---|---|---|
| commitlint + czg | 👤 人 | 提交信息格式 |
| husky + git hooks | 👤 人 | 提交前自动检查 |
| ESLint + Prettier | 👤 人 + 🤖 AI | 代码格式和基础规则 |
| AGENTS.md | 🤖 AI | 项目规范、目录约定、Never 规则 |
推荐组合:
ESLint/Prettier → 管人的代码格式
AGENTS.md → 管 AI 的代码规范
commitlint → 管人的提交信息
社区工具负责底线(格式化、基础 lint),AGENTS.md 负责上限(让 AI 理解项目架构、遵循团队约定)。两者一起用,AI 写出的代码既通过 lint 检查,又符合团队风格。不过话说回来,如果你的项目连 Prettier 都没配置,那就先把 AGENTS.md 上起来,之后慢慢补社区工具。
九、总结
说白了就一件事:花 5 秒跑个脚本,之后 AI 写的代码就不用你反复纠正了。
实际跑下来的数据:
- 初始化耗时:5 秒
- 团队学习成本:0(git pull 自动生效)
- 代码规范遵循率:从 ~60% 涨到 95%+
- AI 输出一次通过率:从 ~40% 涨到 80%+
最大的体感变化是——以前让 AI 写完还得花 10 分钟改格式、换导入、调目录。现在基本生成出来就能用了。老实说,我一开始也觉得 AGENTS.md 没多大必要,直到自己在 7 个项目上都用了才发现——省下来的时间远超预期。
十、精简版 vs 完整版
| 功能 | 精简版(本文) | 完整版 |
|---|---|---|
| AGENTS.md | ✅ ~130 行,10 章节 | ✅ ~200 行,12 章节 + 进化声明 |
| DESIGN.md | ✅ ~35 行 | ✅ ~70 行,含 CSS 变量 + 暗色模式 |
| AGENTS.local.md | ✅ | ✅ |
| AI 指令 | 3 个 | 7 个(含分支名 / 最佳实践 / 规范一致性 / Never 更新) |
| Never 规则 | 14 条 | 15 条 |
| 命名规范 | 6 条 | 6 条 + 类型前缀 |
| 导入顺序 | ✅ 6 层基础 | ✅ 6 层 + 示例 |
| 安全规范 | ❌ | ✅ 5 条约束 |
| 代码生成模板 | ❌ | ✅ 组件 / Hook / Service |
| 半自动进化 | ❌ | ✅ 错误记录 + Never 升级 |
| 脚本参数 | 默认覆盖 | --update 智能合并 / --check 自检 |
| 增量策略 | 默认覆盖 | 默认覆盖 + 智能合并 + 自检 |
十一、下一步
- 深度蒸馏:对 AI 说
分析项目规范,让它扫描源码产出 500+ 行的最佳实践文档 - CR 代码:对 AI 说
CR 代码,自动 Review 暂存区代码并生成 commit 信息 - 完整版 Skill 体系:支持代码模板注入、半自动进化、团队共享配置
📢 下篇预告
《一句"分析项目规范",AI 自动蒸馏出你团队的隐性编码规范》
本篇解决了"AI 不知道你项目的规范"——用脚本自动生成 AGENTS.md。
但每个项目还有一堆没写下来的规矩:Model 的命名是
Chat.index格式、SSE 统一用回调式 + MessageAccumulator 模式、API 层必须用namespace API做类型分组……这些"只有老员工才知道"的潜规则,靠初始化脚本搞不定。
下篇教你对 AI 说一句
分析项目规范,让它扫描你的源码,自动蒸馏出隐性编码规范——从 9 个维度(命名/文件组织/导入顺序/注释风格/状态管理/请求封装……)提炼团队的真实编码习惯,产出一份 AI 可消费的最佳实践文档。
📌 本文精简版脚本已经能覆盖 80% 的使用场景(3 个文件 + 3 个 AI 指令)。
想要完整版(含代码生成模板、半自动进化、6~8 个 AI 指令、
--update智能合并)?关注我,私信发送"AGENTS"即可获取。觉得有用?点赞 👍 + 收藏 ⭐,让更多前端团队看到。
附:多 AI 工具兼容
AGENTS.md 是一个开放的约定格式,不绑定任何特定 AI 工具。以下 AI 编程助手都会自动读取项目根目录的 AGENTS.md:
| 工具 | 读取方式 |
|---|---|
| Cursor | 自动识别 AGENTS.md |
| Claude Code | 自动识别 AGENTS.md |
| GitHub Copilot (Agent 模式) | 自动识别 AGENTS.md |
| Windsurf | 自动识别 AGENTS.md |
| Trae | 自动识别 AGENTS.md |
写一份 AGENTS.md,所有工具通用。不管你团队成员用哪个 AI 助手,看到的项目规范都是同一份。