anomalyco / anomalyco/opencode

codemode: tool discovery helper documented three ways; only bare search(input) works on 1.18.21 — README's 'never fails' claim is false

Open
#45,521 2 comments 0 reactions 1 assignee View on GitHub

@jlongster is already working on this.

Since Aug 27, 2026.

Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

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):

  1. Start a session with Code Mode active and a partial inline catalog.
  2. In one execute() sandbox, run tools.$codemode.search({ query: "jira", limit: 2 })
    — the README's documented form.
    Unknown tool '$codemode.search'.
  3. In another sandbox, run Object.keys(tools) → lists the 6 MCP namespaces with
    no $codemode namespace present, confirming it is not registered there at all.
  4. 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

  1. One canonical invocation form should hold everywhere: scaffold, README, and the
    Workflow/Rules guidance baked into every execute() description.
  2. The UnknownTool suggestions for these paths should point at whichever form is
    real (e.g. "use bare search({ query })"), instead of failing circularly —
    notably, upstream tool-runtime.ts already attaches helpful suggestions to
    UnknownTool errors; this build surfaced none for either failed form.
  3. 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 tools section whose
    entries are all tools.*.
  • The codemode README (and current dev/v2 source in tool-runtime.ts) document the
    same helper as tools.$codemode.search(...), always registered under a reserved
    namespace, and Object.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:

  • #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.
  • #41389 — catalog-listed MCP tools failing when invoked outside execute. This
    report concerns the discovery helper itself, inside execute.

Additional Context

Suggested fix directions (any one suffices):

  1. Register the discovery tool in both places inside the sandbox (alias bare
    searchtools.$codemode.search), so all three documented forms work.
  2. Version-scope/correct the README's "never fails as an unknown tool" claim, or
    restore registration under $codemode.
  3. 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.*.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.