Один и тот же параметр может прийти из нескольких источников, и вся тонкая настройка держится на том, чтобы знать их приоритет. Для обычного скалярного значения он таков: managed (политика организации) перекрывает CLI-аргументы, те - local (личное для этого репозитория), затем project (командное в репозитории) и user (личный default для всех проектов). Верхний слой перекрывает нижние - это и есть precedence, и без его понимания настройка превращается в гадание, почему значение "не то".
Слои различаются не только приоритетом, но и тем, коммитят ли их. managed приходит от администратора и несёт обязательные security- и compliance-правила. user живёт в ~/.claude и не коммитится - это личные defaults и UI. project лежит в .claude/settings.json и .mcp.json, коммитится и задаёт единый workflow команды. local в settings.local.json не коммитится - для машинных путей и экспериментов. Полезно один раз свести это в таблицу, чтобы класть настройку в правильный слой.
| Scope | Где | Коммитить | Для чего |
|---|---|---|---|
| managed | server / OS policy / managed-settings.json | администратор | Обязательные security/compliance |
| user | ~/.claude/settings.json | нет | Личные defaults, UI |
| project | .claude/settings.json, .mcp.json | да | Единый workflow команды |
| local | .claude/settings.local.json | нет | Машинные пути, эксперименты |
Слияние слоёв устроено по типу значения. Скалярное значение из более высокого источника просто заменяет нижнее. Объекты обычно deep-merge, а документированные массивы могут объединяться и дедуплицироваться. Но есть принципиальное исключение - permission allow, ask и deny: правила из разных scopes сохраняются вместе, а не заменяются. Это сделано намеренно, чтобы широкий user-allow не стирал project- или managed-deny; безопасность здесь важнее удобства перекрытия.
Полезно один раз увидеть минимальный settings с $schema, чтобы редактор давал автодополнение и валидацию. Ниже - фрагмент с моделью и permissions. Оговорка: schema может обновляться с задержкой относительно самого свежего CLI, поэтому при расхождении сначала сверяются с официальной страницей settings и changelog, а затем проверяют /doctor. Схема - помощник редактора, а не финальная истина о доступных ключах.
Managed-настройки доставляются несколькими путями, и их место зависит от ОС. Они могут прийти удалённо после входа, через MDM, реестр или plist, либо из системного каталога - своего на macOS, Linux/WSL и Windows. В системном каталоге можно использовать managed-settings.d с drop-in-файлами: база грузится первой, drop-in сортируются по имени, более поздние скаляры выигрывают, массивы объединяются, объекты deep-merge. Числовые префиксы вроде 10-telemetry.json делают порядок видимым.
Отдельно стоит понимать, что ~/.claude.json - не файл настроек. В нём Claude Code хранит OAuth-сессию, user- и local-состояние MCP, доверие к проектам и разрешённые инструменты, кэши. Его не редактируют как командную конфигурацию и не коммитят. Путать этот файл с settings - частая ошибка: правки в нём не задают политику, а могут повредить состояние сессии и доверия, которое потом придётся восстанавливать вручную.
Главное правило работы со слоями - проверять источник, а не предполагать. /status показывает строку Setting sources: сломанный JSON-источник вообще не считается загруженным, и это легко пропустить. /doctor диагностирует невалидные или вырезанные записи и конфликтующие определения. Claude Code хранит до пяти timestamped-бэкапов конфигурации, но это не заменяет version control для project-политики - настоящая история изменений живёт в git.
Официально большинство настроек перечитывается на лету, но есть исключения, о которых нужно знать: model читается при старте (менять через /model), а outputStyle входит в system prompt и требует /clear или перезапуска. Типичные провалы работы со scopes - положить обязательный deny в user-файл, откуда его снимут; спутать ~/.claude.json с settings; предположить эффективное значение вместо проверки /status. Кладите настройку в правильный слой и всегда сверяйтесь с фактическим источником.
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"model": "sonnet",
"permissions": {
"allow": ["Bash(npm run test:*)"],
"deny": ["Read(./.env)"]
}
}
// приоритет: managed > CLI > local > project > user; deny из scopes не снять