Claude Code 实战分享(1):从“代码助手“到“AI 协调者“

Claude Code 实战分享(1):从"代码助手"到"AI 协调者"

本文基于一个真实的全栈项目演进过程,记录我使用 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 开始"失忆"------前面说好的路由守卫忘了,已经写好的类型定义重复定义。最离谱的是,它把 customerNamecustomerCode 混为一谈,生成了一份连它自己都不知道在干什么的代码。

我愤怒地拍桌子:"这 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:需要验证数据库设计

  • 优先:本地 Readdocs/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"
      ]
    }
  }
}

进入项目目录时,自动加载对应技能;离开项目时,技能自动卸载。

可组合技能链

更高级的技巧是"技能链"------把多个技能组合使用。

比如实现一个"带权限控制的表单页面",我可以同时启用三个技能:

  1. vupstack-frontend(前端规范)
  2. vupstack-backend(后端规范)
  3. 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

约束:
- 不要修改业务代码
- 保持现有部署流程兼容

团队模式:主终端指挥分工明确的子代理

主终端(协调者)的职责:

  1. 任务分配:根据优先级和依赖关系,分配任务给子代理
  2. 进度同步:定期(比如每天站会时)检查各分支进度
  3. 冲突解决:当两个子代理需要修改同一文件时,协调合并顺序
  4. 质量把关:所有子代理的代码合并前,必须经过主终端的审查
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 的程序员会取代不会用的。而"会用"的层次,决定了你能撬动多大的生产力杠杆------以及,你能多早睡。


给读者的行动建议

如果你还在第一阶段,不要焦虑。我的建议是:

  1. 今天就开始写 CLAUDE.md。哪怕只有 10 行,也比没有强。把它放在项目根目录,Claude Code 会自动读取。

  2. 本周学会 /clear 的节奏。完成一个功能就清空,不要让上下文腐烂。

  3. 本月尝试一次"规划者模式"。不要直接说"帮我实现 X",先说"我们要实现 X,你觉得怎么设计?"

  4. 本季度建立你的第一个 Skill。从你最常重复的任务开始,比如"前端组件规范"或"API 设计规范"。

  5. 今年尝试一次"协调者模式"。找个复杂的特性,拆成 2-3 个独立任务,用 Git Worktree 并行推进。

记住:AI 的能力边界,取决于使用者的认知边界。 当你从"命令者"进化为"协调者",你会发现,AI 不是替代你的对手,而是放大你能力的杠杆。


本文基于真实项目经验撰写。所有代码示例均来自实际代码库(已做脱敏和简化),所有对话场景均为真实发生------虽然部分时间线和情绪渲染经过了"文学加工"。毕竟,技术文章也需要一点戏剧性,对吧?

如有疑问,欢迎交流讨论。但请不要问我"第 17 版重构方案"的具体内容------那确实是编的。

相关推荐
AI前沿资讯1 小时前
支持视频动作迁移的AI 3D平台有哪些?2026全维度测评
人工智能·3d
机器之心1 小时前
VEGA-3D:释放视频生成模型中的隐式3D知识,重塑3D场景理解与具身交互
人工智能·openai
机器之心1 小时前
超越VLA与世界模型,银河通用发布LDA,全谱系数据跑通Scaling Law
人工智能·openai
事变天下1 小时前
第四届超声医学青年学术会议,推出全新启元AI超声生态
大数据·人工智能
AI科技星1 小时前
ELN 升级:π 级数自动生成器全域数理架构
大数据·人工智能·python·算法·金融
多年小白1 小时前
日报 - 2026年4月28日(周二)
网络·人工智能·科技·深度学习·ai
极智视界1 小时前
分类数据集 - 棉花病虫害检测图像分类数据集下
人工智能·yolo·数据集·图像分类·算法训练·棉花病虫害检测
龙腾AI白云1 小时前
AI项目团队意见分歧?协调与决策方法
人工智能·pygame
Mr数据杨1 小时前
AIGC工具平台-Tauri2.x智能工具桌面介绍与使用
人工智能·aigc·tauri