models.json
La tabla editable de perfiles de modelo y effort con la que el commander despacha. Es tuya para cambiar.
Este archivo es tuyo para editar
.vexillum/models.json está pensado para que lo edites vos. Guarda los valores (qué modelo y effort para qué tipo de tarea); el criterio de qué perfil encaja con una tarea sigue siendo del commander. vx init escribe los valores por defecto una vez y nunca pisa el archivo, y vx upgrade nunca toca tus cambios.
Dónde vive
Se combinan tres capas, y las posteriores ganan:
| Capa | Ubicación | Notas |
|---|---|---|
| valores por defecto embebidos | dentro del binario | lo que vx init escribe en un proyecto nuevo |
| base global | ~/.vexillum/models.json | opcional; aplica a todos los proyectos |
| proyecto | .vexillum/models.json | por proyecto; pisa a la base global |
Un archivo que falta se omite. Corré vx models para ver el resultado combinado y qué archivos se leyeron.
Formato
El archivo es JSON, en inglés:
{
"profiles": {
"<name>": { "model": "sonnet", "effort": "high", "when": "...", "harness": "claude" }
},
"default": { "model": "sonnet", "effort": "medium" }
}| Campo | Significado |
|---|---|
profiles.<name> | Un perfil con nombre. El nombre no tiene espacios y no puede ser default. |
profiles.<name>.model | El modelo que se le pasa al harness. En claude: haiku, sonnet, opus o fable. En pi: un provider/id como anthropic/claude-sonnet-5, que se pasa como --model. En opencode: un provider/model con un #variant opcional, como opencode/glm-5.3-flash-free o anthropic/claude-sonnet-5#high. |
profiles.<name>.effort | El effort que se le pasa al harness. En claude: low, medium, high, xhigh o max. En pi: un nivel de thinking, off, minimal, low, medium, high, xhigh o max, que se pasa como --thinking (Pi lo ajusta a lo que el modelo soporta). En opencode: cualquier etiqueta simple, que se registra en la tarea y nunca se le pasa a OpenCode; el variant sale solo del string del modelo. |
profiles.<name>.when | Texto libre que le dice al commander cuándo aplica el perfil. No puede estar vacío. |
profiles.<name>.harness | Opcional. El CLI de agente en el que corren los soldiers del perfil. claude (Claude Code) es el default cuando el campo no está. pi corre los soldiers del perfil en el agente de código Pi. opencode corre los soldiers en OpenCode, 1.x o 2.x. Cualquier otro nombre es un error que nombra el archivo y el campo. |
default.model, default.effort | El valor de respaldo cuando ningún perfil encaja. Mismos valores válidos. |
Los campos desconocidos se rechazan, así que un error de tipeo no queda sin efecto en silencio. Un valor que el harness del perfil no aceptaría es un error que nombra el archivo y el campo. Los valores se revisan después de combinar las capas, contra el harness con el que termina el perfil: un archivo de proyecto puede poner un modelo provider/id en un perfil pi que definió la base global, y pasar un perfil existente a pi falla hasta que su modelo sea un provider/id. Un modelo de pi se revisa solo por su forma, porque los modelos de Pi son los que ofrezcan tus proveedores; ver Usar Pi. La entrada default no tiene harness: siempre corre en claude. El archivo no tiene schema_version; el parseo estricto ya hace que un vexillum más viejo rechace un archivo que usa un campo que no conoce.
Los perfiles incluidos, en orden de prioridad (gana el primero que coincide):
| Perfil | Modelo, effort | Cuándo |
|---|---|---|
scout-facts | haiku, low | un scout cuya pregunta se reduce a hechos verificables |
scout-judgment | sonnet, medium | un scout que requiere criterio |
mission-mechanical | haiku, low | una edición mecánica trivial |
mission-big | sonnet, high | una mission grande, ambigua o riesgosa |
opus-on-request | opus, high | solo cuando pedís Opus explícitamente |
| default | sonnet, medium | nada de lo anterior aplica |
Cómo se combinan las capas
La combinación es por campo, no por archivo:
- Una capa puede pisar un solo campo de un perfil existente, como
effort, y el resto se hereda. - Un perfil nuevo tiene que definir
model,effortywhen, porque no hay de dónde heredar.harnesssiempre es opcional. - Un perfil no se puede borrar, solo redefinir.
defaultse puede cambiar de a un campo.defaultes un nombre reservado: no se puede usar como nombre de perfil. Selecciona la entrada por defecto envx dispatch --profile default.
Leerlo con vx models
vx models es de solo lectura. Imprime cada perfil como name (model, effort) (con , harness <name> agregado cuando el perfil define uno) seguido de su línea when, después el default, y al final los archivos que se combinaron:
scout-facts (haiku, low)
Scout whose question reduces to verifiable facts ...
...
default (sonnet, medium)
Nothing above fits. Fall back to it, do not reach for it on purpose.
Source: built-in defaults onlyMirá vx models.
Despachar con un perfil
vx dispatch "update the changelog wording" --kind mission --profile mission-mechanical--profile <name> busca el modelo, el effort y el harness. El harness queda registrado en la tarea y se conserva cuando se la vuelve a despachar. Un --model o --effort explícito gana sobre el perfil, campo por campo. Un perfil desconocido es un error que lista los válidos, y --profile default selecciona la entrada por defecto. Ver vx dispatch.
Cómo lo usa el commander
La skill vexillum le indica al commander que corra vx models, lea las líneas when y elija el perfil que encaja con la tarea, y después despache con --profile. Elegir sigue siendo criterio, escrito en markdown. El archivo solo guarda los valores, así que cambiás un número en vez de reescribir prosa.
Un perfil en Pi
Un perfil que corre en Pi nombra un modelo provider/id, un nivel de thinking como su effort, y el harness pi:
{
"profiles": {
"pi-scout": {
"model": "anthropic/claude-haiku-4-5",
"effort": "low",
"when": "Scout cuya pregunta se reduce a hechos verificables, corrido en Pi.",
"harness": "pi"
}
}
}Dejá entero en model un id que termina en un segmento con dos puntos, como el :free de OpenRouter, y poné el nivel de thinking en effort; vexillum lo pasa con --thinking y nunca como sufijo. Usar Pi cubre la preparación, en qué se diferencia de un soldier de Claude Code y la privacidad de los planes gratuitos.
Un perfil en OpenCode
Un perfil que corre en OpenCode nombra un provider/model (con un #variant opcional), una etiqueta simple como su effort, y el harness opencode. El mismo perfil sirve en OpenCode 1.x y 2.x:
{
"profiles": {
"opencode-scout": {
"model": "opencode/glm-5.3-flash-free",
"effort": "low",
"when": "Scout cuya pregunta se reduce a hechos verificables, corrido en un modelo gratuito de retención cero.",
"harness": "opencode"
}
}
}El effort solo se registra, porque los nombres de variant cambian según el modelo; escribí un variant después del modelo, como en anthropic/claude-sonnet-5#high. El modelo se revisa solo por su forma. Usar OpenCode cubre la preparación, los archivos que vexillum escribe en el camp y la privacidad de los modelos gratuitos.
Un ejemplo completo
Supongamos que querés que las missions grandes corran con effort xhigh, un perfil barato para trabajo solo de documentación, y Opus como respaldo. Escribí esto en .vexillum/models.json:
{
"profiles": {
"mission-big": { "effort": "xhigh" },
"docs-sweep": {
"model": "haiku",
"effort": "medium",
"when": "Mission that only touches documentation or comments, no behavior change."
}
},
"default": { "model": "opus" }
}mission-big pisa solo su effort, así que conserva sonnet y su when incluido. docs-sweep es nuevo, así que define los tres campos. default cambia solo su modelo. vx models entonces muestra:
mission-big (sonnet, xhigh)
Mission that is a big or ambiguous multi-file feature, a risky refactor, or work that requires holding many moving parts in mind.
opus-on-request (opus, high)
Only when the general explicitly asks for Opus on this task. Never chosen on your own.
docs-sweep (haiku, medium)
Mission that only touches documentation or comments, no behavior change.
default (opus, medium)
Nothing above fits. Fall back to it, do not reach for it on purpose.El perfil nuevo aparece después de los incluidos, y el commander ya puede elegirlo a partir de su línea when.