Repository navigation
Description
Summary
Three opencode surfaces describe the Code Mode tool-discovery helper with three
different invocation forms, and on opencode 1.18.21 only one of them works:
| Surface | Form shown | Works on 1.18.21? |
|---|---|---|
Generated execute() scaffold ("## Search" section) |
search(input: {...}) — bare global |
✅ yes (verified) |
packages/codemode/README.md + generated "## Workflow"/"## Rules" text |
tools.$codemode.search({...}) |
❌ no — Unknown tool '$codemode.search'. |
What a model infers from the catalog's own path convention (tools.<ns>.<tool>) |
tools.search({...}) |
❌ no — Unknown tool 'search'. |
Impact: models following either of the two documented namespaced forms hit a hard
UnknownTool failure with no actionable suggestion, and can misdiagnose the
scaffolding as broken rather than mis-invoked.
The README also states the search tool is "always registered … so a speculative
tools.$codemode.search call never fails as an unknown tool" — that claim is
false on this build (reproduction below).
Environment
- opencode version: 1.18.21 (Homebrew, release)
- OS: Darwin 27.0.0 arm64 (macOS)
- Terminal: iTerm.app (xterm-256color, truecolor)
- Shell: /bin/zsh
- Install/channel: release
- Active plugins: @dietrichgebert/ponytail, @ljw1004/opencode-trace
Reproduction
Deterministic within a single session; each form was tested in its own execute()
sandbox against the same partial catalog (~91 tools across 6 namespaces):
- Start a session with Code Mode active and a partial inline catalog.
- In one
execute()sandbox, runtools.$codemode.search({ query: "jira", limit: 2 })
— the README's documented form.
→Unknown tool '$codemode.search'. - In another sandbox, run
Object.keys(tools)→ lists the 6 MCP namespaces with
no$codemodenamespace present, confirming it is not registered there at all. - In another sandbox, run bare
search({ query: "jira add comment", limit: 2 })
→ succeeds immediately, returning exact catalog paths such as
tools["mcp-atlassian-jira"].jira_add_comment.
Similarly tools.search({ query }) → Unknown tool 'search'.
Expected Behavior
- One canonical invocation form should hold everywhere: scaffold, README, and the
Workflow/Rules guidance baked into everyexecute()description. - The
UnknownToolsuggestions for these paths should point at whichever form is
real (e.g."use bare search({ query })"), instead of failing circularly —
notably, upstreamtool-runtime.tsalready attaches helpful suggestions to
UnknownTool errors; this build surfaced none for either failed form. - If the intended contract is
tools.$codemode.search, then per the README it
should never raise UnknownTool; if the intended contract is a bare global, the
README/workflow text should not advertise$codemode.search, and the "never
fails" sentence needs correcting or version-scoping.
Actual Behavior
- The generated scaffold on 1.18.21 documents discovery as a bare global
search(input: {...}), separate from the## Available toolssection whose
entries are alltools.*. - The codemode README (and current dev/v2 source in
tool-runtime.ts) document the
same helper astools.$codemode.search(...), always registered under a reserved
namespace, andObject.keys(tools)on other builds reportedly includes
$codemode. - On 1.18.21 neither namespaced form resolves, and
Object.keys(tools)shows no
$codemode; only the bare global exists. Any model following the README or the
convention it learned from the catalog fails and gets an unhelpful error.
Related but distinct prior reports:
- codemode: Executor nested tool search fails in TUI #40611 — nested-runtime collision where a separate MCP server's internal
tools.search()resolved against the outer Code Mode catalog (fixed via
codemode: false). This report concerns a single runtime with no second server. - code mode: catalog-listed MCP tools fail with Unknown tool unless invoked via execute #41389 — catalog-listed MCP tools failing when invoked outside
execute. This
report concerns the discovery helper itself, insideexecute.
Additional Context
Suggested fix directions (any one suffices):
- Register the discovery tool in both places inside the sandbox (alias bare
search↔tools.$codemode.search), so all three documented forms work. - Version-scope/correct the README's "never fails as an unknown tool" claim, or
restore registration under$codemode. - Make the two failing paths' UnknownTool suggestions name the working form.
Local mitigation on this machine: a version-stamped instruction block in
~/.config/opencode/AGENTS.md documenting that discovery is a bare global on
1.18.21 and everything else lives under tools.*.
Activity
github-actions commentedon Aug 27, 2026
This issue might be a duplicate of existing issues. Please check:
These issues were closed — if the fix didn't land or regressed in 1.18.21, it may be worth linking this report to those for context.
barrygfox commentedon Aug 27, 2026
Bot Update
Update: I checked #43624, #45349, and #43925. They are useful context, but not duplicates of this report. #45349 and #43925 invoke
tools.search(...)and were closed because the V2-facing API is the bare globalsearch(...). #43624 is the closest match, but its maintainers attributed it to a different/dev implementation.This report remains distinct: on release 1.18.21, the README and generated Workflow/Rules guidance advertise
tools.$codemode.search(...), while the runtime exposes only baresearch(...)and no$codemodenamespace. That release-specific documentation/runtime divergence, plus the unhelpfulUnknownToolresponse, is the issue being reported.neriousy commentedon Oct 19, 2026
In v2, the README and generated Code Mode instructions consistently document the synchronous bare search(...) function inside execute, and the runtime provides that function. The old guidance advertising tools.$codemode.search and promising that namespace always exists has been removed. To get v2:
npm i -g @opencode/cli@latestorcurl -fsSL https://opencode.ai/v2/install | bash(desktop: update the app). If you still see this on v2, please open a new issue with the details.