---
name: updating-llm-client-model-lists
description: Synchronizes model configurations across Zed, Crush, Octofriend, and Pi from Plexus' /v1/models endpoint. Use when the user asks to update model lists, sync models, refresh available models, or mentions Plexus model availability.
---

Updates four LLM client configs from the Plexus proxy's available models.

## max_completion_tokens

Always use `floor(context_length * 0.2)` as the max_completion_tokens value for all clients. Do NOT use the `top_provider.max_completion_tokens` field from the API — some models report their entire context window as max completion tokens, which is not a sensible default. 20% of context length is a more practical cap.

## Network reachability

1. Ping `harp-willow.snowy-egret.ts.net` once
2. If unreachable and Tailscale DNS is disabled, enable it:
   ```bash
   tailscale set --accept-dns=true
   ```
3. Test ping again. If still unreachable, STOP and inform the user

Remember to disable after finishing the whole process if it was previously disabled.

```bash
tailscale set --accept-dns=false
```

## Fetch Plexus models

```bash
curl -s http://harp-willow.snowy-egret.ts.net:4000/v1/models | \
  jq -r '.data[]
    | select(.id | IN("nomic-embed-text-v1.5", "diff-apply", "fix-json") | not)
    | [.id, (.name // .id), (.context_length | tostring),
       ((.context_length * 0.2 | floor | tostring)),
       (if (.supported_parameters | index("tools"))     then "tools"     else "" end),
       (if (.supported_parameters | index("reasoning"))  then "reasoning" else "" end),
       (if (.architecture.input_modalities | index("image")) then "image" else "" end)]
    | @tsv' | column -t -s $'\t'
```

This should provide all the info you need in a table. The data in this table is the same as what you'd get directly querying Plexus. The display names are the same. You do not need to query Plexus any other way. Review the display names in the table, and if they need modification, make the modification while editing the configs.

## Rules

- Always exclude `nomic-embed-text-v1.5` (embedding model, not supported by any client)
- Exclude `diff-apply` and `fix-json` from Zed, Crush, and Pi because it's only supported by Octofriend
- Exclude models with no `context_length` field (e.g. voxtral-small, mistral-ocr) unless the user provides values manually
- Omit special characters from display names. For example, "MiniMax-M2.7" should become "MiniMax M2.7". "nemotron-3-super" becomes "Nemotron 3 Super".

## Update Zed config

File: `~/.config/zed/settings.json`

Update `language_models.Plexus.available_models[]`. Each entry:

```json
{
  "name": "<id>",
  "display_name": "<name>",
  "max_tokens": <context_length>,
  "max_completion_tokens": <max_completion_tokens>,
  "capabilities": {
    "chat_completions": true,
    "prompt_cache_key": false,
    "tools": <true if "tools">,
    "parallel_tool_calls": true,
    "images": <true if "image">
  }
}
```

## Update Crush config

File: `~/.local/share/chezmoi/dot_config/crush/crush.json`

Update `providers.plexus.models[]`. Each entry:

```json
{
  "id": "<id>",
  "name": "<name>",
  "context_window": <context_length>,
  "default_max_tokens": <max_completion_tokens>,
  "can_reason": <true if "reasoning">,
  "supports_attachments": <true if "image">
}
```

After editing: `chezmoi apply ~/.config/crush/crush.json`
STOP if chezmoi has any output other than success.

## Update Octofriend config

File: `~/.local/share/chezmoi/dot_config/octofriend/octofriend.json5`

Update `models[]`. Each entry:

```json
{
  "nickname": "<name>",
  "baseUrl": "http://100.77.116.78:4000/v1",
  "model": "<id>",
  "context": <context_length>,
  "apiEnvVar": "PLEXUS_API_KEY"
}
```

Leave `diffApply` and `fixJson` objects unchanged.

After editing: `chezmoi apply ~/.config/octofriend/octofriend.json5`
STOP if chezmoi has any output other than success.

## Update Pi config

File: `~/.local/share/chezmoi/dot_config/pi/models.json`

Update `providers.plexus.models[]`. Each entry:

```json
{
  "id": "<id>",
  "name": "<name>",
  "reasoning": <true if "reasoning">,
  "input": <["text"] or ["text", "image"]>,
  "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
  "contextWindow": <context_length>,
  "maxTokens": <max_completion_tokens>,
  "compat": {
    "supportsReasoningEffort": <true if "reasoning">,
    "supportsDeveloperRole": false
  }
}
```

After editing: `chezmoi apply ~/.config/pi/models.json`
NEVER use `--force` with chezmoi apply. If it reports the file has changed since last write, STOP and inform the user — they may have local changes not yet added to chezmoi.
