在终端里找、读、改一个文件:OpenCode 文件工具 read/write/grep 完整用法
【免费下载链接】opencodeThe open source coding agent.项目地址: https://gitcode.com/GitHub_Trending/openc/opencode
晚上十一点,线上报了个错,你分不清它出自哪个文件。打开终端 grep 一遍,再开编辑器,来回切了五次窗口,改完也不确定有没有打错字。OpenCode 是一个开源 AI 编码代理,内置的 read、write、grep 三个文件工具把查找、阅读、修改都收在终端里:写入前弹确认给你看 diff,写入后自动附上语法诊断。
它替我省掉了什么
| 老办法 | 用它之后 |
|---|---|
rg找位置,再开编辑器看上下文,两个窗口来回切 | grep 定位、read 读上下文,输出都在同一个会话里 |
| 改完手动跑类型检查,或等编辑器标红 | write 落盘即触发 LSP 诊断,结果跟写入输出一起回来 |
| 覆盖文件前自己默背一遍"这个路径是不是已存在" | write 的确认框带完整 diff,改哪个文件、改了什么一眼可见 |
| 搜索结果散落在终端滚动历史里 | grep 按文件分组,行号加匹配内容,可直接拿去当 read 的 offset |
先说结论:它替代的不是编辑器,是来回切换和人工校验这两件事。
五秒上手
装完跑一条非交互命令:
npm i -g opencode-ai@latest opencode run "找到 tool 目录下定义 MAX_LINE_LENGTH 的文件,读出来并解释它的作用"这条就能得到反馈:代理内部先做正则搜索,再读取命中的文件,最后给你解释。它填的参数就三套,看完你就有底了:
- read:
filePath(绝对路径)、offset(起始行,从 1 计)、limit(行数,默认 2000) - write:
filePath加content(完整新内容) - grep:
pattern(正则)、path(搜索目录,默认当前目录)、include(文件过滤,如*.ts)
日常的文件操作,基本就是这三套参数的组合。
🔧 逐项拆解核心能力
read:怎么防止一个大文件撑爆上下文
一句话:读文件或目录,输出每行带行号,默认截断。
示例任务:"把 read.ts 从第 130 行开始读 40 行"。
截断逻辑很直白,一行长文本不会把输出冲掉:
const line = text.length > MAX_LINE_LENGTH ? text.substring(0, MAX_LINE_LENGTH) + MAX_LINE_SUFFIX : text ... output += file.raw.map((line, i) => `${i + file.offset}: ${line}`).join("\n")MAX_LINE_LENGTH 取 2000,整体输出还有 50KB 的总上限;触顶时它不甩一句"已截断",而是告诉你下一段该从哪个 offset 继续。二进制文件靠扩展名清单加不可打印字符比例判断;图片和 PDF 则作为附件直接返回。路径写错也不是一句 404,它会列出最接近的三个候选名。
write:写入前的确认怎么防手滑
一句话:写入完整内容,自动格式化,自动取 LSP 诊断。
示例任务:"把 MAX_LINE_LENGTH 从 2000 改成 4000,写回去"。
最有用的是写之前的确认,不是简单 y/n,diff 直接摆在框里:
yield* ctx.ask({ permission: "edit", patterns: [path.relative(instance.worktree, filepath)], metadata: { filepath, diff }, })你看得见改的是哪个文件、具体改了什么。配套说明文件还写死了一条:覆盖已有文件前必须先读过它。落盘之后它会主动抓诊断:
output += `\n\nLSP errors detected in this file, please fix:\n${block}`如果改动连带弄坏了别处的引用,也会追加 "LSP errors detected in other files"。检查不等你回编辑器保存,当场给结论。
grep:怎么在大仓里定位代码
一句话:按正则搜文件内容,基于 ripgrep,单次最多 100 条结果。
示例任务:"找出 ctx.ask 的所有调用点"。
结果不是原始 rg 输出,而是按文件重组过的:
const result = yield* ripgrep.grep({ cwd, pattern, include, limit: 100 }) ... output.push(`${match.path}:`) output.push(` Line ${match.line}: ${match.text}`)文件路径、行号、匹配内容三要素齐全,看到的行号可以直接丢给 read 当 offset。命中满 100 条时结尾会标 "Results truncated",提示你收窄 path 或 pattern。
一个完整任务走一遍
任务是修一个截断常量:日志里看到长行被切得不够,需要调大。
你只说一句"找到 MAX_LINE_LENGTH 的定义,改成 4000"。接下来发生的事:grep 命中 packages/opencode/src/tool/read.ts 第 14 行;代理读了一下第 130 行附近,确认周围是截断逻辑而不是别的常量;write 前弹出确认,diff 显示只有一行变化,2000 到 4000;写完 LSP 诊断干净,没有追加输出。全程没碰编辑器,你唯一做过的决定是按下那个 y。
⚠️ 这些坑提前说
三条值得提前知道:
- 权限确认不是走形式的 y。write 的确认框带 diff,选"始终允许"后同类操作就不再询问了——新项目第一次先选"仅本次",看清楚它到底要动什么,再决定要不要加白名单。
- 截断不等于出错。单行超 2000 字符会带截断标记;输出总量触到 50KB 上限时会给出可继续的 offset,照抄即可;offset 超出文件总行数时,直接报 "Offset N is out of range for this file (X lines)",不用猜。
- grep 的"无结果"和"结果太多"长得不一样:没命中输出 "No files found",范围太宽则在 100 条处截断并提示收窄。真要统计命中次数,去 shell 里直接跑 rg,工具说明里自己也写了这条。
三个工具一条主线:grep 定位、read 给上下文、write 落盘,诊断跟在修改后面自动回。源码在 packages/opencode/src/tool/,每个工具一个 .ts 加一份 .txt 说明;安装方式与代理配置见 README.md。权限行为不符合预期时直接提 issue,想动手改的话先读 AGENTS.md。
【免费下载链接】opencodeThe open source coding agent.项目地址: https://gitcode.com/GitHub_Trending/openc/opencode
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考