diff --git a/.opencode/tool/foo.ts b/.opencode/tool/foo.ts index 3d350de1..44ce990e 100644 --- a/.opencode/tool/foo.ts +++ b/.opencode/tool/foo.ts @@ -1,6 +1,6 @@ -import z from "zod/v4" +import { tool } from "@opencode-ai/plugin" -export default { +export default tool((z) => ({ description: "foo tool for fooing", args: { foo: z.string().describe("foo"), @@ -8,4 +8,4 @@ export default { async execute() { return "Hey fuck you!" }, -} +})) diff --git a/packages/web/astro.config.mjs b/packages/web/astro.config.mjs index 02ea4fe1..fb7bd75b 100644 --- a/packages/web/astro.config.mjs +++ b/packages/web/astro.config.mjs @@ -84,6 +84,7 @@ export default defineConfig({ "permissions", "lsp", "mcp-servers", + "custom-tools", ], }, diff --git a/packages/web/src/content/docs/custom-tools.mdx b/packages/web/src/content/docs/custom-tools.mdx new file mode 100644 index 00000000..e67fe533 --- /dev/null +++ b/packages/web/src/content/docs/custom-tools.mdx @@ -0,0 +1,105 @@ +--- +title: Custom tools +description: Create custom tools to extend opencode capabilities. +--- + +Custom tools are functions you create that the LLM can call during conversations. They work alongside opencode's built-in tools like `read`, `write`, and `bash`. + +--- + +## Tool structure + +The easiest way to create tools is using the `tool()` helper which provides type safety and validation: + +```ts title=".opencode/tool/database.ts" +import { tool } from "@opencode-ai/plugin" + +export default tool((z) => ({ + description: "Query the project database", + args: { + query: z.string().describe("SQL query to execute"), + }, + async execute(args) { + // Your database logic here + return `Executed query: ${args.query}` + }, +})) +``` + +You can also import Zod directly and return a plain object: + +```ts +import z from "zod/v4" + +export default { + description: "Tool description", + args: { + param: z.string().describe("Parameter description"), + }, + async execute(args, context) { + // Tool implementation + return "result" + }, +} +``` + +The filename becomes the tool name. This creates a `database` tool. + +--- + +## Arguments + +Use the `z` parameter to define tool arguments with validation and descriptions: + +```ts title=".opencode/tool/calculator.ts" +import { tool } from "@opencode-ai/plugin" + +export default tool((z) => ({ + description: "Perform mathematical calculations", + args: { + expression: z.string().describe("Mathematical expression to evaluate"), + precision: z.number().optional().describe("Decimal precision"), + }, + async execute(args) { + // Your calculation logic here + return `Result: ${eval(args.expression).toFixed(args.precision || 2)}` + }, +})) +``` + +--- + +## Context + +Tools receive context about the current session: + +```ts title=".opencode/tool/project.ts" +import { tool } from "@opencode-ai/plugin" + +export default tool((z) => ({ + description: "Get project information", + args: {}, + async execute(args, context) { + // Access context information + const { project, directory, worktree } = context + return `Project: ${project.name}, Directory: ${directory}` + }, +})) +``` + +--- + +## Tool locations + +Custom tools are loaded from: + +- Project: `.opencode/tool/` +- Global: `~/.config/opencode/tool/` + +Files must use `.js` or `.ts` extensions. + +--- + +## Built-in tools + +opencode includes several built-in tools: `read`, `write`, `edit`, `bash`, `glob`, `grep`, `list`, `patch`, `todo`, and `task`. [Learn more](/docs/tui#tools).