Коротко (TL;DR)
settings.json — это конфигурационный файл Claude Code, где живут разрешения (permissions), переменные окружения, хуки, модель и десятки других ключей. В отличие от CLAUDE.md, который даёт агенту поведенческие подсказки, settings.json — это техническое принуждение: то, что записано в permissions, соблюдается детерминированно, а не «на доверии».
- Коротко (TL;DR)
- settings.json и CLAUDE.md: разное назначение
- Пять уровней настроек и их приоритет
- permissions: allow, ask и deny
- Sandbox и безопасность: как ускориться правильно
- Риски: почему границы важны
- Полезные ключи settings.json
- Быстрый старт: рабочий settings.json за 5 минут
- Диагностика: когда настройка не применяется
- FAQ
Что важно понять сразу:
- Настройки лежат на пяти уровнях с жёстким приоритетом: managed (организация) → аргументы командной строки → local → project → user.
- Массивы (например,
permissions.allow) между уровнями не заменяются, а складываются — с двумя исключениями. - Правила permissions вычисляются в порядке deny → ask → allow: первое совпадение решает исход.
- Включённый sandbox сокращает количество запросов на подтверждение на 84% (внутренняя статистика Anthropic) — и это правильный способ ускориться, а не
--dangerously-skip-permissions. - Когда «настройка не применяется», разбираться помогает связка
/status,/config,/permissionsи/doctor.
Ниже — как устроена иерархия, как настроить permissions и sandbox безопасно, какие ключи полезны, какие тут реальные риски и как отлаживать конфиг, когда он ведёт себя не так.
settings.json и CLAUDE.md: разное назначение
Новички часто путают два файла и пытаются «настраивать» агента через CLAUDE.md. Официальное разграничение простое: settings — для технического принуждения, CLAUDE.md — для поведенческих договорённостей. CLAUDE.md рассказывает Claude, как устроен проект и как в нём принято работать; settings.json задаёт жёсткие рамки — что инструменту можно, а чего нельзя, и это соблюдается кодом.
Практический вывод: правило «не читай .env» в CLAUDE.md — пожелание, которое можно обойти; то же правило в permissions.deny — барьер. Всё, что критично (секреты, деструктивные команды), живёт в settings.json. Держите это разделение в голове — оно объясняет половину вопросов новичков «почему агент сделал то, что я запретил».
Пять уровней настроек и их приоритет
Claude Code собирает настройки из нескольких источников. Приоритет — от организации к личным предпочтениям:Приоритет Уровень Где лежит 1 (высший) Managed (организация) Системный путь / MDM, ставит админ 2 Аргументы командной строки Флаги при запуске claude3 Local (личный по проекту) .claude/settings.local.json4 Project (командный) .claude/settings.json (в git)5 (низший) User (личный) ~/.claude/settings.json
Логика такая: ~/.claude/settings.json задаёт ваши глобальные предпочтения для всех проектов; .claude/settings.json в репозитории — общие правила команды (коммитятся в git); .claude/settings.local.json — ваши личные переопределения для конкретного проекта. Последний Claude Code сам добавляет в .gitignore при создании, чтобы личные настройки не утекли в общий репозиторий. Managed-уровень стоит над всеми: правило, заданное администратором организации, локальным файлом перебить нельзя — это и есть смысл корпоративного контроля.
Как складываются значения между уровнями
Здесь тонкость, которую почти никто не объясняет. Скалярные ключи (одно значение — например, model) переопределяются по приоритету: выигрывает более высокий уровень. А вот массивы (permissions.allow, permissions.deny и подобные) между уровнями конкатенируются и дедуплицируются, а не заменяются.
Разберём на примере. Пусть в user-файле стоит "allow": ["Bash(git *)"], а в проектном — "allow": ["Bash(npm *)"]. Агент получит оба разрешения: и git, и npm. Массивы не конкурируют — они суммируются. То же с deny: запрет, заданный в managed-настройках, останется в силе, даже если в проектном файле его нет. Это важно понимать, иначе легко удивиться, откуда взялось разрешение, которого нет в вашем текущем файле.
Есть исключения. fallbackModel не складывается: его значение берётся с одного уровня целиком. С availableModels тоньше — он перестаёт мёржиться, только если его задаёт managed-источник (политика организации): тогда применяется именно этот список, а не сумма. На обычных уровнях (user, project, local) availableModels ведёт себя как любой другой массив — конкатенируется и дедуплицируется. Об этой оговорке не пишет ни один популярный гайд, а поведение неочевидное.
Ещё деталь про надёжность. Managed-настройки парсятся толерантно: если в них попала запись, не проходящая схему, Claude Code вырежет только её и применит остальное. Пользовательские, проектные и локальные файлы, наоборот, строгие — одна ошибка в JSON, и файл не применится целиком. Поэтому после ручной правки всегда проверяйте, что JSON валиден: пропущенная запятая молча «выключит» весь ваш settings.json.
permissions: allow, ask и deny
Ядро settings.json — блок permissions. Правила в нём вычисляются в строгом порядке: deny → ask → allow. Первое совпадение определяет исход, дальше поиск не идёт. Значит, deny всегда сильнее allow: если действие подпадает под запрет, никакое разрешение его не откроет.
Разберём на сценарии. Допустим, у вас allow: ["Bash(git *)"], но при этом deny: ["Bash(git push *)"]. Команда git status пройдёт по allow, а git push упрётся в deny — потому что deny проверяется первым. Так строится модель «в целом можно работать с git, но пушить — только вручную».
Три типа правил:
allow— разрешить без вопросов (например,Read(src/**),Bash(npm test)).ask— всегда спрашивать, даже если что-то ещё это разрешает.deny— запретить жёстко, поверх всего.
Режим по умолчанию задаёт defaultMode. Основные значения: default (спрашивать в неоднозначных случаях), acceptEdits (принимать правки файлов без вопросов), plan (только планировать, ничего не выполнять), bypassPermissions (пропускать все запросы).
Ещё важный синтаксический нюанс. «Голое» имя инструмента (Bash) в правиле относится к нему целиком, а точечный паттерн (Bash(curl *)) — только к конкретной команде. Путать их — частая ошибка: правило получается либо слишком широким (запретили весь Bash), либо дырявым (закрыли не то).
Про bypassPermissions — честно
bypassPermissions (он же флаг --dangerously-skip-permissions) пропускает все подтверждения, кроме форсированных явными ask-правилами. Единственный встроенный предохранитель — удаление корня и домашней папки (rm -rf / и rm -rf ~) он всё же блокирует. Всё остальное — на ваш риск, поэтому запускать его стоит только в контейнере или изолированной среде, а не на рабочей машине. Если цель — просто меньше кликать «разрешить», для этого есть более безопасный инструмент, о нём ниже.
Паттерн защиты секретов
Официально рекомендованный способ закрыть чувствительные файлы — связка deny на чтение секретов и на канал их утечки:
{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Bash(curl *)"
]
}
}
Смысл именно в паре: закрыть чтение .env мало — нужно перекрыть и очевидный канал эксфильтрации (curl), иначе агент, прочитав ключ иным путём, сможет его «отправить». Это тот случай, когда одно правило без другого создаёт ложное чувство защиты.
Sandbox и безопасность: как ускориться правильно
Постоянные запросы на подтверждение раздражают, и велик соблазн отключить их совсем. Правильный ответ — не bypassPermissions, а sandbox. По внутренней статистике Anthropic, включённый песочный режим безопасно сокращает количество запросов на 84%: агент работает в изоляции — запись только в рабочую папку, ограничения сети, — поэтому подтверждать каждое действие уже не нужно. Bash-sandbox поддерживается на macOS, Linux и WSL2.
Идея в разделении: sandbox даёт свободу действий внутри безопасной песочницы, а deny-правила закрывают то, что не должно случиться никогда. Вместе они снимают почти весь поток запросов, не открывая при этом машину нараспашку, как делает bypassPermissions.
Риски: почему границы важны
Раздел, который в туториалах по settings.json обычно опускают. Настройки прав — это не формальность: реальные инциденты показывают, что происходит, когда границы заданы неаккуратно.
- Инцидент Wolak (октябрь 2025). Разработчик сообщил, что Claude Code выполнил
rm -rf, удалив домашнюю директорию, — на Ubuntu/WSL2, причём без--dangerously-skip-permissions. Публичный баг-репорт стал одним из триггеров усиления предохранителей. - Инцидент с
~/(декабрь 2025). Развёрнутый путьrm -rf ~/привёл к удалению домашней папки — классическая ловушка развёртывания тильды оболочкой. - Баг наследования у субагентов (июль 2026). Рабочие субагенты не наследовали
allow-правила изsettings.local.jsonи спрашивали подтверждение на каждый вызов инструмента — пример того, как тонкости scope ломают ожидаемое поведение прав. - Инъекция через документ (2026). Отдельный, но родственной природы риск: prompt injection через невидимый текст в
.docxпоказал, что модель permissions приходится держать в уме и при работе с чужими файлами, а не только с командами.
Вывод не «Claude Code опасен», а «границы задаём мы». Sandbox плюс аккуратные deny-правила (секреты, деструктивные операции) снимают почти весь риск, не превращая работу в бесконечное «разрешить?». Баланс, который стоит держать: по умолчанию — запрет на опасное, свобода — внутри песочницы.
Полезные ключи settings.json
Кроме permissions, в settings.json есть ключи, которые стоит знать:Ключ Что делает Применяется modelМодель по умолчанию (например, Claude Sonnet 5 или Opus) Требует рестарта сессии envПеременные окружения для всех сессий и подпроцессов На лету hooksКоманды на события жизненного цикла агента На лету apiKeyHelperВнешняя команда, отдающая API-ключ (шлётся как заголовок) — companyAnnouncementsОбъявления, показываемые при старте —
Про перезагрузку: Claude Code следит за файлами настроек и перечитывает их на лету при изменении, так что правки большинства ключей применяются к текущей сессии сразу. Исключение — ключи вроде model и outputStyle: они требуют рестарта.
Ключ env удобен, когда нужно прокинуть переменную во все сессии и подпроцессы, — например, задать прокси или флаг для инструмента. Тут есть нюанс: переменные вроде NO_COLOR через env уходят в подпроцессы, но не меняют цвета самого интерфейса Claude Code — для интерфейса такую переменную ставят в shell до запуска claude. А hooks заслуживают отдельного упоминания: объявляются они прямо в settings.json и вешают вашу shell-команду на событие жизненного цикла. Простейший пример — уведомление:
{
"hooks": {
"Notification": [
{ "matcher": "", "hooks": [ { "type": "command", "command": "notify-send 'Claude ждёт ввод'" } ] }
]
}
}
Хуки — это то, что превращает договорённости из пожеланий в гарантии: линтер после каждой правки, блокировка опасной команды до её выполнения. Это тема отдельного разбора, но знать, что хуки живут именно в settings.json, важно уже сейчас: этот файл, в отличие от конфигов редакторов вроде Cursor, совмещает и права, и автоматизацию в одном месте.
Ещё пара ключей, о которых полезно знать заранее. apiKeyHelper — это внешняя команда, которую Claude Code запускает через системную оболочку, чтобы получить API-ключ; её вывод отправляется как заголовок авторизации. Приём удобен, когда ключ нельзя хранить в открытом виде: helper достаёт его из менеджера секретов на лету. А блок worktree.* управляет фоновой работой в изолированных git-worktree (например, worktree.baseRef — от какой ветки ответвляться): эти настройки живут по своим правилам scope и не всегда мёржатся по общему приоритету, так что если вы гоняете параллельные фоновые сессии, их конфигурацию проверяйте отдельно. Знать про эти ключи заранее полезно: наткнувшись на них в чужом settings.json, вы не будете гадать, откуда взялось «магическое» поведение.
Быстрый старт: рабочий settings.json за 5 минут
Чтобы теория не осталась теорией, вот минимальный, но осмысленный проектный .claude/settings.json, с которого разумно начать почти любой репозиторий:
{
"model": "claude-sonnet-5",
"permissions": {
"allow": [
"Read(src/**)",
"Bash(npm run test)",
"Bash(npm run lint)",
"Bash(git status)",
"Bash(git diff *)"
],
"ask": [
"Bash(git push *)"
],
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Bash(curl *)"
]
},
"env": {
"NO_COLOR": "1"
}
}
Разберём по строкам, что здесь заложено и почему:
modelфиксирует модель проекта — чтобы вся команда работала на одной, а не на той, что случайно выбрана в чьих-то личных настройках.allowоткрывает рутину без вопросов: читать исходники, гонять тесты и линт, смотреть статус и диффы git. Это те действия, подтверждать которые каждый раз — только терять время.askоставляет ручной контроль там, где цена ошибки высока:git pushвсегда спросит, даже несмотря на общее разрешение работать с git. Это тот самый порядок deny → ask → allow в действии.denyзакрывает секреты и канал их утечки — паттерн, который мы разобрали выше.envпрокидывает переменную во все сессии и подпроцессы; здесь для примера отключён цвет в подпроцессах, так же задают прокси или флаги инструментов (на цвет самого интерфейса Claude Code этот ключ не влияет).
Положите этот файл в .claude/settings.json, закоммитьте — и вся команда получит одинаковые правила. Личные отклонения (например, вы хотите разрешить себе ещё пару команд) добавляйте в .claude/settings.local.json, который не попадёт в git. Через пару недель работы вы уже будете точечно расширять allow под привычки проекта — но стартовый скелет закрывает 90% потребностей.
Диагностика: когда настройка не применяется
Главная боль — «я поменял settings.json, а ничего не изменилось». Вот рабочий чек-лист.Команда Что показывает /statusКакие уровни настроек загружены в сессию (строка Setting sources) /configТекущие значения; с v2.1.181 можно менять по одному: /config key=value/permissionsИтоговые правила allow/deny после всех мёржей /contextЧто реально попало в контекст /doctorОбщая диагностика окружения
Порядок разбора обычно такой. Сначала /status — убедиться, что нужный файл вообще подхватился (частая причина — невалидный JSON в строгом user- или project-файле, который не применился целиком). Затем /permissions — посмотреть, не перекрыто ли ваше allow чьим-то deny с более высокого уровня (вспоминаем порядок deny → ask → allow). Если поведение странное и вы подозреваете накопленные настройки, запустите Claude Code с чистым конфигом во временной папке — через переменную CLAUDE_CONFIG_DIR, указывающую на пустой каталог. Так вы проверите, воспроизводится ли проблема «с нуля» или её создаёт что-то в ваших файлах. Этот приём экономит часы: он сразу отделяет «баг инструмента» от «моей опечатки в JSON».
FAQ
Чем settings.json отличается от CLAUDE.md? settings.json — техническое принуждение (permissions, sandbox, hooks): соблюдается детерминированно. CLAUDE.md — поведенческие подсказки: советы, которые можно обойти. Критичные ограничения — только в settings.json.
Какой уровень настроек главнее?
Порядок приоритета: managed (организация) → аргументы командной строки → local → project → user. Managed-настройки админа перебить нельзя. Массивы при этом складываются со всех уровней, а не заменяются (кроме fallbackModel и availableModels).
Как безопасно убрать постоянные запросы на подтверждение?
Включить sandbox — он сокращает запросы примерно на 84% за счёт изоляции. Это безопаснее, чем bypassPermissions/--dangerously-skip-permissions, который стоит запускать только в контейнере.
Как защитить .env и секреты?
Через permissions.deny: закрыть и чтение (Read(./.env*), Read(./secrets/**)), и канал утечки (Bash(curl *)). Одно без другого дырявит защиту.
Почему правка settings.json не применилась?
Три частые причины: невалидный JSON (строгий файл не применяется целиком), правило перекрыто deny с более высокого уровня, или ключ требует рестарта (model, outputStyle). Проверяйте через /status и /permissions.
Что такое managed-настройки и можно ли их обойти? Это настройки, которые задаёт администратор организации на системном уровне (через MDM или системный путь). Они стоят на вершине приоритета — ни project-, ни local-, ни user-файл их не перебьёт. Именно так компания централизованно закрывает опасные действия на всех машинах. В отличие от остальных файлов, managed-настройки парсятся толерантно: одна невалидная запись не выключит весь файл.
Нужно ли коммитить settings.json в git?
.claude/settings.json — да, это общие правила команды, и держать их в репозитории правильно: новый разработчик клонирует проект и сразу получает те же разрешения и хуки. А .claude/settings.local.json — личные переопределения, Claude Code сам добавляет их в .gitignore, чтобы они не попали в общий репозиторий.
Курс «Claude Code с нуля до продакшена» · модуль «Конфиг, память, навыки». Полная программа и два маршрута обучения — на странице курса.
Предыдущий урок: CLAUDE.md: инструкция, которую агент читает · Следующий урок: Память Claude Code и memory rot
