What it is

A tool is a capability the LLM can invoke to perform actions on your system—reading files, executing commands, searching code, or interacting with external services. Tools bridge the gap between the model's reasoning and real-world operations.

What it is in real OpenCode terms

In OpenCode, tools are the built-in functions that let the AI agent interact with your codebase. When you ask the agent to "fix the bug in auth.js," it uses tools like read, grep, edit, and bash to accomplish the task.

Built-in tools include: bash, edit, write, read, grep, glob, lsp (experimental), apply_patch, skill, todowrite, webfetch, websearch, and question.

Why it exists

Without tools, an LLM can only generate text. Tools transform the model from a text predictor into an autonomous coding agent that can explore, understand, modify, and verify code. Every real coding task—finding a bug, writing a test, deploying code—requires tool use.

Anatomy / main elements

  • Name: Unique identifier (e.g., bash, read)
  • Parameters: Inputs the tool accepts (e.g., file path, command string)
  • Context: Each tool receives: agent, sessionID, messageID, directory, worktree
  • Output: The result returned to the LLM for further reasoning

Where it lives

Built-in tools ship with OpenCode. Custom tools are TypeScript/JavaScript files placed in:

.opencode/tools/          # project-local
~/.config/opencode/tools/  # global

How to create one

Create a TypeScript file in .opencode/tools/ and export a tool definition using the tool() helper from @opencode-ai/plugin:

// .opencode/tools/my-tool.ts
import { tool } from "@opencode-ai/plugin"

export default tool({
  name: "my_tool",
  description: "Does something useful",
  parameters: {
    input: { type: "string", description: "The input text" }
  },
  execute: async (params, context) => {
    return `Processed: ${params.input}`
  }
})

Multiple exports per file create separate tools named <filename>_<exportname>. Custom tools take precedence over built-ins if names collide.

Minimal example

// A tool that counts lines in a file
import { tool } from "@opencode-ai/plugin"
import { readFile } from "fs/promises"

export default tool({
  name: "count_lines",
  description: "Count lines in a file",
  parameters: {
    path: { type: "string", description: "File path" }
  },
  execute: async ({ path }) => {
    const content = await readFile(path, "utf-8")
    const lines = content.split("\n").length
    return `File has ${lines} lines`
  }
})

Common confusion

Tool vs MCP: Tools are built-in or local custom. MCP connects to external services.
Tool vs Command: Tools are low-level actions. Commands are higher-level workflows composed of prompts.
Permissions: Default is all tools enabled with no permission needed. Control this via permission config in opencode.json.