# How to Customize Available Models in NextChat Using the CUSTOM_MODELS Environment Variable

> Easily customize NextChat models with the CUSTOM_MODELS environment variable. Add, remove, or rename models without changing source code. Control your AI chatbot experience.

- Repository: [NextChat/NextChat](https://github.com/ChatGPTNextWeb/NextChat)
- Tags: how-to-guide
- Published: 2026-02-28

---

**Set the `CUSTOM_MODELS` environment variable to add, remove, or rename models in NextChat without modifying any source code.**

The `CUSTOM_MODELS` environment variable in [ChatGPTNextWeb/NextChat](https://github.com/ChatGPTNextWeb/NextChat) provides a declarative way to control which AI models appear in the web interface. By configuring this variable, administrators can override the default model list defined in [`app/constant.ts`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/app/constant.ts), hide specific providers, or register entirely custom deployments. Changes take effect immediately after a server restart, reshaping the model selector UI without requiring code changes.

## Server-Side Configuration Loading

When the NextChat server boots, it reads the `CUSTOM_MODELS` variable from the environment and stores the raw string in the server configuration object.

In [`app/config/server.ts`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/app/config/server.ts) (lines 140–149), the initialization logic captures the variable:

```typescript
let customModels = process.env.CUSTOM_MODELS ?? "";
…
customModels,          // later returned as part of the server config

```

This raw string is then passed to the model-handling utilities that merge it with the `DEFAULT_MODELS` constant.

## Model Table Generation and Parsing

The core parsing logic resides in [`app/utils/model.ts`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/app/utils/model.ts) (lines 77–132) inside the `collectModelTable` function. This utility splits the `CUSTOM_MODELS` string by commas and processes each token to build the final model table.

The parser interprets each entry according to specific prefix operators:

- **`+model`** – **Add** a model or enable an existing one that is hidden by default
- **`-model`** – **Remove** or hide a model from the selector
- **`name=displayName`** – **Rename** the entry in the UI while preserving the internal ID
- **`model@provider`** – Target a **specific provider** (e.g., Azure, ByteDance) for the deployment

The special token `all` toggles visibility for every default model at once. As implemented in lines 86–92 of [`app/utils/model.ts`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/app/utils/model.ts):

```typescript
if (name === "all") {
  Object.values(modelTable).forEach(
    (model) => (model.available = available),
  );
}

```

When a supplied name does not match any existing model in `DEFAULT_MODELS`, the code creates a brand-new custom entry (lines 115–132):

```typescript
const provider = customProvider(customProviderName || customModelName);
modelTable[`${customModelName}@${provider?.id}`] = {
  name: customModelName,
  displayName: displayName || customModelName,
  available,
  provider,
  sorted: CustomSeq.next(`${customModelName}@${provider?.id}`),
};

```

The resulting model list is cached and sent to the frontend, where the model selector displays only entries marked as `available`.

## CUSTOM_MODELS Syntax Patterns

The variable accepts a comma-separated list of directives. The parser processes each segment sequentially, so order matters when using `all` or overlapping rules.

### Add or Enable Models

Use the `+` prefix to append models to the selector or force-enable existing entries:

```dotenv
CUSTOM_MODELS="+llama,+claude-2"

```

This adds `llama` and `claude-2` alongside the default models.

### Hide Default Models

Use the `-` prefix to remove specific models from the UI:

```dotenv
CUSTOM_MODELS="-gpt-3.5-turbo"

```

This hides GPT-3.5 Turbo while keeping other defaults visible.

### Rename Models for Display

Use the `=` operator to change the human-readable label without altering the API identifier:

```dotenv
CUSTOM_MODELS="gpt-4-1106-preview=gpt-4-turbo"

```

The model retains its internal ID `gpt-4-1106-preview` but appears as *gpt-4-turbo* in the dropdown.

### Bulk Operations with "all"

Target all default models simultaneously, then apply exceptions:

```dotenv
CUSTOM_MODELS="+all,-gpt-4"

```

This enables every default model, then disables any model matching `gpt-4`.

### Provider-Specific Deployments

Append `@provider` to route requests to specific backends like Azure or ByteDance:

**Azure deployment example:**

```dotenv
CUSTOM_MODELS="+gpt-3.5-turbo@Azure=gpt35"

```

This displays *gpt35(Azure)* in the UI and uses the Azure provider configuration.

**ByteDance endpoint example:**

```dotenv
CUSTOM_MODELS="+Doubao-lite-4k@bytedance=ep-xxxx"

```

This appears as *Doubao-lite-4k(ByteDance)* and utilizes the specified deployment ID `ep-xxxx`.

### Complete List Replacement

Disable every built-in model and define a single custom entry:

```dotenv
CUSTOM_MODELS="-all,+my-model@openai=MyModel"

```

This results in a selector containing only *MyModel* provided by OpenAI.

## Implementation Reference

The following files constitute the complete pipeline for model customization:

- **[`app/config/server.ts`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/app/config/server.ts)** – Reads `CUSTOM_MODELS` from `process.env` and injects it into the server config (lines 140–149)
- **[`app/utils/model.ts`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/app/utils/model.ts)** – Parses the string, merges it with defaults via `collectModelTable`, and constructs the final model table (lines 77–132)
- **[`app/constant.ts`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/app/constant.ts)** – Defines the `DEFAULT_MODELS` array that serves as the baseline for all modifications

## Summary

- **`CUSTOM_MODELS`** controls the NextChat model selector via environment configuration alone
- **Syntax operators:** `+` adds, `-` removes, `=` renames, and `@` specifies providers
- **Special keyword:** `all` modifies every default model simultaneously for bulk enable/disable operations
- **Custom models:** Unknown model names trigger automatic creation of new entries with generated provider metadata
- **No rebuild required:** Changes apply after a simple server restart since the variable is evaluated at runtime in [`app/config/server.ts`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/app/config/server.ts)

## Frequently Asked Questions

### Do I need to rebuild the Docker image after changing CUSTOM_MODELS?

No. Because NextChat reads `CUSTOM_MODELS` from `process.env` at runtime in [`app/config/server.ts`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/app/config/server.ts), you only need to restart the container. Update your `.env` file or Docker Compose configuration, then run `docker-compose restart` to apply changes.

### What happens if I specify a model name that does not exist in the default list?

According to the logic in [`app/utils/model.ts`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/app/utils/model.ts) (lines 115–132), NextChat automatically creates a custom model entry for unknown names. It generates a provider object using `customProvider()`, assigns a display name (defaulting to the model name if no `=` is provided), and adds it to the model table with a unique sort sequence.

### How do I target my Azure OpenAI deployment specifically?

Use the `@Azure` provider suffix combined with the `=` display name operator. For example, `+gpt-3.5-turbo@Azure=my-deployment-name` routes requests through the Azure provider while showing *my-deployment-name(Azure)* in the UI. This syntax is parsed in [`app/utils/model.ts`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/app/utils/model.ts) by splitting on `@` and `=` respectively.

### Can I both add a new model and hide a default one in the same variable?

Yes. The parser processes directives sequentially from left to right. For example, `CUSTOM_MODELS="+custom-llama,-gpt-3.5-turbo"` first adds the custom model, then removes the default GPT-3.5 Turbo entry from the selector.