一行命令,让 AI 从此懂你项目的规范

679 阅读16分钟

一行命令,让 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.jsontsconfig.json.prettierrc,输出类似这样的结果:

📦 项目: imp-data-agent
🔍 检测结果: React 19 + Umi | Ant Design | Less + CSS Modules | yarn | TypeScript

原理:从多个配置文件中提取信息,用 grep 匹配关键词:

检测项来源识别方式
框架package.jsonreact / vue / next / nuxt / angular / svelte / umi
UI 库package.jsonantd / element-plus / @arco-design / semi / vant / @mui
样式方案package.jsonless / 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/ 下实际存在的目录
Monorepolerna.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 ConventionConventional Commits + lint-staged + git 禁止操作~12 行
Component & API Conventions组件目录规则 + API 放置规则~10 行
Never Rules14 条禁止规则~16 行
Multi-Agent Safety并发安全规则~5 行
Quick Commands3 个 AI 指令(分析规范 / CR 代码 / 生成命名)~10 行
Error Handling错误处理约定(try-catch / ErrorBoundary)~6 行

🎨 生成 DESIGN.md(~35 行)

基于检测到的 UI 库,自动适配设计 Token:

UI 库主色圆角
Ant Design#1677ff6px
Element#409EFF4px
Arco Design#165DFF4px
Semi Design#0077FA6px
Vant#1989fa4px
Material UI#1976d24px

还包含间距系统(8px 网格)、字体、响应式断点等基础设计规范。

文件已存在?跳过。不会覆盖你手动调整过的内容。

🚀 完整版额外能力(私信获取)

精简版生成 AGENTS.md + DESIGN.md 两个文件。完整版额外做这些:

文件作用
AGENTS.local.md个人偏好(不入仓库)
.agents/generation-spec.md代码生成模板(组件/Hook/Service 模板)
.agents/logs/corrections.mdAI 错误修正记录(半自动进化用)
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 自检
增量策略默认覆盖默认覆盖 + 智能合并 + 自检

十一、下一步

  1. 深度蒸馏:对 AI 说 分析项目规范,让它扫描源码产出 500+ 行的最佳实践文档
  2. CR 代码:对 AI 说 CR 代码,自动 Review 暂存区代码并生成 commit 信息
  3. 完整版 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 助手,看到的项目规范都是同一份。