Skip to content

feat: Add CLAUDE_MEM_OPENROUTER_BASE_URL setting for custom API endpoint #2382

Description

@bloodf

Before submitting


Is your feature request related to a problem? Please describe.

The OpenRouter provider has a hardcoded API URL in src/services/worker/OpenRouterProvider.ts (line 20):

const OPENROUTER_API_URL = 'https://openrouter.ai/api/v1/chat/completions';

This prevents users from routing OpenRouter-provider calls through a local OpenAI-compatible proxy (LiteLLM, Bifrost, vLLM, Ollama, etc.) without patching worker-service.cjs after every plugin update.

My use case: I run a local AI gateway (Bifrost) at http://127.0.0.1:8888/v1 that aggregates multiple LLM providers (MiniMax, Z.AI, Moonshot, OpenAI) behind a single OpenAI-compatible endpoint. I want claude-mem's OpenRouter provider to route through this gateway instead of directly to openrouter.ai. Currently I must sed the bundled worker-service.cjs every time the plugin updates, which breaks on any version bump.

Describe the solution you'd like

Add a CLAUDE_MEM_OPENROUTER_BASE_URL setting (readable from both the settings file and environment variable) that overrides the base URL for the OpenRouter provider. When empty or unset, it defaults to https://openrouter.ai/api/v1 — no behavior change for existing users.

Affected files (I have a working implementation in my fork):

  1. src/services/worker/OpenRouterProvider.ts — Replace the hardcoded constant with a function that reads from settings/env:

    const DEFAULT_OPENROUTER_BASE_URL = 'https://openrouter.ai/api/v1';
    
    function getOpenRouterApiUrl(): string {
      const settings = SettingsDefaultsManager.loadFromFile(USER_SETTINGS_PATH);
      const baseUrl = (
        settings.CLAUDE_MEM_OPENROUTER_BASE_URL ||
        process.env.CLAUDE_MEM_OPENROUTER_BASE_URL ||
        DEFAULT_OPENROUTER_BASE_URL
      ).replace(/\/+$/, '');
      return `${baseUrl}/chat/completions`;
    }

    Then change the fetch call from fetch(OPENROUTER_API_URL, { to fetch(getOpenRouterApiUrl(), {.

  2. src/shared/SettingsDefaultsManager.ts — Add type and default:

    // In the interface:
    CLAUDE_MEM_OPENROUTER_BASE_URL: string;
    
    // In DEFAULTS:
    CLAUDE_MEM_OPENROUTER_BASE_URL: '',  // Custom OpenRouter-compatible base URL. Empty = https://openrouter.ai/api/v1
  3. src/services/worker/http/routes/SettingsRoutes.ts — Add URL validation (same pattern as CLAUDE_MEM_OPENROUTER_SITE_URL):

    if (settings.CLAUDE_MEM_OPENROUTER_BASE_URL) {
      try {
        new URL(settings.CLAUDE_MEM_OPENROUTER_BASE_URL);
      } catch (error) {
        return { valid: false, error: 'CLAUDE_MEM_OPENROUTER_BASE_URL must be a valid URL' };
      }
    }
  4. src/ui/viewer/hooks/useSettings.ts — Include in UI hook defaults:

    CLAUDE_MEM_OPENROUTER_BASE_URL: data.CLAUDE_MEM_OPENROUTER_BASE_URL ?? DEFAULT_SETTINGS.CLAUDE_MEM_OPENROUTER_BASE_URL,

Describe alternatives you've considered

  1. Patching worker-service.cjs with sed after each update — This is what I do now. It works but breaks on every version bump and requires a maintenance script.
  2. Reusing CLAUDE_MEM_OPENROUTER_SITE_URL — This is actually the HTTP-Referer header, not the base URL, so repurposing it would be a breaking change.
  3. Forking the plugin permanently — Unnecessary maintenance burden for a one-line change.

Additional context

  • This follows the same pattern as other configurable settings (CLAUDE_MEM_OPENROUTER_MODEL, CLAUDE_MEM_OPENROUTER_API_KEY, etc.)
  • The implementation is backward-compatible: empty/unset value = current behavior
  • I have a working fork with this change at bloodf/claude-mem branch feat/openrouter-base-url-env (4 files, +20/-2 lines) — happy to submit as PR if fork PRs are enabled
  • Total change is ~20 lines across 4 files

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions