Skip to content

Start from the symptom

Four checks answer almost everything, then a table keyed on the first thing you see.

Four checks answer almost everything. Run them in this order, and stop as soon as one of them explains what you are seeing.

Check What it tells you
/claude-code-doctor in the session The plugin version actually loaded, the claude path and version, which providers and accounts registered, proxyTools, the permissionPreset per provider and what it replaced, the working directory and which rule picked it, every live claude child, and every pending proxy call. No model is called and nothing is billed. Start here.
/claude-code-doctor bundle in the session The same report plus this process’s recent NOTICE/WARN/ERROR log lines, redacted by allowlist so you can paste the lot into a public issue. This is what to attach to a bug report. See Filing an issue.
OPENCODE_CLAUDE_CODE_LOG_FILE=1 opencode, then grep ~/.local/share/opencode-claude-code/plugin.log Whether the plugin loaded at all, and every warning it emitted. The log file is off by default, so turning it on needs a relaunch. The raw log is not safe to attach to an issue: it has no redaction guarantee and can hold whole system prompts. Use /claude-code-doctor bundle for that.
claude --version Whether a version-gated feature can work at all. Version floors: 2.1.142 thinking summaries, 2.1.220 fast mode, 2.1.258 /btw and --restricted, 2.1.263 --permission-prompts none, 2.1.280 claude-opus-5-5.
claude auth status, or CLAUDE_CONFIG_DIR=~/.claude-<name> claude auth status Which account is signed in, and whether its login is still valid.

Start from the symptom

What you see first The one check The fix
No claude-code provider or model in the picker at all Is there a plugin ready line in the log? None means the plugin never loaded, an older version means the package cache. See Nothing in the picker.
Model unavailable for a model id you typed The providers field of the ready block, or the same line in /claude-code-doctor Use the provider id that line actually lists. With no accounts configured on opencode 2 the id is claude-code, so claude-code-default/<model> fails while the plugin is perfectly healthy (measured on opencode 2.0.16, 2026-09-27). Declaring accounts is what creates claude-code-default.
400 Third-party apps now draw from your extra usage… /claude-code-doctor for the account the conversation is on, then claude auth status for its plan An account-level usage gate, not a plugin fault: extra usage is off, or the window is exhausted. Wait for the reset, or move to another configured account. This is one of the two error texts that open the account failover form, so with several accounts you get the form instead of the error. Enabling paid usage or changing authentication is a billing decision and nothing here makes it for you.
Tool result name changed, and the turn aborts, on opencode 2 The plugin version in /claude-code-doctor Fixed in 0.28.1: a CLI-executed tool’s result used to reach opencode under a different name than its call, and opencode 2.0.16 aborts the turn on that mismatch, which broke every Claude-side MCP server call. Upgrade, then fully quit and relaunch every opencode window: plugin code is read once at process start, so a new package in a running window changes nothing.
A Claude Code hook you configured has no effect, and Claude never mentions it The Hooks Claude Code ran that failed section of /claude-code-doctor The hook exited non-zero, so Claude Code discarded its contribution and answered the turn anyway. The section gives the exit code and the hook’s stderr. Fix or remove it in your own Claude Code settings; only SessionStart and Setup hooks are visible here, because the plugin does not pass --include-hook-events.
plugin ready is missing from the log That the log file is actually on, since it is off by default If it is on and the line is still absent, the plugin never loaded. Check the package is in plugin (1.x) or plugins (2.x), that a local checkout points at dist/ on 2.x, and that you relaunched rather than opened a new session. /claude-code-doctor answers the same questions without enabling logging.
Failed to authenticate: OAuth session expired, one account, every turn failing in milliseconds CLAUDE_CONFIG_DIR=~/.claude-<name> claude auth status for that account Log it in again. The plugin writes a ▌ **claude account:** note naming the account and the exact command, for example CLAUDE_CONFIG_DIR=~/.claude-work claude auth login, and offers the switch form when another account exists. Restart opencode afterwards: a switch made from that form lasts until opencode restarts.
A tool call reported as rejected although it really ran The plugin version in /claude-code-doctor Upgrade to 0.26.2 or newer. Two separate causes, both fixed: opencode 1.18.32 aborts the provider signal of every step that ends in tool calls and the plugin read that as you pressing stop (0.26.1), and a call waiting on an unanswered permission prompt was rejected at the flat 10-minute deadline, after which your late approval cancelled Claude’s next call (0.26.2). A deadline now waits while opencode reports the session busy, so an unanswered prompt is never a reason to raise proxyToolTimeoutMs.
proxy call still waiting in the log, or a task that looks stuck /claude-code-doctor, which lists every pending call with its tool, age and deadline Usually nothing is wrong. See A proxy call that will not finish.
⚙ invalid or ⚙ unknown tool rows Which tool name the row carries ⚙ invalid todowrite inside a subagent means that agent has no permission.todowrite: "allow"; see Subagent todos. Any other name is a Claude tool this plugin version does not map for your CLI version: record the plugin version, the CLI version and the tool name, and report it. A permanently pending ⚙ unknown row is the same problem in its older shape, an input delta for a call opencode never saw start.
A -fast model clearly ran at ordinary speed Grep plugin.log for fast mode Fast mode fails soft, so the plugin warns once per reason and names it; the CLI reports fast_mode_state: "off". The usual cause is that usage credits are off (/usage-credits in an interactive claude). Also: a CLI below 2.1.220, a cooldown after a fast-mode rate limit, free tier or an organization that disabled it, CLAUDE_CODE_DISABLE_FAST_MODE=1, or a non-first-party route, since Bedrock, Vertex and Foundry are excluded. Until it is fixed, switch to the non-fast id so the picker’s price matches your bill.
An MCP server’s tools are simply absent The WARN the plugin logs once per process at session start for each server Claude Code could not connect Authenticate or repair that server where it is configured. mcpServers in the ready block is on-disk discovery, so a server can be listed there and still be unreachable.
A freshly published version does not appear The plugin version in /claude-code-doctor against the version you expect Remove the frozen cache entry and relaunch: see Nothing in the picker. If npm itself does not list the version, a local security scanner with a minimum-package-age policy can be filtering it out of the reply, so read that tool’s event log before blaming the registry.
permissionPreset is set but nothing about the session looks restricted The permissionPreset row in /claude-code-doctor, for the provider the conversation is actually on none there means the option never reached this provider: it belongs under provider.<id>.options, and with accounts configured each account is its own provider id. readonly (unknown, nothing applied) means the name is not one the plugin knows, so nothing was applied at all; the only name today is read-only. When it did apply, the Permission preset overrides block names every option it replaced.
permissionPreset: "read-only" is set, but reads are not confined or something still prompts claude --version The preset holds on any CLI, but two of its four layers are version-gated: --restricted needs 2.1.258 and --permission-prompts none needs 2.1.263. Below those it falls back to --disallowedTools plus the plugin’s own denial of every permission request, and warns naming what is missing. Below 2.1.258 you lose the working-directory confinement on reads; below 2.1.263 the denial happens in the plugin instead of in the CLI, one layer instead of two. See Read-only mode.
A reply that is only “There’s an issue with the selected model (…). It may not exist or you may not have access to it.” Whether that model id is in the picker, and claude -p --model <id> "hi" The CLI refused the model: it is retired, misspelled, or this account cannot use it. The result’s subtype is success, so without a chain the turn finishes as an ordinary reply with that sentence as the answer. Fix the id in the agent’s forceModel or in your picker, or declare a fallback model chain so the turn degrades to the next model instead of dying.
▌ **model fallback:** on a turn you expected to run on a specific model The note itself, which names the model that failed and why Working as configured: your fallbackModels chain moved the turn. model_not_found means fix the first id. out of usage on this account means that account’s cap, and the reason you got a chain rather than the account failover form is that no other account was available to offer. The chain never changes account, only model.
A chain is declared but a refused model still kills the turn Grep plugin.log for fallback model refused: unknown model Every entry has to be a model id this plugin registers; an unknown one is skipped with that warning, and a chain whose entries are all unknown is an empty chain. The other empty-chain case is a list containing only the model the turn already runs on, which is dropped from its own chain. Compaction turns, title stubs and the interactive transport never fall back at all.
A config change did nothing /claude-code-doctor, which reports the options in force Provider options are read once at opencode startup. Quit every opencode window, serve and GUI processes included, and relaunch. A /new session is not enough.
A question form never renders and the turn hangs GET /question on the same opencode server and workspace See A question form never renders.

Free and MIT-licensed. If the plugin saves you time, you can buy its maintainer a coffee.

Buy me a coffee