

0 / 2 embers
0 / 3000 xp
click for more info
Complete a lesson to start your streak
click for more info
Difficulty: 6
click for more info
Not enough gems
Cost: 6 gems
1: Tools
incomplete
2: Built-in Tools
incomplete
3: Specialized Tools
incomplete
4: Custom Tools
incomplete
5: Create a Custom Tool
incomplete
6: Tool Permissions
incomplete
7: Sandboxing
incomplete
Back
ctrl+,
Next
ctrl+.
This lesson's interactive features are locked, please to keep using them
Like other OpenCode config, tools (and the plugins that define them) can be project-specific or apply to all your personal projects:
.opencode/plugins/ in the repo. Assuming you allow that folder to be tracked, the tools will also be shared among collaborators.~/.config/opencode/plugins/ for use across many projects.OpenCode loads TypeScript and JavaScript plugins directly, but we recommend using TypeScript so that Plugin.define() has nice type information.
Now, local plugin dependencies are not installed automatically. Plugin.define() needs to have @opencode/plugin listed in a package.json, for example:
cd .opencode
bun add @opencode/[email protected]
With that dependency available, you create a plugin file and register the tool with ctx.tool.transform(). For example:
import { Plugin } from "@opencode/plugin";
export default Plugin.define({
id: "applymaxxing.database-tool",
setup: async (ctx) => {
await ctx.tool.transform((tools) => {
tools.add({
name: "database",
description: "Query the project database",
input: {
type: "object",
properties: {
query: { type: "string" },
},
required: ["query"],
additionalProperties: false,
},
options: { codemode: false },
execute: async (input) => {
const { query } = input as { query: string };
return { content: `Executed query: ${query}` };
},
});
});
},
});
If that file lives at .opencode/plugins/database.ts, OpenCode discovers the plugin automatically and registers the database tool. The id names the plugin, and the name of the tool is what OpenCode exposes to the model.
Each tool needs a name, description, JSON-compatible input schema, and execute function. It can also declare an output schema. If you omit that schema, you'll need to return model-visible content (plain text) as the example does.
The optional second argument to execute contains session metadata like sessionID, agent, and messageID, plus a progress function for reporting status.
By default, custom tools use Code Mode, meaning the model writes JavaScript that calls tools, and OpenCode runs it through the execute tool. This lets the model combine tool calls and process their results in code.
That said, this example sets options: { codemode: false } so the model will call database directly, just to show that you can.
Tool names are normalized, so duplicate names can collide. Give your tool a specific name instead of trying to replace a built-in... unless you really want to override one.
Give OpenCode a tool for running SlopLang programs.
curl -fsSL https://bun.com/install | bash
Tell OpenCode to run and submit the CLI tests from the project root.