为什么必须写文档教 AI 用代码
这是 LLM 插件和传统开发最本质的区别,我用你输入的这个命令做完整演示,保证你看完立刻懂。
一、先搞清楚一个核心事实
你输入的/understand C:\xxx\aus-life-java,根本不是直接运行的脚本命令 。 它只是你发给 Claude 的一句 "自然语言指令",Claude 收到后,会自己去读project-scanner.md这个文档,然后自己生成真正要执行的脚本命令,再在后台偷偷运行。
project-scanner.md不是给人看的,是给 Claude 写的 "操作手册"。Claude 只会严格按照手册里写的步骤来做,手册里没写的,它绝对不会做。
二、你输入的命令,到底发生了什么
你输入的:
plaintext
/understand C:\Users\Administrator\Desktop\zyf\aus-life-java
Claude 看到后,会立刻打开project-scanner.md,看到你写的:
调用扫描脚本的格式是:
bash
运行
node scan-project.mjs "$PROJECT_ROOT" "$OUTPUT_PATH"其中:
$PROJECT_ROOT= 用户输入的项目路径$OUTPUT_PATH= 固定为$PROJECT_ROOT/.understand-anything/tmp/ua-scan-files.json
然后 Claude 会自己生成真正执行的命令:
bash
运行
node scan-project.mjs
"C:\Users\Administrator\Desktop\zyf\aus-life-java"
"C:\Users\Administrator\Desktop\zyf\aus-life-java\.understand-anything\tmp\ua-scan-files.json"
然后 Claude 在后台运行这个命令,你完全看不到。
三、传入路径和输出路径分别是干什么的
1. 第一个参数:传入路径($PROJECT_ROOT)
就是你要分析的项目的根目录。
- 扫描脚本会从这个目录开始,遍历所有文件
- 所有的相对路径(比如
tests/、src/)都是相对于这个目录计算的 - 就是你输入的
C:\Users\Administrator\Desktop\zyf\aus-life-java
2. 第二个参数:输出路径($OUTPUT_PATH)
扫描脚本生成的 "文件清单 JSON" 的保存位置。 这是整个流程最关键的中间产物:
- 扫描脚本遍历完所有文件,过滤掉不需要的之后,会生成一个 JSON 文件
- 这个 JSON 里包含了所有要分析的文件的路径、语言、行数、分类等信息
- 后面所有的 LLM 文件分析、知识图谱构建,都是基于这个 JSON 文件来做的
- 这个路径是 Claude 自动生成的,不需要你输入,固定在项目的
.understand-anything/tmp/目录下
四、为什么你加的那两行文档是必须的
现在你输入带--exclude的命令:
plaintext
/understand C:\xxx\aus-life-java --exclude "target/*,bin/*"
如果没有你加的那两行文档:
Claude 看到--exclude参数,但它去读project-scanner.md,发现手册里只写了要传两个参数,根本没提--exclude这回事。 所以它会完全忽略这个参数,生成的命令还是:
bash
运行
node scan-project.mjs "C:\xxx\aus-life-java" "C:\xxx\...\ua-scan-files.json"
没有--exclude,你前面写的所有代码都白写了。
有了你加的那两行文档之后:
Claude 再读手册,就会看到:
如果用户输入里有
--exclude参数,记得在调用脚本时把它加在输出路径的后面,格式是--exclude "a/*,b/*"
所以它生成的命令就变成了:
bash
运行
node scan-project.mjs
"C:\xxx\aus-life-java"
"C:\xxx\...\ua-scan-files.json"
--exclude "target/*,bin/*"
这时候你的代码才会真正生效。
五、用 Java 开发者最熟悉的类比
表格
| 传统 Java 开发 | LLM 插件开发 |
|---|---|
| 你写了一个 Controller 接口 | 你写了一个脚本函数 |
| 你需要写 Swagger 文档告诉前端怎么调用这个接口 | 你需要写 Markdown 文档告诉 Claude 怎么调用这个脚本 |
| 前端只会按照 Swagger 文档里写的参数来传 | Claude 只会按照 Markdown 文档里写的参数来传 |
| Swagger 里没写的参数,前端不会传 | Markdown 里没写的参数,Claude 不会传 |
你加的那两行文档,就相当于在 Swagger 里给接口新增了一个exclude参数。没有这两行,就相当于接口加了参数但没更新 Swagger,前端永远不会传这个参数。
这就是为什么说 "如果不改这个文件,你前面所有代码都白写了"。