第 2 节 · 45 分钟
Vibe Coding

开机:
怎么跟它说话

今天你发出这门课的第一段 prompt(提示词,你发给模型的那段话),让 agent(能替你执行任务的 AI 程序)做出游戏的外壳:输入框、假分数、历史列表。

开始 Guoliang · 共 16 页
第 2 节 · 今天的成品

今天做的是外壳:能输入、能记录,分数先是假的

游戏刚开局的第一屏:顶部「已猜 0 / 50 · 目标词 2 个字」、一个输入框、下面一行提示、页脚的分数与名次说明

老师版参考实现开局的第一屏。你今天做出来的那一屏长得像它,只是分数是你随口定的假数。

一 · 输入框

敲一个中文词,回车提交。这是玩家跟游戏之间唯一的入口。

二 · 假分数

今天返回一个 0 到 100 的随机数,刷新一次就变。它只是个占位,不代表任何意思。

三 · 历史列表

猜过的词一行一条,按分数从高到低排。第 3 节接上真分数时,这张表一个字都不用改。

先做能看见的外壳,再接看不见的计算 —— 这样每一步你都能亲眼验收。

第 2 节 · 项目图

你要做的不是一个网页,是两个一起跑的程序

你的项目文件夹 semantle/
浏览器

前端

localhost:5173 client/
输入框
假分数
历史列表
后端

同时跑着的另一个程序

localhost:3001 server/
今天只会给一个随机数

两个程序会互相说话
(怎么说,第 3 节)

node_modules/ · 零件(npm install 拿回来的)

第 5 节这里
会多一个框

前端 / 后端 · 餐厅

前端是前厅,你在这儿点单;后端是后厨,菜在那儿做。

端口 · 同一台电脑上的门牌号

localhost 是你这台电脑;5173、3001 是门牌号。

依赖 · 零件

别人写好的零件,npm install 从仓库拿回来。

npm run dev 一条命令把两个程序一起叫醒;浏览器打开的是前端的门牌号。

开课排障10分钟
第 2 节 · 排障

先把上节课的坑填了:
三类报错,各有一节可查

  1. 打开终端:Mac 用 Terminal,Windows 用 PowerShell(不是 CMD)。把第 1 节作业那四条验证命令重跑一遍。
  2. 第一条没过的,照下面这张表认出它属于哪一类,翻到安装指南对应的小节,照着做。
  3. 照着做还是不通就按顺序排除:先把终端整个关掉重开,再核对版本号,最后重新登录一次。表里没有的报错,把原文整段给我看。
  4. 十分钟到了还不通,就先用我的电脑做今天的动手,你那台下课再修。走之前写四行给我:哪一步、什么命令、什么报错、试过什么。
你看到的字这是哪一类翻到哪里
command not found: claude(Windows 上是 'claude' is not recognized找不到命令(PATH)指南 7.1
OAuth error: Invalid code403 Request not allowed登录没过Mac 7.4 / Win 7.6
node -v 打出 v22v20,或者什么都没打出来Node 版本过低指南 1.3
「指南」= docs/setup-mac.mddocs/setup-windows.md,两份的小节号一一对应。PATH(路径)= 系统去哪几个文件夹里找命令。
你应该看到什么

四条全绿:node -vv24.x.xgit --versiongit version 2.x.xclaude --version2.1.xxx (Claude Code);进对话后它用一句话介绍自己。

卡住了先做什么

跑一句 claude doctor(只读检查,不会改你电脑上的任何东西),把整段输出复制下来,连同报错原文一起给我看。复制文字,不要拍照,也不要自己先翻译。

老师注意

十分钟是硬上限。到点还没装好就换我的电脑做动手,机器的问题留到下课修 —— 不要让装环境吃掉今天唯一的动手时间。

第 2 节 · 交接

临时工还是那个临时工,今天你要真的把三样东西交出去

01 · 真实任务
说你真正想要的那个

别说一个擦边的任务再指望它猜中。想要网页就说网页,想要能在 localhost 打开就说清楚。

02 · 外部化假设
把脑子里默认的写出来

你觉得「猜词游戏当然要有历史列表」,它不觉得,因为你没说。今天这一条占的篇幅最多。

03 · 退路
允许它说「我不确定」

不给退路,它只能编一个看起来合理的答案继续做。这一条是今天最短、也最值钱的两句话。

上节课的结论只有一句:它是个极其聪明、但今天早上才到岗的临时工。上节课那三件事还只是三段大白话;今天它们要变成三样能交出去的东西 —— 一份 briefing(任务交接单)、一条退路条款、一份写下来的团队手册。

第 2 节 · 意图外部化

把脑子里的默认假设写出来,它就不用替你猜

坏例 · 一句话甩过去

「帮我做一个猜词游戏。」

你脑子里其实还挂着一堆条件:网页还是命令行?跑在谁的电脑上?页面上有什么?分数从哪来?这些你一个字都没说,它只能替你选,而且每次选得都不一样。

这些条件有个名字,叫「默认假设」:你觉得不言而喻,所以懒得写。可对一个今天早上才到岗的人来说,没有一样是不言而喻的。

结果:三分钟后你拿到一个 Python 命令行小游戏。它没做错,是你没说。

好例 · 一份 briefing(任务交接单)

目标:做一个中文猜词游戏的网页。

给谁用:我自己,在笔记本上打开 localhost 玩,不部署、不给别人访问。

页面有什么:一个输入框(回车提交)、一个提交按钮、一个历史列表,按分数从高到低排。

技术栈:Node 一栈 —— 前端 React(Vite),后端 Express,npm run dev 一条命令同时起前后端。

先做假分数:分数先用 0 到 100 的随机数,第 3 节再换成真的。

结果:第一版就是网页。之后改的是细节,不是方向。

右边多出来的不是字数,是「我默认了什么」。五行里没有一个形容词 —— 全是别人能拿着核对的事实。

第 2 节 · 退路条款

两句话,把「它自己编一个继续做」这条路堵死

# 退路条款 · 逐字照抄就行

一、如果某一步你不确定,
停下来问我,不要猜。

二、改动前先列出你要改的文件,
等我确认再动手# 不写这两句,你会收到这种话

「文档里没说用哪个数据库,我按常见做法装了
SQLite 并建好了表,现在继续做下一步。」

← 这句话里没有一个字是你说过的。
第一句为什么管用

它输出的是最像的那句话,不是最真的那句话。不给它「我不确定」这个选项,它就只剩一条路:编一个看起来合理的答案继续做。允许它说不知道,它才不会编。

第二句为什么管用

它列文件的那三十秒,是你唯一能在事情变坏之前叫停的窗口。装了一个你没要的依赖、动了 .env、把 data/ 覆盖掉 —— 都是在这一步能拦下来的。

高中生类比

像小组作业里那句「你要是没听懂就别硬做,先来问我」。说过这句的组,返工次数明显少 —— 不是因为组员变聪明了,是因为你给了他不装懂的余地。

没有退路条款,它就会替你做决定。第 8 节所有翻车故事的共同起点都在这里。

第 2 节 · 存档

改坏了不用修,回到上一个存档

# 逐字对它说

一、先存档,再动手。

二、你改了哪些文件?给我看改前改后的对照。

三、回到上一个存档。
    ← 执行前要它先说清这条会丢掉哪些改动

# 背后的工具叫 git,一次存档叫 commit。
# 命令它来敲,你一条都不用学。
高中生类比 · 游戏存档

存档就是把整个项目文件夹此刻的样子拍一张照片存起来,随时能回到任何一张。像打游戏:打 boss 前先存一档,翻车就读档,不用从头打。

写进 CLAUDE.md 的一条

每次改完能跑就存档,存档说明写清楚这次改了什么。说明写得清楚,下次读档才知道该回到哪一档。

不进存档的两样

.env:以后放 key 的地方,key 就是钱。node_modules/:零件,随时能重新拿。agent 用 .gitignore 把这两样挡在外面。

退路有两层:第一层是刚才那两句退路条款,第二层是存档。
存档说明写清楚这次改了什么,也是意图外部化。

第 2 节 · 结构化表达

用标签把一段话切成四块,它就不会串着读

<goal> 做一个中文猜词游戏的网页外壳。 </goal>

<constraints>
前端 React(Vite),后端 Express;
npm run dev 一条命令同时起前后端;
分数先用 0 到 100 的随机数;不要引入 UI 组件库。
</constraints>

<ui>
一个输入框(回车提交)、一个提交按钮、
一个历史列表:每行「词 + 分数」,按分数从高到低。
</ui>

<out>
先列出你要新建和修改的文件,等我说「可以」再动手;
做完告诉我用哪条命令启动、打开哪个地址。
</out>
标签是给模型看的边界

XML 标签就是 <goal>…</goal> 这样成对的尖括号。模型在预训练时读过海量网页和配置文件,闭合标签是它最熟的分隔符:一眼就知道哪段是目标、哪段是限制。

高中生类比

像试卷上把大题答案框起来:框里是答案,框外是草稿。不框,阅卷老师就可能把你的草稿当成最终答案。

怎么起名

名字随便起,中文的 <目标> 也认,成对、别嵌太深就行。四块够用整门课:要什么、不许怎么做、界面长什么样、交付时给我什么。第 7 页那两句退路,塞进 <constraints> 或单开一个 <fallback> 都可以。

一句提醒

标签只回答「哪段是哪段」,不回答「你想清楚了没有」。想不清楚,包再多标签也没用。

第 2 节 · 两层话

它读到的话分两层:开工前的说明书,和你当面交代的活

# 第一层 · 开工前就在的说明书,每一轮都排在最前面
system  你是 Claude Code,在终端里替人干活;
        能读写文件、能跑命令;改动前要……(几千字)
        ← Anthropic 写的。你看不见,也改不了
        + 项目根目录 CLAUDE.md 的全文
        ← 开工时自动读进去,排在你第一句话前面。这一份你能写

# 第二层 · 你一句一句敲进去的话,说完就往后排
user    <goal> 做一个中文猜词游戏的网页外壳 </goal> ……
        ← 你刚才那份 briefing
assistant 我打算新建这几个文件:……
user    可以,动手。

# 第 4 节会讲:这一整段每一轮都要重新发一遍,所以越聊越贵
system prompt
系统提示词 · 说明书

开工前就固定在最前面的那段说明:它是谁、能用什么工具、守什么规矩。每一轮都在,你不用重发;CLAUDE.md 就写在这一层。

像上岗前 HR 发的岗位说明书:他到你这儿之前就读过了。

user prompt
用户提示词 · 当面交代

你每一轮敲进去的话:那份 briefing,还有每句「第 2 条要从高到低」。说完就往后排,下一轮靠重发整段历史才记得。

像你当面交代的活:今天做这个、改那个,说一次算一次。

还会撞见两次:第 4 节网页版里你敲的全是 user;第 5 节你写的猜词 prompt 就是 system prompt。

第 2 节 · 团队手册

规矩写进 CLAUDE.md,它每次开工都会自己读一遍

# 这个项目的规矩

1. 每次改完能跑就存档,存档说明写清楚这次改了什么。
2. 不要装我没点头的依赖;能用自带的就别装包。
3. 每次改动前,先说明你要改哪些文件、为什么。
4. 不要碰 .env 和 data/ 目录。
5. 跑完要给证据:把你执行的命令和它的输出贴给我。

# 写下来之后会发生什么

下次你说「加个排行榜」,它会自己想起第 2 条,
先问你「要不要装图表库」,而不是直接装上。

# 五条以内,每条都要能判断做没做到。
# 「代码要优雅」这种没法核对的,等于没写。
CLAUDE.md
项目手册

放在项目根目录的一个纯文本文件。Claude Code 每次开工前都会整份读进去,排在你第一句话前面。写一次,它每次都照做。

像新员工手册:不用每天口头交代一遍「我们这儿不这么干」。

AGENTS.md
同一件事,换个文件名

Codex CLI 读的是 AGENTS.md,作用完全一样。两个名字,一件事:把团队的品味和禁忌写下来。

像同一份班规,抄一遍贴在隔壁班的墙上。

第 2 节 · 手册与操作卡

CLAUDE.md 是每次都读的手册,
SKILL 是要用时才抽的操作卡

CLAUDE.md · 手册SKILL · 操作卡
放在哪项目根目录,一个文件.claude/skills/<名字>/SKILL.md,一张卡一个文件夹
什么时候读每次开工,整份读进去开工时只读名字和一句简介;你敲 /名字,或它判断用得上,才整份读
写什么每次都要守的规矩:别装没点头的包、改前先列文件有时才做、步骤又长的流程:怎么验收、怎么跑 benchmark
多长五条以内可以长,几十行也行 —— 不用时不占地方
今天建,写 3 到 5 条不建。第 6 节写第一张 /bench:同一套步骤要来 12 遍
一句判断:每次都要守的进 CLAUDE.md;有时才做、步骤又长的进 SKILL。用 Codex CLI 的话,问它一句「你有没有 skills、放在哪」。
# .claude/skills/verify/SKILL.md
---
name: verify
description: 改完代码后跑一遍验证,把证据贴回来
---
1. 跑 npm run dev,确认终端没有红字。
2. 列出这次新建和修改的文件,每个一句为什么。
3. 把执行的命令和它的输出原样贴给我。

# 用法:在 Claude Code 里敲 /verify
高中生类比

手册是贴在墙上的班规,天天看得见,所以不能长;操作卡是实验室抽屉里那张「离心机怎么用」,用到那台机器才抽出来,所以抽屉里放一百张也不碍事。

课堂活动20分钟
第 2 节 · 动手

用你写的 briefing,把外壳做出来

  1. 新建一个空文件夹(比如 semantle),终端 cd 进去,敲 claude。第一次会问你信不信任这个目录,选是。先让它把这个文件夹建成有存档功能的项目,并做第一次存档(它会用 git,你不用学命令)。
  2. 把你的 briefing 整段粘进去发送:第 6 页那五行内容,装进第 9 页的四个标签,末尾加上第 7 页的两句退路。
  3. 它会先列出计划和要新建的文件。先读一遍再允许:只碰你要的地方吗?有没有多做你没说的事?不对现在就说。
  4. 让它跑起来:npm install,然后 npm run dev。把终端打印的地址(一般是 http://localhost:5173)粘进浏览器。
  5. 在输入框敲三个词回车,列表多了三行就让它存档,说明写「外壳第一版」。
你应该看到什么

浏览器里:一个输入框、一个提交按钮、一个历史列表。敲「苹果」回车,列表多一行,旁边一个 0 到 100 的假分数,刷新会变(这是对的)。终端里 Vite 还在跑,没有红字。

卡住了先做什么

把报错原文整段贴回给它,用 <error> 标签包住,并要求它:先说你认为的原因,再说你打算用哪条命令验证;修完把验证命令和它的输出一起贴给我。别只说「报错了,帮我修」。

老师注意

坐到他旁边,盯第 3 步:他要是没读计划就一路回车放行,当场按停,让他念一遍 agent 打算改哪些文件。

第 2 节 · 验收

别问它做完没有,自己问三句:跑起来了吗、一致吗、多做了吗

一问 · 跑起来了吗
看你自己的屏幕,不看它的措辞

「已完成」不是证据。证据是浏览器里那一屏,和终端里没有红字。

怎么问:「把启动命令和要打开的地址给我,我自己跑一遍。」

二问 · 和 briefing 一致吗
拿 <ui> 那几行逐条对屏幕

输入框有吗?提交按钮有吗?历史列表是按分数从高到低排的吗?

不一致时只指出那一条:「第 3 条:我要的是从高到低。」不要把整件事重讲一遍。

三问 · 有没有偷偷多做
多做和少做一样是问题

怎么问:「你新建和修改了哪些文件?逐个说明为什么需要。」

装了 UI 组件库、加了登录页、接了数据库 —— 你没说要,就该没有。多出来的每一样,将来都要你自己维护。

这三问就是这门课评分里「工程规范性」那三分之一:出错时你有没有让它给证据,而不是听它说一句「好了」就信。

作业 · 第 2 节

把外壳改成自己的样子,保留对话记录

  1. 确认外壳还在:npm run dev,打开终端里显示的地址,看到输入框、假分数、历史列表。
  2. 先别开口,先写:三处要改的地方,每处写清「改成什么样」。「名字换一个」不算;「游戏名改成〈你的名字〉的猜词机,放在页面最上方,字号比其他文字大一倍」才算。
  3. 三句话装进一条 prompt,用 <goal> <constraints> <fallback> 分区,末尾要它列出改动清单。
  4. 它说「改好了」时先别看页面,先问:你改了哪些文件?给我看改前改后的对照。再刷新浏览器逐条对照,不符合的只指出那条。
  5. CLAUDE.md 加一条今天学到的规矩,比如存档那条,自己打开文件,亲眼看到那一行。
  6. 存下对话记录:在 Claude Code 里输入 /export;没有这个命令就问它怎么导出。放进 docs/chat-logs/。最后再跑一次 npm run dev,确认还能启动,然后让它存档。
交什么

改后截图 1 张(最好再带一张改前的做对照);对话记录文件(或截图);你的三句话原文,以及 CLAUDE.md 里新增的那一行。

交之前自检三条:三处改动我都能指着屏幕说「这就是我写的那句话」;prompt 里有一条退路条款;它说「改好了」之后,我看过它列出的文件清单,而不是只听它说。

完整版在 docs/homework/lesson-02.md,里面有全套自检清单和「卡住了怎么办」的三步顺序。

下节课开头 10 分钟摆出来 · 预计 30–45 分钟
下次见

你今天写的
不是代码,是意图。

第 3 节:词变成数字。你会亲手算一次余弦相似度,再把今天那个假分数换成真的。

回到封面 Vibe Coding · 第 2 节 · 开机:怎么跟它说话
01 / 16