第 05 期 | 第一个 Hello World 项目

更新于 2026/4/5

🎯 学习目标

学完本期你将:

  1. 用一条指令从零创建一个完整的 Web 应用
  2. 理解 Claude Code 如何协调多个 Tools 完成复杂任务
  3. 观察 Write → Bash → Edit 的工具调用链

📖 核心概念讲解

5.1 工具调用链 (Tool Chain)

当你给 Claude Code 一个复杂指令时,它会自动规划并按序调用多个工具:

用户指令: "创建一个 Express + TypeScript 的 REST API 项目"

Claude 的执行计划:
  1. Bash("mkdir my-api && cd my-api && npm init -y")   → 创建目录
  2. Bash("npm install express typescript ts-node @types/express @types/node") → 安装依赖
  3. Write("tsconfig.json")                              → 写入 TS 配置
  4. Write("src/index.ts")                               → 写入入口文件
  5. Write("src/routes/health.ts")                       → 写入路由
  6. Edit("package.json")                                → 添加 scripts
  7. Bash("npx tsc --noEmit")                            → 编译检查
  8. Bash("npm run dev")                                 → 启动验证

5.2 理解 Claude 的决策过程

Claude Code 不是随机调用工具,而是基于 目标分解 的策略:

  1. 分析目标:用户想要什么?
  2. 环境感知:当前目录有什么?(Glob, Read)
  3. 规划步骤:需要哪些操作?按什么顺序?
  4. 逐步执行:每步执行后检查结果
  5. 自我修正:如果出错,读取错误信息并修复

💻 模拟 Claude TUI 交互:从零开始建项目

$ mkdir my-first-app && cd my-first-app
$ claude

╭──────────────────────────────────────────────────────╮
│  Claude Code v2.3.0                                  │
│  📁 Working directory: ~/my-first-app (empty)        │
╰──────────────────────────────────────────────────────╯

> 帮我创建一个 React + TypeScript 的待办事项应用,
  包含添加、删除、标记完成的功能,使用 Vite 构建

╭─ Claude ─────────────────────────────────────────────╮
│                                                      │
│  好的!我来为你创建一个完整的 Todo 应用。             │
│                                                      │
│  ⚙️ Tool: Bash                                       │
│  $ npm create vite@latest ./ -- --template react-ts  │
│  ╭────────────────────────────────────────────╮      │
│  │ [Y] Allow  [n] Deny  [a] Always allow     │      │
│  ╰────────────────────────────────────────────╯      │
│                                                      │
╰──────────────────────────────────────────────────────╯

> Y

╭─ Claude (继续) ──────────────────────────────────────╮
│                                                      │
│  ✅ Bash: npm create vite — 成功                      │
│                                                      │
│  ⚙️ Tool: Bash                                       │
│  $ npm install                                       │
│  ✅ 安装完成                                          │
│                                                      │
│  ⚙️ Tool: Write → src/types/todo.ts                  │
│  ╭─ NEW FILE ─────────────────────────────────╮      │
│  │ export interface Todo {                     │      │
│  │   id: string;                               │      │
│  │   text: string;                             │      │
│  │   completed: boolean;                       │      │
│  │   createdAt: Date;                          │      │
│  │ }                                           │      │
│  ╰─────────────────────────────────────────────╯      │
│  ╭────────────────────────────────────────────╮      │
│  │ [Y] Allow  [n] Deny                        │      │
│  ╰────────────────────────────────────────────╯      │
│                                                      │
╰──────────────────────────────────────────────────────╯

> Y

╭─ Claude (继续) ──────────────────────────────────────╮
│                                                      │
│  ⚙️ Tool: Write → src/components/TodoItem.tsx        │
│  ╭─ NEW FILE ─────────────────────────────────╮      │
│  │ import { Todo } from '../types/todo';       │      │
│  │                                             │      │
│  │ interface Props {                           │      │
│  │   todo: Todo;                               │      │
│  │   onToggle: (id: string) => void;           │      │
│  │   onDelete: (id: string) => void;           │      │
│  │ }                                           │      │
│  │                                             │      │
│  │ export function TodoItem({ todo, onToggle,  │      │
│  │   onDelete }: Props) {                      │      │
│  │   return (                                  │      │
│  │     <div className={`todo-item ${           │      │
│  │       todo.completed ? 'completed' : ''}`}> │      │
│  │       <input                                │      │
│  │         type="checkbox"                     │      │
│  │         checked={todo.completed}            │      │
│  │         onChange={() => onToggle(todo.id)}   │      │
│  │       />                                    │      │
│  │       <span>{todo.text}</span>              │      │
│  │       <button onClick={() =>                │      │
│  │         onDelete(todo.id)}>🗑️</button>     │      │
│  │     </div>                                  │      │
│  │   );                                        │      │
│  │ }                                           │      │
│  ╰─────────────────────────────────────────────╯      │
│  ✅ Accepted                                          │
│                                                      │
│  ⚙️ Tool: Write → src/components/AddTodo.tsx         │
│  ✅ Created (表单组件,包含 input + submit button)    │
│                                                      │
│  ⚙️ Tool: Write → src/App.tsx                        │
│  ✅ Created (主应用,useState 管理 todo 列表)         │
│                                                      │
│  ⚙️ Tool: Write → src/App.css                        │
│  ✅ Created (现代化样式,渐变背景 + 卡片设计)         │
│                                                      │
│  ⚙️ Tool: Bash                                       │
│  $ npm run dev                                       │
│                                                      │
│  ✅ Dev server started at http://localhost:5173       │
│                                                      │
│  🎉 Todo 应用已创建完成!                             │
│                                                      │
│  创建的文件:                                         │
│  📄 src/types/todo.ts     → 类型定义                  │
│  📄 src/components/TodoItem.tsx → 单条待办组件        │
│  📄 src/components/AddTodo.tsx  → 添加表单组件        │
│  📄 src/App.tsx            → 主应用逻辑               │
│  📄 src/App.css            → 样式文件                 │
│                                                      │
│  打开浏览器访问 http://localhost:5173 查看效果!       │
│                                                      │
╰──────────────────────────────────────────────────────╯

💻 代码演示:用一行命令完成

如果你不想交互,可以用 Print Mode 一步到位:

# 一行命令创建项目
claude "在当前目录创建一个 Vite + React + TypeScript 的 Todo 应用,
包含添加、删除、标记完成功能,使用现代化 CSS 样式,
创建完成后运行 dev server"

初始传入 prompt 的技巧

# 带初始提示的启动方式
claude "explain this project"

# 等同于启动后输入第一句话
# 但更适合脚本化或快速任务

🔧 本期用到的全部 Tools

工具 调用次数 作用
Bash 3 次 初始化、安装依赖、启动 dev server
Write 5 次 创建 5 个源码文件
Glob 0 次 空目录无需搜索
Read 0 次 新项目无需读取已有文件

观察:在"从零创建"场景中,WriteBash 是主力工具;而在"理解已有代码"场景中,ReadGlobGrep 是主力。


⚡ 进阶技巧:一条命令创建后继续迭代

> 给 Todo 应用加上 localStorage 持久化,
  刷新页面后数据不丢失

╭─ Claude ─────────────────────────────────────────────╮
│                                                      │
│  🔍 Using tool: Read (src/App.tsx)                   │
│                                                      │
│  ⚙️ Tool: Edit (src/App.tsx)                         │
│  ╭─ DIFF ──────────────────────────────────────╮     │
│  │ - const [todos, setTodos] =                 │     │
│  │ -   useState<Todo[]>([]);                   │     │
│  │ + const [todos, setTodos] =                 │     │
│  │ +   useState<Todo[]>(() => {                │     │
│  │ +     const saved =                         │     │
│  │ +       localStorage.getItem('todos');       │     │
│  │ +     return saved ? JSON.parse(saved) : [];│     │
│  │ +   });                                     │     │
│  │ +                                           │     │
│  │ + useEffect(() => {                         │     │
│  │ +   localStorage.setItem('todos',           │     │
│  │ +     JSON.stringify(todos));                │     │
│  │ + }, [todos]);                              │     │
│  ╰─────────────────────────────────────────────╯     │
│                                                      │
│  ✅ 已添加 localStorage 持久化!                      │
│  刷新页面后数据不会丢失。                             │
│                                                      │
╰──────────────────────────────────────────────────────╯

注意这里 Claude 先用 Read 读取了现有的 App.tsx,然后用 Edit 精确修改了需要改的部分,而不是重写整个文件。


📝 本期要点回顾

  1. Claude Code 通过 工具调用链 自动拆解复杂任务
  2. 创建新项目时,Bash + Write 是主力工具组合
  3. 修改已有项目时,Read + Edit 是主力工具组合
  4. 一行 claude "描述" 可以从零创建完整应用
  5. Claude 会先读再写,总是基于当前代码状态进行修改

🔗 参考资料