Documentation

Custom Configurations

Feature In Beta

Plugin support is currently in private beta. Join the beta here.

Overview

LM Studio plugins support custom configurations. That is, you can define a configuration schema and LM Studio will present a UI to the user so they can configure your plugin without having to edit any code.

There are two types of configurations:

  • Per-chat configuration: tied to a specific chat. Different chats can have different configurations. Most configurations that affects the behavior of the plugin should be of this type.
  • Global configuration: apply to all chats and are shared across the application. This is useful for global settings such as API keys.

Types of Configurations

You can define configurations in TypeScript using the createConfigSchematics function from the @lmstudio/sdk package. This function allows you to define fields with various types and options.

Supported types include:

  • string: A text input field.
  • numeric: A number input field with optional validation and slider UI.
  • boolean: A checkbox or toggle input field.
  • stringArray: An array of string values with configurable constraints.
  • select: A dropdown selection field with predefined options.

See the Defining New Fields section for more details on how to define these fields.

The config.ts File

By default, the plugin scaffold will create a config.ts file in the src/ directory which will contain the schematics of the configurations. If the files does not exist, you can create it manually:

import { createConfigSchematics } from "@lmstudio/sdk";

export const configSchematics = createConfigSchematics()
  .field(
    "myCustomField", // The key of the field.
    "numeric", // Type of the field.
    // Options for the field. Different field types will have different options.
    {
      displayName: "My Custom Field",
      hint: "This is my custom field. Doesn't do anything special.",
      slider: { min: 0, max: 100, step: 1 }, // Add a slider to the field.
    },
    80, // Default Value
  )
  // You can add more fields by chaining the field method.
  // For example:
  //   .field("anotherField", ...)
  .build();

export const globalConfigSchematics = createConfigSchematics()
  .field(
    "myGlobalCustomField", // The key of the field.
    "string",
    {
      displayName: "My Global Custom Field",
      hint: "This is my global custom field. Doesn't do anything special.",
    },
    "default value", // Default Value
  )
  // You can add more fields by chaining the field method.
  // For example:
  //  .field("anotherGlobalField", ...)
  .build();

If you've added your config schematics manuall, you will also need to register the configurations in your plugin's index.ts file.

This is done by calling context.withConfigSchematics(configSchematics) and context.withGlobalConfigSchematics(globalConfigSchematics) in the main function of your plugin.

// ... other imports ...
import { toolsProvider } from "./toolsProvider";

export async function main(context: PluginContext) {
  // ... other plugin setup code ...

  // Register the configuration schematics.
  context.withConfigSchematics(configSchematics);
  // Register the global configuration schematics.
  context.withGlobalConfigSchematics(globalConfigSchematics);

  // ... other plugin setup code ...
}

Accessing Configurations

You can access the configuration using the method ctl.getPluginConfig(configSchematics) and ctl.getGlobalConfig(globalConfigSchematics) respectively.

For example, here is how to access the config within the promptPreprocessor:

import { type PreprocessorController, type ChatMessage } from "@lmstudio/sdk";
import { configSchematics } from "./config";

export async function preprocess(ctl: PreprocessorController, userMessage: ChatMessage) {
  const pluginConfig = ctl.getPluginConfig(configSchematics);
  const myCustomField = pluginConfig.get("myCustomField");

  const globalPluginConfig = ctl.getGlobalPluginConfig(configSchematics);
  const globalMyCustomField = globalPluginConfig.get("myCustomField");

  return (
    `${userMessage.getText()},` +
    `myCustomField: ${myCustomField}, ` +
    `globalMyCustomField: ${globalMyCustomField}`
  );
}

Defining New Fields

We support the following field types:

  • string: A text input field.

    // ... other fields ...
    .field(
      "stringField", // The key of the field.
      "string", // Type of the field.
      {
        displayName: "A string field",
        subtitle: "Subtitle", // Optional subtitle for the field. (Show below the field)
        hint: "Hint", // Optional hint for the field. (Show on hover)
        isParagraph: false, // Whether to show a large text input area for this field.
        isProtected: false, // Whether the value should be obscured in the UI (e.g., for passwords).
        placeholder: "Placeholder text", // Optional placeholder text for the field.
      },
      "default value", // Default Value
    )
    // ... other fields ...
    
  • numeric: A number input field with optional validation and slider UI.

    // ... other fields ...
    .field(
      "numberField", // The key of the field.
      "numeric", // Type of the field.
      {
        displayName: "A number field",
        subtitle: "Subtitle for", // Optional subtitle for the field. (Show below the field)
        hint: "Hint for number field", // Optional hint for the field. (Show on hover)
        int: false, // Whether the field should accept only integer values.
        min: 0, // Minimum value for the field.
        max: 100, // Maximum value for the field.
        slider: {
          // If present, configurations for the slider UI
          min: 0, // Minimum value for the slider.
          max: 100, // Maximum value for the slider.
          step: 1, // Step value for the slider.
        },
      },
      42, // Default Value
    )
    // ... other fields ...
    
  • boolean: A checkbox or toggle input field.

    // ... other fields ...
    .field(
      "booleanField", // The key of the field.
      "boolean", // Type of the field.
      {
        displayName: "A boolean field",
        subtitle: "Subtitle", // Optional subtitle for the field. (Show below the field)
        hint: "Hint", // Optional hint for the field. (Show on hover)
      },
      true, // Default Value
    )
    // ... other fields ...
    
  • stringArray: An array of string values with configurable constraints.

    // ... other fields ...
    .field(
      "stringArrayField",
      "stringArray",
      {
        displayName: "A string array field",
        subtitle: "Subtitle", // Optional subtitle for the field. (Show below the field)
        hint: "Hint", // Optional hint for the field. (Show on hover)
        allowEmptyStrings: true, // Whether to allow empty strings in the array.
        maxNumItems: 5, // Maximum number of items in the array.
      },
      ["default", "values"], // Default Value
    )
    // ... other fields ...
    
  • select: A dropdown selection field with predefined options.

    // ... other fields ...
    .field(
      "selectField",
      "select",
      {
        displayName: "A select field",
        options: [
          { value: "option1", displayName: "Option 1" },
          { value: "option2", displayName: "Option 2" },
          { value: "option3", displayName: "Option 3" },
        ],
        subtitle: "Subtitle", // Optional subtitle for the field. (Show below the field)
        hint: "Hint", // Optional hint for the field. (Show on hover)
      },
      "option1", // Default Value
    )
    // ... other fields ...
    

Examples

The following are some plugins that make use of custom configurations