871e0589cd
- .claude/skills/new-project/ 自带 scripts/verify.sh:拷了即用、可移植, 不再依赖 install 时从根 scripts/ 组装 - install-skill.sh 简化:本地整目录 cp -R / 远程按清单拉取 - check-docs.sh 增加一致性校验:根 scripts/verify.sh 与 skill 内副本必须相同 (改了根副本需同步,CI/本地都会报漂移) - README 更新 skill 自包含说明 + 文件树 取舍:接受 verify.sh 两份小重复,换 skill 自包含可移植——符合 Anthropic skills 惯例, 比'安装时组装'更专业、更好维护;漂移由 CI 兜底。
465 lines
20 KiB
Markdown
465 lines
20 KiB
Markdown
# scaffold · new-project skill
|
||
|
||
> 一个 **Claude Code Skill**:在任意项目里对 Claude 说一句"帮我新建项目",即可生成含完整质量门禁(pre-commit、CI、Docker、Claude 规则)的 FastAPI + React 工程骨架,并随选型自动裁剪规则文件。
|
||
|
||
## 🚀 安装(推荐)
|
||
|
||
一条命令装到全局,**任意项目可用**,无需克隆本仓库:
|
||
|
||
```bash
|
||
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`(先测试后实现)自己填。
|
||
|
||
---
|
||
|
||
## 架构基座(每个生成项目自带,开箱即跑)
|
||
|
||
不加任何功能,生成的项目第一天就有**完整分层结构 + 与业务无关的横切基础设施**,三服务各自通过 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 ← 项目说明参数化
|
||
├── .claude/commands/
|
||
│ └── new-feature.md.jinja ← 项目内命令:按规则引导生成功能分层代码
|
||
├── .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 方式。
|
||
|
||
前置依赖:
|
||
|
||
```bash
|
||
pip install copier # 或 uv tool install copier
|
||
```
|
||
|
||
### 交互式问卷
|
||
|
||
```bash
|
||
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 / 脚本中)
|
||
|
||
```bash
|
||
# 全栈 + 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
|
||
```
|
||
|
||
---
|
||
|
||
## 模板更新(推送给已有项目)
|
||
|
||
```bash
|
||
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 参数错误
|
||
```
|
||
|
||
```bash
|
||
# 检查当前目录
|
||
./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)
|
||
```
|
||
|
||
```bash
|
||
# 补装工具链到当前目录
|
||
./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 验证最终结果
|
||
```
|
||
|
||
---
|
||
|
||
## 典型组合示例
|
||
|
||
```bash
|
||
# 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
|
||
```
|
||
|
||
---
|
||
|
||
## 发布到团队
|
||
|
||
```bash
|
||
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
|
||
```
|
||
|
||
之后团队成员只需:
|
||
|
||
```bash
|
||
pip install copier
|
||
copier copy git+https://github.com/baozaotumao2025/scaffold.git my-project
|
||
```
|
||
|
||
---
|
||
|
||
## 贡献模板
|
||
|
||
1. 修改 `template/` 下的 `.jinja` 文件或静态规则文件
|
||
2. 本地测试:`copier copy . /tmp/test && cd /tmp/test && pre-commit run --all-files`
|
||
3. 用 `verify.sh` 验证生成项目合规性:`./scripts/verify.sh -v /tmp/test`
|
||
4. 打 semver tag:`git tag v1.1.0 && git push --tags`
|
||
5. 已有项目运行 `copier update --defaults` 三路合并收到更新
|
||
|
||
### 添加新的 LLM provider 支持
|
||
|
||
1. 在 `copier.yml` 的 `llm_provider.choices` 中增加新选项
|
||
2. 在 `template/.claude/rules/agent.md.jinja` 中添加对应 `{% elif llm_provider == '...' %}` 分支
|
||
3. 在 `template/.claude/rules/agent-concurrency.md.jinja` 中视需要添加分支
|
||
4. 若新 provider 使用不同机制(非 API SDK),按需新建对应规则文件并在 `copier.yml` 的 `_exclude` 中添加互斥条件
|
||
5. 更新 `scripts/verify.sh` 中 `agent/pyproject.toml` 的 SDK 包名检查
|
||
|
||
### 添加新的数据库支持
|
||
|
||
1. 在 `copier.yml` 的 `database.choices` 中增加新选项
|
||
2. 在 `template/.claude/rules/backend-db.md.jinja` 中添加对应 `{% elif database == '...' %}` 分支
|
||
3. 在 `scripts/verify.sh` 的 `local_driver` 映射中添加新数据库的驱动包名
|