Cursor 刚火起来的时候自己还是比较保守的,或者说不想费事去搞,毕竟在从业者眼中 Agentic Coding 还多半是一个「半成品」的状态,因为一个半成品而消耗自己的精力,这显然是不值当的。后来,接触了 Cursor 之后,的确是了解了一些高效的用法,比如快速地写函数注释以及参数的 type,抑或是快速了解新 repo 的某些代码段作用。现在,使用了 Claude Code,可以确信地说,Claude Code + IDE (Vscode / Cursor) 才是真正高效的编程,编程不仅可以更快,同时可以更好,而在编程的过程自己也能学的更多

以下将分为几个大的部分来详细介绍如何更好地使用 Claude Code (CC) 部分内容参考自 Anthropic Best Practices

安装

首先是在 IDE 终端内完成对 CC 的安装,这里泛指 Vscode 类 IDE,用 IDE 的原因很简单,CC Desktop 的更改是终端式的,不便于查看;而 CC 在 IDE 中可以新建一个窗口,非常方便查看差别(除非该终端是计算节点)(注:如果是 Remote 开发,在 Remote 开发机中装即可)

# 没有 npm 可以去官网进行安装: https://nodejs.org/en/download
npm install -g @anthropic-ai/claude-code

接着安装插件:Claude Code,如果是 Remote 开发,记得装到 Remote 机器上

运行时 CC 会对「区域」进行检测,有些区域会被 block,可以用这个跳过:

echo '{ "hasCompletedOnboarding": true }' > ~/.claude.json

接着设置 API Base 和 Key 即可进行玩耍:

export ANTHROPIC_BASE_URL=xxx
export ANTHROPIC_API_KEY=xxx

最后开启终端输入 claude 即可

如果你说 Claude 又贵又容易被封,代理站不稳定,那么为什么不试试便宜又同样好用的 kimi/k2 呢?去官网的 API 开通之后,即可使用:

export ANTHROPIC_BASE_URL=https://api.moonshot.ai/anthropic
export ANTHROPIC_API_KEY=月之暗面的 key

基本元素

CLAUDE.md

如果你需要让 CC 可以在修改 repo 的时候如鱼得水,那么你需要给其一份有关于 repo 的 manual,当然它可以每次都自己探索理解,但这样效率低而且不如你告诉它来的精准。这份 manual 在 CC 中即为「CLAUDE.md」,里面包含 repo 的信息以及「你需要它额外记住」的信息

那么如何得到 CLAUDE.md 呢?当然你可以纯手写,那样效率不高。我们可以让 CC 自己生成,只需要在终端中输入 /init 命令即可,这是第一步。接着你还需要:

  • 修改不正确的:毕竟让它直接理解肯定会出现问题,比如 Development Commands(就是运行的命令)
  • 开发示例:有些模块之间会有比较复杂依赖,可以给它一些修改的示例,即 Development Notes,比如你可以教它添加新优化器实现的步骤
  • 工具使用:如果你自己手搓了一些「工具」,也可以单独放在 Tools 章节
  • 除了以上这些,还可以使其原先的表述更加精准,或是加上一些它未曾注意到的,精准的开发需要精确的信息作为辅助

除了 repo 相关的信息可以放在 CLAUDE.md,我们还可以将写代码的注意点放进去,比如 Coding Style,还有 Getting Help 部分。以下是个人示例:

## Best Practices

### Code Style

- Make the code neat and pythonic
- Follow existing patterns in the codebase. NEVER write new features into a file without first having a complete understanding of its underlying logic
- Make the smallest reasonable changes to get to the desired outcome
- DO NOT simply override the current code to implement new feature. Use configuration unless I told you to remove some feature
- You MUST ask permission before reimplementing features or systems from scratch instead of updating the existing implementation
- Use type hints, but omit the return type for functions that return `None`
- Single quotes are preferred over double quotes
- Use specific function or variable name

### Getting help

- ALWAYS ask for clarification rather than making assumptions.
- If you're having trouble with something, it's ok to stop and ask for help. Especially if it's something your human might be better at.

总而言之,CLAUDE.md 应该包括以下部分:

  • 运行代码的命令(训练,单元测试等)
  • 代码的整体结构(训练,模型,数据,优化器等)以及不同 python 文件所负责的 module
  • 代码的参数配置:参数的含义是什么,这个可以按照 module 来划分
  • 如何修改不同的 module (Development Notes)
  • Coding Style 以及一些额外的信息

另外还可以让 CC 假装不熟悉 repo,让其对 CLAUDE.md 进行补充以便让新手上手并修改 repo

Commands

一些重复的 prompt 可以收集起来,变成特定的命令,方便直接调用,在项目根目录创建 .claude/commands,将命令以 *.md 的形式添加进该目录即可在 CC 中调用。比如创建 fix-issue.md

Please analyze and fix the GitHub issue: `$ARGUMENTS.$`

Follow these steps:

1. Use `gh issue view` to get the issue details
2. Understand the problem described in the issue
3. Search the codebase for relevant files
4. Implement the necessary changes to fix the issue
5. Write and run tests to verify the fix
6. Ensure code passes linting and type checking
7. Create a descriptive commit message
8. Push and create a PR

Remember to use the GitHub CLI (`gh`) for all GitHub-related tasks.

使用 / 来唤出命令,即 /fix-issue: ... 即可使用该命令

工作流

比较直接的就是让 CC 直接给你实现某个 feature,但这样通常不高效,因为这其实涉及了「阅读 -> 思考 -> 写代码」几个流程,一下子完成就容易出错。复杂的任务应该拆分为步骤来完成(除非实现的特别简单),而不同的工作流可以用 command 来表示,这样调用的时候比较方便

Read-Plan-Code-Submit

四个英文单词分别代表一个「动作」,即将写代码拆分为四个过程:

  1. Read:你可以指定其阅读特定的内容,比如 model.py,或者 URL,图像等等,让其充分理解相关的内容,并强调该过程只需要理解不需要写代码
  2. Plan: 阅读完之后,让其对需要实现的东西列一个简要的计划,以便你进行检查
  3. Code: 这一步就是让它正式写代码
  4. Submit:让其写完代码后进行 github submit,并且把你的需求和它的实现清单都放上去,方便日后 review

当然如果是方便测试的代码,可以在 Code 之后加上 Test,让其保证本地运行无报错或是通过单元测试才可进行 Submit

Test-Code-Iterate-Submit

与上方不同,第一个动作变成了「Test」,即单元测试的意思,之所以放在第一位,是因为如果先写代码再写 test,很有可能 test 就比较专注于当前的实现,会忽略一些特殊的 cases(就好像自己检查自己的代码,比较难看出问题)

其实这个工作流的核心就是「test-iterate」,让模型提前写好单元测试,并且不断其迭代,直到通过测试。这种工作流比较适合于需求非常精确,可用测试具体化的任务,比如后端 API 调用,或者是你让其重构当前代码,将「老代码的运行结果作为对照」

如果有时候比较模糊,比如 UI 开发,也可以将 test 换成「screenshot」,让其对照截图来不断完善实现

人为干预

人为干预是和任意工作流一起配合使用,毕竟 CC 是一步步实现需求,如果有时候实现错误,人为进行干预会得到更精确的结果,全自动说实话人也没办法放心。比较常用的是以下几种:

  • 按 Esc 直接打断
  • 连续按两次 Esc,可以在历史中回跳选择,比如当前实现错误,而之前都是对的情况就可以用

复杂任务的 prompt

对于复杂 & 精确的任务,我们需要好的 prompt 让其完成工作,当然简单的任务有时候也需要更加精确的 prompt,一般情况下怎么写好的 prompt 可以参见我之前的博客 How to Prompt LLMs Better? ,下面针对 CC 开发来说一下好的 prompt 还需要满足什么(老生常谈的 specific 就不聊了)

强调顺序性

当任务复杂时,尤其是不同步骤看起来有点像的时候,很容易直接进行合并,而合并会带来更大的复杂度,多半结果差强人意。那么,此时就需要一些 prompt 来让其遵循顺序,不要跳步:

**Objective: Example Command**

**Directive:** Your task is to process the request defined by ``$ARGUMENTS`. You MUST follow the five-phase process outlined below in strict sequential order. **Combining phases or proceeding to the next phase before explicitly completing the current one is a critical failure.** For each phase, you will announce its start, perform the required tasks, produce the specified deliverable, and then announce its completion before moving on.$`

---

## Phase 1: This is Phase 1

**Objective:** This is the objective of Phase 1

**Tasks:**

1. xxx
2. xxx

**Transition:** After xxx, state: "Phase 1 Complete. Proceeding to Phase 2."

---

## Phase 2: This is Phase 2

**Objective:** This is the objective of Phase 2

**Tasks:**

1. xxx
2. xxx

**Transition:** After xxx, state: "**Phase 2 Complete. Proceeding to Phase 3.**"

上方的 prompt 模板基本上在复杂任务上可以让模型一步一步来进行编程,而不会一下子突然合并,然后暴毙

将指令编程化

如果你将 Agent 当成一种代码来写,大概率都能得到满意的结果,比如我在做 k2 demo 的时候,最后的 HTML Report 需要加上所有的图片,而有时候随着图片生成的数量一多起来,加上整个过程本来就是非常复杂的连续推理,模型很容易就忘掉。一开始尝试的就是「上强度」,比如加入 **Critical**: You must attach all the figures into HTML report 这种字眼,但其实模型还是做不到,或者骗自己全部加上

此时正确的做法应该是,将该指令尽可能向编程靠齐,如果你要写代码判断是否全部添加,比较朴素的思维就是,先 list 出图片原来一共有多少,再 grep HTML 中 src 为图片的数量,两者进行对比,如果对不上,则说明有图片被遗漏。那么就可以将上述过程写入 prompt,你还可以将对应的 bash 命令告诉它,这样之后,它多半情况都能正确添加,哪怕图片数量多

复杂的 prompt 是否合理

你会不会觉得 CLAUDE.md 已经够长了,加上模型还需要游走仓库各个文件,此时如果 prompt 写的复杂,会不会反倒起副作用? 结论是不必担心,确保 prompt 和完成的任务复杂度成正比即可,你的任务如果无比简单,那没必要用复杂的 prompt;而如果你的任务是多步精确的推理,那么你的 prompt 复杂点反倒会让其执行地更加精确

让 Gemini 出手

有些时候可以让 Gemini 来修改你的 prompt,这里之所以是 Gemini,是因为其是所有 LLMs 最话痨的一个,会事无巨细地修改你的 prompt,让其更加精确具体,比如:

My objective is to xxx. Please re-frame the following prompt to make it easier for LLMs agents to follow.

<Your Prompt>

当然,别忘了对其返回的结果进行二次修改,多半情况下 Gemini 还会顺手把不需要改的地方也改了,也可以在一开始输入时限制它不要这么做。总之,检查还是必要的~

使用场景

Repo QA

这个其实是最靠谱的功能(写代码会出错,这个大概率不会),当上手一个新仓库时,或者阅读一段比较费解的代码,有时候可以让 CC 进行解释,以下列出几种提问方式:

  • How is the logging module implemented?
  • Why does the line 139 in xxx.py call function a()?
  • What is the meaning of parameter p on line 139 of xxx.py?

这个还可以反着用,当你在一个项目上加越来越多 feature,潜在的依赖关系就会越来越复杂,有时候你可能忙着实现一个 feature 而忘记一些依赖关系,也可以先让 CC 进行分析,此时就可以提前规避错误

Linter

这个是我经常使用的功能,写完代码后,可以让 CC 对代码进行检查,查看其是否符合 pythonic and neat 的要求,常见的修改需求如下:

  • 将某个大函数拆分为几个原子化的小函数
  • 修改某个变量 / 函数的名字使其更加具体和精确
  • 对复杂的模块及其参数添加注释
  • 对函数的变量加上 type 标识

除了 Repo QA,CC 还可以 Git QA,比如你好奇某个模块的功能是在哪个 commit 实现的,或者是想要问责是哪个实现导致了目前的报错

同时还可以让 CC 帮助你完成 git 的提交,比如写 commit message 以及自动化 push

Tips

  • /clear 可以直接清除所有上下文
  • Shift+Tab 可以灵活切换状态,比如「自动接受」
  • 修改命令之后得重启 CC 才可以生效
  • 可以向 CC 传数据,比如图片,或者是读取 URL 文件,本地文件可以通过路径来读,还可以使用管道命令,比如 cat foo.txt | claude
  • 多个 Claude 协同,这个适合一个 Claude 解决不了的时候,可以开两个终端,每个 CC 负责不同的功能,比如一个实现,一个检查
  • 使用一些额外的工具,比如 MCP(Model Context Protocol),当然你也可以写一些「工具代码」供其调用
  • 重要的提示词:比如 IMPORTANT,YOU MUST 来强调服从性;思考相关的:think, think hard, think harder(适合 Claude 模型)
  • 有时候我们想一直「自动运行」,但它有时候会弹出一些「命令申请」,此时就可以在 .claude/settings.local.json 内加入一些命令的权限管理:
    {
        "env": {
            "BASH_DEFAULT_TIMEOUT_MS": "3000000" // bash command 超时时间
        },
        "permissions": {
            "allow": [
                "Bash", // 允许终端执行所有命令, 不要使用 Bash(cat:*), 这种 CC 有 Bug, 会一直请求
            ],
            "deny": []
        }
    }