Skip to content

fix(settings): forward saved API keys to sidecar in same session#14

Merged
mrdulasolutions merged 1 commit into
mainfrom
claude/settings-secrets-forward-to-sidecar
May 13, 2026
Merged

fix(settings): forward saved API keys to sidecar in same session#14
mrdulasolutions merged 1 commit into
mainfrom
claude/settings-secrets-forward-to-sidecar

Conversation

@mrdulasolutions
Copy link
Copy Markdown
Owner

Summary

Fixes user report: "OpenRouter API key isn't saving" (and the same bug for the Anthropic key).

Root cause

`sidecar/src/lib/secrets.ts` documents the intended flow:

"When the user changes a key in Settings, the renderer writes the keychain first, then forwards the new value to the sidecar via `setSecret(name, value)` ..."

The renderer did the first step but not the second. Result: after Save in Settings:

  • Keychain is correctly written ✓
  • Sidecar's in-memory secrets map still has the old key (or null) ✗
  • Agent calls fail with 401 / "API key not set" until the app restarts (which re-bootstraps from keychain at boot)

This affects both `handleSaveApiKey` (Anthropic) and `handleSaveOpenRouterKey`.

Fix

After the keychain write, forward to the sidecar:

  • Anthropic → `settings.set({ anthropicApiKey: trimmed })` (routes through `SECRET_KEYS` in `settings.ts`, lands in `setSecret()` plus clears the cached Anthropic SDK client).
  • OpenRouter → `openrouter.setApiKey` / `openrouter.clearApiKey` (purpose-built RPC, lands in `setSecret()`).

Both are best-effort follow-ups to the keychain write — the keychain remains source of truth, so a sidecar transient failure here can still be recovered by an app restart.

What this PR does NOT fix (raised by user, separate issues)

  • "Model changes in General not saving": General tab's model picker at SettingsPanel.tsx:1378 only updates local React state; persistence requires clicking Save (line 1661). That's the existing UX. If you're clicking Save and it still isn't persisting, paste a screen recording / log line and I'll dig in. The second model picker in the AI Models tab (line ~2273) DOES auto-save.
  • "Notifications / test notifications not working": code looks correct on inspection (`src/renderer/services/notifications.ts:180`). The failure could be at any of: `bridge.isTauri`, macOS system permission, the `isPermissionGranted()`/`requestPermission()` calls, or the actual `sendNotification()`. Need a runtime diagnostic to know which. Suggest: open DevTools while clicking Test, check the return value (`{ ok: false, reason: "browser" | "denied" | "disabled" }`) — that tells us which gate failed.

Test plan

  • Open Settings → Agent Tools → AI Models, paste a fresh OpenRouter key, click Save
  • Without restarting the app, trigger `drafts.rerunAgent` (or any OpenRouter-backed flow)
  • Should succeed (was: 401 / "OpenRouter API key not set")
  • Same flow for Anthropic key

🤖 Generated with Claude Code

User report: "OpenRouter API key isn't saving." Same underlying bug
affects the Anthropic key.

Architecture (per sidecar/src/lib/secrets.ts): keychain is the
canonical store, sidecar caches keys in memory, and the renderer is
responsible for writing the keychain AND forwarding the new value to
the sidecar via the appropriate RPC. The sidecar comment even spells
this out:

> "When the user changes a key in Settings, the renderer writes the
>  keychain first, then forwards the new value to the sidecar via
>  setSecret(name, value)..."

But handleSaveApiKey and handleSaveOpenRouterKey both stopped at
step one. The keychain got written; the sidecar's in-memory map
never did. Result: the new key only takes effect after restart
(which re-bootstraps secrets from the keychain at boot). Within the
same session — set key → run agent → 401 / "API key not set."

Fix: after writing the keychain, forward to the sidecar.

  - Anthropic: settings.set({ anthropicApiKey: trimmed }) — already
    routes through SECRET_KEYS in settings.ts, lands in setSecret()
    plus clears the cached Anthropic SDK client.
  - OpenRouter: openrouter.setApiKey / openrouter.clearApiKey — the
    purpose-built RPC, lands in setSecret() too.

Both writes are best-effort follow-ups to the keychain write; the
keychain remains the source of truth, so a sidecar transient failure
here can still be recovered by an app restart.

Doesn't address two adjacent reports also flagged by the user:

  - "Model changes in General not saving" — General tab's first
    model picker (line ~1378) only updates local React state; user
    must click the Save button. That's the existing UX; if the user
    clicks Save and it still doesn't persist, that's a separate
    issue I couldn't reproduce from code-read alone.
  - "Notifications / test notifications not working" — needs
    runtime diagnostics to know which step fails (macOS permission,
    bridge.isTauri, sendNotification). Code looks correct on
    inspection.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@mrdulasolutions mrdulasolutions merged commit 1d44c41 into main May 13, 2026
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant