# custom_providers Model Names in /model Picker

The `/model` picker in Telegram/CLI shows models listed under `custom_providers:` in
`~/.hermes/config.yaml`. By default, these are GGUF filenames (ugly). You can override
the display name using one of the options below.

## Option A: Per-model display name (cleanest)

Use separate custom_providers entries with a `name:` field:

```yaml
custom_providers:
  - name: Local
    base_url: http://127.0.0.1:8081/v1
    models:
      Qwen3.6-35B-A3B-UD-Q4_K_S.gguf:
        context_length: 128000
      qwen3.5-9b-uncensored-Q4_K_M.gguf:
        context_length: 128000
      qwen3-8b-Q4_K_M.gguf:
        context_length: 65536
```

In this single-endpoint group, the picker shows "Local" as the provider name and each
model's GGUF key as the model name. There is no `name:` key per model inside the
`models:` dict — Hermes uses the key itself.

## Option B: Multiple endpoint groups (per port)

Since each local model uses a different port, you can create one custom_providers entry
per port, each with a friendly name:

```yaml
custom_providers:
  - name: Qwen3.6-35B
    base_url: http://127.0.0.1:8081/v1
    models:
      Qwen3.6-35B-A3B-UD-Q4_K_S.gguf:
        context_length: 128000
  - name: Qwen3-9B-UD
    base_url: http://127.0.0.1:8082/v1
    models:
      qwen3.5-9b-uncensored-Q4_K_M.gguf:
        context_length: 128000
```

This shows each model as its own provider row with a friendly name. Downside: many rows.

## Option C: Single entry with all models (current default)

All models under one base_url, but the auto-model-switch.py handles port switching
behind the scenes. The base_url in custom_providers is just the *default* — when
auto-switch fires, it rewrites `model.base_url` to the correct port.

The picker shows GGUF filenames as model names. Users who dislike this are best served
by Option B, Option D, or by accepting that the auto-switch overrides the port at
runtime anyway.

## Option D: Single entry — friendly names via dual matching (recommended)

Requires a one-time change to auto-model-switch.py (see below), then you get clean
names with a single provider row. No per-port groups, no ugly filenames.

**How it works:** auto-model-switch.py's lookup previously matched only
`m["model_name"]` (the GGUF filename). By updating both `is_cloud_model()` and the
model lookup in `_main_impl()` to match on **either** `m["name"]` (friendly) **or**
`m["model_name"]` (GGUF filename), you can use friendly `name` values directly as the
model keys in custom_providers:

```yaml
custom_providers:
- name: Local
  base_url: http://127.0.0.1:8081/v1
  models:
    Qwen3.6-35B-A3B-UD:
      context_length: 128000
    Qwen3-14B:
      context_length: 65536
    Gemma-4-26B:
      context_length: 131072
```

**Changes needed in auto-model-switch.py** (two functions, two lookups):

```python
# 1. is_cloud_model() — match both fields
def is_cloud_model(model_name: str) -> bool:
    return not any(
        m["model_name"] == model_name or m["name"] == model_name for m in MODELS
    )

# 2. Primary model lookup (~line 417) — match both fields
target = next(
    (m for m in MODELS if m["model_name"] == config_model or m["name"] == config_model),
    None,
)

# 3. State-guard lookup (~line 431) — same dual-match pattern
target = next(
    (m for m in MODELS if m["model_name"] == config_model or m["name"] == config_model),
    None,
)
```

The `name` values in models.py are already clean ("Qwen3-14B", "Gemma-4-26B") — just
use them as custom_providers model keys and the picker shows those names.

## Note on auto-switch interaction

The auto-model-switch.py (triggered by hermes-config.path) is what actually writes the
correct `model.base_url` (with the right port) to config.yaml when a model is selected.
So even though custom_providers has a single base_url, the runtime URL gets corrected.
The custom_providers entry mainly determines *what appears in the picker*, not the
runtime routing.
