SKILL.md

  1---
  2name: updating-llm-client-model-lists
  3description: Synchronizes model configurations across Zed, Crush, Pi, and ECA from Plexus' /v1/models endpoint. Use when the user asks to update model lists, sync models, refresh available models, or mentions Plexus model availability.
  4user-invocable: true
  5license: LicenseRef-MutuaL-1.2
  6metadata:
  7  author: Amolith <amolith@secluded.site>
  8---
  9
 10Updates four LLM client configs from the Plexus proxy's available models.
 11
 12## max_completion_tokens
 13
 14Always 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.
 15
 16## Network reachability
 17
 181. Ping `harp-willow.snowy-egret.ts.net` once
 192. If unreachable and Tailscale DNS is disabled, enable it:
 20   ```bash
 21   tailscale set --accept-dns=true
 22   ```
 233. Test ping again. If still unreachable, STOP and inform the user
 24
 25Remember to disable after finishing the whole process if it was previously disabled.
 26
 27```bash
 28tailscale set --accept-dns=false
 29```
 30
 31## Fetch Plexus models
 32
 33```bash
 34curl -s http://harp-willow.snowy-egret.ts.net:4000/v1/models | \
 35  jq -r '.data[]
 36    | select(.id | IN("nomic-embed-text-v1.5", "diff-apply", "fix-json") | not)
 37    | select(.context_length != null and .context_length > 0)
 38    | [.id, (.name // .id), (.context_length | tostring),
 39       ((.context_length * 0.2 | floor | tostring)),
 40       (if (.supported_parameters | index("reasoning"))  then "reasoning" else "" end),
 41       (if (.architecture.input_modalities | index("image")) then "image" else "" end)]
 42    | @tsv' | column -t -s $'\t'
 43```
 44
 45This 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.
 46
 47## Rules
 48
 49- Always exclude `nomic-embed-text-v1.5` (embedding model, not supported by any client)
 50- Exclude `diff-apply` and `fix-json` from all client model lists
 51- Exclude models with no `context_length` field (e.g. voxtral-small, mistral-ocr) unless the user provides values manually
 52- Assume every listed model supports tools, regardless of whether Plexus reports `tools` in `supported_parameters`
 53- Omit special characters from display names. For example, "MiniMax-M2.7" should become "MiniMax M2.7". "nemotron-3-super" becomes "Nemotron 3 Super".
 54
 55## Update Zed config
 56
 57File: `~/.config/zed/settings.json`
 58
 59Update `language_models.openai_compatible.Plexus.available_models[]`. Each entry:
 60
 61```json
 62{
 63  "name": "<id>",
 64  "display_name": "<name>",
 65  "max_tokens": <context_length>,
 66  "max_completion_tokens": <max_completion_tokens>,
 67  "capabilities": {
 68    "chat_completions": true,
 69    "prompt_cache_key": false,
 70    "tools": true,
 71    "parallel_tool_calls": true,
 72    "images": <true if "image">
 73  }
 74}
 75```
 76
 77## Update Crush config
 78
 79File: `~/.local/share/chezmoi/dot_config/crush/crush.json`
 80
 81Update `providers.plexus.models[]`. Each entry:
 82
 83```json
 84{
 85  "id": "<id>",
 86  "name": "<name>",
 87  "context_window": <context_length>,
 88  "default_max_tokens": <max_completion_tokens>,
 89  "can_reason": <true if "reasoning">,
 90  "supports_attachments": <true if "image">
 91}
 92```
 93
 94After editing: `chezmoi apply ~/.config/crush/crush.json`
 95STOP if chezmoi has any output other than success.
 96
 97## Update Pi config
 98
 99File: `~/.local/share/chezmoi/dot_config/pi/models.json`
100
101Update `providers.plexus.models[]`. Each entry:
102
103```json
104{
105  "id": "<id>",
106  "name": "<name>",
107  "reasoning": <true if "reasoning">,
108  "input": <["text"] or ["text", "image"]>,
109  "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
110  "contextWindow": <context_length>,
111  "maxTokens": <max_completion_tokens>,
112  "compat": {
113    "supportsReasoningEffort": <true if "reasoning">,
114    "supportsDeveloperRole": false
115  }
116}
117```
118
119After editing: `chezmoi apply ~/.config/pi/models.json`
120NEVER 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.
121
122## Update ECA config
123
124Reference docs: <https://eca.dev/config/introduction/> and <https://eca.dev/config/models/>
125
126File: `~/.config/eca/config.json`
127
128Update `providers.plexus`. ECA custom providers use an OpenAI-compatible provider config with a static model map:
129
130```json
131{
132	"api": "openai-chat",
133	"url": "http://100.77.116.78:4000/v1",
134	"key": "${cmd:fnox get PLEXUS_API_KEY}",
135	"reasoningHistory": "all",
136	"fetchModels": false,
137	"models": {
138		"<id>": {}
139	}
140}
141```
142
143ECA's custom-provider docs list `api`, `url`, `key`, and `models` as the important fields for OpenAI-compatible providers. Use `api: "openai-chat"` for Plexus, because Plexus exposes `/v1/chat/completions`. Set `fetchModels: false` so ECA uses the Plexus model list from this config rather than attempting dynamic discovery from models.dev.