An agent thread on a non-Claude provider loads a skill written for the Claude desktop app. The skill names tools like mcp__Claude_Browser__* and a ToolSearch loading step that do not exist in that thread's catalog. Two things go wrong from there. The agent burns the start of the task searching for tools that were never going to be there, and when it does reach for the local equivalent it invents a hybrid - tool names stitched together from both products' vocabularies - and calls none of them. On a UI task it can also take the skill's wrong-nature guidance at face value and tell you the built-in browser is offline instead of retrying.
Filed as t3code#19978.
Why it happens
Skill discovery is global. OpenCode registers ~/.claude/skills as a skill source and scans it for every provider, so a skill meant for one harness is offered to all of them. Nothing checks whether the tool surface a skill references exists in the thread that loaded it. The symptom looks like model confusion but it is a discovery scoping problem.
What to do
Deny the offending skills per provider so they never reach threads where their tools are missing:
{
"permission": {
"skill": {
"built-in-browser": "deny",
"chrome-browser": "deny",
"computer-use": "deny"
}
}
}
That is in opencode.json. Swap the names for whatever skills reference a tool surface your harness does not have.
The broader fix is scoping skill injection to the provider - a skill whose referenced tools are absent should not be advertised at all. That is an upstream design question rather than something you can configure away today, so the deny list is the lever you have. If you write skills yourself, this is the argument for naming the tools a skill needs up front, so a host can filter on them instead of guessing.