Настройка

Настройка через settings.json

Все настройки Ferret хранятся в одном JSON-файле, рядом с которым лежит JSON Schema, поэтому вы или ваш собственный агент для написания кода (например, Claude Code, Codex или Gemini CLI) можете настраивать приложение, редактируя файл. Изменения применяются, пока приложение работает.

#Где находится файл

Путь одинаков во всех ОС:

~/.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
  • Чтобы использовать другую папку, например внутри репозитория dotfiles, задайте FERRET_CONFIG_DIR (старое имя MOVIE_ADE_CONFIG_DIR тоже работает). ~ раскрывается.
  • Сборки для разработки (pnpm dev) используют ~/.ferret/dev/, поэтому работа над самим Ferret никогда не перезаписывает ваши настоящие настройки.
  • Обновление с 0.1.0: при первом запуске старый <userData>/settings.json копируется в новые файлы. Старый файл остаётся на месте как резервная копия и никогда не изменяется.

Обновление с MOVIE-ADE: при первом запуске settings.json, state.json, usage/ и .env копируются из ~/.movie-ade/ в ~/.ferret/. Старая папка остаётся на месте и не изменяется.

В приложении путь показан вверху страницы Настройки, вместе с кнопками Открыть settings.json (редактирование во встроенном редакторе с автодополнением по схеме) и Показать в папке.

#Схема и проверка

Первая строка settings.json — "$schema": "./settings.schema.json". Редакторы, такие как VS Code, и агенты, такие как Claude Code, используют её для автодополнения, проверки и описания каждого поля. Схема поставляется внутри приложения и записывается рядом с файлом при каждом запуске, поэтому всегда соответствует установленной версии.

Ключи, которые Ferret не знает, при сохранении остаются как есть. Открытые вкладки, последний URL и другое состояние сеанса хранятся в state.json, а не здесь.

#Пример с пояснениями

В JSON нет комментариев, поэтому пояснения даны под примером. Все поля необязательны; опускайте то, что вам не нужно.

{
  "$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: цели ревью для меню URL. Первая открывается при открытии проекта. id может быть любой уникальной строкой.
  • agents.customAgents: любой CLI или скрипт-обёртка. startupAgents перечисляет вкладки агентов, открываемые вместе с проектом, по порядку.
  • capture.sttEndpoints.compatible: любой сервер, реализующий /v1/audio/transcriptions OpenAI (speaches, vLLM, LocalAI…). costLimitUsd: null отключает лимит расходов, что разумно для собственного GPU. См. Распознавание речи и расходы.
  • organizer: Обработать замечания с отправкой напрямую на OpenAI-совместимый сервер /v1/chat/completions (здесь Ollama). Чтобы вместо этого использовать собственный вход в CLI, укажите "runner": "claude-code" или "codex", а модель для них выберите в organizer.cliModels.
  • decision: модель, которая проверяет, исправлено ли каждое замечание. Clef Flash на локальном Ollama бесплатна и читает скриншоты. preset также может быть cloudflare, vercel, typesafe или custom.
  • Каждый блок провайдера (sttEndpoints.*, organizer.endpoints.*) также принимает timeoutMs, headers и, для Azure, apiVersion.

Ferret никогда не платит за ИИ от вашего имени. Встроенного ключа и релея нет: каждый запрос идёт с вашего компьютера на настроенный вами эндпоинт с вашим ключом.

#Любой провайдер: свои эндпоинты

Пресеты лишь заранее заполняют URL и модель. Каждое подключение (распознавание, обработка замечаний, модель решений) также принимает любой URL, модель, заголовки и способ аутентификации, поэтому можно использовать любого провайдера: Cloudflare, шлюз, корпоративный прокси или собственный сервер. Поля ниже называются и устроены одинаково во всех трёх.

ПолеЗначение
baseUrl, modelЛюбой URL http(s) и имя модели. {account_id} в URL заменяется на accountId или на переменную окружения CLOUDFLARE_ACCOUNT_ID
authSchemebearer (Authorization: Bearer <key>), header (ключ в заголовке, имя которого задано в authHeader) или none. Не указывайте, чтобы оставить значение провайдера по умолчанию
headersДополнительные заголовки. Значение — обычная строка или {"env": "VAR"}, чтобы взять его из переменной окружения (поиск как у apiKeyEnv). Секретные заголовки, такие как Authorization или токен шлюза, принимаются только в виде {"env": …}. На странице настроек пишите Name: ${VAR}
apiKey / apiKeyEnvКлюч, см. API-ключи

Распознавание на любом OpenAI-совместимом сервере /v1/audio/transcriptions, который ожидает ключ в заголовке 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" }
    }
  }
}

Обработка замечаний через Cloudflare Workers AI (OpenAI-совместимые chat completions), при желании через 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" } }
    }
  }
}

Модель решений на Cloudflare Workers AI (Clef Flash) или, с "preset": "custom", на любом сервере, поддерживающем System One API. Модель решений принимает полный URL запроса в endpoint (с подставленными {account_id} и {model}); остальные поля называются и устроены так же, как выше:

"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" } }
}

Поместите CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_API_TOKEN и другие переменные в ~/.ferret/.env. Имена моделей выше — примеры. Сверьтесь со списком моделей вашего провайдера.

#API-ключи

Каждый блок провайдера принимает ключ одним из трёх способов. Используется первый найденный:

  1. "apiKey": "…": ключ открытым текстом в settings.json. Любой, кто может прочитать файл, может прочитать ключ, и пока такой ключ есть, Настройки показывают предупреждение. Избегайте этого, особенно если файл лежит в репозитории dotfiles.
  2. "apiKeyEnv": "OPENAI_API_KEY": имя переменной окружения. Ferret ищет её в своём окружении, затем в .env открытого проекта, затем в ~/.ferret/.env. Приложения, открытые из Finder или меню «Пуск», не видят переменных, экспортированных в профиле оболочки, поэтому надёжнее всего ~/.ferret/.env.
  3. Ключ, сохранённый в Настройки: шифруется хранилищем ключей ОС в <userData>/stt-keys.bin (см. Где хранятся ключи).

Ferret читает переменную окружения, только если вы указали её имя в apiKeyEnv. Ключи никогда не пишутся в журнал, не показываются в интерфейсе и не включаются в отчёты о сбоях.

#Применение на лету

Редактирование settings.json: приложение применяет изменение, не прекращая работы.

Ferret следит за settings.json. Когда файл меняется, приложение перечитывает его, проверяет по схеме и применяет: тема, язык, раскладка, агенты, проекты и эндпоинты ИИ обновляются без перезапуска, а страница настроек обновляется.

  • Если в файле синтаксическая ошибка JSON или значение неверного типа, ничего из этой правки не применяется. Приложение сохраняет последние корректные настройки, показывает ошибку с номером строки и не перезаписывает ваш файл, пока вы её не исправите.
  • Когда сохраняет само приложение (вы что-то изменили в Настройки), оно пишет во временный файл и переименовывает его поверх settings.json, поэтому сбой никогда не оставит наполовину записанный файл.

#Пусть агент настроит Ferret

Вставьте это в Claude Code, Codex или любого агента, который умеет редактировать файлы:

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">

Тот же промпт с подставленными реальными путями находится в Настройки → Пусть агент настроит Ferret вместе с кнопкой Копировать промпт.

Помочь с переводом этой страницы на GitHub (откроется в новой вкладке)