# How to Configure Lobe Chat Settings: Zustand Store Architecture and API Guide

> **Lobe Chat persists all user preferences through a centralized Zustand store called `UserStore` that merges default constants with server-side overrides, exposing read access via pure selectors in [`src/store/user/slices/setti...

- Repository: [LobeHub/lobe-chat](https://github.com/lobehub/lobe-chat)
- Tags: api-reference
- Published: 2026-03-03

---

**Lobe Chat persists all user preferences through a centralized Zustand store called `UserStore` that merges default constants with server-side overrides, exposing read access via pure selectors in [`src/store/user/slices/settings/selectors/settings.ts`](https://github.com/lobehub/lobe-chat/blob/main/src/store/user/slices/settings/selectors/settings.ts) and write access through async actions in [`src/store/user/slices/settings/action.ts`](https://github.com/lobehub/lobe-chat/blob/main/src/store/user/slices/settings/action.ts).**

To configure Lobe Chat settings effectively, you must understand its type-safe state management architecture. In the `lobehub/lobe-chat` repository, every user-adjustable option flows through dedicated store slices that synchronize with the backend while maintaining optimistic UI updates.

## Architecture of the Settings Store

The configuration layer resides in `src/store/user/slices/settings/` and follows a strict three-part separation of concerns.

- **Selectors**: Pure functions located in [`src/store/user/slices/settings/selectors/settings.ts`](https://github.com/lobehub/lobe-chat/blob/main/src/store/user/slices/settings/selectors/settings.ts) that compute the merged view of defaults and user overrides
- **Actions**: Async methods in [`src/store/user/slices/settings/action.ts`](https://github.com/lobehub/lobe-chat/blob/main/src/store/user/slices/settings/action.ts) handling mutations, backend synchronization, and import/export logic
- **Initial State**: Default values imported from `@lobechat/const` and TypeScript interfaces defined in [`src/types/user/settings.ts`](https://github.com/lobehub/lobe-chat/blob/main/src/types/user/settings.ts) and [`src/store/user/slices/settings/initialState.ts`](https://github.com/lobehub/lobe-chat/blob/main/src/store/user/slices/settings/initialState.ts)

The `currentSettings` selector demonstrates the merge strategy between baked-in defaults and user-specific overrides:

```typescript
// src/store/user/slices/settings/selectors/settings.ts
export const currentSettings = (s: UserStore): UserSettings =>
  merge(s.defaultSettings, s.settings);

```

## Reading Lobe Chat Settings with Selectors

Components never access the raw store directly. Instead, they import typed selectors that return fully merged configuration objects, ensuring consistent default-to-user-override resolution throughout the UI layer.

```tsx
import { useStore } from '@/store';
import { settingsSelectors } from '@/store/user/slices/settings/selectors';

export const LanguageModelInfo = () => {
  const model = useStore(settingsSelectors.currentLLMSettings);
  return <div>Current LLM: {model.provider ?? 'default'}</div>;
};

```

This pattern appears in routes such as `src/routes/(main)/settings/common/features/Appearance/Preview.tsx`, where the selector `currentLLMSettings` provides the final configuration object for rendering.

## Updating Lobe Chat Settings via Store Actions

All mutations flow through the action layer in [`src/store/user/slices/settings/action.ts`](https://github.com/lobehub/lobe-chat/blob/main/src/store/user/slices/settings/action.ts). When a user submits a form in the settings pages under `src/routes/(main)/settings/`, the component invokes a store action rather than calling the API directly.

```typescript
import { useStore } from '@/store';

export const saveGeneral = async (newConfig: Partial<UserGeneralConfig>) => {
  const { updateGeneralConfig } = useStore.getState().settings;
  await updateGeneralConfig(newConfig);
};

```

The update lifecycle follows a six-step optimistic pattern:

1. **Optimistic Patch**: The action immediately updates local state using `difference` and `merge` utilities
2. **Signal Creation**: An abort controller (`internal_createSignal`) is instantiated for request cancellation
3. **API Invocation**: The action calls `userService.updateUserSettings` to persist changes
4. **State Refresh**: `refreshUserState` repopulates the store from the backend to ensure eventual consistency

## Desktop Configuration for Electron

When running as a desktop application, Lobe Chat exposes additional settings for network proxies and global hotkeys through a dedicated Electron slice.

The desktop-specific logic resides in three locations:

- **Actions**: [`src/store/electron/actions/settings.ts`](https://github.com/lobehub/lobe-chat/blob/main/src/store/electron/actions/settings.ts) exports `setProxySettings` and `updateDesktopHotkey`
- **Service Layer**: [`src/services/electron/settings.ts`](https://github.com/lobehub/lobe-chat/blob/main/src/services/electron/settings.ts) wraps IPC calls to the main process
- **UI Components**: `src/routes/(main)/settings/hotkey/features/Desktop.tsx` renders the hotkey interface

```typescript
import { useStore } from '@/store';

export const setProxy = async (proxy: Partial<NetworkProxySettings>) => {
  const { setProxySettings } = useStore.getState().electron.settings;
  await setProxySettings(proxy);
};

```

These actions use **SWR** hooks to maintain synchronization between the React layer and the native main process, calling `desktopSettingsService` to persist changes.

## Reset, Import, and Export Operations

The action layer provides utilities for bulk configuration management:

- **`resetSettings`**: Invokes `userService.resetUserSettings` to restore defaults, then refreshes the store state
- **`importAppSettings`**: Decodes shared configuration strings via `shareService` and feeds them into `setSettings`
- **`importUrlShareSettings`**: Handles URL-based setting imports from share links

```typescript
import { useStore } from '@/store';

export const resetAll = async () => {
  const { resetSettings } = useStore.getState().settings;
  await resetSettings();
};

```

## Summary

- **Store Location**: All settings logic lives in `src/store/user/slices/settings/` with selectors, actions, and initial state clearly separated
- **Merge Strategy**: The `currentSettings` selector combines `defaultSettings` with user overrides to produce the final configuration object
- **Update Flow**: Changes follow an optimistic update pattern through actions in [`src/store/user/slices/settings/action.ts`](https://github.com/lobehub/lobe-chat/blob/main/src/store/user/slices/settings/action.ts), using `userService` for backend persistence
- **Desktop Extensions**: Electron-specific settings use a parallel slice in [`src/store/electron/actions/settings.ts`](https://github.com/lobehub/lobe-chat/blob/main/src/store/electron/actions/settings.ts) with IPC wrappers in [`src/services/electron/settings.ts`](https://github.com/lobehub/lobe-chat/blob/main/src/services/electron/settings.ts)
- **Key Files**: Reference [`src/types/user/settings.ts`](https://github.com/lobehub/lobe-chat/blob/main/src/types/user/settings.ts) for TypeScript definitions and `src/routes/(main)/settings/` for UI route implementations

## Frequently Asked Questions

### Where are Lobe Chat settings stored in the codebase?

All user settings are managed by the `UserStore` Zustand slice located at `src/store/user/slices/settings/`. Default values come from `@lobechat/const` as defined in [`src/store/user/slices/settings/initialState.ts`](https://github.com/lobehub/lobe-chat/blob/main/src/store/user/slices/settings/initialState.ts), while the merged runtime state is computed by selectors in [`src/store/user/slices/settings/selectors/settings.ts`](https://github.com/lobehub/lobe-chat/blob/main/src/store/user/slices/settings/selectors/settings.ts).

### How do I programmatically update a Lobe Chat setting?

Import the store hook and call the appropriate action from [`src/store/user/slices/settings/action.ts`](https://github.com/lobehub/lobe-chat/blob/main/src/store/user/slices/settings/action.ts). For example, use `updateGeneralConfig` for general settings or `setSettings` for bulk updates. These methods handle optimistic UI updates, API calls to `userService.updateUserSettings`, and eventual state reconciliation automatically.

### Can I configure proxy settings in the Lobe Chat desktop app?

Yes, but only in the Electron desktop version. Proxy configuration uses the desktop-specific slice in [`src/store/electron/actions/settings.ts`](https://github.com/lobehub/lobe-chat/blob/main/src/store/electron/actions/settings.ts). The `setProxySettings` action communicates through the IPC wrapper at [`src/services/electron/settings.ts`](https://github.com/lobehub/lobe-chat/blob/main/src/services/electron/settings.ts) to update native network settings, with the UI available in `src/routes/(main)/settings/hotkey/features/Desktop.tsx`.

### How do I reset all settings to their default values?

Call the `resetSettings` action from the settings slice. This invokes the `userService.resetUserSettings` backend endpoint, clears user overrides, and refreshes the store to reflect the default configuration from [`src/store/user/slices/settings/initialState.ts`](https://github.com/lobehub/lobe-chat/blob/main/src/store/user/slices/settings/initialState.ts).