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.