Configuración
Configurar con settings.json
Todos los ajustes de Ferret están en un único archivo JSON con un JSON Schema a su lado, así que tú o tu propio agente de programación (por ejemplo Claude Code, Codex o Gemini CLI) podéis configurar la app editando un archivo. Los cambios se aplican con la app en marcha.
#Dónde está el archivo
La ruta es la misma en todos los sistemas operativos:
~/.ferret/settings.json # your settings (edit this)
~/.ferret/settings.schema.json # JSON Schema, rewritten by the app on launch
~/.ferret/state.json # open folder, last URL, open tabs (managed by the app)
~/.ferret/.env # optional: API keys referenced by apiKeyEnv
- Define
FERRET_CONFIG_DIR(el nombre antiguoMOVIE_ADE_CONFIG_DIRtambién funciona) para usar otra carpeta, p. ej. una dentro de un repositorio de dotfiles.~se expande. - Las versiones de desarrollo (
pnpm dev) usan~/.ferret/dev/, así que trabajar en el código de Ferret nunca reescribe tus ajustes reales. - Al actualizar desde la 0.1.0: en el primer inicio, el antiguo
<userData>/settings.jsonse copia a los archivos nuevos. El archivo antiguo se deja en su sitio como copia de seguridad y nunca se modifica.
Al actualizar desde MOVIE-ADE: en el primer inicio, settings.json, state.json, usage/ y .env se copian de ~/.movie-ade/ a ~/.ferret/. La carpeta antigua se deja en su sitio y no se modifica.
En la app, Ajustes muestra la ruta arriba, con Abrir settings.json (lo edita en el editor integrado con autocompletado del esquema) y Mostrar en la carpeta.
#Esquema y validación
La primera línea de settings.json es "$schema": "./settings.schema.json". Editores como VS Code y agentes como Claude Code lo usan para el autocompletado, la validación y la descripción de cada campo. El esquema viene dentro de la app y se escribe junto al archivo en cada inicio, así que siempre coincide con la versión instalada.
Las claves que Ferret no conoce se conservan tal cual cuando la app guarda. Las pestañas abiertas, la última URL y el resto del estado de la sesión se guardan en state.json, no aquí.
#Ejemplo comentado
JSON no admite comentarios, así que las notas están debajo del ejemplo. Todos los campos son opcionales; omite lo que no necesites.
{
"$schema": "./settings.schema.json",
"theme": "dark",
"locale": "en",
"projects": [
{
"id": "shop",
"name": "shop",
"folderPath": "/Users/you/src/shop",
"kind": "web",
"urls": [
{ "id": "local", "label": "local", "url": "http://localhost:3000" },
{ "id": "prd", "label": "prd", "url": "https://shop.example.com" }
]
}
],
"agents": {
"customAgents": [
{ "id": "custom:my-agent", "name": "My agent", "command": "my-agent", "args": "--yes" }
],
"startupAgents": ["claude", "custom:my-agent"]
},
"capture": {
"transcription": "compatible",
"language": "auto",
"costLimitUsd": null,
"sttEndpoints": {
"compatible": {
"baseUrl": "http://gpu-box.local:8000/v1",
"model": "Systran/faster-whisper-large-v3",
"apiKeyEnv": "WHISPER_SERVER_TOKEN"
}
}
},
"organizer": {
"runner": "api:compatible",
"endpoints": {
"compatible": { "baseUrl": "http://localhost:11434/v1", "model": "qwen3:14b" }
}
},
"decision": {
"enabled": true,
"preset": "ollama",
"endpoint": "http://localhost:11434/v1/systemone",
"model": "clef-flash"
},
"layout": {
"panels": {
"projects": { "dock": "left", "visible": true },
"terminal": { "dock": "bottom", "visible": true },
"files": { "dock": "right", "visible": false }
}
}
}
projects[].urls: objetivos de revisión para el menú de URL. El primero se abre al abrir el proyecto.idpuede ser cualquier cadena única.agents.customAgents: cualquier CLI o script envoltorio.startupAgentsenumera, en orden, las pestañas de agente que se abren con un proyecto.capture.sttEndpoints.compatible: cualquier servidor que implemente/v1/audio/transcriptionsde OpenAI (speaches, vLLM, LocalAI…).costLimitUsd: nulldesactiva el límite de coste, lo que tiene sentido con tu propia GPU. Consulta Transcripción y costes.organizer: Organizar hallazgos enviado directamente a un servidor/v1/chat/completionscompatible con OpenAI (aquí Ollama). Usa"runner": "claude-code"o"codex"para usar en su lugar tu propia sesión del CLI, yorganizer.cliModelspara elegir su modelo.decision: el modelo que comprueba si cada hallazgo se corrigió. Clef Flash en un Ollama local es gratis y lee capturas de pantalla.presettambién puede sercloudflare,vercel,typesafeocustom.- Cada bloque de proveedor (
sttEndpoints.*,organizer.endpoints.*) también admitetimeoutMs,headersy, para Azure,apiVersion.
Ferret nunca paga IA en tu nombre. No hay ninguna clave integrada ni servidor relay: cada solicitud va de tu máquina al endpoint que configures, con tu clave.
#Cualquier proveedor: endpoints personalizados
Los preajustes solo rellenan la URL y el modelo. Cada conexión (transcripción, Organizar hallazgos, modelo de decisión) acepta además cualquier URL, modelo, cabeceras y autenticación, así que puedes usar cualquier proveedor: Cloudflare, un gateway, un proxy corporativo o tu propio servidor. Los campos de abajo tienen el mismo nombre y la misma forma en los tres.
| Campo | Significado |
|---|---|
baseUrl, model | Cualquier URL http(s) y nombre de modelo. {account_id} en la URL se sustituye por accountId o por la variable de entorno CLOUDFLARE_ACCOUNT_ID |
authScheme | bearer (Authorization: Bearer <key>), header (la clave en la cabecera indicada por authHeader) o none. Omítelo para mantener el valor predeterminado del proveedor |
headers | Cabeceras adicionales. Un valor es una cadena simple, o {"env": "VAR"} para leerlo de una variable de entorno (se busca igual que apiKeyEnv). Las cabeceras secretas, como Authorization o un token de gateway, solo se aceptan como {"env": …}. En la página de Ajustes, escribe Name: ${VAR} |
apiKey / apiKeyEnv | La clave; consulta Claves de API |
Transcripción con cualquier servidor /v1/audio/transcriptions compatible con OpenAI que quiera la clave en una cabecera api-key:
"capture": {
"transcription": "compatible",
"sttEndpoints": {
"compatible": {
"baseUrl": "https://stt.internal.example.com/v1",
"model": "whisper-large-v3",
"authScheme": "header",
"authHeader": "api-key",
"apiKeyEnv": "INTERNAL_STT_KEY",
"headers": { "X-Team": "design" }
}
}
}
Organizar hallazgos con Cloudflare Workers AI (chat completions compatible con OpenAI), opcionalmente a través de AI Gateway:
"organizer": {
"runner": "api:compatible",
"endpoints": {
"compatible": {
"baseUrl": "https://api.cloudflare.com/client/v4/accounts/{account_id}/ai/v1",
"model": "@cf/meta/llama-3.3-70b-instruct-fp8-fast",
"apiKeyEnv": "CLOUDFLARE_API_TOKEN",
"headers": { "cf-aig-authorization": { "env": "CF_AIG_TOKEN" } }
}
}
}
Modelo de decisión en Cloudflare Workers AI (Clef Flash), o con "preset": "custom" en cualquier servidor que hable la API de System One. El modelo de decisión recibe una URL de solicitud completa en endpoint (con {account_id} y {model} sustituidos); todos los demás campos tienen el mismo nombre y la misma forma que arriba:
"decision": {
"enabled": true,
"preset": "cloudflare",
"endpoint": "https://api.cloudflare.com/client/v4/accounts/{account_id}/ai/run/@cf/cloudflare/{model}",
"model": "clef-flash",
"authScheme": "bearer",
"apiKeyEnv": "CLOUDFLARE_API_TOKEN",
"headers": { "cf-aig-authorization": { "env": "CF_AIG_TOKEN" } }
}
Pon CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_API_TOKEN y las demás variables en ~/.ferret/.env. Los nombres de modelo de arriba son ejemplos. Consulta la lista de modelos de tu proveedor.
#Claves de API
Cada bloque de proveedor acepta una clave de una de estas tres formas. Gana la primera que se encuentre:
"apiKey": "…": la clave en texto plano ensettings.json. Cualquiera que pueda leer el archivo puede leer la clave, y Ajustes muestra una advertencia mientras haya una. Evítalo, sobre todo si el archivo está en un repositorio de dotfiles."apiKeyEnv": "OPENAI_API_KEY": el nombre de una variable de entorno. Ferret busca en su propio entorno, luego en el.envdel proyecto abierto y después en~/.ferret/.env. Las apps abiertas desde el Finder o el menú Inicio no ven las variables exportadas en el perfil de tu shell, así que~/.ferret/.enves el sitio fiable.- La clave guardada en Ajustes: cifrada con el llavero del sistema operativo en
<userData>/stt-keys.bin(consulta Dónde se guardan las claves).
Ferret solo lee una variable de entorno cuando la indicas en apiKeyEnv. Las claves nunca se registran, nunca se muestran en la interfaz y nunca se incluyen en los informes de fallos.
#Recarga en vivo
Ferret vigila settings.json. Cuando cambia, la app lo vuelve a leer, lo comprueba con el esquema y lo aplica: el tema, el idioma, el diseño, los agentes, los proyectos y los endpoints de IA se actualizan sin reiniciar, y la página de Ajustes se refresca.
- Si el archivo tiene un error de sintaxis JSON o un valor de tipo incorrecto, no se aplica nada de esa edición. La app mantiene los últimos ajustes válidos, muestra el error con su número de línea y no sobrescribe tu archivo hasta que lo corrijas.
- Cuando es la app la que guarda (cambiaste algo en Ajustes), escribe en un archivo temporal y lo renombra sobre
settings.json, así que un fallo nunca deja un archivo a medio escribir.
#Deja que tu agente de programación configure Ferret
Pega esto en Claude Code, Codex o cualquier agente que pueda editar archivos:
Edit ~/.ferret/settings.json following the JSON Schema in
~/.ferret/settings.schema.json (read the field descriptions first).
Keep unknown keys and keep the file valid JSON. Never write API keys in
plaintext: set "apiKeyEnv" to an environment variable name instead and
tell me which variable to put in ~/.ferret/.env.
Ferret applies the change as soon as the file is saved.
Task: <what you want, e.g. "use my Ollama at http://localhost:11434 with
qwen3:14b for Organize findings and add a prd URL for the shop project">
El mismo prompt, con tus rutas reales ya puestas, está en Ajustes → Deja que tu agente de programación configure Ferret, con un botón Copiar prompt.
Ayuda a traducir esta página en GitHub (se abre en una pestaña nueva)