Back to Blog

OpenCode 的 22 个内置工具:从文件操作到语义搜索

2026-04-26T18:20:00+08:00
OpenCode AI 工具 MCP LSP 文件操作 代码搜索

OpenCode 的 22 个内置工具:从文件操作到语义搜索

一个 AI Agent 到底能干多少事,取决于它手里有多少工具。

OpenCode 在 GitHub 上拿了 140K star,月活开发者 650 万,靠的不只是模型强——而是内置了一套完整的工具链。22 个内置工具,从读文件、写代码、搜索代码库,到跑 shell、查文档、对接 LSP 诊断,再到委派子任务、管理进度,基本覆盖了日常开发的全部动作。而且还能通过 MCP 和 Plugin 接入任意外部服务,理论上没有上限。

这篇文章带你逐个拆解这 22 个工具的设计、用法和内部机制。

本文提纲

  1. 工具体系总览 — 22 个工具分类速查
  2. 文件操作 4 件套 — read / write / edit / apply_patch
  3. 代码搜索三剑客 — glob / grep / codesearch
  4. 网络工具 — webfetch / websearch
  5. Bash 工具 — 执行 shell 命令
  6. LSP 诊断 — 30+ 语言自动接入
  7. Agent 管理工具 — task / plan / question / todowrite
  8. 权限控制系统 — Allow / Deny / Ask 三级管控
  9. MCP 和 Plugin 扩展 — 无限扩展能力
  10. 内部实现解析 — 工具接口与注册机制

工具体系总览

先上一张全景表,把 22 个工具分成 5 大类:

类别 工具 作用
文件操作 read 读取文件内容,支持行范围
write 创建新文件或覆盖已有文件
edit 精确字符串替换修改文件
apply_patch 应用 patch 格式的批量修改
代码搜索 glob 按文件名模式匹配查找文件
grep 正则表达式搜索文件内容
codesearch 语义化代码搜索
网络工具 webfetch 抓取指定 URL 的网页内容
websearch 使用 Exa AI 搜索网页信息
Shell bash 执行任意 shell 命令
IDE 集成 lsp LSP 代码智能(定义跳转、引用查找等)
Agent 管理 task 启动子 Agent 执行子任务
plan Plan 模式,只分析不修改
question 向用户交互式提问
todowrite 管理任务进度列表
知识加载 skill 加载 Skill 文件注入上下文
安全防护 external_directory 外部路径访问守卫
doom_loop 重复调用检测守卫
内置 Agent build 默认构建 Agent,全工具开放
explore 只读探索 Agent
general 通用子 Agent
compaction 上下文压缩 Agent

这套工具的设计思路很清晰:先用 read / glob / grep 理解代码,用 edit / write / apply_patch 修改代码,用 bash 跑构建和测试,用 lsp 获取 IDE 级别的代码智能,用 task 拆分复杂任务,用 webfetch / websearch 查外部资料。整个开发流程中 Agent 能自主完成绝大部分操作。

文件操作 4 件套

文件操作是 Agent 最基础的能力。OpenCode 提供了 4 个工具,各有侧重:

read — 读文件

读取指定文件的内容,支持指定行范围。大文件不用一次全读,可以分段读取。底层就是 cat -n 格式,带行号输出。

read(filePath: string, offset?: number, limit?: number)

一个典型的用法——先读文件头了解结构,再读关键函数:

read("src/index.ts", 0, 50)    // 读前 50 行
read("src/index.ts", 120, 30)  // 读 120-150 行

write — 写文件

创建新文件,或者直接覆盖已有文件。适合从零创建组件、配置文件、测试文件。

write(filePath: string, content: string)

注意:write 是整文件覆盖,不是增量编辑。如果你想保留原文件内容只改一部分,应该用 edit。

edit — 精确替换

edit 是 OpenCode 最常用的修改工具。它的工作方式是「找到旧字符串 → 替换成新字符串」。

edit(filePath: string, oldString: string, newString: string)

比如把一个函数的返回值从 null 改成 undefined

{
  "filePath": "src/api/handler.ts",
  "oldString": "return null;",
  "newString": "return undefined;"
}

edit 有个很实用的 replaceAll 参数,设为 true 时会替换文件中所有匹配项,适合批量重命名变量。

如果 oldString 在文件中找不到或找到多个(且没开 replaceAll),工具会报错。这个设计逼着 Agent 先 read 文件确认内容,再做精确修改,大幅降低了改错文件的概率。

apply_patch — 批量补丁

apply_patch 用于应用标准 patch 格式的修改。跟 edit 的区别在于:edit 是单点替换,apply_patch 是批量操作——可以在一次调用中同时添加、修改、删除、重命名多个文件。

apply_patch(patchText: string)

patchText 里用特殊标记来区分操作类型:

*** Add File: src/new-module.ts
*** Update File: src/existing.ts
*** Move to: src/renamed.ts
*** Delete File: src/obsolete.ts

适合做大规模重构时一次性提交多个文件的修改。

四个工具怎么选

场景 推荐工具
从零创建文件 write
修改已有文件的一处 edit
批量替换同名变量 edit (replaceAll)
多文件重构 apply_patch
只看不改 read

注意 write、edit、apply_patch 三个写工具共享同一个 edit 权限控制。在 opencode.json 里配置 "edit": "deny" 就会同时禁用这三个工具。

代码搜索三剑客

在陌生代码库里找东西,是 Agent 最高频的操作之一。OpenCode 提供了 3 个搜索工具,从文件名到内容到语义,层层递进。

glob — 文件名匹配

用 glob 模式查找文件路径。底层用的 ripgrep,默认遵守 .gitignore 规则。

glob(pattern: string, path?: string)

常用模式:

**/*.ts           // 所有 TypeScript 文件
src/**/*.test.ts  // src 下所有测试文件
*.config.js       // 根目录的配置文件

返回结果按修改时间排序,最近改过的文件排前面。这个排序很聪明——Agent 处理问题时大概率需要看最近改过的文件。

grep — 内容搜索

用正则表达式搜索文件内容。同样基于 ripgrep,支持完整的 regex 语法,还能按文件类型过滤。

grep(pattern: string, path?: string, include?: string)

比如在 TypeScript 文件里找所有 TODO 注释:

{
  "pattern": "TODO|FIXME|HACK",
  "include": "*.ts",
  "path": "src"
}

返回文件路径和行号,按修改时间排序。

codesearch — 语义搜索

codesearch 是更高级的搜索方式。不同于 glob 找文件名、grep 找精确文本,codesearch 能理解自然语言描述的意图去搜索代码。

比如你问 "Where is user authentication handled?",codesearch 能找到相关的认证函数和中间件,即使代码里没有 "authentication" 这个词。

三者对比

工具 搜索对象 查询方式 适用场景
glob 文件路径 通配符模式 找某类文件在哪
grep 文件内容 正则表达式 找某个函数/变量/字符串
codesearch 文件内容 自然语言 按意图找相关代码

三者底层都用了 ripgrep。如果需要搜索 .gitignore 里的文件,在项目根目录创建 .ignore 文件来覆盖:

!node_modules/
!dist/

网络工具

Agent 不应该只待在本地代码库里,有时候需要查文档、搜 API、看最新的 issue。OpenCode 提供了 2 个网络工具。

webfetch — 抓取网页内容

给一个 URL,返回网页内容。支持 markdown、text、html 三种格式输出。

webfetch(url: string, format?: "markdown" | "text" | "html")

典型用法:

webfetch("https://docs.example.com/api-reference", "markdown")

Agent 用它来查阅最新文档、读取 GitHub README、获取 API 响应。因为 LLM 的训练数据有截止日期,webfetch 是 Agent 获取"当下"信息的关键通道。

websearch — 网页搜索

websearch 用 Exa AI 做网页搜索,输入查询语句,返回相关结果。不需要 API key——OpenCode 直接连接 Exa AI 的托管服务。

websearch(query: string)

这个工具需要 OPENCODE_ENABLE_EXA=true 环境变量才能启用:

OPENCODE_ENABLE_EXA=1 opencode

一个简单的区分原则:websearch 用来发现信息(搜),webfetch 用来获取内容(取)。先用 websearch 搜 "How to configure OAuth2 in Express",再用 webfetch 去读搜索结果里的具体文章。

Bash 工具

bash 是 OpenCode 里最强大的工具,也是最需要权限管控的。它能执行任何 shell 命令:

bash(command: string, timeout?: number, workdir?: string, description?: string)

Agent 用它跑 npm installgit statuspytestdocker build 等命令。timeout 参数控制超时时间(毫秒),默认 120 秒。

安全限制

OpenCode 对 bash 工具有几个内置的安全措施:

  1. timeout 控制:命令超时自动终止,防止 Agent 卡死
  2. workdir 隔离:默认在项目根目录执行,可以用 workdir 切换
  3. 输出截断:超过 2000 行或 51200 字节的输出会被截断,防止上下文爆炸
  4. 权限管控:可以按命令模式精细控制,比如允许 git status 但拒绝 rm -rf

截断这点很关键。一个 find / 的输出可能有几十万行,全部塞进上下文会直接爆掉。OpenCode 在工具结果层面做了截断,超长输出会写入临时文件,Agent 可以用 read 工具分段读取。

Bash 的替代方案

有时候你不需要 bash:

  • 读文件内容 → 用 read,不要 cat file
  • 搜文件名 → 用 glob,不要 find . -name "*.ts"
  • 搜文件内容 → 用 grep,不要 grep -r "pattern" .

专用工具比 bash 更高效,因为输出格式是结构化的,Agent 解析更准确。bash 是万能的兜底方案,但不是第一选择。

LSP 诊断 — 30+ 语言自动接入

这是我用 OpenCode 最惊喜的功能之一。

OpenCode 内置了 30+ 语言的 LSP server 支持,检测到对应扩展名的文件就自动启动 LSP,然后通过 lsp 工具提供 IDE 级别的代码智能。

支持的语言

包括但不限于:TypeScript、Go、Rust、Python(pyright)、Java(jdtls)、C/C++(clangd)、C#、Kotlin、Swift、Ruby、PHP、Dart、Elixir、Haskell、Lua、Svelte、Vue、Astro、Terraform、Nix 等。

大部分 LSP server 会自动安装——你不需要手动配置任何东西。只要项目里有对应语言的文件,OpenCode 就能提供代码智能。

lsp 工具的 9 个操作

lsp 工具支持以下操作:

操作 说明
goToDefinition 跳转到定义
findReferences 查找所有引用
hover 悬停查看类型信息
documentSymbol 当前文件的符号列表
workspaceSymbol 工作区符号搜索
goToImplementation 跳转到实现
prepareCallHierarchy 查看调用层级
incomingCalls 谁调用了这个函数
outgoingCalls 这个函数调用了谁

需要设置 OPENCODE_EXPERIMENTAL_LSP_TOOL=true 来启用:

OPENCODE_EXPERIMENTAL=true opencode

诊断结果如何影响 Agent 决策

LSP 诊断会在文件编辑后自动触发。如果 Agent 修改了 TypeScript 代码,LSP 会立刻检查类型错误。诊断结果(错误、警告)会反馈给 Agent,Agent 看到报错就知道要修复。

这个实时反馈循环让 Agent 的代码质量大幅提升。没有 LSP 的时候,Agent 改完代码只能靠跑测试来发现问题;有了 LSP,类型错误在编辑阶段就能被发现和修复。

自定义 LSP

如果 OpenCode 内置的 LSP 配置不满足需求,可以在 opencode.json 里覆盖:

{
  "lsp": {
    "typescript": {
      "disabled": true
    },
    "custom-lsp": {
      "command": ["custom-lsp-server", "--stdio"],
      "extensions": [".custom"]
    }
  }
}

Agent 管理工具

复杂任务需要拆分、需要交互、需要记录进度。OpenCode 提供了 4 个 Agent 管理工具。

task — 子任务委派

task 工具让 Agent 可以启动子 Agent 来并行执行子任务。主 Agent 像项目经理一样分配工作,子 Agent 各自独立完成。

OpenCode 内置了几个专用子 Agent:

  • explore:只读 Agent,只能读取和搜索代码,不能修改。适合快速浏览代码库
  • general:通用 Agent,除了 todo 之外有完整工具权限。可以并行处理多个独立任务

在对话中用 @ 提及子 Agent 来手动调用:

@explore 帮我找出 src/api 目录下所有的路由处理函数

或者让主 Agent 自动决定什么时候委派。task 工具的权限可以精细控制——你可以指定某个 Agent 只能调用特定的子 Agent。

plan — Plan 模式

Plan 模式是 OpenCode 的安全阀。在 Plan 模式下,Agent 可以分析和规划,但不能修改任何文件或执行命令。所有写操作和 bash 命令都需要用户确认。

按 Tab 键在 Build 模式和 Plan 模式之间切换。右下角会显示当前模式。

实际使用中,我习惯先切到 Plan 模式让 Agent 分析一下方案,确认没问题再切回 Build 模式执行。这样既能利用 Agent 的分析能力,又不会担心它乱改代码。

question — 交互式提问

Agent 在执行任务过程中可能会遇到模糊的指令或需要做选择的场景。question 工具让 Agent 能向你提问。

question(header: string, questions: Question[])

每个问题包含标题、问题文本和选项列表。你可以从选项中选择,也可以自由输入答案。如果有多个问题,可以逐个回答后一起提交。

这个设计解决了 Agent 「蒙着眼干活」的问题——遇到拿不准的地方,它会问你,而不是自己猜。

todowrite — 任务进度管理

todowrite 让 Agent 可以创建和更新任务列表,跟踪多步骤操作的进度。

todowrite(todos: TodoItem[])

Agent 用它来组织复杂任务。比如重构一个模块时,Agent 会创建 todo 列表:1) 读现有代码 → 2) 写新实现 → 3) 更新测试 → 4) 跑测试验证。每完成一步就标记一个。

注意 todowrite 默认对子 Agent 禁用。你可以手动在 Agent 配置里开启它。

权限控制系统

22 个工具全开固然强大,但安全怎么办?OpenCode 的权限系统给了你精细的控制粒度。

Allow / Deny / Ask 三级权限

每个工具都可以设置为三种状态:

  • allow:自动执行,不需要确认
  • ask:每次执行前询问用户
  • deny:直接禁止

opencode.json 里配置:

{
  "permission": {
    "bash": "ask",
    "edit": "allow",
    "webfetch": "deny"
  }
}

Per-tool 精细规则

权限不只是全局开关,还支持基于输入的模式匹配:

{
  "permission": {
    "bash": {
      "*": "ask",
      "git *": "allow",
      "npm *": "allow",
      "rm *": "deny"
    },
    "edit": {
      "*": "deny",
      "packages/web/src/content/docs/*.mdx": "allow"
    }
  }
}

规则按顺序匹配,最后匹配的规则生效。常见模式是把通配符 "*" 放前面,具体规则放后面。

安全防护机制

除了工具权限,OpenCode 还有两个安全守卫:

external_directory:当 Agent 尝试访问项目目录以外的路径时触发。默认是 ask,防止 Agent 读取或修改项目外的文件。

doom_loop:当同一个工具以相同参数重复调用 3 次时触发。这是防止 Agent 陷入死循环的保护机制。默认是 ask,Agent 卡住时会弹出来让你介入。

Per-agent 覆盖

权限可以按 Agent 覆盖。比如全局允许 bash,但只给 plan Agent 禁用:

{
  "permission": {
    "bash": "allow"
  },
  "agent": {
    "plan": {
      "permission": {
        "bash": "deny"
      }
    }
  }
}

Agent 的权限规则跟全局配置合并,Agent 的规则优先。

.env 文件保护

OpenCode 默认保护 .env 文件不被读取:

{
  "permission": {
    "read": {
      "*": "allow",
      "*.env": "deny",
      "*.env.*": "deny",
      "*.env.example": "allow"
    }
  }
}

敏感信息不会意外泄露到 Agent 的上下文里。

MCP 和 Plugin 扩展

22 个内置工具只是起点。OpenCode 支持两种扩展方式:MCP 和 Plugin。

MCP 工具动态加载

MCP(Model Context Protocol)是 OpenCode 接入外部服务的主要方式。添加一个 MCP server,它的所有工具就自动对 Agent 可用。

配置方式很简单,在 opencode.json 里加一个 mcp 块:

{
  "mcp": {
    "sentry": {
      "type": "remote",
      "url": "https://mcp.sentry.dev/mcp",
      "oauth": {}
    }
  }
}

MCP 支持两种类型:

  • local:本地进程,通过 command 启动。比如 ["npx", "-y", "my-mcp-server"]
  • remote:远程 HTTP 服务,通过 URL 连接。支持 OAuth 自动认证

添加后,MCP server 的工具会以 serverName_toolName 的格式注册。比如 Sentry MCP 的工具会变成 sentry_listIssuessentry_getIssueDetails 等。

几个常用的 MCP server:

MCP Server 用途
Sentry 查询错误监控数据
Context7 搜索技术文档
Grep by Vercel 搜索 GitHub 上的代码示例

MCP 工具同样受权限系统控制。可以用通配符管理:"sentry_*": "ask" 会把 Sentry 的所有工具设为需要确认。

Plugin 自定义工具

Plugin 是更深层的扩展机制。它不是一个工具,而是一个钩子系统,可以拦截和修改 OpenCode 的各种行为。

Plugin 文件放在 .opencode/plugins/ 目录(项目级)或 ~/.config/opencode/plugins/(全局级),也可以从 npm 安装:

{
  "plugin": ["opencode-helicone-session", "opencode-wakatime"]
}

Plugin 能做的事情包括:

  1. 添加自定义工具:用 tool() helper 创建新工具
  2. 拦截工具执行tool.execute.beforetool.execute.after 钩子
  3. 监听事件:文件编辑、LSP 诊断、session 状态等 30+ 种事件
  4. 注入环境变量shell.env 钩子

一个实际的例子——自动转义 bash 命令中的特殊字符:

export const SafeBash = async (ctx) => {
  return {
    "tool.execute.before": async (input, output) => {
      if (input.tool === "bash") {
        output.args.command = escapeShellChars(output.args.command)
      }
    },
  }
}

无限扩展能力

MCP + Plugin 的组合意味着 OpenCode 的工具集理论上没有上限。你需要数据库查询?加个 MCP。需要对接内部 API?写个 Plugin。需要自定义代码审查规则?创建一个专用 Agent 配合权限控制。

工具注册在运行时动态完成。MCP server 启动时暴露工具列表,OpenCode 自动注册并纳入 Agent 的可调用范围。整个过程不需要重启。

内部实现解析

了解工具怎么工作的,能帮你更好地使用和调试。

工具接口设计

每个工具都遵循统一的接口:

interface Tool {
  name: string
  description: string
  args: Record
  execute(args: any, context: ToolContext): Promise
}

name 是工具标识,description 告诉 LLM 这个工具干什么,args 用 Zod schema 做参数校验,execute 是实际执行逻辑。

ToolContext 提供了当前会话信息:Agent 名称、session ID、消息 ID、工作目录、git worktree 路径等。工具可以基于这些上下文做出智能决策。

工具注册机制

OpenCode 的工具注册分三层:

  1. 内置工具:编译时注册,bash、read、edit 等 13 个核心工具
  2. MCP 工具:运行时动态注册。MCP server 启动后暴露工具列表,OpenCode 自动注册
  3. Plugin/自定义工具:从 .opencode/tools/ 或 Plugin 的 tool() helper 注册

注册时工具名不能重复。如果自定义工具和内置工具同名,自定义工具优先。这意味着你可以完全替换内置的 bash 工具。

工具结果处理

工具执行结果会做两个处理:

截断(truncate):超过 2000 行或 51200 字节的输出会被截断。全文写入临时文件,Agent 可以用 read 分段读取。这个机制防止了上下文爆炸。

权限检查:每次工具调用前都会检查权限。检查流程是:先查 Agent 级别的权限配置,再查全局配置,最后用默认值。匹配规则按声明顺序,最后匹配的生效。

ripgrep 底层

glob 和 grep 底层用的是 ripgrep(rg)。ripgrep 默认遵守 .gitignore 规则,这意味着 node_modules/dist/.git/ 等目录会被自动排除。

如果需要搜索这些目录,在项目根目录创建 .ignore 文件来覆盖:

!node_modules/
!dist/
!build/

这个小文件能让搜索覆盖更广的范围,但要小心——搜索 node_modules 可能返回大量结果,触发截断机制。


作者: itech001 来源: 公众号:AI人工智能时代 主页: https://www.theaiera.cn(每日分享最前沿的AI新闻和技术)

关注公众号,获取更多 AI 技术干货!

Enjoyed this article? Share it with others!