Step-by-step diagnostics for the most common problems. If none of these
help, open a bug report using the template under
.github/ISSUE_TEMPLATE/bug_report.md
and attach the relevant log snippet from the Logs section below.
The plugin locates claude via ClaudeBinaryLocator, which checks, in order:
- The path configured in Settings ▸ Claude Code ▸ claude executable path, if set. A configured path that has gone stale does not fail hard — detection continues.
- The system
PATHof the IDE process. - The usual install directories:
~/.local/bin,~/.claude/local,/usr/local/bin,/opt/homebrew/bin,/usr/bin— and on Windows%APPDATA%\npm,%LOCALAPPDATA%\Programs\claude, scoop, volta and chocolatey shims.
Fixes:
- The chat's own card will install it for you, using the official route for your OS. Detection re-runs every few seconds while no session is running, so installing it in a terminal also takes effect without closing the tab.
- Confirm in a terminal:
which claude(Linux/macOS),where claude(Windows). The path that prints should also be reachable by the IDE. - On macOS / Linux, GUI IDEs do not always inherit the shell's
PATH. Either add the directory to the system-wide path or set the explicit binary path in Settings. - On Windows, prefer the native
claude.exe. The extensionless npm shim is a bash script andCreateProcessrejects it outright ("%1 is not a valid Win32 application"); the plugin therefore triesclaude.exe, thenclaude.cmd, thenclaude.bat. - If you use a custom env script (Settings → "Source script before spawn"),
make sure it really exports
PATHin a way the plugin can read.
The plugin will not start a session without a credential it holds itself, so this is rarely auth any more — but when it is, the tab shows the sign-in card rather than failing a turn. Sign in from there.
If ANTHROPIC_API_KEY is set in your environment but the value is wrong, the
binary will fail regardless. Note also that an API key must be approved once
before the binary will use it; typing it into the sign-in card is that
approval, and the key is validated before being stored — which is why a key that
"looks invalid" when exported by hand works when entered through the card.
Fixed in 5.0.1 — upgrade if you are below it.
The credential was persisting correctly all along; what expired was the access
token inside it, which auth login issues with a life of about ten hours. Any
restart the next day found a perfectly good blob that authenticated nothing, and
"no usable token" was read as "signed out". The blob always carried a refresh
token good for weeks, but spending it means the binary rewriting
~/.claude/.credentials.json — the file the plugin exists to remove.
The plugin now renews it through the binary's own non-interactive branch (no browser, no terminal), takes custody of the result, and the refresh token rotates each time, so ordinary use extends it indefinitely. A failed renewal arms a five-minute cooldown rather than retrying every poll.
If it still happens on 5.0.1 or later, the renewal itself is failing — check
idea.log for CredentialsVault around IDE startup, and confirm the machine had
network at that moment.
Since 5.5.0 the settings live in the IDE's PasswordSafe, not in a file.
The old .idea/claude-code.xml is read once, copied into the safe, and deleted
only after the safe has accepted the copy. Two things follow:
- Settings are kept per IDE installation, per project since 5.7.0. The safe is application-wide, but each entry is keyed by the IDE's configuration directory and the project, so two IDEs — or two checkouts — do not share a document. The single global document that 5.5.0–5.7.0 wrote is still read as the seed for a project that has none of its own, which is why it is never deleted.
- If the safe cannot be read, the plugin refuses to save over it rather than treating a failed read as an empty configuration. On Linux that usually means a locked KWallet/keyring — unlock it and restart the IDE. A read that failed once, followed by a save, is exactly how a configuration gets lost, and that is the case being refused.
Deleting the old file by hand before it has been migrated loses the settings; there is no other copy.
Most of these are the intended behaviour, so it is worth knowing which is which.
- A finished task keeps its row, its tab and its output. That is deliberate.
The binary's
background_tasks_changedis a level signal — it lists what is live right now — so rendering it directly made a task's output vanish at the exact moment there was something to read. The plugin keeps its own record and uses the level only for liveness. - An agent shown as running belongs to a turn that is still running. A nested subagent has no tool call of its own to settle it, so it inherits its parent's ending; it cannot outlive the turn that spawned it.
- Agents restored from a previous run are judged by their transcripts. The plugin cannot know how a past agent ended, so it reads the last record of the agent's own transcript: a finished assistant turn is completed, anything else is stopped. It does not paint them all red, and does not paint them all green.
- Agents you started from a terminal never appear, even in the same session.
An agent is shown only if this plugin saw the
Taskcall, or recorded it previously in its agent index, or its parent is already shown. That index lives in the IDE's safe, per project; Restore Plugin to default state clears it, and past agents then disappear from restored chats. - A backgrounded task with no output is showing you the truth: a backgrounded shell command publishes no output file, so what is displayed is what the binary actually reported. A backgrounded agent does publish one, and it is tailed live and replayed from the session transcript after a restart.
By default the plugin reopens the previously active chat tabs by calling
claude --resume <session-id>.
- If the binary cannot find the session file under
~/.claude/projects/<cwd-encoded>/<sessionId>.jsonl, the tab opens empty. - Disable the behaviour: Settings ▸ Claude Code → Restore open chats on startup → off.
- Open a specific older session via the chat tab menu → Open Previous Session….
When permission mode is bypassPermissions or acceptEdits, tools are
auto-approved and the inline Accept / Reject card is suppressed by design.
Switch to default or plan from the mode chip in the composer to see
the card again.
The reverse also happens and is not a bug: a card appears even in
bypassPermissions when the call touches credential material, a dangerous
command or foreign territory. That check runs before any auto-approval, and no
permission mode and no Always allow tool can answer it. The per-rule toggles
under Settings ▸ Claude Code Security only downgrade an automatic refusal to a
card, never to a silent allow.
Three things do let a watched call through, all of them switched by hand: the shield in the composer (or the master switch on that page), which stops the guard evaluating anything for a chosen duration; a whitelisted command; and Always allow on the card itself, which lasts for that chat until the IDE closes. If a call you expected to be stopped went through, the shield is the first thing to look at — it is unlit whenever the guard is off.
If the card is missing in default mode, check the IDE log
(see Logs) for entries from PermissionBroker — a hung control
request will be visible as a 30s watchdog warning.
Diffs opened for review are real editor tabs, not modal dialogs, so they remain until you close them. Close them the way you close any editor tab — the standard close shortcut, or right-click ▸ Close All Tabs. The plugin also closes the ones it opened when the session that opened them goes away.
The whole chat UI is the IDE's embedded browser (JCEF), so without it there is nothing to show.
- Below build
253.29346.138(IDEA 2025.3.1): this plugin does not run there at all, and that includes the first 2025.3 (253.28294.334) as well as 2025.1 and 2025.2. The platform serves the browser classes through a module id (com.intellij.modules.jcef) that a plugin must declare a dependency on, and that id does not exist in any of those builds — so the dependency is mandatory where it can be satisfied and unsatisfiable before it. Update the IDE, or stay on 5.1.1 on those versions. Your build number is in Help ▸ About. - On
253.29346.138or newer: check that the IDE's embedded browser is available — Help ▸ Find Action ▸ Registry, keyide.browser.jcef.enabled. Some stripped or remote-development setups ship without it. - The stack trace names
JcefHost.<init>; anything else with the same symptom belongs in an issue, with the log.
⚙ ▸ Git Operations ▸ Branches — or any other popup the IDE owns — appears and then discards every click, while the keyboard still drives it.
This is not the plugin, and there is nothing in it to change. The intuition it invites is that a tool window made of an embedded browser has captured the pointer, and three separate facts have to be false for that to be possible:
- The chat's browser runs off-screen (
JBCefOsrComponent), so it is a Swing component painted by Java2D. It owns no native surface for a popup to be attached to, or for a compositor to hand a pointer grab to. - A Wayland popup's parent is resolved structurally, not from focus:
WLComponentPeer.getToplevelForwalks the AWT container chain and returns the firstWindowthat is not itself a popup, andAbstractPopup.showforcesSwingUtilities.getRoot(owner)on Wayland. A child component can never be the answer, so the parent is the project frame however the browser is rendered. - The plugin installs no global
AWTEventListenerand noIdeEventQueuedispatcher, so it cannot consume a click addressed to something else.
Moving focus out of the chat before invoking the action therefore changes
nothing. The one thing that does change a popup's owner is undocking the
tool window: AbstractPopup.getTargetWindow returns a FloatingDecorator
early, so a floating tool window — not the project frame — becomes the popup's
parent toplevel. Dock it back if it is floating.
What to do, in order:
-
Open the chat's Git button and press Branches there. It is the same platform action (
Git.Branches; the gear menu and the Git view read one catalogue, so they cannot offer different things), invoked with no menu popup to unwind first. If it works here and not from the gear, the compositor is mishandling the gear's popup chain and this button is the standing way round it. -
If it fails there too, the popup path is broken for the whole IDE rather than for this plugin, and the way out is to leave the native Wayland toolkit: Help ▸ Edit Custom VM Options…, add
-Dawt.toolkit.name=XToolkitand restart. Since 2026.1 the launcher passes
-Dawt.toolkit.name=auto, which selectssun.awt.wl.WLToolkitwhenever the session is Wayland; the line above pins the X11 toolkit and the IDE runs under XWayland. What it costs is crisp fractional scaling — nothing at an integer scale factor. Confirm which toolkit is live inidea.log: the startup banner printstoolkit: sun.awt.wl.WLToolkitortoolkit: sun.awt.X11.XToolkit.
Upstream. No JetBrains ticket matches this symptom exactly, so there is no number to quote as the bug. The open meta issues for it are JBR-563 and IJPL-55086 ("mouse clicks are blocked" on Linux). The nearest exact precedent, IDEA-353169 — KDE Plasma 6 on Wayland, clicks on toolbars, dialogs and popups ignored while the editor and the keyboard stayed fine — was closed Third Party Problem when a plugin's global AWT listener turned out to be eating the events, so disabling third-party plugins is worth doing before filing anything. Native Wayland support itself is tracked under JBR-3206.
- Make sure the plugin is enabled: Settings → Plugins → Installed → Claude Code Native → enabled.
- View → Tool Windows → Claude Code.
- If the menu entry is missing, the plugin failed to load — check the log for a stack trace at startup.
- The JetBrains MCP server toggle requires the MCP Server plugin from JetBrains to be installed and enabled.
- For
stdiotransport the plugin synthesizes a command line from the running IDE'smcpserverlib. If you launched the IDE from a stripped install, that lib may be missing — switch tosseorstreamable-http. - Custom MCP entries must be valid JSON keyed by server name. Invalid JSON blocks saving the settings and is logged.
The quickest route to a report is the Log view in the chat's view row,
next to Guard and Vulnerabilities: the plugin's own entries, filtered by
level, with a Copy button that puts a report-ready text on the clipboard
(plugin, IDE, OS and binary versions in the header) and a Debug switch that
turns the trace on for the current IDE session. Credentials, sk-ant-… keys
and your home directory are redacted before a line is stored, and prompt text
is never logged. Paths outside the project are kept — which binary ran, which
file the guard refused — because a report needs them, so read the copied
text once before publishing it.
The same lines go to the IDE's single rolling log file, idea.log. Every
entry is written under the category of the class that wrote it,
#dev.lain.claudejb.<package>.<Class> — controller.process.ClaudeProcess
for the binary's lifecycle and stderr, controller.session.guard.SessionGuard
for the guard's verdicts, view.jcef.JcefHost for the chat page's own
console — so
claudejb matches all of them. Three levels, one meaning each: WARN is
something that went wrong, INFO a lifecycle step, DEBUG the trace, which
is off unless switched on.
To trace before the plugin loads, or across restarts, use Help ▸ Diagnostic
Tools ▸ Debug Log Settings and add #dev.lain.claudejb (a full class
category narrows it). A sandbox IDE started with ./gradlew runIde traces
from the start.
Log file locations:
- Linux:
~/.local/share/JetBrains/IntelliJIdea*/log/idea.log - Windows:
%LOCALAPPDATA%\JetBrains\IntelliJIdea*\log\idea.log - macOS:
~/Library/Logs/JetBrains/IntelliJIdea*/idea.log
(Replace IntelliJIdea* with your product — PyCharm*, GoLand*,
WebStorm*, etc.)
Quick way to extract a relevant snippet on Linux/macOS:
grep -nE 'claudejb|ClaudeSession|ClaudeProcess|PermissionBroker' \
~/.local/share/JetBrains/IntelliJIdea*/log/idea.log | tail -n 200On Windows PowerShell:
Select-String -Pattern 'claudejb|ClaudeSession|ClaudeProcess|PermissionBroker' `
-Path "$env:LOCALAPPDATA\JetBrains\IntelliJIdea*\log\idea.log" |
Select-Object -Last 200Redact any path under /home/<you>/ or C:\Users\<you>\ that you do not
want public before attaching to a bug report.