- template/.claude/commands/coauthor.md.jinja:生成项目自带 /coauthor on|off|status, 薄包装调用 ./scripts/claude-attribution.sh,Claude Code 里打 / 即可发现 - 仅本项目生效,不装全局、不影响用户其它项目(install-skill.sh 未改) - 两个脚本不变(开关 + 门禁);终端/CI 仍可直接用脚本 - README 署名章节补 /coauthor 用法 + 文件树补 coauthor.md.jinja 验证:仅后端/全栈两配置均生成 coauthor.md + 两脚本;命令体动作 off/on/status 读写 git config 正确;~/.claude/commands 未受影响;check-docs 通过。
22 KiB
scaffold · new-project skill
一个 Claude Code Skill:在任意项目里对 Claude 说一句"帮我新建项目",即可生成含完整质量门禁(pre-commit、CI、Docker、Claude 规则)的 FastAPI + React 工程骨架,并随选型自动裁剪规则文件。
🚀 安装(推荐)
一条命令装到全局,任意项目可用,无需克隆本仓库:
curl -fsSL https://raw.githubusercontent.com/baozaotumao2025/scaffold/main/scripts/install-skill.sh | bash
用法
安装后,在 Claude Code 中任选一种方式:
/new-project # 交互式问卷,逐步选服务/数据库
/new-project my-app # 指定项目名,其余交互确认
/new-project my-rules --preset principles # 仅生成 10 个原理层规则,无服务代码
或者直接用自然语言——Claude 会自动识别并触发 skill:
「帮我新建一个全栈项目,要 FastAPI + React,数据库用 postgresql」
可用 preset:principles(仅规则)· fullstack · fullstack-ai · api-only。
模板由 copier 从 GitHub 实时拉取。skill 目录
.claude/skills/new-project/自包含(SKILL.md + scripts/verify.sh),安装即整目录拷贝,符合 skill 可移植惯例。
核心设计
两层规则体系
脚手架内置的 Claude Code 规则文件分为两层,职责不同:
| 层级 | 规则文件 | 加载方式 | 说明 |
|---|---|---|---|
| 原理层 | architecture.md / ddd.md / design-discipline.md 等 10 个 |
全局恒加载 | 六边形架构、DDD、SOLID、TDD 等通用原则,换项目不变 |
| 落地层 | backend*.md / agent*.md / frontend*.md |
按 paths 按需加载 |
原理在本项目具体服务中的落地约束,随选型生成 |
落地层规则根据问卷答案动态生成或选择,而非固定复制:
问卷选择 生成的落地层规则
────────────────────────────────────────────────────────────────────
include_agent=true
llm_provider=gemini-cli → agent.md + agent-concurrency.md
+ agent-llm-pty.md(PTY/CLI 规范)
llm_provider=openai-api → agent.md + agent-concurrency.md
+ agent-llm-api.md(API 流式规范)
llm_provider=anthropic-api → 同上(agent-llm-api.md)
include_agent=false → 所有 agent*.md 全部排除
database=sqlite → backend-db.md(SQLite + WAL 模式)
database=postgresql → backend-db.md(asyncpg + 连接池 + pg 迁移注意)
include_backend=false → 所有 backend*.md 排除
include_frontend=false → 所有 frontend*.md 排除
────────────────────────────────────────────────────────────────────
四层质量护栏(左移,编码即查错)
同一套规则(ruff/mypy 读 pyproject.toml,eslint/prettier 读各自配置)贯穿四层,越靠前越早发现,到 commit 时基本只是确认:
| 层 | 时机 | 机制 | 是否默认生成 |
|---|---|---|---|
| 1 编辑器 LSP | 边打字 | .vscode/settings.json + extensions.json:保存自动格式化/修复、实时标红 |
✅ 始终 |
| 2 watch 监听 | 一保存 | .vscode/tasks.json:打开项目自动起 tsc --watch / ruff --watch |
开关 vscode_auto_watch |
| 3 pre-commit | git commit | .pre-commit-config.yaml:ruff/mypy/eslint/tsc/gitleaks |
✅ 始终 |
| 4 CI | push / PR | .github/workflows/ci.yml |
✅ 始终 |
关于 .vscode/:
- 只影响当前项目(工作区级),不碰你的 VSCode 全局配置;个人偏好(主题/字号)仍走全局。
- 是团队级规则,随 scaffold 演进——
copier update走 3-way 合并推送改进,仅改了同一行才提示冲突。 - 首次用 watch 需在命令面板执行一次 "Tasks: Allow Automatic Tasks" 授权。
按规则生成功能:/new-feature
生成的项目自带一个 Claude Code 命令 /new-feature,把"按规则搭功能骨架"固化成一条标准提示词。
/new-feature 订单
/new-feature 用户认证
模式:纯结构 + 契约(不猜业务逻辑)。 Claude 现场阅读本项目的 .claude/rules,按六边形分层为该功能生成跨层的文件骨架:
domain/(实体+值对象+端口 Protocol) → application/services → infrastructure/db(repository)
→ routers → 依赖注入;前端 types/schemas → store → hooks → components
- 每个方法写完整签名 + docstring(前置/后置条件),方法体留
raise NotImplementedError - 接好依赖注入、注册路由、登记错误码
- 不臆造业务逻辑、不写假设断言的测试——避免你去调试 AI 猜的代码
- 自检只跑
ruff + mypy(验证结构能编译、类型自洽),不跑 pytest
命令按选型自动裁剪,只生成存在服务对应的层,末尾给出待填充 TODO 清单。
分工:脚手架 copier 预生成完整架构基座(分层目录 + 横切层,确定性、能跑、过门禁,见下「架构基座」);
/new-feature引导 Claude 在基座上搭功能切片骨架;业务逻辑你按testing-tdd.md(先测试后实现)自己填。
Claude 署名策略(每个生成项目自带)
控制提交信息里是否包含 Co-Authored-By: Claude 署名。默认 off(不含),由 commit-msg 门禁每次提交强制执行。仅本项目生效。
在 Claude Code 里(项目自带斜杠命令,打 / 即可找到):
/coauthor status # 查看当前策略
/coauthor off # 不含署名(默认)
/coauthor on # 保留署名
或在终端直接用脚本(CI / 不用 Claude 时):
./scripts/claude-attribution.sh status # 查看当前策略
./scripts/claude-attribution.sh off # 不含署名(默认)
./scripts/claude-attribution.sh on # 保留署名
- 策略存于
git config scaffold.includeClaude(项目级),_tasks生成时默认设为false - 门禁:
check-claude-attribution.sh挂在 pre-commit 的 commit-msg 阶段——策略 off 时自动剥除任何 Claude 署名行并提示,on 时保留 - 即使有人/AI 在提交里带了署名,off 策略下也会被自动清掉,保证不入库
架构基座(每个生成项目自带,开箱即跑)
不加任何功能,生成的项目第一天就有完整分层结构 + 与业务无关的横切基础设施,三服务各自通过 ruff/mypy/build 门禁:
backend/src/ agent/src/ frontend/src/
├── domain/ (空层包) ├── domain/ dag/ llm/ ├── components/ErrorBoundary
├── application/services/ ├── providers/ export/ storage/ ├── services/wsClient
├── infrastructure/db/ base(engine) │ (空层包) ├── utils/logger
├── routers/ health + ws ├── domain/exceptions ├── App / main(ErrorBoundary
├── middleware/ request_id+access ├── utils/ ids/files/concurrency│ + Toaster) + tailwind
├── exceptions/ AppException+handler ├── core/ config+logging └── vite 类型
├── utils/ ids+files(防穿越) └── main health/ready + ws
└── core/ config+logging+deps
- 横切层是确定性的(中间件、异常、DB 接线、日志、WS、错误边界规则里逐字给定)→ copier 预生成,永远一致、不漂移。
- 运行时目录(日志
~/{项目}/logs/、临时~/{项目}/{uuid}/)由代码按需创建,不入库。 - 空层包(domain/services 等)等
/new-feature或你按规则填业务。
脚手架内容
scaffold/
├── copier.yml ← 问卷变量 + 条件排除逻辑
├── README.md
├── .claude/skills/new-project/ ← 自包含 skill(拷了即用,符合惯例)
│ ├── SKILL.md ← skill 元数据 + 生成指令
│ └── scripts/verify.sh ← skill 自带(与根 scripts/verify.sh 同步,CI 防漂移)
├── .github/workflows/docs-check.yml ← scaffold 自身 CI:防文档/verify.sh 漂移
├── scripts/
│ ├── verify.sh ← 工具链合规检查(幂等只读,维护/retrofit 用)
│ ├── install-skill.sh ← 整目录拷贝安装 skill 到 ~/.claude/skills/
│ ├── check-docs.sh ← 校验 README 覆盖 template 架构基座目录
│ └── retrofit.sh ← 补装工具链到已有项目
└── template/
├── .copier-answers.yml.jinja ← 记录模板版本+答案,供 copier update
├── .pre-commit-config.yaml.jinja ← 按服务条件生成 hooks(含 gitleaks)
├── .github/workflows/ci.yml.jinja ← 按服务条件生成 CI jobs
├── .vscode/ ← 编辑器实时护栏(始终生成)
│ ├── settings.json.jinja ← 保存自动格式化/修复(按服务裁剪)
│ ├── extensions.json.jinja ← 推荐扩展(ruff/eslint/mypy…)
│ └── tasks.json.jinja ← 自动 watch(仅 vscode_auto_watch=true)
├── docker-compose.yml.jinja
├── CLAUDE.md.jinja ← 项目说明参数化
├── scripts/
│ ├── claude-attribution.sh ← 开关:本项目提交是否含 Claude 署名(默认 off)
│ └── check-claude-attribution.sh ← commit-msg 门禁:按开关移除/保留署名
├── .claude/commands/
│ ├── new-feature.md.jinja ← 项目内命令:按规则引导生成功能分层代码
│ └── coauthor.md.jinja ← 项目内命令:/coauthor 切换 Claude 署名开关
├── .claude/rules/
│ ├── # 原理层(10 个,静态,始终复制)
│ ├── architecture.md / ddd.md / design-discipline.md ...
│ │
│ ├── # 落地层:静态但条件复制(按服务选择)
│ ├── agent-dag.md ← DAG 模式(不随 LLM 选型变)
│ ├── agent-extension-points.md ← 扩展点模式(不随 LLM 选型变)
│ ├── agent-llm-pty.md ← LLM CLI/PTY 规范(仅 gemini-cli)
│ ├── agent-llm-api.md ← LLM API/SDK 规范(非 gemini-cli)
│ ├── backend.md / backend-concurrency.md
│ ├── frontend.md / frontend-runtime.md
│ ├── communication-catalog.md / error-codes.md / observability.md
│ │
│ └── # 落地层:动态渲染(.jinja,内容随选型变化)
│ ├── agent.md.jinja ← 技术栈表 / 依赖 / 目录 / 配置 / 测试
│ ├── agent-concurrency.md.jinja ← PTY 并发节 vs API 并发节
│ └── backend-db.md.jinja ← SQLite 配置 vs PostgreSQL 配置
├── backend/ pyproject / Dockerfile / .env.example
│ └── src/ 架构基座:domain application infrastructure/db routers middleware
│ exceptions utils core(详见上「架构基座」)
├── agent/ pyproject / Dockerfile / .env.example
│ └── src/ 架构基座:domain dag llm providers export storage utils core + WS
└── frontend/ package.json / pnpm-workspace / tsconfig / tailwind / postcss / eslint / vite
└── src/ 架构基座:components(ErrorBoundary) services(wsClient) utils(logger) + 入口
进阶:不装 skill,直接用 copier
以下面向 CI、脚本,或不使用 Claude Code 的场景。日常使用推荐上面的 skill 方式。
前置依赖:
pip install copier # 或 uv tool install copier
交互式问卷
copier copy git+https://github.com/baozaotumao2025/scaffold.git my-new-project
问卷包含以下选择:
| 变量 | 类型 | 默认 | 说明 |
|---|---|---|---|
project_name |
str | My Awesome Service | 项目显示名称 |
project_slug |
str | 自动派生 | snake_case 包名 |
org_name |
str | my-org | GitHub 组织名 |
description |
str | — | 一行项目描述 |
include_backend |
bool | true | 包含 FastAPI backend |
include_agent |
bool | false | 包含 LLM Agent 服务 |
include_frontend |
bool | true | 包含 React + Vite 前端 |
backend_port |
int | 8000 | Backend 端口 |
agent_port |
int | 8001 | Agent 端口 |
frontend_port |
int | 5173 | 前端端口 |
python_version |
choice | 3.12 | 3.11 / 3.12 / 3.13 |
database |
choice | sqlite | sqlite / postgresql |
node_version |
choice | 22 | 20 / 22 |
llm_provider |
choice | gemini-cli | gemini-cli / openai-api / anthropic-api / custom |
vscode_auto_watch |
bool | false | VSCode 打开项目自动启动 watch 任务(编码即时查错) |
llm_provider仅在include_agent=true时出现。
静默生成(CI / 脚本中)
# 全栈 + OpenAI API + PostgreSQL
copier copy git+https://github.com/baozaotumao2025/scaffold.git my-project \
--data project_name="My Service" \
--data include_backend=true \
--data include_agent=true \
--data include_frontend=true \
--data database=postgresql \
--data llm_provider=openai-api
# 仅 API(backend only,SQLite)
copier copy git+https://github.com/baozaotumao2025/scaffold.git my-api \
--data include_backend=true \
--data include_agent=false \
--data include_frontend=false
# 本地模板调试
copier copy ./scaffold /tmp/test-project
模板更新(推送给已有项目)
cd my-existing-project
# 复用上次答案,自动三路合并
copier update --defaults
# 修改某个答案(如切换数据库)
copier update --data database=postgresql
# 查看更新预览(不实际写入)
copier update --defaults --pretend
.copier-answers.yml 由 Copier 自动维护,记录模板版本和答案,不要手动修改。
工具脚本
verify.sh — 合规检查
检查项目工具链配置是否符合 scaffold 规范。只读幂等,不修改任何文件,可重复运行。
用法:./scripts/verify.sh [OPTIONS] [PROJECT_PATH]
选项:
-h, --help 显示帮助信息
-v, --verbose 详细输出(显示所有通过项和跳过项)
-s, --strict 严格模式:警告(△)也视为失败,退出码 1
退出码:
0 全部通过(严格模式下无警告)
1 存在失败项
2 参数错误
# 检查当前目录
./scripts/verify.sh
# 详细模式(显示每项通过/跳过的路径)
./scripts/verify.sh -v
# 严格模式(CI 中使用,警告也阻断)
./scripts/verify.sh -s /path/to/project
# 详细 + 严格(组合简写)
./scripts/verify.sh -vs .
智能检查内容:
- 自动读取
.copier-answers.yml获取llm_provider和database配置 - 按存在的目录(
backend//agent//frontend/)决定检查哪些服务 - LLM 驱动规则互斥验证:
gemini-cli时检查agent-llm-pty.md存在且agent-llm-api.md不存在(反之同理),两个同时存在时输出 WARN - Claude 规则文件完整性检查(全局规则 + 对应落地层规则)
- 工具链可用性检查(uv / pnpm / pre-commit / copier 版本)
汇总输出示例:
═══════════════════════════════════════════════════════════════
分类 通过 警告 失败
根目录 6 1 0
Backend 8 0 0
Agent 7 0 0
Frontend 9 0 0
Pre-commit 钩子 4 0 0
Claude 规则文件 18 0 0
工具链可用性 4 0 0
───────────────────────────────────────────────────────────────
合计 56 1 0
═══════════════════════════════════════════════════════════════
✓ 核心检查全部通过 △ 1 项警告(建议修复)
retrofit.sh — 补装工具链到已有项目
对未经 copier 创建的已有项目,叠加 scaffold 模板。全部步骤幂等,重复运行安全。
用法:./scripts/retrofit.sh [OPTIONS] [PROJECT_PATH]
选项:
-h, --help 显示帮助信息
-n, --dry-run 预览所有操作,不实际执行任何命令
-f, --force 强制覆盖配置文件(移除 _skip_if_exists 保护,慎用)
--no-deps 跳过依赖安装,仅运行 copier copy
--scaffold URL 指定 scaffold 来源(覆盖 $SCAFFOLD_URL)
环境变量:
SCAFFOLD_URL scaffold 来源(默认:git+https://github.com/baozaotumao2025/scaffold.git)
# 补装工具链到当前目录
./scripts/retrofit.sh
# 先预览将执行哪些步骤(不实际运行)
./scripts/retrofit.sh --dry-run /path/to/project
# 使用本地 scaffold(开发调试)
SCAFFOLD_URL=./scaffold ./scripts/retrofit.sh /path/to/project
# 使用远程 scaffold,仅运行 copier(跳过 uv/pnpm)
./scripts/retrofit.sh --scaffold git+https://github.com/baozaotumao2025/scaffold.git --no-deps .
# 补装后立即验证
./scripts/retrofit.sh . && ./scripts/verify.sh .
幂等性保证:
| 步骤 | 幂等机制 |
|---|---|
| Copier 模版叠加 | _skip_if_exists 保护 src/ 代码不被覆盖 |
uv sync |
--frozen 保证锁文件一致;已安装时仅校验,不重装 |
pnpm install |
--frozen-lockfile 保证锁文件一致 |
| Pre-commit 安装 | 检测 .git/hooks/pre-commit 已存在时 SKIP,--force 才重装 |
步骤汇总输出示例:
═══════════════════════════════════════════════════════════════
Retrofit 步骤汇总: /path/to/project
───────────────────────────────────────────────────────────────
步骤 状态
Copier 模版叠加 ✓ 完成
Backend uv sync ✓ 完成
Agent uv sync – 跳过
Frontend pnpm install ✓ 完成
Pre-commit 钩子 – 跳过(已安装,幂等)
───────────────────────────────────────────────────────────────
完成: 3 跳过: 2 警告: 0 失败: 0
═══════════════════════════════════════════════════════════════
后续步骤:
• 运行 ./scripts/verify.sh /path/to/project 验证最终结果
典型组合示例
# 1. 全栈 AI 项目(默认 gemini-cli PTY 模式)
copier copy ./scaffold /tmp/test-full \
--data include_backend=true --data include_agent=true --data include_frontend=true
# 2. 全栈 AI 项目(OpenAI API 模式,生成 agent-llm-api.md 而非 agent-llm-pty.md)
copier copy ./scaffold /tmp/test-openai \
--data include_backend=true --data include_agent=true --data include_frontend=true \
--data llm_provider=openai-api --data database=postgresql
# 3. 仅 API 服务(无前端,无 agent)
copier copy ./scaffold /tmp/test-api \
--data include_backend=true --data include_agent=false --data include_frontend=false
# 4. 验证生成结果(详细模式)
./scripts/verify.sh -v /tmp/test-full
发布到团队
cd my-scaffold
git init && git add . && git commit -m "chore: initial scaffold"
git remote add origin git@github.com:baozaotumao2025/scaffold.git
git push -u origin main
# 打版本 tag(copier update 按 tag 追踪)
git tag v1.0.0 && git push --tags
之后团队成员只需:
pip install copier
copier copy git+https://github.com/baozaotumao2025/scaffold.git my-project
贡献模板
- 修改
template/下的.jinja文件或静态规则文件 - 本地测试:
copier copy . /tmp/test && cd /tmp/test && pre-commit run --all-files - 用
verify.sh验证生成项目合规性:./scripts/verify.sh -v /tmp/test - 打 semver tag:
git tag v1.1.0 && git push --tags - 已有项目运行
copier update --defaults三路合并收到更新
添加新的 LLM provider 支持
- 在
copier.yml的llm_provider.choices中增加新选项 - 在
template/.claude/rules/agent.md.jinja中添加对应{% elif llm_provider == '...' %}分支 - 在
template/.claude/rules/agent-concurrency.md.jinja中视需要添加分支 - 若新 provider 使用不同机制(非 API SDK),按需新建对应规则文件并在
copier.yml的_exclude中添加互斥条件 - 更新
scripts/verify.sh中agent/pyproject.toml的 SDK 包名检查
添加新的数据库支持
- 在
copier.yml的database.choices中增加新选项 - 在
template/.claude/rules/backend-db.md.jinja中添加对应{% elif database == '...' %}分支 - 在
scripts/verify.sh的local_driver映射中添加新数据库的驱动包名