Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
5e667b6
docs: defaults settings redesign mockups and implementation plan
ProfSynapse Oct 14, 2026
a25b849
chore(settings): remove unused StatusBadge and stray header statement
ProfSynapse Oct 14, 2026
67277d1
fix(chat): keep context window edits scoped to one chat
ProfSynapse Oct 14, 2026
adf3c6f
fix(chat): carry settings saved with no chat open into the next chat
ProfSynapse Oct 14, 2026
79ea236
fix(search): reach conversation embeddings through the plugin manager
ProfSynapse Oct 14, 2026
e71d917
fix(search): resolve the content-search embedding service on every call
ProfSynapse Oct 14, 2026
0bf765e
fix(chat): make [[ note suggestions semantic again
ProfSynapse Oct 14, 2026
1dcf04e
fix(tasks): use the embedding accessor for task note linking
ProfSynapse Oct 14, 2026
5f2dd8c
test: require every looked-up service name to be registered
ProfSynapse Oct 14, 2026
ceaa09c
fix(chat): welcome "Open settings" opens the Providers tab
ProfSynapse Oct 14, 2026
cab775e
fix(settings): preselect the prompt bound to a workspace on Defaults
ProfSynapse Oct 14, 2026
f0df063
fix(settings): keep Defaults ingestion rows ordered and through redraws
ProfSynapse Oct 14, 2026
a9c9806
feat(llm): gate thinking by model capability at the request boundary
ProfSynapse Oct 14, 2026
7c1114a
fix(chat): sentence-case the provider settings fallback notice
ProfSynapse Oct 14, 2026
a799853
feat(subagents): agent model precedence and subagent Creativity/windo…
ProfSynapse Oct 14, 2026
da3f08a
feat(subagents): make subagent settings reach subagent and executePro…
ProfSynapse Oct 14, 2026
504e81c
feat(storage): add clearEmbeddingIndex for deleting vectors only
ProfSynapse Oct 14, 2026
5ba87bb
feat(embeddings): turn semantic search off and on at runtime
ProfSynapse Oct 14, 2026
0e1ffc1
feat(settings): hot-apply synced enableEmbeddings instead of reloading
ProfSynapse Oct 14, 2026
0986137
feat(search): fall back to keyword search when semantic search is off
ProfSynapse Oct 14, 2026
7cf208b
test(embeddings): shut down managers left running by phase-order tests
ProfSynapse Oct 14, 2026
0c798b6
test(mocks): element tree for settings layout assertions
ProfSynapse Oct 14, 2026
839ce82
chore: require Obsidian 1.11 for SettingGroup
ProfSynapse Oct 14, 2026
7d96c7f
feat(settings): shared accordion, fold memory and one slider readout
ProfSynapse Oct 14, 2026
0d01b7e
feat(settings): Essentials + folds layout for Defaults and Chat settings
ProfSynapse Oct 14, 2026
070fee4
Merge branch 'redesign/n3-subagent-runtime' into redesign/n5-capabili…
ProfSynapse Oct 14, 2026
ddd10a8
Merge branch 'redesign/n7-semantic-runtime' into redesign/n8-semantic-ui
ProfSynapse Oct 14, 2026
aa34ee0
feat(settings): semantic search copy and turn-off confirmation modal
ProfSynapse Oct 14, 2026
236e499
feat(settings): semantic search status, progress, hot-apply and delet…
ProfSynapse Oct 14, 2026
eb8d2b3
feat(settings): capability-driven Creativity, Context window and Thin…
ProfSynapse Oct 14, 2026
045915b
feat(settings): persist subagent Creativity and context limit on both…
ProfSynapse Oct 14, 2026
c3e0634
feat(settings): router pages, Node.js lookup and MCP client config he…
ProfSynapse Oct 14, 2026
5b695b0
feat(settings): Get started row and in-tab setup pages
ProfSynapse Oct 14, 2026
4853b17
fix(copy): call the Google-login provider Antigravity, not Gemini CLI
ProfSynapse Oct 14, 2026
08ab54a
Merge redesign/n5-capability-ui into feat/defaults-settings-redesign
ProfSynapse Oct 14, 2026
9dfc706
Merge redesign/n6-get-started into feat/defaults-settings-redesign
ProfSynapse Oct 14, 2026
3e61f59
Merge redesign/n8-semantic-ui into feat/defaults-settings-redesign
ProfSynapse Oct 14, 2026
01ecc91
fix(get-started): Claude Desktop not-found state, legacy Antigravity …
ProfSynapse Oct 14, 2026
4865aa3
fix(settings): release the Defaults tab and tab listeners with the se…
ProfSynapse Oct 14, 2026
c727068
fix(accordion): load itself so unload() frees its listener; heading a…
ProfSynapse Oct 14, 2026
b3e1f59
fix(chat-settings): keep saved per-model limits on Defaults; Web sear…
ProfSynapse Oct 14, 2026
320b602
fix(embeddings): stale service references cannot revive the engine; t…
ProfSynapse Oct 14, 2026
765dc77
fix(storage): VACUUM after Delete index so the cache file shrinks
ProfSynapse Oct 14, 2026
27940f2
fix(semantic-search): fold picks up an embedding runtime created afte…
ProfSynapse Oct 14, 2026
d25c0a4
fix(mcp-configs): Reconnect keeps the user's settings; repair legacy …
ProfSynapse Oct 14, 2026
8e437be
test(subagents): Defaults keeps a subagent model's saved context limi…
ProfSynapse Oct 14, 2026
1cb4e40
fix(subagents): never pair a cloud fallback provider with no model
ProfSynapse Oct 14, 2026
f4f2f81
feat(get-started): connect Claude Code alongside Claude Desktop
ProfSynapse Oct 14, 2026
349d98c
fix(settings): full-width setting groups and aligned page titles
ProfSynapse Oct 14, 2026
2b15f95
fix(embeddings): host the model iframe in the main window; dispose he…
ProfSynapse Oct 14, 2026
1ef1568
fix(embeddings): report a model that fails to load as an error, not c…
ProfSynapse Oct 14, 2026
5e8b0e5
fix(storage): bind the cache blob store to the main window's IndexedDB
ProfSynapse Oct 14, 2026
43f6f46
Merge redesign/fix-embeddings into feat/defaults-settings-redesign
ProfSynapse Oct 14, 2026
983dfe4
docs(mcp-setup): call the Google MCP client Antigravity and point at …
ProfSynapse Oct 14, 2026
d2083b2
fix(lifecycle): drop the dead stateManager lookup from shutdown
ProfSynapse Oct 14, 2026
0163b65
fix(tasks): resolve the embedding service per query in note-link sugg…
ProfSynapse Oct 14, 2026
e4951b2
fix(settings): show a semantic search model that failed to load, with…
ProfSynapse Oct 14, 2026
48ec61d
fix(multiwindow): host the voice output and base-query render in the …
ProfSynapse Oct 14, 2026
97ec817
fix(chat): bind the composer suggesters to the input's own window
ProfSynapse Oct 14, 2026
a657984
fix(desktop): load Node modules through the main window's require
ProfSynapse Oct 14, 2026
8b2a31f
fix(tests): stop the leaked timers behind Jest's forced worker exit
ProfSynapse Oct 14, 2026
ce0427a
docs(changelog): draft the Unreleased entry for the settings redesign
ProfSynapse Oct 14, 2026
47cf712
fix(workspaces): stop re-creating the default workspace on every load
ProfSynapse Oct 14, 2026
1a1e2cc
fix(storage): a rejected workspace create must not write an event
ProfSynapse Oct 14, 2026
21fab55
Merge redesign/fix-active-window into feat/defaults-settings-redesign
ProfSynapse Oct 14, 2026
3da6028
Merge redesign/fix-leftovers into feat/defaults-settings-redesign
ProfSynapse Oct 14, 2026
ee6e3af
Merge redesign/fix-workspace-unique into feat/defaults-settings-redesign
ProfSynapse Oct 14, 2026
c91a918
fix(settings): stop Defaults describing models no provider can serve
ProfSynapse Oct 14, 2026
12a7ca3
Merge redesign/fix-ui-followups into feat/defaults-settings-redesign
ProfSynapse Oct 14, 2026
5ca829b
chore: stop tracking a node_modules symlink and ignore it in any form
ProfSynapse Oct 14, 2026
87ac532
fix(embeddings): let the conversation backfill converge after it comp…
ProfSynapse Oct 14, 2026
ffce9ba
fix(embeddings): make indexing progress describe the work being done
ProfSynapse Oct 14, 2026
ed9b99b
fix(search): list each file once in semantic content search
ProfSynapse Oct 14, 2026
af9341d
docs(skills): record that plugin:reload vault= hit the focused vault
ProfSynapse Oct 14, 2026
9163367
Merge redesign/fix-search-backfill into feat/defaults-settings-redesign
ProfSynapse Oct 14, 2026
ac337a5
fix(sync): keep the workflow scheduler watermark on the device, not i…
ProfSynapse Oct 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .claude/skills/nexus-testing/refinement-log.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,11 @@ Used the existing loader suite with a fake clock to check production text update
### 2026-10-13 — Whole-turn header activity

Expanded the actual store/reducer lifecycle test to cover reasoning completion, tool execution and answer streaming before terminal settlement. The existing selector failed the new expectation before the fix. The mock does not decide phases. No protocol change needed.

### 2026-10-14 — Slider readout settled statically (defaults redesign, Phase 1 step 1a)

The plan asked for an in-app `obsidian eval` check of slider markup. It was settled without touching a vault by reading the installed app bundle (`obsidian.asar` → `app.js`, Obsidian 1.14.4): `SliderComponent` creates its own `span.slider-value` before the range input, refreshes it on every `input` event through `updateDisplay()`, and formats it with `setDisplayFormat(fn)` (absent from the 1.12.3 typings). It also fires the change callback from `setValue` when the value changes, so register `onChange` after `setValue`. The duplicate "High 2" / "1,000,000 tokens 1000000" readouts were the plugin's own span next to that native one. `bindSliderReadout` now writes into the native element and adds one span only when none exists. The SliderComponent mock reproduces the native element in FakeElement mode, so a reintroduced second readout fails `SliderReadout.test.ts`. Still worth one in-app glance on 1.11/1.12, where the native element may be missing. No protocol change.

### 2026-10-14 — `plugin:reload … vault=<name>` reloaded the focused vault

Linux, four vaults open. `obsidian plugin:reload id=nexus vault="Nexus Redesign Test"` did not reload the named vault: its plugin instance's `lifecycleManager.getInitializationStatus().startTime` did not move, while the focused Synaptic-Labs vault's did. The first call printed `Reloaded: nexus`, later ones printed nothing; neither output says which vault. What worked and is provably targeted: one guarded `eval` in the named vault that asserts `app.vault.getName()`, then runs `app.plugins.disablePlugin('nexus').then(() => app.plugins.enablePlugin('nexus'))` into a `window` status object, polled separately; confirm the new instance by its startTime. Here `vault=` came after the command, the shape step 3 of `live-loop.md` shows; the 2026-10-13 entry above found that putting it before the command targeted correctly, which was not retried. Never verify a reload by its command output. Prefer that in-band reload whenever more than one vault is open.
8 changes: 8 additions & 0 deletions .cline/skills/nexus-testing/refinement-log.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,11 @@ Used the existing loader suite with a fake clock to check production text update
### 2026-10-13 — Whole-turn header activity

Expanded the actual store/reducer lifecycle test to cover reasoning completion, tool execution and answer streaming before terminal settlement. The existing selector failed the new expectation before the fix. The mock does not decide phases. No protocol change needed.

### 2026-10-14 — Slider readout settled statically (defaults redesign, Phase 1 step 1a)

The plan asked for an in-app `obsidian eval` check of slider markup. It was settled without touching a vault by reading the installed app bundle (`obsidian.asar` → `app.js`, Obsidian 1.14.4): `SliderComponent` creates its own `span.slider-value` before the range input, refreshes it on every `input` event through `updateDisplay()`, and formats it with `setDisplayFormat(fn)` (absent from the 1.12.3 typings). It also fires the change callback from `setValue` when the value changes, so register `onChange` after `setValue`. The duplicate "High 2" / "1,000,000 tokens 1000000" readouts were the plugin's own span next to that native one. `bindSliderReadout` now writes into the native element and adds one span only when none exists. The SliderComponent mock reproduces the native element in FakeElement mode, so a reintroduced second readout fails `SliderReadout.test.ts`. Still worth one in-app glance on 1.11/1.12, where the native element may be missing. No protocol change.

### 2026-10-14 — `plugin:reload … vault=<name>` reloaded the focused vault

Linux, four vaults open. `obsidian plugin:reload id=nexus vault="Nexus Redesign Test"` did not reload the named vault: its plugin instance's `lifecycleManager.getInitializationStatus().startTime` did not move, while the focused Synaptic-Labs vault's did. The first call printed `Reloaded: nexus`, later ones printed nothing; neither output says which vault. What worked and is provably targeted: one guarded `eval` in the named vault that asserts `app.vault.getName()`, then runs `app.plugins.disablePlugin('nexus').then(() => app.plugins.enablePlugin('nexus'))` into a `window` status object, polled separately; confirm the new instance by its startTime. Here `vault=` came after the command, the shape step 3 of `live-loop.md` shows; the 2026-10-13 entry above found that putting it before the command targeted correctly, which was not retried. Never verify a reload by its command output. Prefer that in-band reload whenever more than one vault is open.
8 changes: 8 additions & 0 deletions .codex/skills/nexus-testing/refinement-log.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,11 @@ Used the existing loader suite with a fake clock to check production text update
### 2026-10-13 — Whole-turn header activity

Expanded the actual store/reducer lifecycle test to cover reasoning completion, tool execution and answer streaming before terminal settlement. The existing selector failed the new expectation before the fix. The mock does not decide phases. No protocol change needed.

### 2026-10-14 — Slider readout settled statically (defaults redesign, Phase 1 step 1a)

The plan asked for an in-app `obsidian eval` check of slider markup. It was settled without touching a vault by reading the installed app bundle (`obsidian.asar` → `app.js`, Obsidian 1.14.4): `SliderComponent` creates its own `span.slider-value` before the range input, refreshes it on every `input` event through `updateDisplay()`, and formats it with `setDisplayFormat(fn)` (absent from the 1.12.3 typings). It also fires the change callback from `setValue` when the value changes, so register `onChange` after `setValue`. The duplicate "High 2" / "1,000,000 tokens 1000000" readouts were the plugin's own span next to that native one. `bindSliderReadout` now writes into the native element and adds one span only when none exists. The SliderComponent mock reproduces the native element in FakeElement mode, so a reintroduced second readout fails `SliderReadout.test.ts`. Still worth one in-app glance on 1.11/1.12, where the native element may be missing. No protocol change.

### 2026-10-14 — `plugin:reload … vault=<name>` reloaded the focused vault

Linux, four vaults open. `obsidian plugin:reload id=nexus vault="Nexus Redesign Test"` did not reload the named vault: its plugin instance's `lifecycleManager.getInitializationStatus().startTime` did not move, while the focused Synaptic-Labs vault's did. The first call printed `Reloaded: nexus`, later ones printed nothing; neither output says which vault. What worked and is provably targeted: one guarded `eval` in the named vault that asserts `app.vault.getName()`, then runs `app.plugins.disablePlugin('nexus').then(() => app.plugins.enablePlugin('nexus'))` into a `window` status object, polled separately; confirm the new instance by its startTime. Here `vault=` came after the command, the shape step 3 of `live-loop.md` shows; the 2026-10-13 entry above found that putting it before the command targeted correctly, which was not retried. Never verify a reload by its command output. Prefer that in-band reload whenever more than one vault is open.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
node_modules/
node_modules
.jest-cache/

# Runtime-vendored engine assets (downloaded once at runtime from the pinned CDN,
Expand Down
8 changes: 8 additions & 0 deletions .skills/nexus-testing/refinement-log.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,11 @@ Used the existing loader suite with a fake clock to check production text update
### 2026-10-13 — Whole-turn header activity

Expanded the actual store/reducer lifecycle test to cover reasoning completion, tool execution and answer streaming before terminal settlement. The existing selector failed the new expectation before the fix. The mock does not decide phases. No protocol change needed.

### 2026-10-14 — Slider readout settled statically (defaults redesign, Phase 1 step 1a)

The plan asked for an in-app `obsidian eval` check of slider markup. It was settled without touching a vault by reading the installed app bundle (`obsidian.asar` → `app.js`, Obsidian 1.14.4): `SliderComponent` creates its own `span.slider-value` before the range input, refreshes it on every `input` event through `updateDisplay()`, and formats it with `setDisplayFormat(fn)` (absent from the 1.12.3 typings). It also fires the change callback from `setValue` when the value changes, so register `onChange` after `setValue`. The duplicate "High 2" / "1,000,000 tokens 1000000" readouts were the plugin's own span next to that native one. `bindSliderReadout` now writes into the native element and adds one span only when none exists. The SliderComponent mock reproduces the native element in FakeElement mode, so a reintroduced second readout fails `SliderReadout.test.ts`. Still worth one in-app glance on 1.11/1.12, where the native element may be missing. No protocol change.

### 2026-10-14 — `plugin:reload … vault=<name>` reloaded the focused vault

Linux, four vaults open. `obsidian plugin:reload id=nexus vault="Nexus Redesign Test"` did not reload the named vault: its plugin instance's `lifecycleManager.getInitializationStatus().startTime` did not move, while the focused Synaptic-Labs vault's did. The first call printed `Reloaded: nexus`, later ones printed nothing; neither output says which vault. What worked and is provably targeted: one guarded `eval` in the named vault that asserts `app.vault.getName()`, then runs `app.plugins.disablePlugin('nexus').then(() => app.plugins.enablePlugin('nexus'))` into a `window` status object, polled separately; confirm the new instance by its startTime. Here `vault=` came after the command, the shape step 3 of `live-loop.md` shows; the 2026-10-13 entry above found that putting it before the command targeted correctly, which was not retried. Never verify a reload by its command output. Prefer that in-band reload whenever more than one vault is open.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

[![Release](https://img.shields.io/github/v/release/ProfSynapse/claudesidian-mcp?label=release)](https://github.com/ProfSynapse/claudesidian-mcp/releases)
[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
[![Obsidian](https://img.shields.io/badge/Obsidian-1.10%2B-6f42c1)](https://obsidian.md/plugins)
[![Obsidian](https://img.shields.io/badge/Obsidian-1.11%2B-6f42c1)](https://obsidian.md/plugins)
[![Node](https://img.shields.io/badge/node-%3E%3D18-43853d)](package.json)

# Nexus MCP for Obsidian
Expand All @@ -13,7 +13,7 @@ Nexus gives AI agents and built-in chat access to your Obsidian vault so you can

Nexus can be used in two ways:
- Inside Obsidian with native chat (hook up to your favorite provider or agentic platform!)
- From external agents like Claude Desktop, Claude Code, Codex CLI, Gemini CLI, Cursor, Cline, and other MCP clients
- From external agents like Claude Desktop, Claude Code, Codex CLI, Antigravity, Cursor, Cline, and other MCP clients

> Nexus is the successor to Claudesidian. Legacy installs in `.obsidian/plugins/claudesidian-mcp/` still work.

Expand Down Expand Up @@ -81,7 +81,7 @@ Ollama and LM Studio talk to your own machine and leave it entirely.

| If you want to... | Start here |
|---|---|
| Connect Claude Desktop, Codex CLI, Gemini CLI, Cursor, Cline, or another MCP client | [MCP setup](guide/mcp-setup.md) |
| Connect Claude Desktop, Codex CLI, Antigravity, Cursor, Cline, or another MCP client | [MCP setup](guide/mcp-setup.md) |
| Drive your vault from the shell with Claude Code, Cursor, or Codex — no MCP config | [Nexus CLI](guide/nexus-cli.md) |
| Configure built-in chat providers inside Obsidian | [Provider setup](guide/provider-setup.md) |
| Use live voice, read notes aloud, or save spoken audio back into your notes | [Native chat](guide/native-chat.md) |
Expand Down
39 changes: 39 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,45 @@

## October 2026

**Unreleased** — Redesigned Defaults and Chat settings, Get started pages, subagent settings, and semantic search you can turn on and off

> Draft for the next release. Version number and PR links are added when it is cut.

**Requires Obsidian 1.11.0**
- Nexus now needs Obsidian 1.11.0 or later, because the redesigned settings use Obsidian's setting groups. Obsidian 1.10 keeps offering Nexus 5.20.x.

**Redesigned Defaults tab and Chat settings**
- Defaults and Chat settings share one layout: Provider, Model and Thinking at the top, then collapsed sections (Chat options, Context, Subagents, Images, Voice, and on Defaults also Video, File conversion and Semantic search). Each section summarizes its settings in one line, and Nexus remembers which ones you left open on each device.
- The rows follow the selected model. **Thinking** lists only the levels the model distinguishes, and thinking is not sent to models without reasoning support. **Creativity** is disabled for models that set their own temperature. **Context window** snaps to preset sizes (32K up to 1M) below the model's maximum, plus the maximum itself.
- The **Context window** in Chat settings now applies only to that conversation and no longer changes your Defaults. Changing Defaults no longer alters chats that are already open; new chats use them. Chat settings saved before any chat is open carry into the next new chat.
- Choosing a workspace on Defaults selects the prompt bound to that workspace. Switching models on Defaults keeps each model's saved context window.
- With no provider set up, **Open settings** on the chat welcome screen opens the Providers tab.

**Subagents use their own model and settings**
- Subagents and `executePrompt` runs use the configured subagent model even when the chat model is a cloud model. Before, they inherited the chat model. Without a subagent model, they fall back to the cloud chat model, or to the first cloud provider with a default model when the chat model is local.
- The Subagents section has its own **Creativity** and **Context window**. Set them on Defaults, or for one conversation in Chat settings. The context window also limits how much workspace data and context files a subagent receives. Items that do not fit are dropped and listed in its prompt.

**Get started**
- **Get started** is a row at the top of Nexus settings that opens setup pages inside the tab: **Chat inside Obsidian** and, on desktop, **Connect an external agent**. It opens by itself the first time settings are shown with nothing set up.
- **Connect an external agent** checks for Node.js first and shows the version and path it found, warns when the path belongs to nvm, and offers **Install Node.js** and **Check again** when it is missing.
- Claude Desktop, Claude Code, Codex and Antigravity connect with one click. Claude Code is added through `claude mcp add-json --scope user`, and Antigravity's config is written to `~/.gemini/config/mcp_config.json`. **Reconnect** repairs a connection whose Node.js or connector path has moved and keeps your other settings in that entry. An unreadable config is backed up before it is replaced, and the notice names the backup. Claude Desktop shows **Not found** with a download link when it is not installed.
- **Other agents** walks through four steps (create the connector, copy the config, add it to your app, restart) with paths for your computer.
- The Google sign-in provider and MCP client are called **Antigravity** everywhere in the app and guides; the old "Gemini CLI" name is gone.

**Semantic search**
- Turning semantic search on or off takes effect immediately; no restart. Turning it off asks for confirmation first. A change synced from another device is also applied without a reload.
- While semantic search is on, the Semantic search section shows note and chat counts and indexing progress with an estimate and pause/resume. While it is off, **Delete index** removes the stored vectors and shrinks the cache file. Your notes and conversations are not touched.
- Each indexing pass removes entries for notes that were deleted or renamed and chats that were deleted while semantic search was off.
- With semantic search off, a semantic content search returns keyword results with a note that semantic search is turned off in Nexus settings, and the tool description stops advertising it.
- A model that fails to load is reported as an indexing error instead of finishing "complete" over an empty index.

**Fixes**
- The semantic search model never finished loading when Settings or a popout window had focus at the moment it started, which is usually the case when you turn semantic search on. Initialization timed out, semantic search switched itself off, and indexing reported success with nothing stored. This also affects 5.20.4. Turning semantic search off no longer waits 30 seconds for the model to shut down.
- Semantic search of past conversations, semantic `[[` note suggestions in the chat composer, and semantic note suggestions when linking notes to tasks never used the index. They looked for an embedding service that was never registered and always fell back to keyword matching. They now reach the live index and pick up semantic search being turned on or off without reopening.
- Cache saves no longer fail after you close a popout or the Settings window that had focus when Nexus loaded (for example, when you enable Nexus from Settings).

---

**v5.20.4** — Gemini 4 Argon and a unified thinking accordion

- Thinking appears in one accordion with typed words, cycling dots, a pulsing icon and a silver sweep. The header stays animated through tool use and answer streaming, then settles to a brain icon and **Reasoning** when the response finishes. Tool activity remains in the status bar ([#413](https://github.com/ProfSynapse/nexus/pull/413), [#415](https://github.com/ProfSynapse/nexus/pull/415)).
Expand Down
Loading
Loading