설정

settings.json으로 설정하기

Ferret의 모든 설정은 하나의 JSON 파일에 있고 그 옆에 JSON Schema가 있으므로, 사용자 본인이나 사용 중인 코딩 에이전트(예: Claude Code, Codex, Gemini CLI)가 파일을 편집해 앱을 설정할 수 있습니다. 변경 사항은 앱이 실행 중일 때 바로 적용됩니다.

#파일 위치

경로는 모든 OS에서 같습니다.

~/.ferret/settings.json          # 내 설정 (이 파일을 편집)
~/.ferret/settings.schema.json   # JSON Schema, 앱 시작 시 앱이 다시 씀
~/.ferret/state.json             # 열린 폴더, 마지막 URL, 열린 탭 (앱이 관리)
~/.ferret/.env                   # 선택 사항: apiKeyEnv가 참조하는 API 키
  • 다른 폴더(예: 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 메뉴에 나오는 리뷰 대상입니다. 프로젝트를 열면 첫 번째 URL이 열립니다. id는 겹치지 않는 문자열이면 무엇이든 됩니다.
  • agents.customAgents: 임의의 CLI나 래퍼 스크립트입니다. startupAgents는 프로젝트를 열 때 함께 여는 에이전트 탭을 순서대로 나열합니다.
  • capture.sttEndpoints.compatible: OpenAI의 /v1/audio/transcriptions를 구현한 서버라면 무엇이든 됩니다(speaches, vLLM, LocalAI…). costLimitUsd: null은 비용 한도를 끕니다. 자체 GPU를 쓸 때 적합합니다. 음성 인식과 비용을 참고하세요.
  • organizer: 지적 사항 정리를 OpenAI 호환 /v1/chat/completions 서버(여기서는 Ollama)로 직접 보냅니다. 대신 자신의 CLI 로그인을 쓰려면 "runner": "claude-code" 또는 "codex"를 지정하고, 그 모델은 organizer.cliModels로 고릅니다.
  • decision: 각 지적 사항이 수정되었는지 확인하는 모델입니다. 로컬 Ollama의 Clef Flash는 무료이며 스크린샷을 읽을 수 있습니다. preset에는 cloudflare, vercel, typesafe, custom도 지정할 수 있습니다.
  • 모든 제공자 블록(sttEndpoints.*, organizer.endpoints.*)은 timeoutMs, headers, 그리고 Azure의 경우 apiVersion도 받습니다.

Ferret이 사용자 대신 AI 비용을 내는 일은 없습니다. 내장된 키도 중계 서버도 없습니다. 모든 요청은 사용자의 키로, 사용자의 컴퓨터에서 직접 설정한 엔드포인트로 갑니다.

#어떤 제공자든: 사용자 지정 엔드포인트

프리셋은 URL과 모델을 미리 채워 줄 뿐입니다. 모든 연결(음성 인식, 지적 사항 정리, 판정 모델)은 임의의 URL, 모델, 헤더, 인증을 받으므로 Cloudflare, 게이트웨이, 사내 프록시, 자체 서버 등 어떤 제공자든 쓸 수 있습니다. 아래 필드는 세 곳 모두에서 이름과 형태가 같습니다.

필드의미
baseUrl, model임의의 http(s) URL과 모델 이름. URL 안의 {account_id}는 accountId 또는 CLOUDFLARE_ACCOUNT_ID 환경 변수 값으로 바뀝니다
authSchemebearer (Authorization: Bearer <key>), header (authHeader로 지정한 이름의 헤더에 키를 넣음), none 중 하나. 생략하면 제공자의 기본값을 따릅니다
headers추가 헤더. 값은 일반 문자열이거나, 환경 변수에서 읽으려면 {"env": "VAR"}를 씁니다(apiKeyEnv와 같은 방식으로 찾음). Authorization이나 게이트웨이 토큰 같은 비밀 헤더는 {"env": …} 형태로만 받습니다. 설정 화면에서는 Name: ${VAR}로 적습니다
apiKey / apiKeyEnv키. API 키를 참고하세요

키를 api-key 헤더로 받는 OpenAI 호환 /v1/audio/transcriptions 서버로 음성 인식하는 예:

"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를 지원하는 임의의 서버를 쓰는 예입니다. 판정 모델은 endpoint에 전체 요청 URL을 받습니다({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나 시작 메뉴에서 연 앱은 셸 프로필에서 export한 변수를 볼 수 없으므로 ~/.ferret/.env가 확실한 위치입니다.
  3. 설정에서 저장한 키: OS 키체인으로 암호화되어 <userData>/stt-keys.bin에 저장됩니다(키 저장 위치 참고).

Ferret은 apiKeyEnv에 이름을 지정한 환경 변수만 읽습니다. 키는 로그에 남지 않고, UI에 표시되지 않으며, 충돌 보고서에도 포함되지 않습니다.

#실시간 반영

settings.json 편집: 앱이 실행 중인 상태로 변경 사항을 적용합니다.

Ferret은 settings.json을 감시합니다. 파일이 바뀌면 다시 읽고 스키마로 검사한 뒤 적용합니다. 테마, 언어, 레이아웃, 에이전트, 프로젝트, AI 엔드포인트가 재시작 없이 바뀌고 설정 화면도 새로 고쳐집니다.

  • 파일에 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에서 이 페이지 번역 돕기 (새 탭에서 열림)