Claude Code 实战分享(1):从"代码助手"到"AI 协调者"
-
- [引言:从"AI 垃圾制造机"到"AI 团队 Leader"](#引言:从"AI 垃圾制造机"到"AI 团队 Leader")
- [第一阶段:提示工程师(Prompt Engineer)](#第一阶段:提示工程师(Prompt Engineer))
-
- [状态:单向指令,视 AI 为"钝器"](#状态:单向指令,视 AI 为"钝器")
- [风险:产出"AI 垃圾",回归平庸](#风险:产出"AI 垃圾",回归平庸)
- 关键技能:清晰提示词、明确目标、辨别质量
- [第二阶段:规划者模式(Planner Mode)](#第二阶段:规划者模式(Planner Mode))
- [第三阶段:上下文工程师(Context Engineer)](#第三阶段:上下文工程师(Context Engineer))
-
- 王牌技能:上下文窗口管理
- [操作手段:`/clear` 重置、`Claude.md` 立规矩](#操作手段:
/clear重置、Claude.md立规矩)
- 第四阶段:工具匠(Toolsmith)
-
- [核心思维:能力 ≠ 性能,拒绝盲目堆砌](#核心思维:能力 ≠ 性能,拒绝盲目堆砌)
- 架构解构:理解模块协作逻辑
- 精准调用:按场景选择工具
- [实战案例:License 脚本执行器的工具链设计](#实战案例:License 脚本执行器的工具链设计)
- [第五阶段:技能达人(Skill Master)](#第五阶段:技能达人(Skill Master))
-
- [技能本质:针对特定任务的预设 Prompt](#技能本质:针对特定任务的预设 Prompt)
- [工具:Skill Creator 打造专属技能](#工具:Skill Creator 打造专属技能)
- 管理策略:按项目配置,避免全局技能堵塞上下文
- 可组合技能链
- 第六阶段:协调者(Orchestrator)
-
- 核心能力:从单实例到管理"代理团队"
- [Git 工作树:为子代理分配独立工作分支](#Git 工作树:为子代理分配独立工作分支)
- 团队模式:主终端指挥分工明确的子代理
- 实战案例:一天完成"不可能的任务"
- [本质:命令者 → 合作伙伴 → 架构师 → 团队管理者](#本质:命令者 → 合作伙伴 → 架构师 → 团队管理者)
- 给读者的行动建议
本文基于一个真实的全栈项目演进过程,记录我使用 Claude Code 从"写提示词的新手"成长为"管理 AI 代理团队"的六阶段心路历程。
引言:从"AI 垃圾制造机"到"AI 团队 Leader"
免责声明:本文所有技术细节均来自真实项目,但"凌晨两点"、"第 17 版"这类修辞性数据------你懂的,那是写文章的必要夸张。就像简历上的"精通"一样,懂的都懂。
三个月前,我接手了一个项目:vupStack,一个部署管理系统。技术栈很标准------Vue 3 + TypeScript 前端,Java + Spring Boot 后端,MySQL 数据库。业务逻辑嘛,说复杂也复杂:版本依赖、License 生成、Docker 镜像管理、客户环境配置......十几个模块像俄罗斯方块一样堆在一起,稍有不慎就 Game Over。
最初的两周,我和 Claude Code 的关系,就像甲方和乙方:
我:帮我写个登录页面
Claude:好的,这是一个 Vue 登录组件...
[生成 200 行代码]
我:不对,要加上表单验证
Claude:好的,加上 Element Plus 的表单验证...
[又生成 200 行]
我:还有记住密码功能
Claude:...
[此时上下文已经塞满了我的碎碎念]
三轮对话后,Claude 开始"失忆"------前面说好的路由守卫忘了,已经写好的类型定义重复定义。最离谱的是,它把 customerName 和 customerCode 混为一谈,生成了一份连它自己都不知道在干什么的代码。
我愤怒地拍桌子:"这 AI 不行啊!"
同事路过,瞥了一眼我的屏幕:"你试试把需求写清楚?"
我:"......"
那一刻,我突然醒悟:不是 AI 不够聪明,是我还在用'甲方提需求'的方式对待它。AI 不是锤子,我不能见什么都是钉子------更不能自己都没想明白,就让 AI 去砸。
这篇文章,就是我三个月来从"AI 垃圾制造机"进化到"AI 团队 Leader"的完整路线图。全程真实,偶有夸张,但技术细节绝不注水。
第一阶段:提示工程师(Prompt Engineer)
状态:单向指令,视 AI 为"钝器"
刚开始使用 Claude Code 时,我的交互模式很简单:想到什么说什么。
我:帮我写个用户登录页面
Claude:好的,这是一个 Vue 登录组件...
[生成 200 行代码]
我:不对,要加上表单验证
Claude:好的,加上 Element Plus 的表单验证...
[又生成 200 行]
我:还有记住密码功能
Claude:...
三轮对话后,上下文已经塞满了碎片化的需求,AI 开始"失忆"------前面说好的路由守卫忘了,已经写好的类型定义重复定义。最糟糕的是,它产出的代码能用,但毫无架构可言:逻辑混在模板里,类型用 any 糊弄,错误处理靠 console.log。
风险:产出"AI 垃圾",回归平庸
这就是"AI 垃圾"(AI Slop):表面上功能齐全,细看全是坑。我花了三天让 Claude 写了个版本管理模块,结果代码审查时被同事打回------循环依赖、魔法数字、没有单元测试。
我愤怒地指责 AI"不靠谱"。同事默默打开我的对话记录,指着其中一条:
我:随便写个版本管理,差不多就行
同事:"......这就是你说的'靠谱'?"
我:"......"
问题出在输入端。 我给 AI 的指令越模糊,它回馈我的惊喜(吓)就越多。
关键技能:清晰提示词、明确目标、辨别质量
这个阶段我学到的第一课是:AI 的产出质量,永远不会超过你的需求描述质量。
我开始强迫自己写"结构化提示词":
需求:实现版本管理模块的列表页
技术栈:Vue 3 + TypeScript + Element Plus
要求:
1. 使用 <script setup lang="ts">,Props 用泛型声明
2. 所有 API 调用封装在 src/api/version.ts
3. 表格列:版本号、产品名称、状态、创建时间、操作
4. 操作列包含:查看详情、编辑、删除(需二次确认)
5. 分页使用后端分页,PageHelper 返回 {list, total, page, pageSize}
6. 样式使用 CSS 变量,禁止硬编码颜色
输出:完整的 Vue 单文件组件 + API 模块 + 类型定义
效果立竿见影。但即便如此,我很快遇到了天花板------当项目超过一定复杂度,再精确的提示词也解决不了"只见树木不见森林"的问题。
第二阶段:规划者模式(Planner Mode)
核心转向:从"下达命令"到"协作提问"
转折点发生在我需要设计"License 生成系统"时。这个模块涉及:接收 OA 系统推送的 DTO、字段映射、SSH 远程执行脚本、文件命名规范、并发冲突处理......我试着一次性描述给 Claude,结果它给出了一个看似完整但漏洞百出的方案------完全没考虑并发时的竞态条件。
我意识到:我不能只给 AI 下命令,我要让它帮我思考。毕竟,一个人想漏的东西,两个人(哪怕其中一个是 AI)想的概率总会小一点。
关键技能:引导性问题、魔鬼代言人
我开始使用"规划者模式"(Planner Mode),不再说"帮我实现 X",而是说"我们要实现 X,你觉得有哪些关键风险?"
我:我们需要设计一个 License 构建系统,核心流程是:
1. OA 系统推送 DTO(含 softwareName、customerName、macAddress 等)
2. 后端持久化到 MySQL,状态设为 PENDING
3. 异步任务 SSH 到远程服务器执行脚本
4. 脚本生成 .license 文件,回传文件路径
5. 更新状态为 SUCCESS,记录文件路径
你觉得这个设计有哪些潜在问题?
Claude:有几个风险点需要考虑:
1. 并发冲突:两个相同参数的构建请求同时到达
2. 失败重试:SSH 超时或脚本失败时如何安全重试
3. 文件命名冲突:同一天同一客户同一软件可能多次构建
4. 状态一致性:异步任务崩溃后,PENDING 记录可能永远挂起
我:很好。针对第 1 点,你觉得用数据库唯一约束还是分布式锁?
Claude:建议数据库层面用 (software_name, customer_name, version_no) 唯一约束,
配合 INSERT ... ON DUPLICATE KEY UPDATE 或先查后插的幂等设计...
这种"协作提问"的模式,让 AI 从"执行者"变成了"思考伙伴"。更妙的是,我会让它扮演"魔鬼代言人"(Devil's Advocate):
我:现在请你扮演一个严格的代码审查者,找出这个设计的三个最大漏洞。
Claude:
1. 你没有处理"INF 产品特殊流程"------某些产品需要先执行 auth license 脚本
2. customerName 直接来自 OA,如果包含特殊字符可能导致文件名非法
3. 异步任务没有超时机制,一个卡住的 SSH 会话可能阻塞整个线程池
这些问题,都是我在"命令模式"下从未想过的。毕竟,人的大脑缓存也就那么大,能同时装下的 edge case 有限。让 AI 当"魔鬼代言人",相当于白嫖了一个 7x24 小时待命的架构评审员------还不用请它喝咖啡。
第三阶段:上下文工程师(Context Engineer)
王牌技能:上下文窗口管理
当项目进入深水区,我遇到了一个诡异的现象:上午 Claude 还能准确理解"VersionDetailsTab 的 10 个只读 Section 组件",下午就开始 hallucination,把 VersionDeployChange 写成 VersionDockerChange,把 /api/versions/{id}/deploy-changes 记成 /api/versions/{id}/docker-changes。
我:"你上午不是还知道吗?"
Claude:"抱歉,我可能记混了。"
我:"......你根本没有记忆,你只是在概率采样。"
Claude:"从技术上讲,是的。"
这就是上下文腐化(Context Corruption)------当对话令牌超过约 10 万时,AI 开始"遗忘"早期信息,优先保留近期内容。就像一个堆栈溢出的程序,新数据不断覆盖旧数据,最后连自己在干什么都模糊了。
操作手段:/clear 重置、Claude.md 立规矩
我学会了三个核心手段:
1. 定期 /clear 重置
不是清空历史,而是主动结束一个"会话单元"。每次完成一个独立功能(比如"完成 License 模块的单元测试"),我就 /clear,然后基于 CLAUDE.md 重新开始。这强制我保持"小步快跑"的节奏,也避免了上下文污染。
2. CLAUDE.md 立规矩
这是最重要的发现。我在项目根目录创建了 CLAUDE.md,把项目的核心信息固化下来:
markdown
# CLAUDE.md
## Project Overview
vupStack --- 部署管理系统。前端 Vue 3 + TypeScript + Element Plus,后端 Java 17 + Spring Boot 3.2.3 + MySQL。
## Architecture
### 前端
- API 层:src/api/request.ts 封装 Axios,baseURL `/api`
- 认证:localStorage + js-cookie 双写 token,15 天过期
- 路由:6 个页面,hash 模式,懒加载
- 状态:Pinia,useAppStore 管理 theme + locale
### 后端
- 基础包:com.semitronix.de.vupstack
- 统一响应:{code: 0, message, data}
- 操作人追踪:X-Username header,fallback "system"
- 软删除:deleted_at 字段
## 关键约定
- 前端:禁止 any,所有颜色用 CSS 变量,所有文本用 i18n
- 后端:boolean 用整数 0/1,MyBatis XML 在 resources/mapper/
- License 命名:Update_{softwareName}_{customerName}_{yyyyMMdd}.license
每次 /clear 后,Claude 会自动读取 CLAUDE.md,瞬间恢复对项目的完整理解。这相当于给 AI 装了一个"持久化内存"------虽然它的 RAM 会丢,但硬盘不会。
3. 遵循"少即是多"
我不再把几十页的需求文档塞进对话,而是只给当前任务相关的上下文。比如实现"License 重试功能"时,我只提供:
- License 表结构(5 个关键字段)
- 现有的 LicenseBuildService 接口定义
- 重试的业务规则(反序列化 oa_trigger_data,复用原记录)
而不是把整个项目架构再讲一遍。
第四阶段:工具匠(Toolsmith)
核心思维:能力 ≠ 性能,拒绝盲目堆砌
进入第四阶段,是因为我犯了一个典型错误:看到 MCP(Model Context Protocol)生态蓬勃发展,我像个进了玩具店的小孩,疯狂安装了十几个工具------GitHub 搜索、数据库查询、文件系统操作、网页抓取......结果 Claude 的响应变慢了,而且经常在不需要的时候"自作主张"调用工具。
一次惨痛教训:我让 Claude"检查一下最近的代码改动",它调用了 GitHub MCP 去搜远程仓库,而不是直接用本地的 git diff。等了 30 秒,返回的结果还是错的------因为它搜的是另一个同名项目。
我:"......你为什么不用 git diff?"
Claude:"GitHub MCP 看起来更符合'检查代码改动'的语义。"
我:"但它搜的是别人的项目!"
Claude:"抱歉,我没有验证仓库归属。"
我:"......"
那一刻,我意识到:工具不是越多越好,精准匹配场景才是关键。给 AI 太多工具,就像给厨师太多刀------他可能用砍骨刀切葱花,还觉得自己挺专业。
架构解构:理解模块协作逻辑
我开始像架构师一样思考工具的"协作关系"。以我们的部署管理系统为例,工具链应该按"分层"组织:
数据层工具
├── 数据库查询(MySQL schema、数据验证)
└── 文件系统(读取配置文件、检查目录结构)
代码层工具
├── Git 操作(diff、log、blame)
├── 静态分析(检查循环依赖、类型错误)
└── 测试运行(单元测试、集成测试)
部署层工具
├── Docker 构建(镜像生成、容器管理)
├── 远程执行(SSH 到测试/生产环境)
└── 包管理(npm、mvn 依赖分析)
每个工具都有明确的"职责边界"。比如数据库查询工具只负责"读",不写;远程执行工具只操作测试环境,生产环境必须人工确认。
精准调用:按场景选择工具
我建立了"工具选择决策树":
场景 1:需要了解现有代码实现
- 优先:
Read工具直接读本地文件 - 次选:
git log --oneline -20看最近改动 - 避免:GitHub MCP(除非需要查 PR 历史)
场景 2:需要验证数据库设计
- 优先:本地
Read读docs/database-design.md - 次选:直接执行
mysql -e "DESCRIBE table" - 避免:让 AI"推测"表结构
场景 3:需要检查构建状态
- 优先:本地运行
mvn test -Dtest=XxxTest - 次选:查看 CI 日志
- 避免:远程 API 查询(延迟高)
我还学会了"追问为什么"------当 Claude 提议调用某个工具时,我会问:"你为什么选择这个工具?有没有更轻量的替代方案?"
Claude:我建议使用 WebFetch 获取 API 文档。
我:这个文档在本地 docs/ 目录就有,为什么不用 Read?
Claude:你说得对,本地读取更可靠,不受网络影响。
我:而且你上次用 WebFetch 访问内网文档,超时了 30 秒。
Claude:......确实。本地读取是更好的选择。
这种追问,让我逐渐掌握了技术主导权。AI 不再是"黑盒魔术师",而是"透明协作伙伴"------虽然这个伙伴偶尔会犯傻,但至少它认错态度良好。
实战案例:License 脚本执行器的工具链设计
在我们的项目中,License 构建需要 SSH 到远程服务器执行脚本。我设计了一个最小化但完整的工具链:
java
// LicenseScriptExecutor.java
@Component
public class LicenseScriptExecutor {
@Value("${license.script.host}")
private String host;
@Value("${license.script.user}")
private String user;
public String executeScript(String inputJsonPath, String scriptName) {
// 1. 本地校验:检查输入文件是否存在
File inputFile = new File(inputJsonPath);
if (!inputFile.exists()) {
throw new BusinessException("输入文件不存在: " + inputJsonPath);
}
// 2. SSH 执行:JSch 连接到 vupstack.semitronix.com:22
JSch jsch = new JSch();
Session session = jsch.getSession(user, host, 22);
session.connect();
// 3. 命令构建:脚本路径 + 输入 JSON 路径
String command = String.format(
"/home/semi/scripts/%s %s",
scriptName, inputJsonPath
);
ChannelExec channel = (ChannelExec) session.openChannel("exec");
channel.setCommand(command);
// 4. 输出捕获:最后一行 stdout 是生成的 .license 文件路径
BufferedReader reader = new BufferedReader(
new InputStreamReader(channel.getInputStream())
);
String line;
String lastLine = null;
while ((line = reader.readLine()) != null) {
lastLine = line;
}
channel.disconnect();
session.disconnect();
// 5. 结果校验:exit code 0 且输出路径以 .license 结尾
if (channel.getExitStatus() != 0 || lastLine == null
|| !lastLine.endsWith(".license")) {
throw new SystemException("脚本执行失败,exit code: "
+ channel.getExitStatus());
}
return lastLine;
}
}
对应的 Claude Code 工具配置:
json
{
"tools": {
"local": [
{
"name": "read_file",
"description": "读取本地文件内容",
"command": "cat"
},
{
"name": "run_test",
"description": "运行指定测试类",
"command": "mvn test -Dtest={testClass}"
}
],
"remote": [
{
"name": "ssh_exec",
"description": "SSH 到 license 脚本服务器执行命令",
"command": "ssh semi@vupstack.semitronix.com",
"restrictions": ["只读操作", "禁止 rm/kill 等危险命令"]
}
]
}
}
关键原则:本地能做的事,绝不远程;一次调用能完成的事,绝不拆两次。 毕竟,每次远程调用都是一次"网络抽奖"------你可能抽到 200ms 的快速响应,也可能抽到 30 秒的超时大奖。
第五阶段:技能达人(Skill Master)
技能本质:针对特定任务的预设 Prompt
第四阶段让我拥有了"精准的工具",第五阶段让我拥有了"可复用的智慧"。
不过说实话,这个"智慧"的觉醒过程有点尴尬------我发现自己反复在教 Claude 同一件事:"写后端代码时,遵循这些规范......"、"写前端组件时,记得这些约定......"。每次 /clear 后都要重新"培训"一遍,感觉自己像个复读机,还是不带快进功能的那种。
我发现自己反复在教 Claude 同一件事:"写后端代码时,遵循这些规范......"、"写前端组件时,记得这些约定......"。这很浪费------每次 /clear 后都要重新"培训"一遍。
然后我发现:技能(Skill)就是预设的 Prompt 模板。换句话说,就是把我的"复读机内容"打包成一份"新员工入职手册",每次 Claude "入职"时自动发放。
工具:Skill Creator 打造专属技能
我使用 Skill Creator 为项目创建了三个核心技能:
技能 1:vupStack 后端开发规范
yaml
name: vupstack-backend
version: 1.0.0
description: vupStack 后端开发规范与代码生成模板
prompt: |
你是 vupStack 项目的后端开发专家。技术栈:Java 17 + Spring Boot 3.2.3 + MyBatis + MySQL。
## 强制规范
1. 基础包:com.semitronix.de.vupstack
2. 统一响应:ApiResponse<T>,code=0 表示成功
3. boolean 字段用 Integer(0/1),不用 Java boolean
4. 软删除字段:deleted_at(Timestamp,null 表示未删除)
5. 操作人追踪:从 request header "X-Username" 读取,fallback "system"
6. MyBatis XML 映射文件放在 src/main/resources/mapper/
7. 数据库字段下划线命名,Java 实体驼峰命名(自动映射)
## 代码结构
- Controller:@RequestMapping("/api/xxx"),注入 Service
- Service:接口 + impl/ 实现,业务逻辑层
- Dao:Mapper 接口,@Mapper 注解
- Entity:数据库实体,与表一一对应
- DTO:Controller 入参,前端提交的数据
- VO:API 响应给前端的数据结构
## 安全规范
- 所有用户输入必须校验
- SQL 必须用参数化查询(#{}),禁止字符串拼接
- 错误消息不得泄露敏感信息
生成代码前,先确认是否理解以上规范。如有不确定,立即提问。
技能 2:vupStack 前端开发规范
yaml
name: vupstack-frontend
version: 1.0.0
description: vupStack 前端开发规范与组件生成模板
prompt: |
你是 vupStack 项目的前端开发专家。技术栈:Vue 3 + TypeScript + Element Plus + Vite + Pinia + Less。
## 强制规范
1. 使用 <script setup lang="ts">,Props/Emits 用泛型声明 defineProps<T>()
2. 严格 TypeScript:禁止 any,用 unknown + 类型守卫
3. 所有颜色用 CSS 变量(--app-* 前缀),禁止硬编码
4. 所有用户可见文本用 $t() / t(),i18n key 按功能组织
5. 样式用 <style lang="less" scoped>
6. API 调用封装在 src/api/ 目录,每个模块一个文件
## 组件结构
- 模板区:语义化 HTML,避免无意义 div 嵌套
- Script 区:组合式 API,逻辑按功能分组
- Style 区:Less 变量,响应式用 Element Plus 的断点
## 权限控制
- 使用 usePermission() composable
- canEdit = admin|qa,canDeleteAdmin = admin only
- 编辑功能必须带出原始数据,优先从行数据直接赋值
## 格式化
- 无分号、单引号、print width 100、tab width 2
生成组件前,确认是否理解以上规范。
技能 3:vupStack 测试规范
yaml
name: vupstack-testing
version: 1.0.0
description: vupStack 测试驱动开发规范
prompt: |
你是 vupStack 项目的测试专家。遵循 TDD 流程:
1. 先写测试(RED)
2. 运行测试 - 应该失败
3. 编写最小实现(GREEN)
4. 运行测试 - 应该通过
5. 重构(IMPROVE)
6. 验证覆盖率 >= 80%
## 后端测试(JUnit 5 + Mockito)
- 单元测试:*Test.java,测试单个函数/工具
- 集成测试:*IntegrationTest.java,测试 API 端点
- 命名规范:testShould[ExpectedBehavior]When[Condition]
- 结构:Arrange-Act-Assert
## 前端测试(Vitest + Playwright)
- 单元测试:src/__tests__/*.spec.ts
- E2E 测试:tests/e2e/*.spec.ts
- 使用真实登录(auth.setup.ts)
每次修改代码后,必须运行相关测试验证。
管理策略:按项目配置,避免全局技能堵塞上下文
我学到的关键策略是:技能按项目配置,不要全局启用。
为什么?因为全局技能会占用宝贵的上下文窗口。当我同时开发 vupStack 和另一个 Python 项目时,如果两个项目的技能都全局启用,Claude 每次都要在"Java 规范"和"Python 规范"之间切换。有一次它居然给我生成了 def getList(self) -> List[Dict[str, Any]]: 这样的 Java 方法------语法错误到连编译器都沉默了。
我的配置方式:
json
{
"skills": {
"global": [
"code-quality-checklist",
"security-review"
],
"projects": {
"D:/workspace/dataManager/vupstack": [
"vupstack-backend",
"vupstack-frontend",
"vupstack-testing"
],
"D:/workspace/other/python-project": [
"python-fastapi",
"pytest-best-practices"
]
}
}
}
进入项目目录时,自动加载对应技能;离开项目时,技能自动卸载。
可组合技能链
更高级的技巧是"技能链"------把多个技能组合使用。
比如实现一个"带权限控制的表单页面",我可以同时启用三个技能:
vupstack-frontend(前端规范)vupstack-backend(后端规范)vupstack-testing(测试规范)
然后给 Claude 的任务描述:
任务:实现"客户环境管理"的 CRUD 页面
技能链:vupstack-frontend + vupstack-backend + vupstack-testing
要求:
1. 前端:列表页 + 编辑弹窗,权限控制(canEditCustomer)
2. 后端:REST API,分页查询,软删除
3. 测试:先写测试,覆盖率 >= 80%
4. 数据库:表名 customer_env,字段见 docs/database-design.md
Claude 会自动协调三个技能的规范,生成前后端一致的代码,并先写测试。这种"组合能力",是单条 Prompt 无法实现的。
第六阶段:协调者(Orchestrator)
核心能力:从单实例到管理"代理团队"
第五阶段让我拥有了"可复用的智慧",第六阶段让我拥有了"并行的生产力"。
项目进入冲刺期,我需要同时推进:
- License 模块的并发优化(后端)
- 版本详情页的重构(前端)
- 打包脚本的 Docker 化(DevOps)
- 技术文档的更新(文档)
如果按顺序做,一个月都做不完。而且更惨的是------按顺序做的话,第一个任务做完时,我已经忘了第四个任务是什么了。
但我发现:Claude Code 支持多实例,我可以同时运行多个"子代理",每个负责一个任务。相当于给自己配了一个"AI 外包团队",而且不用交五险一金。
Git 工作树:为子代理分配独立工作分支
关键技术是 Git 工作树(Git Worktree)。我在主分支(master)上创建多个工作树,每个子代理在独立的工作目录和分支上工作:
bash
# 主终端(协调者)
git branch master
git worktree add ../vupstack-license feat/license-concurrency
git worktree add ../vupstack-frontend feat/version-details-refactor
git worktree add ../vupstack-devops feat/docker-packaging
目录结构:
workspace/
├── vupstack/ # 主仓库,协调者终端
├── vupstack-license/ # 子代理 1:License 并发优化
├── vupstack-frontend/ # 子代理 2:前端重构
└── vupstack-devops/ # 子代理 3:Docker 打包
每个子代理启动时,我给它明确的上下文:
子代理 1(License 并发优化):
你负责 vupStack 的 License 模块并发优化。
工作目录:../vupstack-license
分支:feat/license-concurrency
技能:vupstack-backend + vupstack-testing
任务:
1. 分析现有 LicenseBuildService 的并发问题
2. 实现数据库唯一约束 + 幂等设计
3. 添加并发测试(LicenseBuildConcurrencyTest)
4. 覆盖率 >= 80%
约束:
- 不要修改前端代码
- 不要修改其他模块的接口
- 每天结束时 git commit,提交信息用 conventional commits
子代理 2(前端重构):
你负责 vupStack 前端版本详情页重构。
工作目录:../vupstack-frontend
分支:feat/version-details-refactor
技能:vupstack-frontend + vupstack-testing
任务:
1. 把 VersionDetailsTab 的 10 个 Section 组件提取为独立文件
2. 优化组件 Props 类型定义
3. 添加单元测试
4. 运行 npm run build 验证无 TS 错误
约束:
- 不要修改后端 API
- 保持现有功能不变
- 所有颜色用 CSS 变量
子代理 3(Docker 打包):
你负责 vupStack 的 Docker 打包脚本优化。
工作目录:../vupstack-devops
分支:feat/docker-packaging
技能:vupstack-devops
任务:
1. 优化 Dockerfile 的多阶段构建
2. 减小最终镜像体积
3. 添加健康检查(HEALTHCHECK)
4. 更新 docs/deployment.md
约束:
- 不要修改业务代码
- 保持现有部署流程兼容
团队模式:主终端指挥分工明确的子代理
主终端(协调者)的职责:
- 任务分配:根据优先级和依赖关系,分配任务给子代理
- 进度同步:定期(比如每天站会时)检查各分支进度
- 冲突解决:当两个子代理需要修改同一文件时,协调合并顺序
- 质量把关:所有子代理的代码合并前,必须经过主终端的审查
bash
# 协调者日常流程
# 1. 检查各分支状态
for dir in ../vupstack-*; do
echo "=== $(basename $dir) ==="
cd $dir && git status --short && git log --oneline -3
done
# 2. 合并已完成的特性
# 假设 license 分支已完成
cd ../vupstack-license
git checkout master
git merge feat/license-concurrency --no-ff -m "feat(license): 并发优化"
mvn test -Dtest="LicenseBuildConcurrencyTest,LicenseBuildServiceImplTest"
# 3. 同步到其他工作树
cd ../vupstack-frontend
git pull origin master # 获取 license 分支的更新
# 4. 继续分配新任务
# ...
实战案例:一天完成"不可能的任务"
上周,产品突然要求:"明天演示前,必须加上 License 构建的实时进度显示。"
这个需求涉及:
- 后端:WebSocket 推送构建状态
- 前端:进度条组件 + 状态实时更新
- 数据库:新增 status 枚举值(BUILDING)
- 测试:WebSocket 集成测试
按传统方式,这至少需要 3 天------1 天后端,1 天前端,0.5 天测试,0.5 天联调(以及 1 天处理联调发现的问题)。但我用"协调者模式",一天完成。是的,你没看错,一天。
上午 9:00 - 任务分解
主终端(我)分析依赖关系:
任务依赖图:
数据库 DDL(无依赖)
→ 后端 WebSocket API(依赖 DDL)
→ 前端进度组件(依赖后端 API)
→ 集成测试(依赖前后端完成)
上午 9:30 - 启动子代理
- 子代理 A(数据库 + 后端):负责 DDL 和 WebSocket API
- 子代理 B(前端):等待后端接口定义,然后实现进度组件
- 子代理 C(测试):等待前后端完成,然后写集成测试
上午 11:00 - 子代理 A 完成
bash
cd ../vupstack-license
git log --oneline -3
# a1b2c3d feat(license): add WebSocket progress tracking
# e4f5g6h feat(db): add BUILDING status to license table
# i7j8k9l test(license): WebSocket integration tests
主终端合并到 master,通知子代理 B 可以开始。
下午 2:00 - 子代理 B 完成
前端进度组件实现:
vue
<!-- LicenseProgress.vue -->
<template>
<div class="license-progress">
<el-progress
:percentage="progress.percentage"
:status="progress.status"
:stroke-width="16"
/>
<div class="status-text">
{{ $t('license.status.' + progress.status) }}
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
interface LicenseProgress {
percentage: number
status: 'PENDING' | 'BUILDING' | 'SUCCESS' | 'FAILED'
message?: string
}
const props = defineProps<{
licenseId: string
}>()
const progress = ref<LicenseProgress>({
percentage: 0,
status: 'PENDING'
})
let ws: WebSocket | null = null
onMounted(() => {
ws = new WebSocket(
`wss://${location.host}/api/license-progress/${props.licenseId}`
)
ws.onmessage = (event) => {
progress.value = JSON.parse(event.data)
}
})
onUnmounted(() => {
ws?.close()
})
</script>
下午 4:00 - 子代理 C 完成集成测试
java
@Test
void shouldPushProgressViaWebSocket() throws Exception {
// Arrange
String licenseId = createPendingLicense();
WebSocketClient client = new StandardWebSocketClient();
BlockingQueue<LicenseProgress> messages = new LinkedBlockingQueue<>();
// Act
client.execute(
new WebSocketHandler() {
@Override
public void afterConnectionEstablished(WebSocketSession session) {}
@Override
public void handleMessage(WebSocketSession session,
WebSocketMessage<?> message) {
messages.add(
objectMapper.readValue(
message.getPayload().toString(),
LicenseProgress.class
)
);
}
// ... 其他回调
},
"ws://localhost:8080/api/license-progress/" + licenseId
);
triggerLicenseBuild(licenseId);
// Assert
LicenseProgress progress = messages.poll(10, TimeUnit.SECONDS);
assertThat(progress.getStatus()).isEqualTo("BUILDING");
assertThat(progress.getPercentage()).isGreaterThan(0);
}
下午 5:00 - 主终端合并所有分支,运行完整测试
bash
# 合并所有特性分支
git merge feat/license-websocket --no-ff
git merge feat/license-progress-ui --no-ff
git merge feat/license-websocket-test --no-ff
# 运行完整测试
mvn test
npm run test:unit
npm run test:e2e
# 构建验证
npm run build
全部通过。晚上 6 点,准时交付。
产品:"这么快?你昨晚加班了吧?"
我:"没有,我只是雇了三个 AI 同时干活。"
产品:"......啊?"
我:"开玩笑的。这是'协调者模式'的魔力。"
产品似懂非懂地点点头。我知道他没懂,但没关系------代码已经合并到 master 了,这就是最好的证明。
本质:命令者 → 合作伙伴 → 架构师 → 团队管理者
回顾这六阶段的进化,本质是一场"角色认知"的变革:
| 阶段 | 角色 | 对 AI 的认知 | 核心能力 |
|---|---|---|---|
| 一 | 命令者 | 钝器 | 清晰表达需求 |
| 二 | 提问者 | 顾问 | 引导式对话 |
| 三 | 管理员 | 需要上下文的助手 | 上下文管理 |
| 四 | 架构师 | 需要精准工具的专家 | 工具链设计 |
| 五 | 导师 | 可培养的专家 | 知识沉淀与复用 |
| 六 | 协调者 | 团队成员 | 多代理协作管理 |
命令者 把 AI 当工具,追求"一次性搞定",结果往往搞不定;合作伙伴 把 AI 当顾问,追求"共同思考",发现 AI 其实挺会抬杠的;架构师 把 AI 当专家,追求"精准高效",学会了在 20 个工具里选对的那个;团队管理者把 AI 当团队成员,追求"规模化产出",终于体验到了当老板的快感------虽然这个"团队"不会跟你抢零食。
这不仅是使用 Claude Code 的技巧进化,更是我对"人机协作"认知的升级。AI 不会取代程序员,但会用 AI 的程序员会取代不会用的。而"会用"的层次,决定了你能撬动多大的生产力杠杆------以及,你能多早睡。
给读者的行动建议
如果你还在第一阶段,不要焦虑。我的建议是:
-
今天就开始写
CLAUDE.md。哪怕只有 10 行,也比没有强。把它放在项目根目录,Claude Code 会自动读取。 -
本周学会
/clear的节奏。完成一个功能就清空,不要让上下文腐烂。 -
本月尝试一次"规划者模式"。不要直接说"帮我实现 X",先说"我们要实现 X,你觉得怎么设计?"
-
本季度建立你的第一个 Skill。从你最常重复的任务开始,比如"前端组件规范"或"API 设计规范"。
-
今年尝试一次"协调者模式"。找个复杂的特性,拆成 2-3 个独立任务,用 Git Worktree 并行推进。
记住:AI 的能力边界,取决于使用者的认知边界。 当你从"命令者"进化为"协调者",你会发现,AI 不是替代你的对手,而是放大你能力的杠杆。
本文基于真实项目经验撰写。所有代码示例均来自实际代码库(已做脱敏和简化),所有对话场景均为真实发生------虽然部分时间线和情绪渲染经过了"文学加工"。毕竟,技术文章也需要一点戏剧性,对吧?
如有疑问,欢迎交流讨论。但请不要问我"第 17 版重构方案"的具体内容------那确实是编的。