How to Configure LLM API Keys in ChocolateLMLite: A Complete Guide

ChocolateLMLite stores LLM API credentials in the global settings file data/general.yaml, exposing them through the /api/setting REST endpoint and consuming them via the YamlGeneral class when initializing the OpenAI-compatible chat client.

Configuring external LLM providers in the gpsnmeajp/chocolatelmlite repository requires updating the persistent global settings that the application loads at startup. This lightweight C# application reads your endpoint URL and authentication token from a YAML configuration, making them available to the internal LLM class while automatically masking secrets in both logs and UI output.

Where ChocolateLMLite Stores API Credentials

The YamlGeneral Configuration Model

The application defines its global settings schema in src/FileManager.cs through the YamlGeneral class (lines 85–95). This plain-old-data container exposes two critical properties for LLM configuration:

  • LlmEndpointUrl: The base URL of your OpenAI-compatible API provider
  • LlmApiKey: The authentication token for that provider

When the application initializes, FileManager.LoadGeneralSettings() deserializes data/general.yaml into this model, making the credentials available throughout the application lifecycle.

The general.yaml File Structure

On disk, these values live in data/general.yaml relative to the application root. The file is read at startup and updated whenever you modify settings through the REST API or web interface. If the file is missing or fields are empty, the application falls back to default values suitable for local LLM servers that require no authentication.

How to Configure LLM API Keys via the REST API

The primary method for updating credentials is the /api/setting endpoint implemented in src/WebServer.cs (lines 52–58). This endpoint accepts a JSON payload containing your new configuration and persists it to general.yaml.

Use the following curl command to update your API key and endpoint:

curl -X POST http://localhost:8010/api/setting \
  -H "Content-Type: application/json" \
  -d '{
        "LlmEndpointUrl": "https://api.openrouter.ai/v1",
        "LlmApiKey": "sk-xxxx",
        "DefaultModel": "google/gemini-2.5-flash"
      }'

The server responds with { "success": "done" } and immediately writes the values to disk. As documented in API.md (lines 71–76), this endpoint handles the complete settings payload, so include all required fields when updating.

Updating Keys Through the Web Interface

For manual configuration, navigate to http://localhost:<port>/setting.htm in your browser. The settings page renders the "LLM APIキー" field as a password input, preventing shoulder-surfing while you type.

When you click 保存 (Save), the frontend JavaScript in static/js/system.js (lines 10–24) sends the same POST /api/setting request shown above. The SECRET_FIELD_KEYS array in this file designates which fields should be masked in the UI (displayed as ************) and stripped from debug output before being logged to the browser console.

Runtime Consumption in the LLM Class

Once configured, the LLM class consumes these credentials in src/LLM.cs (lines 149–152) within the GenerateResponseAsync method. The implementation constructs an OpenAI.Chat.ChatClient using the values from fileManager.generalSettings:

var settings = fileManager.LoadGeneralSettings();

var clientOptions = new OpenAIClientOptions()
{
    Endpoint = new Uri(settings.LlmEndpointUrl)
};

var chatClient = new OpenAI.Chat.ChatClient(
    model: settings.DefaultModel ?? "-",
    credential: new ApiKeyCredential(settings.LlmApiKey ?? "-"),
    clientOptions);

Key implementation details:

  • Empty key handling: If LlmApiKey is null or empty, the code passes "-" to ApiKeyCredential. This satisfies the OpenAI client constructor while allowing connections to local LLM servers that accept empty authentication strings.
  • HTTP transport: The client uses a custom OpenRouterHttpHandler injected with the FileManager instance, applying timeout settings from the same configuration object.

Reading Credentials in Custom Extensions

If you are extending ChocolateLMLite with custom modules, access the current API key through the FileManager instance:

var fileManager = new FileManager(); // In the real app, this is injected via DI
var settings = fileManager.LoadGeneralSettings();

string endpoint = settings.LlmEndpointUrl;
string apiKey = settings.LlmApiKey;

Console.WriteLine($"Using endpoint: {endpoint}");
Console.WriteLine($"Key configured: {!string.IsNullOrEmpty(apiKey)}");

Security Measures for API Key Protection

The application implements defense-in-depth to prevent accidental credential exposure. In src/WebServer.cs, the API masks the LlmApiKey field before writing to debug logs or returning data in GET responses. Similarly, the frontend JavaScript in static/js/system.js ensures that any field listed in SECRET_FIELD_KEYS is rendered as a password input and its value replaced with asterisks in the UI.

This means the raw key is only transmitted in clear text during the initial POST request to update settings, and when passed to the underlying OpenAI client library at runtime.

Summary

  • Storage location: API keys persist in data/general.yaml, mapped to the YamlGeneral class in src/FileManager.cs (lines 85–95).
  • Update methods: Use POST /api/setting via HTTP API (documented in API.md) or the web UI at /setting.htm.
  • Runtime usage: The LLM class in src/LLM.cs (lines 149–152) initializes the chat client with ApiKeyCredential, falling back to "-" for unauthenticated local models.
  • Security: Both server-side (WebServer.cs) and client-side (system.js) code mask secrets in logs and UI output to prevent leakage.

Frequently Asked Questions

What file format does ChocolateLMLite use for API key storage?

The application uses YAML format stored in data/general.yaml. The FileManager class deserializes this file into the YamlGeneral model at startup, exposing LlmEndpointUrl and LlmApiKey properties that the rest of the application consumes.

Can I use ChocolateLMLite with local LLMs that don't require authentication?

Yes. If you leave the LlmApiKey field empty or set it to an empty string, the code in src/LLM.cs passes "-" as the credential to the OpenAI client constructor. This allows connections to local LLM servers (like LM Studio or Ollama) that accept empty authentication headers.

How does the application prevent API key leakage in logs?

Both the server and frontend implement masking logic. The REST endpoint in src/WebServer.cs strips secret fields before logging requests, while static/js/system.js (lines 10–24) maintains a SECRET_FIELD_KEYS list that ensures password fields display as asterisks in the browser and are excluded from client-side debug output.

Is there a command-line interface for setting the API key?

ChocolateLMLite does not ship with a dedicated CLI configuration tool. However, you can script configuration using the REST API with tools like curl or Invoke-RestMethod, targeting the POST /api/setting endpoint with your credentials in the JSON payload.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →