opencode-tool-search
v0.4.3
Published
Tool search plugin for OpenCode — BM25 and regex search to discover tools on demand, reducing context usage
Maintainers
Readme
opencode-tool-search
An OpenCode plugin that implements Claude's Tool Search Tool pattern. Reduces context usage by deferring tool descriptions and letting the model discover tools on demand via BM25 keyword search or regex matching.
Inspired by famitzsy8/opencode-tool-search-tool (a fork of opencode). This project achieves similar results as a standalone plugin — no core modifications needed.
How it works
- The
tool.definitionhook intercepts every tool before the LLM sees it - Tools not in
alwaysLoadget their descriptions replaced with a short[deferred]stub and parameters stripped - Two search tools (
tool_searchandtool_search_regex) are always available with full descriptions - The system prompt tells the model to use
tool_searchwhen it encounters deferred tools - When the model calls
tool_search("file operations"), it gets back full descriptions and parameter schemas of matching tools
Token savings
| Setup | Total tools | Deferred | Savings per turn | |---|---|---|---| | Built-in only | ~32 | ~24 | ~8,400 tokens (88%) | | 3 MCP servers | ~60 | ~52 | ~17,000 tokens (89%) | | 6+ MCP servers | ~190 | ~182 | ~57,000 tokens (91%) |
Install
npm install opencode-tool-searchAdd to your opencode.jsonc:
{
"plugin": [
["opencode-tool-search", {
"alwaysLoad": ["read", "write", "edit", "bash", "glob", "grep"]
}]
]
}Local development
For local testing with file://:
{
"plugin": [
["file:///path/to/opencode-tool-search/dist/index.js", {
"alwaysLoad": ["read", "write", "edit", "bash", "glob", "grep"]
}]
]
}Configuration
| Option | Type | Default | Description |
|---|---|---|---|
| alwaysLoad | string[] | [] | Tool IDs that keep full descriptions (never deferred) |
| searchLimit | number | 5 | Max results per search query |
| bm25.k1 | number | 0.9 | Term frequency saturation (0.5–2.0) |
| bm25.b | number | 0.4 | Document length normalization (0–1) |
| deferDescription | string | [d] | Custom stub for deferred tools |
BM25 tuning
Defaults are optimized for smaller language models that send vague queries. For capable models writing specific queries, increase k1 toward 1.5.
["opencode-tool-search", {
"alwaysLoad": ["read", "write", "edit", "bash"],
"bm25": { "k1": 1.5, "b": 0.75 },
"searchLimit": 10
}]Search tools
tool_search
BM25 keyword search. Best for natural language queries.
tool_search({ query: "file" }) // → read, write, edit, glob
tool_search({ query: "search code" }) // → grep, ast_grep_search
tool_search({ query: "github issues" }) // → github_list_issues, github_create_issuetool_search_regex
Regex search (case-insensitive). Best for specific patterns.
tool_search_regex({ pattern: "github.*issue" }) // → GitHub issue tools
tool_search_regex({ pattern: "^lsp_" }) // → all LSP tools
tool_search_regex({ pattern: "jenkins|build" }) // → Jenkins/CI toolsHow it differs from the fork
The fork modifies opencode's core to fully hide deferred tools from the LLM's tool list. This plugin uses the official plugin API:
- Tools are still listed (with a
[d]stub description + empty parameters schema) - The
tool.definitionhook strips descriptions; the system prompt guides the model - ~90% of the fork's benefit with zero core changes
- Works with any opencode version that supports
tool.definitionhook (v1.4.10+)
What accounts for the remaining ~10%
Each deferred tool still occupies a slot in the tool list with its name (~5-15 tokens) and minimal stub (~5 tokens). With 180 deferred tools this adds up to ~1,800-3,600 tokens per turn. The fork eliminates these entirely by filtering tools in resolveTools() before they reach the LLM.
Fully closing the gap requires upstream changes to opencode's plugin API — see Scalability.
Scalability
The tool.definition hook can modify tool descriptions and parameters but cannot remove tools from the list entirely. Two upstream proposals would close the remaining gap:
hiddenfield ontool.definitionoutput (opencode#23297) — let plugins suppress tools from the LLM tool list entirelydefer_loadingpassthrough to Anthropic API (opencode#23298) — pass Anthropic's nativedefer_loading: truethrough to the API, enabling server-side tool search with prompt cache preservation
Build
npm install
npm run build # tsc + esbuild bundleLicense
MIT
