Skip to content

Instantly share code, notes, and snippets.

@bpd1069
Created January 26, 2026 03:36
Show Gist options
  • Select an option

  • Save bpd1069/cd4e369fd3cde1c2655a32c80ad31402 to your computer and use it in GitHub Desktop.

Select an option

Save bpd1069/cd4e369fd3cde1c2655a32c80ad31402 to your computer and use it in GitHub Desktop.
Claude-Mem Local LM Studio Integration

Claude-Mem Local LM Studio Integration

Date: 2026-01-25

Patch to enable claude-mem to use local LM Studio models instead of cloud APIs.

Problem

Claude-mem's OpenRouter provider requires an API key and only supports the cloud endpoint (https://openrouter.ai/api/v1). No option to point to local OpenAI-compatible APIs like LM Studio.

Solution

Added CLAUDE_MEM_OPENROUTER_BASE_URL setting and modified the availability check to allow local endpoints without an API key.

Files Modified

1. src/shared/SettingsDefaultsManager.ts

Added new setting to interface and defaults:

// In SettingsDefaults interface:
CLAUDE_MEM_OPENROUTER_BASE_URL: string;  // Custom base URL (e.g., LM Studio at http://localhost:1234/v1)

// In DEFAULTS:
CLAUDE_MEM_OPENROUTER_BASE_URL: 'https://openrouter.ai/api/v1',  // Default OpenRouter, or set to http://localhost:1234/v1 for LM Studio

2. src/services/worker/OpenRouterAgent.ts

Changed hardcoded URL to configurable:

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

// After:
const DEFAULT_OPENROUTER_BASE_URL = 'https://openrouter.ai/api/v1';

Updated getOpenRouterConfig() to return baseUrl:

private getOpenRouterConfig(): { apiKey: string; baseUrl: string; model: string; ... } {
  const baseUrl = settings.CLAUDE_MEM_OPENROUTER_BASE_URL || DEFAULT_OPENROUTER_BASE_URL;
  return { apiKey, baseUrl, model, siteUrl, appName };
}

Skip API key requirement for local endpoints:

const isLocalEndpoint = baseUrl.includes('localhost') || baseUrl.includes('127.0.0.1');
if (!apiKey && !isLocalEndpoint) {
  throw new Error('OpenRouter API key not configured...');
}

Updated isOpenRouterAvailable() to allow local endpoints:

export function isOpenRouterAvailable(): boolean {
  const hasApiKey = !!(settings.CLAUDE_MEM_OPENROUTER_API_KEY || process.env.OPENROUTER_API_KEY);
  const baseUrl = settings.CLAUDE_MEM_OPENROUTER_BASE_URL || '';
  const isLocalEndpoint = baseUrl.includes('localhost') || baseUrl.includes('127.0.0.1');
  return hasApiKey || isLocalEndpoint;
}

Updated queryOpenRouterMultiTurn() to use dynamic URL:

const apiUrl = `${baseUrl}/chat/completions`;
const response = await fetch(apiUrl, { ... });

Configuration

Edit ~/.claude-mem/settings.json:

{
  "CLAUDE_MEM_PROVIDER": "openrouter",
  "CLAUDE_MEM_OPENROUTER_BASE_URL": "http://localhost:1234/v1",
  "CLAUDE_MEM_OPENROUTER_MODEL": "ibm/granite-4-h-tiny"
}

Build & Deploy

cd ~/.claude/plugins/marketplaces/thedotmack
npm run build

# Copy to cache (where the active plugin runs from)
cp plugin/scripts/worker-service.cjs ~/.claude/plugins/cache/thedotmack/claude-mem/9.0.6/scripts/

# Restart worker
pkill -f worker-service
bun ~/.claude/plugins/cache/thedotmack/claude-mem/9.0.6/scripts/worker-service.cjs start

Verification

Check logs for OpenRouter usage:

tail -f ~/.claude-mem/logs/claude-mem-$(date +%Y-%m-%d).log | grep -E "OpenRouter|granite"

Expected output:

[session-X] Generator auto-starting (observation) using OpenRouter
OpenRouter API usage {model=ibm/granite-4-h-tiny, inputTokens=1529, outputTokens=68, totalTokens=1597}

Benefits

  • Zero API costs for observation processing
  • Faster inference with local GPU
  • Works offline
  • Uses Granite 4 H-Tiny (1B active params, 1M context)

Upstream PR

Consider submitting these changes to thedotmack/claude-mem to avoid reapplying after plugin updates.


Update: 2026-01-25 - Dedicated LMStudio Provider & Local Dev Setup

New LMStudio Provider

A dedicated LMStudioAgent.ts was added (commit 459a4f4), separate from OpenRouter. Simpler, no API key required.

Settings:

{
  "CLAUDE_MEM_PROVIDER": "lmstudio",
  "CLAUDE_MEM_LMSTUDIO_BASE_URL": "http://localhost:1234/v1",
  "CLAUDE_MEM_LMSTUDIO_MODEL": "ibm/granite-4-h-tiny"
}

Local Development with --plugin-dir

Instead of installing to marketplace, use local repo directly:

cc --plugin-dir /home/bpd/dev/bpd1069/claude-mem/plugin

Fixes Applied (commit 6b5a337)

  1. Graceful hook failures - Changed exit code from 2 (blocking) to 0 in hook-command.ts to avoid ugly errors

  2. Dynamic plugin root - Fixed hardcoded thedotmack marketplace path in:

    • src/shared/worker-utils.ts
    • src/services/infrastructure/HealthMonitor.ts

    Now uses CLAUDE_PLUGIN_ROOT env var (set by --plugin-dir) with fallback

  3. Simplified build - npm run build-and-sync now just builds and restarts worker locally

Build & Test

cd ~/dev/bpd1069/claude-mem
npm run build-and-sync

# Verify
curl -s http://127.0.0.1:37777/api/settings | jq '.CLAUDE_MEM_PROVIDER'
curl -s http://127.0.0.1:37777/api/version

Repository

Fork: https://github.com/bpd1069/claude-mem

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment