claude-code - 💡(How to fix) Fix [BUG] in VS Code/Cursor extension spinnerVerbs read from claudeCode.* workspace config instead of ~/.claude/settings.json effective view (one-line fix in extension.js)

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Error Message

Error Messages/Logs

vscode.workspace.getConfiguration("claudeCode").get("spinnerVerbs") on the undeclared property returns undefined per the VS Code API contract. No exception, no warning, no log. The only logger.error paths around settings ingestion are guarded against IPC/parse failures only: offset 1620024: .catch((R) => this.logger.error(Failed to fetch Claude settings: ${R})) offset 1652088: } catch (O) { this.logger.error(Failed to refresh Claude settings: ${O}) } offset 1651276: } catch (x) { this.logger.error(Failed to parse settings.json: ${x}) } None of these fire for the spinnerVerbs case because the user's JSON is valid and the IPC succeeds — the value just takes the wrong path through the code and lands in undefined. Either resolves the bug; the current state — read path pointed at an undeclared field, no error surface — leaves users with no way to make the setting take effect short of reading the bundled extension source.

Root Cause

Root cause is a wrong-source read in extension.js (verified against extension build 2.1.143, file ~/.cursor/extensions/anthropic.claude-code-2.1.143-darwin-arm64/extension.js):

Fix Action

Fix / Workaround

Initial-render race. cachedClaudeSettings is undefined until M.getSettings() (offset 1619940) resolves asynchronously after the CLI subprocess launches. The first state push at offset 1667447 fires before that, so the webview receives spinnerVerbsConfig: undefined initially and renders default verbs for ~50-500ms until a second pushStateUpdate() lands with the real value. The current broken code is synchronous via getConfiguration().get(), so this is technically a new flicker. Easy mitigation: gate the first state push on the IPC resolving, or initialize cachedClaudeSettings to a deferred sentinel.

Net effect: the spinner shows default verbs for ~50-500ms at session start, then snaps to "Working". Not a correctness bug but a visible flicker. The original code (v1("spinnerVerbs") — a synchronous VS Code config read) didn't have this race; my patched code does. Mitigation: initialize cachedClaudeSettings to a sentinel and gate the first state push on the IPC resolving — or just accept the flicker.

Nothing re-fetches when the user manually edits ~/.claude/settings.json. So the patched code still requires a window reload (Cmd+Shift+P → "Developer: Reload Window") to pick up edits. The current broken code has the same property (VS Code's getConfiguration().get() does auto-refresh, but the property isn't declared so it doesn't matter). Same observed behavior either way; not a regression — but worth noting in the issue so maintainers don't promise "edit and see immediate effect."

Code Example

function v1(z) { return J3.workspace.getConfiguration("claudeCode").get(z); }
// ...
getSpinnerVerbsConfig() { return v1("spinnerVerbs"); }   // ← reads from VS Code workspace config

The extension is reading from vscode.workspace.getConfiguration("claudeCode").get("spinnerVerbs"), not from the parsed ~/.claude/settings.json it already has cached.

Two facts confirm this is a code defect, not an alternate-but-undocumented config location:

claudeCode.spinnerVerbs is not declared in this extension's own package.json (contributes.configuration.properties lists allowDangerouslySkipPermissions, autosave, claudeProcessWrapper, disableLoginPrompt, enableNewConversationShortcut, enableReopenClosedSessionShortcut, environmentVariables, hideOnboarding, initialPermissionMode, preferredLocation, respectGitIgnore, useCtrlEnterToSend, usePythonEnvironment, useTerminal — but no spinnerVerbs). So the VS Code settings UI can't surface it, and the read on an undeclared property returns undefined silently.

The change-listener at offset 2055742 nevertheless references I.affectsConfiguration("claudeCode.spinnerVerbs") — suggesting the property declaration was dropped at some point and the read path was never updated.

Meanwhile, the correct value is already in memory. The state-push at offset 1648793 simultaneously sends:


spinnerVerbsConfig: this.settings.getSpinnerVerbsConfig(),   // ← broken (VS Code config)
claudeSettings:     this.cachedClaudeSettings,                // ← parsed ~/.claude/settings.json
cachedClaudeSettings is the response from the native binary's get_settings IPC RPC, which has shape { effective, sources } — effective is the merged view across user/project/local scopes, sources is the per-scope breakdown. Existing consumers confirm the shape; the only field paths anywhere in extension.js that touch cachedClaudeSettings are cachedClaudeSettings?.effective?.language and cachedClaudeSettings?.effective?.model. So cachedClaudeSettings?.effective?.spinnerVerbs is the correct path — the data is sitting there, just never read.

The webview side is fine. tL0 at webview/index.js offset 4729488 handles mode: "replace" correctly:


function tL0($) {
  if (!$) return nq1;
  if ($.mode === "replace") return $.verbs.length > 0 ? $.verbs : nq1;
  return [...nq1, ...$.verbs];
}
If spinnerVerbsConfig arrived as {mode:"replace", verbs:["Thinking"]}, the webview would correctly render only "Thinking".


Related open reports that this analysis explains: #41585, #41905, #52532, #56453.

Unlike the other open reports, extensive analysis and proposed fix are contained below under additional information.

### What Should Happen?

With ~/.claude/settings.json containing:


{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "spinnerVerbs": { "mode": "replace", "verbs": ["Thinking"] }
}
…the spinner in the VS Code / Cursor extension chat panel should display "Thinking" exclusively, with no rotation through default verbs. This matches the behavior of the terminal claude CLI, which honors the same setting correctly (the bug is scoped to the VS Code extension's spinner-rendering path; the CLI has a separate, working code path).

Proposed fix — one-line change in extension.js:


- getSpinnerVerbsConfig() { return v1("spinnerVerbs"); }
+ getSpinnerVerbsConfig() { return this.cachedClaudeSettings?.effective?.spinnerVerbs; }
And the now-dead listener reference at offset 2055742:


- I.affectsConfiguration("claudeCode.initialPermissionMode") ||
- I.affectsConfiguration("claudeCode.spinnerVerbs")
+ I.affectsConfiguration("claudeCode.initialPermissionMode")
Known caveats the maintainer should consider for a follow-up:

Initial-render race. cachedClaudeSettings is undefined until M.getSettings() (offset 1619940) resolves asynchronously after the CLI subprocess launches. The first state push at offset 1667447 fires before that, so the webview receives spinnerVerbsConfig: undefined initially and renders default verbs for ~50-500ms until a second pushStateUpdate() lands with the real value. The current broken code is synchronous via getConfiguration().get(), so this is technically a new flicker. Easy mitigation: gate the first state push on the IPC resolving, or initialize cachedClaudeSettings to a deferred sentinel.

No hot-reload on manual settings.json edits. Searching the extension for FileSystemWatcher returns zero occurrences, and the four M.getSettings() call sites are: once at CLI channel launch (1619940), once in a "config loading only" bootstrap (1627405), once after the extension itself writes to settings.json via applySettings (1652045), and the RPC definition (1009674). Nothing re-fetches when the user edits ~/.claude/settings.json outside the IDE. Users still need to reload the window to pick up manual edits. The current broken code has the same property; this isn't a regression introduced by the fix, but it's worth fixing in a follow-up (FileSystemWatcher on the user settings path, or an IPC push from the native CLI's existing settings file watcher).

Silent validation strip. If spinnerVerbs is malformed in user settings (wrong type, empty verbs array, mode outside enum), the native CLI's Zod validator likely strips the field with a warning rather than failing the whole file (it does this for permissions.allow/deny/ask). Maintainers should confirm the validation behavior and surface the warning to the user so they don't think the fix is broken when their config is malformed.

### Error Messages/Logs
RAW_BUFFERClick to expand / collapse

Preflight Checklist

  • I have searched existing issues and this hasn't been reported yet
  • This is a single bug report (please file separate reports for different bugs)
  • I am using the latest version of Claude Code

What's Wrong?

spinnerVerbs set in ~/.claude/settings.json is silently ignored by the VS Code / Cursor extension. The spinner continues to cycle the default verb list ("Frolicking", "Pontificating", "Reticulating", …) regardless of the user's configuration.

Root cause is a wrong-source read in extension.js (verified against extension build 2.1.143, file ~/.cursor/extensions/anthropic.claude-code-2.1.143-darwin-arm64/extension.js):

function v1(z) { return J3.workspace.getConfiguration("claudeCode").get(z); }
// ...
getSpinnerVerbsConfig() { return v1("spinnerVerbs"); }   // ← reads from VS Code workspace config

The extension is reading from vscode.workspace.getConfiguration("claudeCode").get("spinnerVerbs"), not from the parsed ~/.claude/settings.json it already has cached.

Two facts confirm this is a code defect, not an alternate-but-undocumented config location:

claudeCode.spinnerVerbs is not declared in this extension's own package.json (contributes.configuration.properties lists allowDangerouslySkipPermissions, autosave, claudeProcessWrapper, disableLoginPrompt, enableNewConversationShortcut, enableReopenClosedSessionShortcut, environmentVariables, hideOnboarding, initialPermissionMode, preferredLocation, respectGitIgnore, useCtrlEnterToSend, usePythonEnvironment, useTerminal — but no spinnerVerbs). So the VS Code settings UI can't surface it, and the read on an undeclared property returns undefined silently.

The change-listener at offset 2055742 nevertheless references I.affectsConfiguration("claudeCode.spinnerVerbs") — suggesting the property declaration was dropped at some point and the read path was never updated.

Meanwhile, the correct value is already in memory. The state-push at offset 1648793 simultaneously sends:


spinnerVerbsConfig: this.settings.getSpinnerVerbsConfig(),   // ← broken (VS Code config)
claudeSettings:     this.cachedClaudeSettings,                // ← parsed ~/.claude/settings.json
cachedClaudeSettings is the response from the native binary's get_settings IPC RPC, which has shape { effective, sources } — effective is the merged view across user/project/local scopes, sources is the per-scope breakdown. Existing consumers confirm the shape; the only field paths anywhere in extension.js that touch cachedClaudeSettings are cachedClaudeSettings?.effective?.language and cachedClaudeSettings?.effective?.model. So cachedClaudeSettings?.effective?.spinnerVerbs is the correct path — the data is sitting there, just never read.

The webview side is fine. tL0 at webview/index.js offset 4729488 handles mode: "replace" correctly:


function tL0($) {
  if (!$) return nq1;
  if ($.mode === "replace") return $.verbs.length > 0 ? $.verbs : nq1;
  return [...nq1, ...$.verbs];
}
If spinnerVerbsConfig arrived as {mode:"replace", verbs:["Thinking"]}, the webview would correctly render only "Thinking".


Related open reports that this analysis explains: #41585, #41905, #52532, #56453.

Unlike the other open reports, extensive analysis and proposed fix are contained below under additional information.

### What Should Happen?

With ~/.claude/settings.json containing:


{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "spinnerVerbs": { "mode": "replace", "verbs": ["Thinking"] }
}
…the spinner in the VS Code / Cursor extension chat panel should display "Thinking" exclusively, with no rotation through default verbs. This matches the behavior of the terminal claude CLI, which honors the same setting correctly (the bug is scoped to the VS Code extension's spinner-rendering path; the CLI has a separate, working code path).

Proposed fix — one-line change in extension.js:


- getSpinnerVerbsConfig() { return v1("spinnerVerbs"); }
+ getSpinnerVerbsConfig() { return this.cachedClaudeSettings?.effective?.spinnerVerbs; }
And the now-dead listener reference at offset 2055742:


- I.affectsConfiguration("claudeCode.initialPermissionMode") ||
- I.affectsConfiguration("claudeCode.spinnerVerbs")
+ I.affectsConfiguration("claudeCode.initialPermissionMode")
Known caveats the maintainer should consider for a follow-up:

Initial-render race. cachedClaudeSettings is undefined until M.getSettings() (offset 1619940) resolves asynchronously after the CLI subprocess launches. The first state push at offset 1667447 fires before that, so the webview receives spinnerVerbsConfig: undefined initially and renders default verbs for ~50-500ms until a second pushStateUpdate() lands with the real value. The current broken code is synchronous via getConfiguration().get(), so this is technically a new flicker. Easy mitigation: gate the first state push on the IPC resolving, or initialize cachedClaudeSettings to a deferred sentinel.

No hot-reload on manual settings.json edits. Searching the extension for FileSystemWatcher returns zero occurrences, and the four M.getSettings() call sites are: once at CLI channel launch (1619940), once in a "config loading only" bootstrap (1627405), once after the extension itself writes to settings.json via applySettings (1652045), and the RPC definition (1009674). Nothing re-fetches when the user edits ~/.claude/settings.json outside the IDE. Users still need to reload the window to pick up manual edits. The current broken code has the same property; this isn't a regression introduced by the fix, but it's worth fixing in a follow-up (FileSystemWatcher on the user settings path, or an IPC push from the native CLI's existing settings file watcher).

Silent validation strip. If spinnerVerbs is malformed in user settings (wrong type, empty verbs array, mode outside enum), the native CLI's Zod validator likely strips the field with a warning rather than failing the whole file (it does this for permissions.allow/deny/ask). Maintainers should confirm the validation behavior and surface the warning to the user so they don't think the fix is broken when their config is malformed.

### Error Messages/Logs

```shell
None. The bug fails silently — that is part of why it has been hard to debug from outside.

What I checked in extension.js (build 2.1.143):

vscode.workspace.getConfiguration("claudeCode").get("spinnerVerbs") on the undeclared property returns undefined per the VS Code API contract. No exception, no warning, no log.
The webview's tL0(undefined) falls through to "return defaults." It treats "no config" and "user explicitly set defaults" identically — no way to distinguish.
The only logger.error paths around settings ingestion are guarded against IPC/parse failures only:
offset 1620024: .catch((R) => this.logger.error(Failed to fetch Claude settings: ${R}))
offset 1652088: } catch (O) { this.logger.error(Failed to refresh Claude settings: ${O}) }
offset 1651276: } catch (x) { this.logger.error(Failed to parse settings.json: ${x}) } None of these fire for the spinnerVerbs case because the user's JSON is valid and the IPC succeeds — the value just takes the wrong path through the code and lands in undefined.
The Zod schema (offset 1488575) declares spinnerVerbs as .optional(), so its absence is by definition valid; there is no "you set this but it isn't being used" check anywhere.
VS Code Output panel → "Claude Code" channel: silent.
VS Code Output panel → "Log (Extension Host)": silent.
Surfaces I checked manually and found clean — nothing to attach.


I proved my config IS being read correctly by the native binary — separate from whether the extension uses it — by running: claude config get spinnerVerbs

That prints { mode: 'replace', verbs: [ Thinking' ] }, the CLI sees the setting; the bug is confirmed to be 100% on the VS Code extension side. Additionally, running Claude Code from terminal picks up the setting and it works only showing "Thinking" when prompted (and leaving my mellow undisturbed).

Here is Claude's further feedback from the terminal instance:
PROMPT: Why would that work when I run claude from terminal but not when I run Claude from within VS Code/Cursor                                                   
 
RESPONSE:   
⏺ spinnerVerbs is CLI-only — it controls the terminal spinner's verb (e.g.,
  "Thinking…"). The VS Code/Cursor extension renders status through its own
  native UI panel and ignores terminal-only settings like spinnerVerbs,
  spinnerTipsEnabled, and tui.

  Settings split:
  - Both surfaces read ~/.claude/settings.json, but the IDE only honors non-UI
  keys (permissions, hooks, MCP, env vars).
  - The extension has its own settings under VS CodeExtensionsClaude Code
  (e.g., claudeCode.useTerminal, claudeCode.initialPermissionMode).

Steps to Reproduce

Install Claude Code VS Code / Cursor extension at version 2.1.143 (latest as of this report). Create ~/.claude/settings.json with:

{ "$schema": "https://json.schemastore.org/claude-code-settings.json", "spinnerVerbs": { "mode": "replace", "verbs": ["Thinking"] } } Reload the IDE window (Cmd+Shift+P → "Developer: Reload Window") so the extension re-reads settings. Send any prompt that triggers the spinner. Observed: Spinner cycles through default verbs ("Frolicking", "Pontificating", "Reticulating", etc.). Expected: Spinner shows "Thinking" exclusively.

Sanity-check the setting is being parsed correctly upstream:

claude config get spinnerVerbs On my machine this returns { mode: 'replace', verbs: [ 'Thinking' ] } — confirming the native CLI sees the setting. The bug is scoped entirely to the VS Code/Cursor extension's spinner-rendering path.

Claude Model

Not sure / Multiple models

Is this a regression?

I don't know

Last Working Version

No response

Claude Code Version

2.1.143 (CLI + VS Code/Cursor extension, same version)

Platform

Other

Operating System

macOS

Terminal/Shell

Cursor

Additional Information

  • OS macOS Darwin 25.5.0 (arm64)
  • Extension path: ~/.cursor/extensions/anthropic.claude-code-2.1.143-darwin-arm64/

Related open reports describing the same symptom — this analysis explains the root cause for all of them:

#41585 (opened 2026-03-31, oldest report, no maintainer response) #41905 (opened 2026-04-01) #52532 (opened 2026-04-23, reports failure even after a full restart — consistent with my analysis, since restart doesn't help when the read path is pointed at an undeclared config field) #53022 (opened 2026-04-24, observes that even when spinnerVerbs is respected, a separate "thinking-mode flavor phrases" path exists that the setting doesn't cover — would need a parallel thinkingVerbs setting or extension of spinnerVerbs semantics) #56453 (opened 2026-05-05)

If the design intent is actually that spinnerVerbs should live in VS Code workspace config under claudeCode.spinnerVerbs rather than in ~/.claude/settings.json — please correct one of two things, because the current state is unrecoverable from the user side:

  1. Update the documented source (https://www.schemastore.org/claude-code-settings.json and https://code.claude.com/docs/en/settings both currently describe ~/.claude/settings.json as the location), AND declare claudeCode.spinnerVerbs in the extension's package.json contributes.configuration.properties so the VS Code settings UI surfaces it; or
  2. Apply the one-line fix above so the documented source actually works. Either resolves the bug; the current state — read path pointed at an undeclared field, no error surface — leaves users with no way to make the setting take effect short of reading the bundled extension source.

Other weaknesses (less critical, but worth flagging)

Initial-render race

cachedClaudeSettings starts as undefined. It's populated asynchronously by M.getSettings() only after the CLI subprocess launches (offset 1619940). The state push at offset 1667447 fires BEFORE that resolves on extension startup, so the first state the webview receives has spinnerVerbsConfig: undefined. The webview's tL0(undefined) returns the default verb list. Then a second pushStateUpdate() fires once cachedClaudeSettings lands, and the webview re-renders with the correct verb.

Net effect: the spinner shows default verbs for ~50-500ms at session start, then snaps to "Working". Not a correctness bug but a visible flicker. The original code (v1("spinnerVerbs") — a synchronous VS Code config read) didn't have this race; my patched code does. Mitigation: initialize cachedClaudeSettings to a sentinel and gate the first state push on the IPC resolving — or just accept the flicker.

No hot-reload on manual settings.json edits

I grepped extension.js for file watchers on ~/.claude/settings.json — none (FileSystemWatcher: 0 occurrences). The four getSettings() call sites are:

WhereTrigger
1619940Once, after CLI channel launches
1627405Once, in the bootstrap "config loading only" path
1652045After the extension WRITES to settings.json via the in-IDE settings UI
1009674The RPC method definition itself

Nothing re-fetches when the user manually edits ~/.claude/settings.json. So the patched code still requires a window reload (Cmd+Shift+P → "Developer: Reload Window") to pick up edits. The current broken code has the same property (VS Code's getConfiguration().get() does auto-refresh, but the property isn't declared so it doesn't matter). Same observed behavior either way; not a regression — but worth noting in the issue so maintainers don't promise "edit and see immediate effect."

The fix doesn't address the dead listener

The affectsConfiguration("claudeCode.spinnerVerbs") line in the change handler (offset 2055742) becomes truly orphaned after the patch — it's listening for a config event that will never trigger because the property is undeclared. My draft already proposed removing it; just confirming that part of the diff is necessary, not optional. A FileSystemWatcher on ~/.claude/settings.json (or, better, an IPC push from the native CLI's existing settings-file watcher) is the right replacement if hot-reload is wanted.

Schema validation strips silently

The native binary's settings ingestion validates with Zod. If the user's spinnerVerbs is malformed (wrong type, missing verbs array, verbs: [] empty, mode not in enum), the binary may strip the field rather than reject the file — I see Non-string value in X array was removed warnings in the binary's strings dump for permissions.allow/deny/ask, suggesting the validator removes-with-warning rather than fails. If spinnerVerbs uses the same pattern, a malformed user config produces NO cachedClaudeSettings.effective.spinnerVerbs and the user thinks the fix is still broken when actually their config is wrong. Maintainers should confirm whether spinnerVerbs validation rejects-the-file vs strips-the-field, and surface the warning to the user either way.

My fix touches only the extension; not the native CLI

The bug is in the VS Code/Cursor extension only. The terminal claude CLI honors spinnerVerbs correctly (separate code path, separate spinner rendering). So users who report spinnerVerbs working in CLI but not in IDE — that's expected and proves the fix surface is correctly scoped to the extension. Worth mentioning in the issue to pre-empt a "we can't reproduce in the CLI" rejection.

DISCLAIMER:

The analysis in this post was generated by Opus and may contain errors.

PS: Under U.S. case law, a "frolic" is an employees substantial departure from the employers assignment for the employee’s own purposes, for which the employer is generally not liable.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix [BUG] in VS Code/Cursor extension spinnerVerbs read from claudeCode.* workspace config instead of ~/.claude/settings.json effective view (one-line fix in extension.js)