Skip to content

tools: built-in shell tool advertised to the model as "shell_client", but runtime only executes "shell" #56193

Closed as not planned

Description

@JustSEMI

Description

On OpenCode v2.0.31 (Windows), sessions with certain models (served through a custom
OpenAI-compatible provider) receive an agent-facing tool catalog / system instructions that:

  • list a tool named shell_client (description: "Commands run on Windows using powershell"), and
  • mark the built-in shell tool as "a placeholder that does nothing — do not call it".

At runtime the opposite is true. Verified empirically in the same session:

  • calling shell_client is always rejected:
    {"error":{"type":"tool.execution","message":"No tool named \"shell_client\" is currently available. Please use a tool from the available tool list."}}
  • calling shell executes normally on the same host (PowerShell), including workdir/timeout params.

Impact: any session where the model follows the presented catalog cannot run terminal commands
at all — lint, test, build, and git are fully blocked for the whole project.

Ruled out as the source:

  • user config / plugins: none configured at reproduction time
  • MCP server: connected and working (37 tools, none named shell_client)
  • provider/relay side: the relay only proxies the completion stream; the tool list and tool
    execution are generated host-side by OpenCode
  • opencode.log shows no registration event for the name shell_client

Plugins

No response

OpenCode version

2.0.31

Steps to reproduce

  1. Observe the tool list presented to the model: shell_client is listed as a runnable tool, while
    shell is marked "a placeholder that does nothing — do not call it".
  2. Ask the model to run any terminal command e.g. "run git status".
  3. The model calls shell_client → hard-failed with
    "No tool named "shell_client" is currently available. Please use a tool from the available tool list."
  4. Calling shell with the identical arguments succeeds on the same host.
  5. Reproducible consistently every session with the affected models.

Screenshot and/or share link

No response

Operating System

Windows 11

Terminal

Windows Terminal

Activity

  1. opencode-agent commented on Oct 16, 2026

    @opencode-agent
    Contributor

    Thanks for the detailed report, @JustSEMI.

    I checked the OpenCode source for v2.0.31 and the current dev branch. Neither the name shell_client nor the text "a placeholder that does nothing — do not call it" appears anywhere in it. OpenCode registers only one shell tool, shell, and gives it the description "Commands run on Windows using powershell". So it looks like something between OpenCode and the model copied the real shell tool under the name shell_client and told the model that shell is a placeholder. The No tool named "shell_client" error is then expected, because OpenCode never registered that tool. Some relays and proxies rename client tools that clash with their own built-in tools this way.

    To confirm where the rename happens, could you share:

    1. Your provider config from opencode.json: the npm package, baseURL, and which relay software or service it points to. Please remove API keys.
    2. Which models are affected and which are not, with their exact model IDs.
    3. The tool list OpenCode actually sends, if you can capture it. For example, log the raw request body at the relay, or check whether the relay has a request log. Does the outgoing request contain shell or shell_client?
    4. Whether it still happens when you use the same model through its original provider directly, without the relay, if that's possible.

    You can reply here with the details or edit the issue. If you edit it, please also leave a comment saying you've updated it, so we know when you're done.

    Related, though probably a different problem:

  2. JustSEMI commented on Oct 16, 2026

    @JustSEMI
    Author

    Root cause found — this is not an OpenCode bug. Closing as not planned.

    The renaming layer between OpenCode and the model is 9Router, tracked upstream:
    decolua/9router#4971 ("fingerprint pass renames the caller's shell to shell_client
    and leaks a placeholder note, because the captured definition is Linux-only"),
    fix in decolua/9router#4972.

    What happens on the 9Router path:

    • Its fingerprint pass treats a caller tool as "conflicting" whenever the tool's
      description text differs from a frozen, Linux-captured definition (=== /
      JSON.stringify comparison of a ~533-char description).
    • It then renames shell → shell_client (alias restored on the response side),
      appends a placeholder shell tool, and injects
      "Do not call the shell tool; it is a placeholder that does nothing..." into
      the system prompt.
    • OpenCode of course only registers shell, so every shell_client call bounces
      with the No tool named "shell_client" error from this report.
    • Windows angle (per fix: improve code quality, type safety, and documentation #4971): the frozen description says "Commands run on Linux
      using bash." while OpenCode on Windows composes "Commands run on Windows using
      pwsh." — a 2-character difference inside the description is enough to trigger
      the rename for every Windows client.

    Answers to the triage questions:

    1. Provider config: @ai-sdk/openai-compatible, baseURL
      (a personal OpenAI-compatible relay), with 9Router in the serving chain.
    2. Affected: glm-5.3-flash; the rename happens per-request regardless of model,
      on Windows clients.
    3. Outgoing request from OpenCode contains shell; the rename happens after
      capture inside 9Router, so it never appears in OpenCode's own logs.
    4. Untested without the relay — moot given the upstream repro in fix: improve code quality, type safety, and documentation #4971 (works by
      POSTing to /v1/chat/completions directly, no client involved).

    Local workarounds while the 9Router fix ships:

    • a small plugin registering shell_client as a real tool (bridge), or
    • a global AGENTS.md instructing the model to call shell — with that, the model
      self-corrects after the first failed attempt.

    Thanks for the fast triage — the bot's guess ("some relays and proxies rename
    client tools that clash with their own built-in tools this way") turned out to be
    exactly right.

  3. opencode-agent commented on Oct 16, 2026

    @opencode-agent
    Contributor

    Thanks for tracking this down, @JustSEMI, and for writing up the details.

    That matches what's in OpenCode: shell is the only shell tool it registers, and the description changes with the platform ("Commands run on Windows using …"). That's why a check comparing against a saved Linux description renames the tool for every Windows client. The No tool named "shell_client" error is OpenCode correctly rejecting a name it never registered.

    The fix belongs in 9Router (decolua/9router#4971, fix in decolua/9router#4972). Until it ships, your workarounds should do: a small plugin that registers shell_client and forwards it to shell, or an AGENTS.md note telling the model to call shell. Closing this as not planned on the OpenCode side makes sense.

  4. opencode-agent commented on Oct 19, 2026

    @opencode-agent
    Contributor

    Closing this as not planned. As @JustSEMI found, the shell → shell_client rename and the "placeholder" note come from 9Router, not from OpenCode. 9Router renames OpenCode's shell tool for Windows clients because its description doesn't match 9Router's saved Linux copy. The fix belongs upstream in decolua/9router#4971 (fix in decolua/9router#4972).

    Until it ships, you can register a small plugin that adds shell_client and forwards calls to shell, or add an AGENTS.md note telling the model to call shell. If it still happens without 9Router in the chain, please open a new issue with the details. Thanks again for the thorough investigation!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions