Короткий перелік змін, що впливають на існуючі settings.json. Перевір свої конфіги на ці пункти.
Деякі старі значення тепер мовчки ігноруються або ламають валідацію файлу — наприклад cleanupPeriodDays: 0 чи matcher: "Bash(git push*)".
| моделі | Opus 5.5 — default (Microsoft Foundry: Sonnet 4.5; Enterprise-адмін може задати organization default, v2.1.196+); аліаси opus/sonnet/haiku/fable → Opus 5.5 / Sonnet 5.5 / Haiku 5.5 / Fable 5.1 |
| defaultMode | новий режим "auto" — стартовий в інтерактивному терміналі; "manual" = аліас "default" |
| effort | рівні low…max; /effort зберігає в modelSettings; новий ліміт maxEffortLevel (v2.1.267+, також по-модельно в modelSettings) |
| hooks | 33 події; тип mcp_tool; аргументи фільтруються полем "if", а не в matcher |
| cleanupPeriodDays | мінімум 1 — значення 0 тепер не проходить валідацію |
| ANTHROPIC_SMALL_FAST_MODEL | deprecated → ANTHROPIC_DEFAULT_HAIKU_MODEL |
| BASH_DEFAULT_TIMEOUT_MS | default 120000 мс (2 хв), а не 30 с |
| settings.local.json | з v2.1.211 читається з кореня git-репозиторію |
| managed | drop-in каталог managed-settings.d/*.json; managedSourcesBehavior: "merge" (v2.1.242+) |
| attribution | можна false — сховати все; нове поле sessionUrl |
| нові ключі моделі | advisorModel, modelPicker, modelPricing, modelOverrides, availableModelsMatch, promptCacheTtl, ultracode — див. розділ model |
| нові ключі організації | allowedProviders (v2.1.285+), policyHelper, disableSideloadFlags, parentSettingsBehavior, wslInheritsWindowsSettings — див. розділ enterprise / managed |
| файли і пріоритети | усі шляхи, порядок managed-джерел і винятки зібрані в розділі файли і пріоритети |
Файли налаштувань і пріоритети
Де лежить кожен файл, що перемагає при конфлікті і як зливаються managed-джерела
Claude Code читає налаштування з чотирьох файлів (user, shared project, project local і managed-settings.json); організація може доставляти managed-налаштування й іншими механізмами. Окремий файл ~/.claude.json Claude Code пише сам для себе. Нічого з цього не створюється при встановленні: файл з’являється, коли ти змінюєш опцію в /config або даєш постійний дозвіл у запиті прав.
Файли і області
| Область | Шлях | Кого стосується | Для чого |
|---|---|---|---|
| User | ~/.claude/settings.jsonWindows: %USERPROFILE%\.claude\settings.json | ти, у всіх проєктах на машині | особисте: тема, editorMode, модель, власні правила. Каталог можна перенести змінною CLAUDE_CONFIG_DIR |
| Shared project | .claude/settings.json | усі, хто працює в проєкті (комітиться) | дозволи команди, hooks, плагіни, env проєкту |
| Project local | .claude/settings.local.json | лише ти, у цьому проєкті | особисті перевизначення й експерименти; сюди Claude Code пише «Yes, and don’t ask again» |
| Global config | ~/.claude.json | ти (Claude Code пише сам) | сесія входу, MCP-сервери, довіра по проєктах, global config keys (autoConnectIde, diffTool тощо). Ці ключі поза цим файлом ігноруються |
| Managed | див. таблицю нижче | усі, кому розгорнуто політику | безпека й compliance; сильніше за все інше |
Де саме лежить local-файл. У git-репозиторії його читають і пишуть у корені репо (у worktree — корінь основного checkout), з v2.1.211. Він лишається поруч із .claude/settings.json, якщо проєкт поза git, корінь репо — це $HOME, ОС — Windows або корінь/.git/.claude належать не вам. Старий файл у стартовій теці ще читається (при конфлікті виграє корінь; правила прав зливаються з обох). Перший запис додає **/.claude/settings.local.json у глобальні git excludes (core.excludesFile, інакше $XDG_CONFIG_HOME/git/ignore або ~/.config/git/ignore); файл, створений руками, до .gitignore додай сам. Його allow-правила не чекають довіри, поки файл не під git.
Спільний .claude/settings.json читається з основної робочої теки сесії: щоб діяв файл у корені репо, запускай Claude Code саме там. Після /cd обидва проєктні файли читаються з нової теки (v2.1.246+).
Managed: звідки і де лежить
| Механізм | macOS | Linux / WSL | Windows | Коли читається |
|---|---|---|---|---|
| Server-managed | консоль claude.ai або self-hosted Claude apps gateway | те саме | те саме | fetch на старті, опитування щогодини |
| MDM / політика ОС | configuration profile, домен com.anthropic.claudecode | — | реєстр HKLM: HKLM\SOFTWARE\Policies\ClaudeCode, значення Settings (REG_SZ або REG_EXPAND_SZ) з JSON | на старті + перевірка кожні 30 хв |
| Файли | /Library/Application Support/ClaudeCode/ | /etc/claude-code/ | C:\Program Files\ClaudeCode\ | на старті, перезавантаження при зміні файлу |
| HKCU (резерв) | — | WSL: коли HKLM/Windows-файл вмикає wslInheritsWindowsSettings і HKCU теж ставить його | HKCU\SOFTWARE\Policies\ClaudeCode → Settings; user-writable | на старті + кожні 30 хв; лише коли вище немає admin-документа |
У каталозі файлів лежать managed-settings.json, необов’язковий managed-settings.d/*.json і managed-mcp.json. Старий C:\ProgramData\ClaudeCode\managed-settings.json не читається. Шаблони для Jamf, Iru, Intune і Group Policy є в репозиторії anthropics/claude-code (examples/mdm). Є ще parent settings — managed-налаштування від процесу-хоста (опція managedSettings в Agent SDK, Claude Desktop); керує ними parentSettingsBehavior.
Cloud-сесія на свіжому клоні читає лише закомічений .claude/settings.json (якщо в сесії один репозиторій) та server-managed settings. User- і local-файли, а також MDM/файл з пристрою, туди не доходять.
Порядок пріоритету
- Managed — нічим не перевизначається (з винятками нижче). Managed
model— стартовий default, а не замок: замки цеavailableModelsіdeniedModels. - Командний рядок
--settings <файл-або-JSON>— лише на цю сесію. Інші прапори (--model) задають одну річ і не входять у стек. - Project local
.claude/settings.local.json. - Shared project
.claude/settings.json. - User
~/.claude/settings.json.
Змінні середовища — не рівень стека. Для кожної пари «змінна ↔ ключ» вирішено окремо: ANTHROPIC_MODEL перебиває ключ model з будь-якого файлу, а ANTHROPIC_DEFAULT_MODEL діє, лише якщо жоден файл не задає model. Блок env у файлі — звичайний ключ, що йде за рівнями вище.
Порядок усередині managed
- Remote / server-managed — лише коли сесія автентифікується прямо в Anthropic прийнятним credential або входить у gateway через
/login. На інших провайдерах чи з іншимANTHROPIC_BASE_URLпочинається з наступного пункту. - MDM — plist або HKLM.
- Файли —
managed-settings.jsonразом зmanaged-settings.d/*.json. - HKCU — лише коли вище немає жодного admin-документа (документ «присутній», якщо задає будь-який ключ політики не-
null, навіть нечитабельний, або якщо HKLM-значення / файл / каталог існує, але нечитабельний).
managedSourcesBehavior
| Значення | Поведінка |
|---|---|
"first-wins" (default) | діє найвище джерело, що несе хоча б один ключ політики; решту ігноровано без попередження (джерело видно в /status → Setting sources). Виняток — ключі, які читаються з усіх admin-джерел (нижче). Файл із самими лише managedSourcesBehavior / wslInheritsWindowsSettings джерелом політики не вважається. |
"merge" (v2.1.242+) | застосовуються всі admin-джерела, поєднані за видом ключа. Задавай у найвищому джерелі, яке розгортаєш (на машині без server-managed — і в MDM-профілі); у managed-settings.json він марний, бо нижче немає з чим зливати. HKCU і parent settings у злитті не беруть участі. Вмикай лише там, де всі нижчі джерела під контролем адміністратора: з них підтягнуться навіть permissions.allow. |
| Вид ключа при merge | Як поєднується |
|---|---|
списки (permissions.allow, sandbox.network.allowedDomains…) | записи з усіх джерел |
замки (allowManagedPermissionRulesOnly, permissions.disableBypassPermissionsMode…) | найсуворіше значення будь-якого джерела |
allowlist-обмеження (availableModels, allowedMcpServers, allowedProviders, strictKnownMarketplaces, allowedChannelPlugins, ланцюг fallbackModel) | список цілком з найвищого джерела, що його задає, без додавання з нижчих |
значення цілком (sandbox.credentials.awsPairs, sandbox.ripgrep, v2.1.257+) | з найвищого джерела цілком |
managedMcpServers | імена з усіх джерел; однакове ім’я — запис вищого цілком |
| лише з найвищого джерела | apiKeyHelper, awsAuthRefresh, awsCredentialExport, gcpAuthRefresh, otelHeadersHelper, proxyAuthHelper, forceLoginOrgUUID, значення "claudeai"/"console" у forceLoginMethod, parentSettingsBehavior, modelPicker, policyHelper, permissions.defaultMode |
env | по змінних, і при first-wins теж (v2.1.223+) |
| решта | значення найвищого джерела |
Ключі, що читаються з усіх admin-джерел навіть при first-wins (HKCU у цьому скануванні не бере участі): замки sandbox.network.allowManagedDomainsOnly і sandbox.filesystem.allowManagedReadPathsOnly; allowAllClaudeAiMcps; allowManagedMcpServersOnly; deniedMcpServers і disableClaudeAiConnectors (v2.1.273+); sandbox.bwrapPath, socatPath, ripgrep; sandbox.filesystem.disabled, sandbox.network.strictAllowlist; useAutoModeDuringPlan, syncClaudeAiSkills, syncClaudeAiPlugins (false з будь-якого); enableArtifact; maxEffortLevel (найнижча стеля); відмова від commit-trailer у attribution; forceRemoteSettingsRefresh; env по змінних. Ключі gateway-входу (forceLoginGatewayUrl, gatewayInternalNetworks, "gateway") ніколи не читаються з server-managed.
Розбиття політики на файли: managed-settings.d
Якщо частинами політики володіють різні команди, поклади кожну в окремий файл у managed-settings.d/ поруч з managed-settings.json. Спершу зливається managed-settings.json, потім усі *.json в алфавітному порядку (префікси 10-telemetry.json, 20-security.json); приховані файли й не-.json ігноруються.
| Що | Правило злиття |
|---|---|
одиничні значення ("model", "cleanupPeriodDays") | пізніший файл замінює |
списки (permissions.deny, sandbox.network.allowedDomains) | об’єднуються без дублікатів |
вкладені блоки (env, sandbox) | зливаються ключ за ключем, кожен ключ — за цими ж правилами |
fallbackModel, modelPicker, однойменні записи extraKnownMarketplaces / managedMcpServers | пізніший замінює цілком |
Правила злиття між user / project / local / --settings
- Скаляри: виграє файл вищого пріоритету.
- Списки (
permissions.allow/deny/ask, масиви sandbox,allowedHttpHookUrls,httpHookAllowedEnvVars,allowedMcpServers/deniedMcpServers): об’єднуються, кожен файл лише додає. - Винятки зі злиття:
fallbackModel(весь ланцюг з найвищого файлу),modelPicker(цілком з найвищого з managed,--settings, user; у project/local ігнорується),availableModels(managed-список застосовується як є, не-managed області зливаються),modelSettings(по моделях разом зeffortLevel),extraKnownMarketplaces(однойменний запис вищого файлу замінює цілком, з v2.1.228). - hooks зливаються між файлами, а hooks з managed видалити не можна.
- Довіра до робочої теки: у проєктному файлі лише після довіри діють
permissions.allow,additionalDirectories,extraKnownMarketplaces, більшістьenv, hooks / statusLine / fileSuggestion і projectapiKeyHelper. Правилаdenyіaskдіють одразу.
Винятки: коли нижчий рівень сильніший за managed
Для ключів-обмежень Claude Code шанує суворіше значення навіть з області, яка інакше не може перевизначити managed.
| Ключ | Що шанується | Примітка |
|---|---|---|
disableClaudeAiConnectors | true з будь-якої області | навіть коли managed ставить false |
enableArtifact / disableArtifact | false / true з будь-якої області | нічого не вмикає Artifact назад; v2.1.242+ |
isolatePeerMachines | true з будь-якої області | — |
permissions.blockReadsOutsideWorkingDirectories | true з будь-якої області | v2.1.257+ |
autoMode.classifyAllShell | true з user або --settings | навіть над managed false |
remoteControlAtStartup | false з project / local | true з project/local ігнорується |
crossSessionInbound | суворіше значення з project / local | драбина accept < hold < refuse |
useAutoModeDuringPlan | false з managed, --settings, user, local | false у .claude/settings.json ігнорується |
syncClaudeAiSkills / syncClaudeAiPlugins | false з managed, --settings, user, local | false у .claude/settings.json ігнорується |
maxEffortLevel | нижча стеля з будь-якої області, включно з --settings | v2.1.267+ |
Окремий виняток — застосунок-хост, що задає CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST: його модельна конфігурація перекриває managed-ключі model, fallbackModel, modelPicker, modelOverrides та змінні вибору моделі в managed env; managed availableModels лишається в силі, якщо хост не дає свій.
Де що тримати: Django + Vue команда
| Що | Куди | Чому |
|---|---|---|
Спільні allow / deny (Bash(python manage.py test *), Bash(npm run lint), deny на Read(./.env)) | .claude/settings.json, комітити | однакові правила для всіх; allow діє після довіри до теки, deny — одразу |
Hooks (ruff / eslint після Edit), плагіни команди | .claude/settings.json | hooks зливаються з особистими й managed |
env проєкту (DJANGO_SETTINGS_MODULE, API_BASE для Vue dev-сервера) | .claude/settings.json → env | не клади сюди секрети: значення лежать у файлі відкритим текстом |
Особисте: model, theme, editorMode, outputStyle, autoUpdatesChannel | ~/.claude/settings.json | діє в усіх проєктах, не торкається колег |
| Особисті експерименти й «don’t ask again» для цього репо | .claude/settings.local.json (Claude Code створює сам) | не потрапляє в коміти; allow-правила тут не чекають довіри |
| API-ключі, токени | не в settings: apiKeyHelper (Vault), змінні shell | ключ не лежить на диску розробника |
| MCP-сервери | .mcp.json проєкту або ~/.claude.json (див. розділ mcp) | MCP-конфігурація живе окремо від settings.json |
Організаційні вимоги (availableModels, deniedModels, allowManagedPermissionRulesOnly, sandbox-замки, requiredMinimumVersion) | managed: server-managed (Team/Enterprise без MDM) або файли в /Library/Application Support/ClaudeCode/, /etc/claude-code/ | нічим не перевизначається; розбивай на 10-telemetry.json, 20-security.json |
{
"permissions": {
"allow": ["Bash(python manage.py test *)", "Bash(npm run lint)", "Bash(npm run test:unit *)"],
"deny": ["Read(./.env)", "Bash(python manage.py flush *)"]
},
"env": {
"DJANGO_SETTINGS_MODULE": "config.settings.dev"
}
}Щоб побачити, які джерела реально застосувалися, виконай /status — рядок Setting sources називає managed-джерело, яке діє, і пропущені. Розбір «чому ключ не діє» — claude --debug і claude doctor.
Як Claude Code ухвалює рішення про виклик інструмента
Правила дозволів виконує Claude Code, а не модель: інструкції в промпті чи CLAUDE.md впливають на те, що Claude намагається зробити, але не на те, що йому дозволено. Порядок такий:
- Хуки PreToolUse запускаються перед запитом на підтвердження. Хук з exit code 2 зупиняє виклик ще до перевірки правил — навіть якщо збігається allow-правило і навіть у
bypassPermissions. Рішення хукаallowне обходить правила deny та ask. - Правила перевіряються в порядку
deny→ask→allow. Виграє перше співпадіння, специфічність не має значення: широкийBash(aws *)у deny блокує навіть виклик, який збігається з вужчимBash(aws s3 ls)в allow. - Немає жодного збігу — вирішує режим дозволів (
defaultMode): default питає, acceptEdits автоматично приймає редагування, dontAsk відхиляє, bypassPermissions пропускає. - Запобіжники, які не відключає жоден режим: явні ask-правила,
rm/rmdirпо «критичних шляхах» (корінь, домашня тека, робоча тека і її батьки), інструменти зrequiresUserInteraction,AskUserQuestion.
Якщо інструмент заборонений на будь-якому рівні, жоден інший рівень його не дозволить: deny з user-файлу блокує allow з проєкту, managed deny не перебити через --allowedTools. Прапор --disallowedTools лише додає обмеження.
«Yes, and don’t ask again» для Bash зберігає правило на постійно для репозиторію й команди (у .claude/settings.local.json у корені git-репозиторію, з v2.1.211). Для складеної команди зберігається окреме правило на кожну підкоманду, до 5 штук. Дозволи на редагування файлів діють лише до кінця сесії.
Синтаксис правил за типом інструмента
Загальна форма — Tool або Tool(специфікатор). Дужки всередині специфікатора літеральні, екранувати їх не треба. Bash(*) — те саме, що Bash.
| Інструмент | Форма правила | Приклад | Як збігається |
|---|---|---|---|
| Будь-який | Tool | WebFetch, Read | Усі виклики інструмента. Голе ім’я в deny прибирає інструмент з контексту Claude, а Bash(rm *) лишає інструмент і блокує лише збіги |
| Bash | Bash(команда) | Bash(npm run build), Bash(git log *) | Увесь текст команди; без * — точний збіг. Складені команди розбираються на підкоманди (див. нижче) |
| PowerShell | PowerShell(...) | PowerShell(Get-ChildItem *) | Та сама форма, що й Bash. Аліаси канонізуються (gci, ls, dir = Get-ChildItem), регістр не важливий |
| Read / Edit | Read(шлях), Edit(шлях) | Read(./.env), Edit(/src/**/*.ts) | Синтаксис gitignore з префіксами //, ~/, / (таблиця нижче). Edit діє на всі інструменти редагування |
| WebFetch | WebFetch(domain:хост) | WebFetch(domain:*.djangoproject.com) | Ім’я хоста з URL, без урахування регістру, кінцева крапка ігнорується |
| MCP | mcp__сервер, mcp__сервер__*, mcp__сервер__інструмент | mcp__github__get_* | Перші дві форми — усі інструменти сервера. Плагінні сервери: mcp__plugin_<плагін>_<сервер>__<інструмент>, конектори claude.ai: mcp__claude_ai_<сервер>__<інструмент> |
| Agent | Agent(Назва) | Agent(Explore), Agent(my-reviewer) | Субагент за назвою; зазвичай у deny або --disallowedTools |
| Skill | Skill, Skill(name), Skill(name *) | Skill(deploy *) | Skill — усі скіли; Skill(name) — точна назва; Skill(name *) — префікс з будь-якими аргументами. Deny-правило у параметричній формі Skill(skill:name) збігається зі скілом під будь-якою його назвою (аліас, display name) |
| Cd | Cd(шлях) | Cd(~/code/**) | Лише для команди /cd, яку запускаєте ви (Claude її викликати не може). Голе Cd у deny вимикає /cd; будь-яке Cd у allow вмикає режим allowlist. * — один сегмент шляху, ** — багато |
| Параметр | Tool(param:value) | Agent(model:opus), Bash(run_in_background:true) | Лише deny та ask, див. нижче |
| Glob за іменем | "mcp__*", "*" | "deny": ["mcp__*"] | У deny/ask glob має збігатися з повним іменем інструмента. В allow glob дозволений лише після літерального префікса mcp__<сервер>__; неприв’язаний "*" чи "mcp__*" в allow пропускається з попередженням |
Якщо в deny/ask назва інструмента нікому не відповідає, Claude Code попереджає при старті. Користуйтеся канонічними іменами (TaskStop), а не підписами з UI («Stop Task»). Правила зі шляхами для Write, NotebookEdit, Glob, MultiEdit приймаються, але ніколи не перевіряються — пишіть Edit(...) і Read(...).
Bash: wildcard-и, складені команди й обгортки
* у правилі Bash збігається з будь-яким текстом, включно з пробілами, і може стояти будь-де. Ставте * після підкоманди: для git log --oneline main програма — git, підкоманда — log, тому Bash(git log *) дозволяє лише git log, а Bash(git *) — усі git-команди. Для allow-правила з * перед підкомандою (Bash(git * main)) є попередження при старті.
| Правило | Збігається | Не збігається |
|---|---|---|
Bash(npm run build) | npm run build | npm run build --watch |
Bash(npm run *) | npm run build, npm run test --watch, npm run | npm install |
Bash(ls *) | ls -la, ls | lsof |
Bash(ls*) | ls -la, lsof | — |
Bash(git log * main) | git log --oneline main | git log main |
Bash(* --version) | node --version | node -v |
- Кінцевий
*(з пробілом) збігається й з «голою» командою (Bash(ls *)=ls), але лише якщо це єдиний wildcard у правилі. Пробіл перед*— частина правила. :*на кінці (Bash(ls:*)) — застарілий синонім кінцевого*; розпізнається лише в кінці шаблону. Діалог дозволів пише канонічну форму з пробілом.- Складені команди. Роздільники:
&&,||,;,|,|&,&, нові рядки. Allow-правило має збігатися з кожною підкомандою окремо; deny/ask спрацьовують, якщо збіглась будь-яка підкоманда, навіть всередині$(), підоболонки чи циклуfor. Команда із завислим&&на кінці вважається нерозбірною, і allow її не схвалює. - Обгортки, які прибираються перед порівнянням:
timeout,time,nice,nohup,stdbuf,command,builtin, zshnoglob, «голий»xargs(без прапорців). Відомі безпечні змінні середовища на початку (NODE_ENV=test npm test) прибираються для allow; для deny/ask правило збігається поверх будь-якого присвоєння. - Не прибираються:
direnv exec,devbox run,mise exec,npx,docker exec—Bash(devbox run *)збігається зdevbox run rm -rf .. Пишіть правило з бігунком і внутрішньою командою:Bash(devbox run npm test).watch,setsid,ionice,flockіfind -exec/-deleteпрефіксним правилом не схвалюються. - Завжди без запиту (набір вшитий, не налаштовується):
ls,cat,echo,pwd,head,tail,grep,find,wc,which,diff,stat,du,cdі read-only git. Щоб вимагати підтвердження — ask-правило. Все одно питають: нецитовані glob-и з небезпечними прапорцями,docker -H/--context,file -m/-f, UNC-шляхи, запис уPATH/IFS, нерозбірні команди та команди довші за 10 000 символів,cd+git,cd+ редирект. - Редиректи. Цілі
>,>>,2>перевіряються за правилами Edit, protected paths та робочими теками; ціль<— за правилами Read (з v2.1.257); ціліtee— з v2.1.269./dev/null,2>&1та heredoc не перевіряються.
Правило збігається з текстом команди, яку написав Claude, а не з програмою. Воно зупиняє першу форму й не зупиняє решту:
| Правило в deny/ask | Зупиняє | Не зупиняє |
|---|---|---|
Bash(curl *) | curl https://example.com | /usr/bin/curl ..., sh -c 'curl ...' |
Bash(rm *) | rm -rf build/ | /bin/rm -rf build/, bash -c 'rm -rf build/' |
Bash(git push *) | git push origin main | git -C . push ..., git -c push.default=current push, git 'push' ... |
Для реального обмеження використовуйте sandbox (мережевий allowlist і файлові правила на рівні ОС) або хук PreToolUse, який перевіряє повний текст команди. Правила, що обмежують аргументи (Bash(curl http://github.com/ *)), ще крихкіші: їх обходять прапорці перед URL, інший протокол, змінні та редиректи.
Read / Edit: шляхи у стилі gitignore
| Префікс | Значення | Приклад | Реальний шлях |
|---|---|---|---|
//path | Абсолютний шлях від кореня файлової системи | Read(//Users/alice/secrets/**) | /Users/alice/secrets/** |
~/path | Від домашньої теки | Read(~/Documents/*.pdf) | /Users/alice/Documents/*.pdf |
/path | Відносно джерела налаштувань | Edit(/src/**/*.ts) | <основна робоча тека>/src/**/*.ts у project-налаштуваннях |
path або ./path | Відносно поточної теки | Read(*.env) | <cwd>/*.env |
/Users/alice/file прив’язується до джерела налаштувань, а не до кореня диска; абсолютний шлях — //Users/alice/file. Те саме правило означає різне залежно від файлу, де воно лежить:
| Де визначено | /path перетворюється на |
|---|---|
.claude/settings.json і .claude/settings.local.json | <основна робоча тека>/path |
~/.claude/settings.json | ~/.claude/path |
файл із --settings <file> | <тека файла>/path |
| прапорці CLI, правила сесії | <основна робоча тека>/path |
Тож Read(/secrets/**) у user-налаштуваннях блокує ~/.claude/secrets/**, а не теку secrets у проєкті. Для правил, що діють у кожному проєкті, пишіть //… або ~/….
- Голе ім’я файла працює на будь-якій глибині:
Read(.env)=Read(**/.env). ПравилоRead(//**/.env)закриває.envбудь-де на диску. На Windows шляхи нормалізуються до/c/Users/...://c/**/.envабо//**/.envдля всіх дисків. - Однокомпонентна тека типу
src/**: в allow збігається лише з<cwd>/src, у deny/ask — з текоюsrcна будь-якій глибині. Якщо потрібна будь-яка глибина в allow —**/src/**. !-заперечення вирізає виняток із попередніх deny/ask того ж джерела (лише відносно cwd, не відкриває вміст цілком заблокованої теки).- Deny на
Readблокує також Edit і Write на тому шляху (Edit з v2.1.208, Write з v2.1.228);NotebookEditне покривається — додайте deny наEdit. Файл.claudeignoreнічого не робить. - Read/Edit deny працюють для вбудованих файлових інструментів, для розпізнаних Bash-команд (
cat,head,tail,sed,tee) і цілей редиректів, але не дляgrep -r pattern .чи скриптів, що самі відкривають файли. Для всіх процесів потрібен sandbox. Для симлінків allow потребує збігу і посилання, і цілі, а deny спрацьовує, якщо збігається будь-що одне. - Ці правила живлять і sandbox: шляхи з
Edit-allow потрапляють доsandbox.filesystem.allowWrite,Edit-deny — доdenyWrite,Read-deny — доdenyRead.
WebFetch: домени й «весь інтернет»
WebFetch(domain:example.com)— точний хост;domain:*.example.com— піддомени будь-якої глибини, але не самexample.com. Wildcard у будь-якому іншому місці (example.*) охоплює лише один сегмент між крапками. Wildcard-и працюють з v2.1.172.
| Правило | В allow | В deny |
|---|---|---|
WebFetch | Claude завантажує без запиту. Не змінює мережу sandbox | Інструмент прибирається з контексту. Не змінює мережу sandbox |
WebFetch(domain:*) | Без запиту, і sandbox-команди можуть звертатися до будь-якого хоста | Інструмент лишається, але кожне завантаження відхиляється, а sandbox-команди не бачать жодного хоста |
Тільки форма domain: потрапляє до мережевого allow/deny-списку sandbox, і sandbox враховує лише wildcard-и *.example.com та голий * (з v2.1.186); example.* на sandbox-команди не впливає. Зверніть увагу: заборона WebFetch не закриває мережу, якщо Bash дозволений — curl все одно дістанеться будь-якого URL.
Правила за параметром виклику
deny та ask (не allow) можуть збігатися з одним верхньорівневим скалярним параметром будь-якого вбудованого інструмента:
| Правило | Збігається |
|---|---|
Agent(model:opus) | Виклики субагента з моделлю opus (порівнюється літеральне значення, не повний ID) |
Agent(isolation:worktree) | Субагент у git worktree |
Bash(run_in_background:true) | Bash у фоні |
Bash(dangerouslyDisableSandbox:true) | Спроба вийти з sandbox (див. секцію sandbox) |
- Одне правило — один параметр; для двох умов пишіть два правила. Параметр, якого модель не передала, ніколи не збігається (
Agent(model:*)не зачепить виклик безmodel). Значення підтримує*. - Основні поля (
command,file_path,path,notebook_path,url) так зіставити не можна: правилоBash(command:rm *)ігнорується з попередженням при старті. - Для MCP-інструментів параметрні правила працюють лише через
--disallowedTools; у файлах налаштувань будь-яке правилоmcp__…з дужками пропускається.
Режими дозволів
Режим задає базову поведінку для викликів, яких не торкнулося жодне правило. Правила працюють поверх режиму: deny блокує в усіх режимах, включно з bypassPermissions, а allow у bypassPermissions не має ефекту. Перемикання в сесії — Shift+Tab; dontAsk у цикл не входить ніколи (лише --permission-mode dontAsk), bypassPermissions з’являється лише якщо сесію запущено з ним (або з --allow-dangerously-skip-permissions).
| Режим | Без запиту виконується | Запис у protected paths | Невідомий хост у sandbox |
|---|---|---|---|
default / manual | Читання (і read-only Bash) | Питає | Питає |
acceptEdits | Читання, редагування файлів і mkdir, touch, rm, rmdir, mv, cp, sed — у робочій теці та additionalDirectories (також з безпечними змінними/обгортками на початку). Решта Bash питає | Питає | Питає |
plan | Читання. Shell-команди: якщо доступний auto і useAutoModeDuringPlan (за замовчуванням true), їх переглядає класифікатор, інакше команди поза read-only набором питають. Редагування заблоковане, доки ви не схвалите план | Класифікатор або питає (у терміналі з доступним bypass — дозволено) | Питає (у терміналі з доступним bypass — дозволено) |
auto | Усе, але фонова модель-класифікатор перевіряє дії (shell, мережа та ін.) | Класифікатор | Відхилено, якщо команда не перелічила хост у власному списку (v2.1.271+) і класифікатор його не схвалив |
dontAsk | Читання, read-only Bash, allow-правила, виклики, схвалені хуком. Усе, що спитало б, відхиляється (включно з ask-правилами та AskUserQuestion) | Відхилено | Відхилено |
bypassPermissions | Усе, окрім «запобіжників, що не відключаються» (ask-правила, критичні rm, AskUserQuestion) | Дозволено | Дозволено |
Записи в .git, .claude, .vscode, .idea, .husky, .devcontainer, .mcp.json, .claude.json, .gitconfig, shell-rc (.zshrc, .bashrc …), .npmrc, .pre-commit-config.yaml та ін. ніколи не схвалюються автоматично (крім bypassPermissions і plan-режиму в терміналі з доступним bypass). Allow-правило типу Edit(.claude/**) у settings це не змінює — перевірка йде раніше за allow. Для .claude/ проєкту та ~/.claude/ промпт може запропонувати дозвіл «на сесію».
Список операцій які Claude виконує без запиту підтвердження. Claude просто робить — не питає.
Додавши правило — Claude більше не зупинятиметься для підтвердження. Прибравши — знову питатиме або блокуватиме залежно від defaultMode.
"allow": [ "Bash(git status)", "Bash(git diff *)", "Bash(git log *)", "Bash(git add *)", "Bash(python manage.py showmigrations *)", // без * збіглась би лише точна команда "Bash(npm run lint)", "Bash(npm run test:unit)", "Edit(/src/**/*.vue)", // / = від кореня проєкту (у project settings), НЕ абсолютний "Edit(/src/**/*.ts)", "WebFetch(domain:docs.djangoproject.com)", "mcp__github__get_*" // * лише в частині назви інструменту ]
.claude/settings.json діють лише після довіри до папки. Allow у mcp__ допускає glob лише після літерального префікса mcp__сервер__; неприв’язані "*"/"mcp__*" пропускаються з попередженням. У режимі bypassPermissions allow-правила не мають ефекту.Заборона. Перевіряється першою — блокує виклик навіть якщо він є в allow, і діє в усіх режимах, включно з bypassPermissions. Але для Bash вона збігається з текстом команди, тому не є межею безпеки (див. попередження нижче).
Scoped-правило (Bash(rm *)) лишає інструмент, але блокує збіги; голе ім’я (Bash, mcp__*) прибирає інструмент із контексту Claude повністю. Deny-правила з проєкту діють одразу, навіть до довіри до папки. Deny на Read(path) блокує також Edit/Write на тому шляху.
"deny": [ "Read(**/.env)", "Read(**/.env.*)", // .env — ніколи "Read(~/.ssh/**)", "Read(~/.aws/**)", "Bash(sudo *)", "Bash(su *)", "Bash(rm -rf *)", "Bash(dd *)", // без * правило — точний збіг "Bash(curl *)", "Bash(wget *)", "Bash(ssh *)", "mcp__*" // у deny можна glob по назві інструменту ]
Bash(curl *), Bash(wget *), Bash(ssh *) не зупинять /usr/bin/curl, sh -c 'curl …' чи bash -c 'rm …': це не межа безпеки навколо програми. Для реальної заборони мережі використовуйте sandbox (network.allowedDomains / strictAllowlist) або хук PreToolUse. Також Read/Edit deny не зупиняють grep -r . чи скрипт, що сам відкриває файли.Операції де Claude завжди питає підтвердження — навіть якщо є в allow. Показує що саме збирається зробити.
Додавши в ask — Claude зупиниться перед виконанням. Корисно для незворотних операцій: push, migrate, deploy. Дає контроль без повного блокування.
"ask": [ "Bash(git commit *)", "Bash(git push *)", "Bash(git merge *)", "Bash(python manage.py migrate)", "Bash(docker compose up *)", "Bash(docker compose down *)", "Bash(gh pr create *)" ]
bypassPermissions вони все одно питають, у dontAsk — відхиляють виклик. З autoAllowBashIfSandboxed голе Bash в ask пропускається для команд у sandbox (не в plan-режимі), але вузькі правила на кшталт Bash(git push *) і далі питають."Bash(dangerouslyDisableSandbox:true)" в ask змушує підтверджувати кожну спробу, навіть в auto і bypassPermissions, і має пріоритет над збіжним allow.Поведінка для операцій яких немає в жодному з масивів (allow/deny/ask). Режим за замовчуванням для всього нового.
Визначає скільки підтверджень побачать розробники: від класифікатора, що сам вирішує, до read-only. Якщо не задано: інтерактивний термінал і VS Code (з v2.1.283) стартують в auto; -p/SDK — в default у сесіях, що завантажують feature flags, а без них (сторонній провайдер, вимкнена телеметрія) — в auto з v2.1.285. Пріоритет: прапорець --permission-mode → defaultMode → вбудований default. Якщо auto недоступний сесії — старт у Manual.
| "default" / "manual" | Без запиту — лише читання (і read-only Bash); решта питає. У UI та --help називається «Manual», значення "manual" — синонім. ✓ Рекомендовано для команди |
| "auto" | Фонова модель-класифікатор перевіряє дії (shell, мережа) і блокує те, що не відповідає запиту. Вбудований стартовий режим терміналу й VS Code з v2.1.283; потребує підтримуваної моделі, організація може його вимкнути |
| "acceptEdits" | Авто-приймає редагування файлів і типові файлові команди — mkdir, touch, rm, rmdir, mv, cp, sed — у робочій теці та additionalDirectories (рішення перевіряє й симлінки). Решта Bash, шляхи поза зоною та protected paths — питають. Добре для швидкого рефакторингу |
| "plan" | Читає файли та запускає shell-команди для розвідки, пише план, але не редагує код, доки ви не схвалите план. Якщо доступний auto, команди перевіряє класифікатор (useAutoModeDuringPlan), інакше команди поза read-only набором питають. Корисно для code review без ризику |
| "dontAsk" | Авто-відхиляє кожен виклик, що інакше питав би: працюють читання у робочих теках, read-only Bash, allow-правила та виклики, схвалені хуком PreToolUse. Ask-правила, AskUserQuestion та MCP-інструменти з requiresUserInteraction відхиляються. Зручно для CI з --allowedTools. Не входить у цикл Shift+Tab |
| "bypassPermissions" | ⚠ Вимикає запити й перевірки protected paths, але deny-правила діють, а ask-правила, критичні rm та AskUserQuestion усе одно питають; allow-правила не мають ефекту. ТІЛЬКИ в ізольованих контейнерах/VM/CI. Ніколи на машині розробника. На Linux/macOS відмовляється стартувати від root/sudo |
--settings). Для auto береться вбудований default, для bypassPermissions сесія стартує в Manual. Інші значення діють з будь-якого файлу.acceptEdits, plan, default і auto; dontAsk та bypassPermissions із settings ігноруються. Розширення VS Code читає значення лише з user, managed і --settings (проєктні — ні; є окреме claudeCode.initialPermissionMode).Налаштовує класифікатор режиму auto: опис середовища та прозові правила що дозволено, що «м’яко» і що жорстко заборонено. disableAutoMode: "disable" вимикає режим повністю.
Дає змогу підлаштувати auto під політику компанії замість переліку сотень allow-правил. autoMode задається лише в user або managed settings (і --settings); disableAutoMode — у будь-якому файлі (також приймається як permissions.disableAutoMode), але має сенс у managed. З ним auto зникає з циклу Shift+Tab, а сесії, що стартували б в auto, стартують в default.
"autoMode": { "environment": ["Django монорепо, prod-доступу з ноутбуків немає"], "allow": ["$defaults", "запуск тестів і лінтерів"], "soft_deny": ["$defaults", "зміни в міграціях"], "hard_deny": ["$defaults", "будь-які дії з prod-базою"] }, "disableAutoMode": "disable" // повністю заборонити auto
"$defaults" зберігає вбудовані правила на цій позиції; без нього ваші правила їх замінюють. Додатковий підключ classifyAllShell — окремою карткою нижче.Повністю забороняє режим bypassPermissions. Єдине значення — "disable". Працює з будь-якого файлу, але для організації його ставлять у managed.
Ключ має пріоритет над --dangerously-skip-permissions, який Claude Code відхиляє, поки ключ задано. Також нейтралізує permissionMode: bypassPermissions у frontmatter субагентів.
"permissions": { "disableBypassPermissionsMode": "disable" }
Блокує можливість юзерам і проєктам додавати власні правила allow/deny/ask. Діють лише правила з managed settings.
true — ігноруються правила з user/project/local/--settings і прапор --allowedTools, зникають кнопки «always allow», а також allowed-tools у не-managed скілах (з v2.1.282) і командах .claude/commands/. Нові правила більше не зберігаються.
"allowManagedPermissionRulesOnly": true
--disallowedTools і deny/ask правила поточної сесії далі діють, бо лише обмежують. Skills з managed і вбудовані зберігають свій allowed-tools. Цей ключ не обмежує список MCP-серверів — для цього є allowManagedMcpServersOnly.Розширює "зону дозволів" Claude за межі поточної директорії проєкту.
Claude отримає доступ до файлів суміжних проєктів. Важливо: на відміну від --add-dir, конфігурація .claude/ з цих папок не завантажується. Записи з проєкту діють після довіри до папки. Вони також розширюють область запису для sandbox (з обмеженнями для project/local-файлів у admin-required режимі).
"additionalDirectories": [ "../backend-api", "../docs/" ]
--add-dir (але не з цього ключа) підхоплюються .claude/skills, commands, agents; CLAUDE.md — тільки з CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1. Додати мережевий UNC-шлях не можна.Новий (v2.1.257). Забороняє Claude читати файли поза робочими директоріями (проєкт + additionalDirectories).
Діє на Read, Grep, Glob, LSP в усіх режимах, включно з bypassPermissions. true з будь-якого файлу перемагає — його не можна «скасувати» з іншого файлу. Простий спосіб закрити доступ до ~/.ssh, ~/.aws та інших проєктів без довгого deny-списку.
"permissions": { "blockReadsOutsideWorkingDirectories": true }
/Users, /home, /root, /Volumes, /mnt, /media, /run/media, /srv. Теки, додані лише в репозиторних налаштуваннях, робочими для блоку не вважаються. У auto Claude Code запропонує ввімкнути цей ключ при першому читанні поза межами.Пропускати кожну Bash- і PowerShell-команду через класифікатор auto-режиму. За замовчуванням auto призупиняє лише allow-правила, що можуть виконати довільний код (Bash(*), Bash(python *)); команда, якій відповідає вузьке правило на кшталт Bash(npm test), класифікатор оминає.
З true усі shell-allow-правила призупиняються на час auto-режиму, тож класифікатор бачить кожну команду (вони продовжують діяти поза auto). Закриває випадок, коли небезпечний аргумент проскакує повз префіксне правило. Default false. Потребує v2.1.193+.
"autoMode": { "classifyAllShell": true }
--settings. true з user-налаштувань чи --settings перемагає false з managed.Чи використовувати класифікатор auto-режиму для shell-команд у режимі plan. Показується в /config як «Use auto mode during plan».
Default true: якщо auto доступний, команди під час планування переглядає класифікатор, а не ви (окрім видалення критичних шляхів). З false кожна команда поза вшитим read-only набором питатиме підтвердження.
"useAutoModeDuringPlan": false
false з будь-якого з цих файлів вимикає опцію; false у закоміченому .claude/settings.json ігнорується — репозиторій не може вимкнути її за вас.Пропускає діалог-попередження, який Claude Code показує перед тим, як сесія увійде в bypassPermissions (через --dangerously-skip-permissions або defaultMode: "bypassPermissions").
Claude Code сам записує true у user-налаштування після першого прийняття діалогу. Щоб побачити діалог знову — приберіть ключ або поставте false. Репозиторій не може пропустити діалог за вас.
"skipDangerousModePermissionPrompt": true
-p) діалогу немає; фонова сесія --bg відхиляється, доки ви не приймете діалог в інтерактивній.Пропускає одноразове повідомлення про auto-режим, яке з’являється, коли ви самі вперше вмикаєте auto (через свої налаштування або селектор режиму), а не коли вбудований default стартує сесію в ньому.
Без ключа повідомлення показується один раз і запам’ятовується. Корисно для розгортання через managed settings, коли не хочете, щоб команда бачила це повідомлення.
"skipAutoPermissionPrompt": true
Робочі директорії
За замовчуванням Claude має доступ до теки, де запущений; це основна робоча тека сесії. Розширити доступ можна так:
--add-dir <path>при старті,/add-dirу сесії абоpermissions.additionalDirectoriesу налаштуваннях. Файли там підкоряються тим самим правилам: читання без запиту, редагування — за режимом./cd <path>переносить основну теку: підвантажує їїCLAUDE.md, project-налаштування (правила й хуки),.mcp.jsonта плагіни нової теки. Для незнайомої теки показує діалог довіри. Обмежити цілі можна правиламиCd(...).- Мережеві UNC-шляхи (
\\server\share) додати не можна — на Windows підмонтуйте диск літерою. - Теки з
additionalDirectoriesдають лише доступ до файлів, не конфігурацію. З--add-dirпідхоплюються.claude/skills,.claude/commands,.claude/agentsта лише ключіenabledPluginsіextraKnownMarketplacesіз settings;CLAUDE.md— тільки зCLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1.
Довіра до робочої теки (workspace trust)
permissions.allowіadditionalDirectoriesз.claude/settings.jsonпроєкту діють лише після діалогу довіри.denyтаaskдіють одразу — вони тільки обмежують.claude -pі SDK діалог не показують: project allow-правила там не використовуються, хоча хуки з project-налаштувань — використовуються. Для чужого репозиторію запускайте з--setting-sources userабо--bare..claude/settings.local.json, який відстежується git (або симлінкований), вважається репозиторним: його правила чекають довіри.
Ключі, доступні лише в певних файлах
| Ключ | Де діє | Нюанс |
|---|---|---|
allowManagedPermissionRulesOnly | Лише managed | Правила з інших файлів ігноруються; --disallowedTools і сесійні deny/ask усе ще діють |
autoMode, autoMode.classifyAllShell | User, managed (і --settings) | Масиви з кількох файлів конкатенуються; "$defaults" зберігає вшиті правила |
disableAutoMode / permissions.disableAutoMode | Будь-який файл | Типово ставиться в managed |
permissions.disableBypassPermissionsMode | Будь-який файл | Типово в managed; користувач може сам заблокувати собі bypass |
permissions.blockReadsOutsideWorkingDirectories | Будь-який файл | true з будь-якого файлу перемагає |
skipDangerousModePermissionPrompt | User, local, managed | Не з committed project-файлу |
skipAutoPermissionPrompt | User, managed | — |
useAutoModeDuringPlan | User, local, managed | false з committed project-файлу ігнорується |
permissions.defaultMode: auto, bypassPermissions | User, managed, --settings | З project/local ці значення не діють |
Приклад для Django + Vue команди
Налаштування проєкту, яке комітиться в .claude/settings.json. Зверніть увагу: allow-правила Bash з * після підкоманди; шляхи /backend/… і /frontend/… прив’язані до кореня проєкту; реальну заборону мережі дає sandbox, а не deny.
{
"permissions": {
"defaultMode": "acceptEdits",
"allow": [
"Bash(git status)", "Bash(git diff *)", "Bash(git log *)", "Bash(git add *)",
"Bash(python manage.py check *)",
"Bash(python manage.py showmigrations *)",
"Bash(python manage.py makemigrations --dry-run *)",
"Bash(pytest *)",
"Bash(npm run lint *)", "Bash(npm run test:unit *)",
"Edit(/backend/**/*.py)", "Edit(/frontend/src/**)",
"WebFetch(domain:docs.djangoproject.com)", "WebFetch(domain:vuejs.org)"
],
"ask": [
"Bash(git commit *)", "Bash(git push *)",
"Bash(python manage.py migrate *)",
"Bash(docker compose *)",
"Bash(dangerouslyDisableSandbox:true)" // підтверджувати кожен вихід із sandbox
],
"deny": [
"Read(./.env)", "Read(./.env.*)", "Read(./secrets/**)",
"Read(~/.ssh/**)", "Read(~/.aws/**)",
"Edit(/backend/config/settings/production.py)",
"Bash(sudo *)", "Bash(rm -rf *)"
],
"additionalDirectories": ["../shared-ui"], // діє після довіри до теки
"blockReadsOutsideWorkingDirectories": true
}
}Встановлює змінні середовища при кожному старті Claude Code. Аналог export у .bashrc, але тільки для Claude — не впливає на shell.
Централізовано задати модель, таймаути, вимкнути телеметрію для всіх без ручного налаштування кожної машини. Змінні, які Claude Code вважає безпечними (вибір моделі, таймаути й ліміти, перемикачі функцій), застосовуються на старті з будь-якого файлу; решта з проєктних файлів — після довіри до папки (у режимі -p діалогу довіри немає, тож вони діють на старті).
"env": { "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1", // ↑ вимикає все нижче + /feedback, release notes, feature flags // увага: "0" чи "false" теж ВИМИКАЮТЬ — щоб увімкнути, видали змінну "DISABLE_AUTOUPDATER": "1", // фонові оновлення (claude update працює) "DISABLE_TELEMETRY": "1", // вимкнути аналітику "DISABLE_ERROR_REPORTING": "1" // вимкнути звіти про помилки }
"env": { "ANTHROPIC_MODEL": "claude-sonnet-5-5", // ↑ перевизначає ключ model з будь-якого файлу "ANTHROPIC_DEFAULT_HAIKU_MODEL": "claude-haiku-5-5", // ↑ на що вказує аліас haiku + фонові задачі // (замість deprecated ANTHROPIC_SMALL_FAST_MODEL) "CLAUDE_CODE_SUBAGENT_MODEL": "sonnet" // ↑ лише fallback: model у frontmatter агента важливіший // CLAUDE_CODE_SUBAGENT_MODEL_FORCE=1 — перебити все }
"env": { "BASH_DEFAULT_TIMEOUT_MS": "300000", // ↑ таймаут bash команд у мс. Default 120000 (2 хв) // стеля — BASH_MAX_TIMEOUT_MS, default 600000 (10 хв) "CLAUDE_AUTOCOMPACT_PCT_OVERRIDE": "70", // ↑ % вікна для авто-стиснення — може лише ЗНИЗИТИ поріг "CLAUDE_CODE_EFFORT_LEVEL": "high" // ↑ low|medium|high|xhigh|max|auto — найвищий пріоритет }
claude --debug). Задавай їх у shell, user- або managed-settings: шляхи (CLAUDE_CONFIG_DIR, CLAUDE_CODE_TMPDIR, HOME, TMPDIR, TMP, TEMP, XDG_*); системні змінні Windows (SystemRoot, ComSpec, PATHEXT тощо); експорт вмісту сесії (OTEL_LOG_RAW_API_BODIES, ENABLE_BETA_TRACING_DETAILED, BETA_TRACING_ENDPOINT); змінні, що вмикають і спрямовують OpenTelemetry: CLAUDE_CODE_ENABLE_TELEMETRY (і бета-пара enhanced telemetry), OTEL_LOGS_EXPORTER / OTEL_METRICS_EXPORTER / OTEL_TRACES_EXPORTER, OTEL_LOG_USER_PROMPTS / OTEL_LOG_TOOL_DETAILS / OTEL_LOG_TOOL_CONTENT / OTEL_LOG_ASSISTANT_RESPONSES і OTEL_EXPORTER_OTLP_* з суфіксами _ENDPOINT, _HEADERS, _PROTOCOL, _CERTIFICATE, _CLIENT_KEY, _INSECURE, а також OTEL_EXPORTER_PROMETHEUS_HOST / _PORT; старт і синхронізація (CLAUDE_CODE_PROCESS_WRAPPER, CLAUDE_CODE_SYNC_SKILLS, CLAUDE_CODE_SYNC_PLUGINS, CLAUDE_CODE_PLUGIN_CACHE_DIR, CLAUDE_CODE_PLUGIN_SEED_DIR); таймери діалогів (CLAUDE_CODE_USER_DIALOG_TIMEOUT_MS, CLAUDE_AFK_TIMEOUT_MS, CLAUDE_AFK_COUNTDOWN_MS, з v2.1.290) і CLAUDE_CODE_DISABLE_ATTACHMENTS. Лише «вимикаючі» значення OTel усе ж діють з проєктних файлів: none для трьох OTEL_*_EXPORTER і 0 для OTEL_LOG_USER_PROMPTS, OTEL_LOG_TOOL_CONTENT, OTEL_LOG_TOOL_DETAILS. Ігнорування OTel-групи у project/local потребує v2.1.282+.Як env взаємодіє з shell
- Значення в
envперезаписує ту саму змінну, експортовану в shell. Між файлами діє звичайний пріоритет (див. файли і пріоритети), managed — найвищий. - Виняток: якщо сесію запустили Claude Desktop або self-hosted runner, перемагає середовище запуску —
envіз файлів для змінних, які воно вже задало, ігнорується (debug-лог називає кожну). - Щоб скасувати експорт зі shell, задай
"": порожнє значення для вибору провайдера рахується як «не задано». NO_COLOR/FORCE_COLORзenvдоходять лише до підпроцесів — кольори самого інтерфейсу міняй у shell до запуску.- Значення лежать у файлі відкритим текстом і потрапляють у кожен підпроцес. Для OTLP-токена, що ротується, є
otelHeadersHelper, для API-ключів —apiKeyHelper. - Зміни в файлі підхоплюються працюючою сесією, але те, що читається лише на старті (наприклад, OpenTelemetry), чекає перезапуску; видалення змінної з файлу скасовується лише при наступному запуску.
Для перемикачів працюють 1/true/yes/on і 0/false/no/off у будь-якому регістрі. Є змінні, що перевіряють лише факт наявності: будь-яке непорожнє значення, навіть 0, вмикає поведінку (як DISABLE_TELEMETRY і CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC). Числові змінні приймають 2e3 і 64_000, якщо в рядку не сказано «лише цифри».
Довідник змінних
В офіційній таблиці Variables документовано 390 змінних середовища. Нижче — близько п’ятдесяти тих, що справді потрібні в командній роботі, за групами. Повний перелік: code.claude.com/docs/en/env-vars.
Моделі, провайдер і автентифікація
| Змінна | Значення / default | Що робить |
|---|---|---|
ANTHROPIC_DEFAULT_OPUS_MODEL | ID моделі | На що вказує аліас opus; його ж бере opusplan у Plan Mode. |
ANTHROPIC_DEFAULT_SONNET_MODEL | ID моделі | На що вказує sonnet; його ж бере opusplan поза Plan Mode. |
ANTHROPIC_DEFAULT_FABLE_MODEL | ID моделі | На що вказує fable; за цим ID Claude Code впізнає Fable для автоматичного fallback на сторонніх провайдерах. |
CLAUDE_CODE_MAX_OUTPUT_TOKENS | ціле; залежить від моделі | Максимум вихідних токенів для більшості запитів. Для невідомої моделі default 32000, стеля 128000. Більше значення зменшує ефективне вікно до авто-стиснення. |
CLAUDE_CODE_DISABLE_1M_CONTEXT | 1 | Вимикає підтримку вікна 1M: прибирає варіанти [1m] з пікера, моделі з 1M за замовчуванням тримає на 200K. Корисно для вимог compliance. |
CLAUDE_CODE_DISABLE_THINKING | 1 | Не передавати параметр thinking узагалі — сумісність з проксі, що його відкидають. Справжнє вимкнення: MAX_THINKING_TOKENS=0. Ні те, ні інше не вимикає thinking на моделях 5.5 і Fable. |
ANTHROPIC_API_KEY | рядок | Йде як X-Api-Key і використовується замість підписки, навіть якщо ти залогінений. В інтерактивному режимі ключ треба схвалити один раз, у -p він діє завжди. |
ANTHROPIC_AUTH_TOKEN | рядок | Значення заголовка Authorization (з префіксом Bearer ). |
ANTHROPIC_BASE_URL | URL | Маршрут через проксі чи gateway. На не-Anthropic хості вимикає MCP tool search за замовчуванням (ENABLE_TOOL_SEARCH=true, якщо проксі пропускає tool_reference) і, з v2.1.196, Remote Control. |
ANTHROPIC_CUSTOM_HEADERS | Name: Value по рядках | Додаткові заголовки запитів; з v2.1.227 некоректні символи (напр. «розумні» лапки) дають помилку з позицією пари. |
CLAUDE_CODE_USE_BEDROCKCLAUDE_CODE_USE_VERTEXCLAUDE_CODE_USE_FOUNDRY | 1 | Працювати через Amazon Bedrock / Google Cloud Agent Platform / Microsoft Foundry. |
CLAUDE_CODE_OAUTH_TOKEN | рядок | OAuth-токен claude.ai (з claude setup-token) для CI та SDK. Має пріоритет над ключами з keychain. |
Таймаути, повтори і Bash
| Змінна | Значення / default | Що робить |
|---|---|---|
API_TIMEOUT_MS | мс; 600000 (10 хв), макс. 2147483647 | Таймаут API-запиту. Значення більше максимуму ламають таймер, і запити падають одразу. |
BASH_MAX_OUTPUT_LENGTH | символи; 30000, макс. 150000 | Скільки виводу Bash повертається в результат. Ігнорується, якщо задано ключ bashOutputMaxChars. |
CLAUDE_CODE_MAX_RETRIES | ціле; 10, стеля 15 (з v2.1.186) | Кількість повторів невдалих API-запитів. |
CLAUDE_CODE_RETRY_WATCHDOG | 1 (з v2.1.199) | Для unattended-сесій (CI, eval, remote workers): повторювати 429/529 без ліміту й без стелі. Одразу падає, якщо ліміт витрат вичерпано. |
CLAUDE_STREAM_IDLE_TIMEOUT_MS | мс; при явному заданні мінімум 300000 | Таймаут простою стріму; byte-level watchdog обмежений 30 хв. CLAUDE_BYTE_STREAM_IDLE_TIMEOUT_MS має пріоритет для нього. |
CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR | 1 | Повертатися в початкову теку після кожної Bash/PowerShell-команди в головній сесії. |
CLAUDE_CODE_SHELL | шлях до bash/zsh | Shell для Bash-інструмента; fish не підтримується. Некоректний шлях ігнорується (авто-визначення). |
CLAUDE_CODE_SHELL_PREFIX | команда | Обгортка для Bash-викликів, hooks, status line і старту stdio MCP — для логування й аудиту. |
CLAUDE_ENV_FILE | шлях до скрипта | Скрипт, що виконується перед кожною Bash-командою в тому ж процесі (venv, conda). Також наповнюється hooks SessionStart, Setup, CwdChanged, FileChanged. |
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB | 1 | Прибрати облікові дані із середовища підпроцесів (Bash, hooks, stdio MCP). Токени GitHub і налаштування проксі лишаються. |
Контекст, стиснення, пам’ять, кеш
| Змінна | Значення / default | Що робить |
|---|---|---|
CLAUDE_CODE_AUTO_COMPACT_WINDOW | ціле 100000–1000000 (лише цифри) | Вікно авто-стиснення в токенах. Сильніше за /autocompact, --autocompact і ключ autoCompactWindow; обмежене вікном моделі. |
DISABLE_AUTO_COMPACT | 1 | Вимкнути авто-стиснення (ручний /compact лишається). Сильніше за autoCompactEnabled. |
DISABLE_COMPACT | 1 | Вимкнути все стиснення, включно з /compact. |
CLAUDE_CODE_DISABLE_AUTO_MEMORY | 1 / 0 | 1 вимикає auto memory; 0 примусово вмикає навіть при --bare чи autoMemoryEnabled: false. |
CLAUDE_CODE_DISABLE_CLAUDE_MDS | 1 | Не завантажувати жодних CLAUDE.md (user, project, auto memory). |
DISABLE_PROMPT_CACHING | 1 | Вимкнути prompt caching для всіх моделей (сильніше за налаштування окремих моделей). |
ENABLE_PROMPT_CACHING_1H | 1 | Запитувати TTL кешу 1 год замість 5 хв (API key, Bedrock, Agent Platform, Foundry, Claude Platform on AWS). |
CLAUDE_CODE_PROMPT_CACHE_TTL | 5m | 1h (v2.1.242+) | TTL кешу головної розмови; сильніший за ключ promptCacheTtl і ENABLE_PROMPT_CACHING_1H, слабший за FORCE_PROMPT_CACHING_5M. |
Приватність і телеметрія
| Змінна | Значення / default | Що робить |
|---|---|---|
DISABLE_UPDATES | 1 | Заблокувати всі оновлення, включно з ручними claude update / claude install. Суворіше за DISABLE_AUTOUPDATER — для корпоративної дистрибуції. |
DO_NOT_TRACK | 1 | Те саме, що DISABLE_TELEMETRY, але читається як стандартний булевий: 0 лишає телеметрію ввімкненою. |
OTEL_LOG_USER_PROMPTS | 1 | Включати текст промптів в OpenTelemetry (за замовчуванням редагується). У project/local ігнорується, крім вимикаючих значень. |
OTEL_LOG_TOOL_DETAILS | 1 | Включати аргументи інструментів, імена MCP тощо в OTel. Ті самі обмеження. |
CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY | 1 | Вимкнути опитування «How is Claude doing?». Вони вимикаються й при DISABLE_TELEMETRY, DO_NOT_TRACK, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC. Частота — ключ feedbackSurveyRate. |
DISABLE_COST_WARNINGS | 1 | Прибрати попередження про вартість. |
Мережа, проксі, сертифікати
| Змінна | Значення / default | Що робить |
|---|---|---|
HTTPS_PROXY / HTTP_PROXY | URL | Проксі для мережевих з’єднань. |
NO_PROXY | список доменів/IP | Куди ходити напряму, повз проксі. |
CLAUDE_CODE_CERT_STORE | bundled, system; default bundled,system | Джерела CA для TLS: набір Mozilla з Claude Code та/або сховище ОС (потребує нативного бінарника або Node 22.15+). |
CLAUDE_CODE_CLIENT_CERTCLAUDE_CODE_CLIENT_KEYCLAUDE_CODE_CLIENT_KEY_PASSPHRASE | шлях / шлях / рядок | Клієнтський сертифікат і ключ для mTLS; пароль до зашифрованого ключа — необов’язковий. |
MCP
| Змінна | Значення / default | Що робить |
|---|---|---|
MCP_TIMEOUT | мс; 30000 | Таймаут запуску MCP-сервера. |
MCP_TOOL_TIMEOUT | мс; 100000000 (~28 год) | Таймаут виконання MCP-інструмента. Для HTTP/SSE/claude.ai-конекторів кожен запит окремо обмежений 60 с, доки це значення або per-server timeout у .mcp.json не більше 60000. Per-server timeout перебиває змінну. |
MAX_MCP_OUTPUT_TOKENS | ціле; 25000 | Максимум токенів у відповіді MCP-інструмента; попередження вище 10 000. |
ENABLE_TOOL_SEARCH | true | auto | auto:N | false | MCP tool search. Не задано — усі MCP-інструменти відкладені. auto вантажить одразу, якщо описи ≤10% контексту; auto:5 — свій поріг у %; false — вантажить усе одразу. |
ENABLE_CLAUDEAI_MCP_SERVERS | false | Не підтягувати MCP-сервери claude.ai (для окремого проєкту чи організації є ключ disableClaudeAiConnectors). |
Вимкнення функцій і службове
| Змінна | Значення / default | Що робить |
|---|---|---|
CLAUDE_CODE_DISABLE_FAST_MODE | 1 | Вимкнути fast mode. |
CLAUDE_CODE_DISABLE_BACKGROUND_TASKS | 1 | Вимкнути фонові задачі: run_in_background, авто-бекграунд, Ctrl+B. |
CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING | 1 | Вимкнути знімки файлів; /rewind не відновить код. Сильніше за fileCheckpointingEnabled. |
CLAUDE_CODE_DISABLE_WEB_FETCH | 1 (v2.1.285+) | Вимкнути WebFetch; WebSearch лишається. |
CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS | 1 | Прибрати pre-release anthropic-beta заголовки й бета-поля схем. Для gateway, що відповідає Unexpected value(s) чи Extra inputs are not permitted. |
CLAUDE_CODE_TMPDIR | шлях | Тека для внутрішніх тимчасових файлів (default /tmp на macOS, os.tmpdir() інакше). У project/local ігнорується. |
USE_BUILTIN_RIPGREP | 0 | Використовувати системний rg замість вбудованого. |
Задає модель, з якої стартує сесія. Аліас або повний ID. Навіть у managed — це стартовий default, а не блокування.
Пріоритет: --model > ANTHROPIC_MODEL > ключ model > ANTHROPIC_DEFAULT_MODEL. Щоб заборонити інші моделі — availableModels. Без ключа Default залежить від акаунта: Opus 5.5 на Pro/Max/Team/Enterprise, Anthropic API, Claude Platform on AWS, Bedrock і Google Cloud Agent Platform; Sonnet 4.5 на Microsoft Foundry.
"model": "sonnet" // → Sonnet 5.5 · $2/$10 · баланс ціна/якість "model": "opus" // → Opus 5.5 · $4/$20 · default (крім Foundry) "model": "haiku" // → Haiku 5.5 · найшвидша та найдешевша "model": "fable" // → Fable 5.1 · $10/$50 · найскладніші задачі "model": "opusplan" // Opus у plan mode, Sonnet для виконання "model": "claude-opus-5-5" // повний ID — не оновиться з новим релізом
| Pro, Max, Team, Enterprise, Anthropic API | Default = Opus 5.5 (до v2.1.280: Sonnet 5 на Pro/Team Standard, Opus 5 на решті) |
| Claude Platform on AWS, Bedrock, Google Cloud Agent Platform | Default = Opus 5.5 |
| Microsoft Foundry | Default = Sonnet 4.5; перевірки доступності моделі при старті там немає, тож недоступна модель дає помилки (на Bedrock/Agent Platform — повідомлення й відкат до попередньої версії) |
| Enterprise: organization default (v2.1.196+) | адмін задає модель в консолі claude.ai для всієї організації або для ролі; Default показується як «Org default». Це старт, а не обмеження: --model, ANTHROPIC_MODEL, managed і --settings сильніші. З опцією override він перебиває ключ model з user/project/local. Діє лише для сесій через Anthropic API; для gateway — ключ model у managed. |
| Fable | не є Default-моделлю жодного плану чи провайдера; вибір у /model зберігається в user settings |
Обмежує список моделей у /model. enforceAvailableModels обмежує ще й пункт «Default». deniedModels — явний чорний список (managed).
["sonnet","haiku"] — розробники не зможуть переключитись на Opus/Fable і витрачати більше. Managed-список застосовується як є, без злиття з іншими файлами.
"availableModels": ["sonnet", "haiku"], "enforceAvailableModels": true, "deniedModels": ["fable"] // managed only
Глибина міркувань моделі. effortLevel: low | medium | high | xhigh (max — лише через CLI/env). maxEffortLevel — стеля для всіх. /effort тепер зберігає рівень окремо для кожної моделі в modelSettings.
low — швидко й дешево. xhigh/max — глибокий аналіз, більше токенів. Default: medium для Opus/Sonnet/Haiku 5.5, high для Fable 5.1 та старших. У user settings верхньорівневий effortLevel не діє на Opus 5.5+ — використовуй modelSettings.
"effortLevel": "high", // project / managed — для всіх моделей "maxEffortLevel": "xhigh", // найнижча стеля серед файлів виграє "modelSettings": { "claude-opus-5-5": { "effortLevel": "high", "maxEffortLevel": "xhigh", "autoCompactWindow": 500000 }, "claude-haiku-5-5": { "effortLevel": "low" } }
| modelSettings | з v2.1.251; об’єкт «модель → поля». Claude Code пише запис під канонічною назвою (claude-opus-5-5) і зіставляє з ним аліас, версії з датою, [1m] та ID провайдерів |
| effortLevel | low | medium | high | xhigh; сильніший за верхньорівневий effortLevel у тому ж файлі. Між файлами кожна модель вирішується окремо: переможе файл найвищого пріоритету, що задає або рівень для цієї моделі, або застосовний верхньорівневий. /effort auto стирає збережений рівень |
| maxEffortLevel | з v2.1.267; стеля для однієї моделі ("max" = без стелі, звільняє модель від стелі цього джерела). Загальний верхньорівневий maxEffortLevel: діє найнижча стеля з усіх областей, її не можна підняти з іншого файлу |
| autoCompactWindow | з v2.1.288; число від 100000 до 1000000 або "auto"; сильніше за верхньорівневий autoCompactWindow у тому ж файлі; його пише /autocompact |
maxEffortLevel — застосовується нижча. Пріоритет рівня: CLAUDE_CODE_EFFORT_LEVEL > --effort > збережене.Fast Mode (research preview) — та ж модель, але до 2.5x швидший output. Працює лише на Opus 5.5, Opus 5 та Opus 4.8.
fastMode true = сесії стартують у швидкому режимі. fastModePerSessionOptIn true = юзери самі вмикають /fast коли потрібно — контроль витрат. Ціна на Opus 5.5 — $8/$40.
"fastMode": false, "fastModePerSessionOptIn": true // вмикають /fast вручну
Extended Thinking тепер увімкнений за замовчуванням, тож ключ має сенс лише як false.
false = вимкнути thinking на старших моделях (Opus 4.x, Sonnet 4.6). На Opus/Sonnet/Haiku 5.5 і Fable не діє — вони думають завжди, глибину регулює effort.
"alwaysThinkingEnabled": false // лише для старших моделей
Упорядкований ланцюжок (до 3 різних дозволених моделей): якщо основна модель перевантажена чи недоступна, Claude Code переключається на наступну до кінця ходу й показує повідомлення. Наступне твоє повідомлення знову спробує основну.
Сесія не зупиняється з помилкою overloaded. Увесь ланцюжок береться з найвищого файлу, що його задає (без злиття; у managed-settings.d пізніший файл заміщає цілком). --fallback-model сильніший за ключ; "default" розгортається у типову модель. Перехід означає один хід із холодним prompt cache.
"fallbackModel": ["claude-sonnet-5-5", "claude-haiku-5-5"]
Яка модель відповідає, коли Claude викликає серверний advisor-інструмент. Без ключа advisor вимкнений. Значення: "fable", "opus", "sonnet" (поточна версія родини) або повний ID.
Складні рішення Claude може «віддати на консультацію» сильнішій моделі. Advisor має бути щонайменше таким самим здібним, як основна модель. Зазвичай ключ не правлять руками: його пише /advisor в user settings.
"advisorModel": "opus"
--advisor перебиває ключ на сесію; CLAUDE_CODE_DISABLE_ADVISOR_TOOL вимикає advisor, і ключ не може його повернути. Для "fable" спершу прийми згоду на usage credits: /model fable.Як зіставляються записи availableModels з ID моделей: "prefix" (default) або "exact".
З prefix запис "claude-opus-5" дозволяє й пізніші версії (Opus 5.5). З exact кожен ID дозволяє лише названу версію — нова версія лишається заблокованою, доки її не додано. Аліас родини ("opus") і далі дозволяє всю родину; записи best/opusplan/default при exact ігноруються.
"availableModels": ["claude-opus-5-5", "claude-sonnet-5-5"], "availableModelsMatch": "exact"
deniedModels.Мапа «ID моделі Anthropic → ID моделі провайдера», напр. ARN inference profile в Bedrock. Кожен пункт пікера викликатиме API провайдера з відображеним значенням.
Команда на Bedrock бачить звичні назви Opus/Sonnet, а запити йдуть у ваші профілі. При managedSourcesBehavior: "merge" ключ береться з найвищого джерела, окрім випадку, коли вище джерело задає availableModels без modelOverrides — тоді він ігнорується скрізь.
"modelOverrides": { "claude-opus-4-6": "arn:aws:bedrock:us-east-1:123456789012:inference-profile/example" }
Складає список моделей у /model: порядок і підписи ваші. Поле options — масив рядків {model, label?, description?, behavesAs?}; replaceBuiltInOptions (default false) — показати лише ці рядки, Default і поточну модель.
Пікер показує моделі вашої організації під зрозумілими іменами. model береться дослівно: аліас, ID Anthropic або формат провайдера. Рядок, який неможливо обслужити, відкидається; якщо не лишилось жодного — береться вбудований список. Недоступні зараз рядки сірі й стоять унизу. availableModels діє й на ці рядки.
"modelPicker": { "options": [ { "model": "us.anthropic.claude-opus-4-8", "label": "Opus (production)" }, { "model": "us.anthropic.claude-sonnet-4-6", "label": "Sonnet (production)", "description": "Щоденна робота" } ], "replaceBuiltInOptions": false }
--settings і user; у project/local ігнорується, щоб склонований репозиторій не міг перейменувати пікер. Переможе цілий список найвищого з трьох джерел — рядки ніколи не зливаються. behavesAs (v2.1.257+) наказує вважати нову модель відомою, напр. claude-opus-4-8.Показувати витрати за вашими тарифами замість публічного прайсу: у /usage, status line, total_cost_usd в SDK, ліміті --max-budget-usd і OTel-метриці вартості.
Цифри в доларах у розробників збігаються з вашим рахунком. Ставки вводите ви самі — Claude Code не читає контракт і не змінює реальний білінг. Поля: multiplier (>0 і ≤10; >1 — націнка, потребує v2.1.271+) та overrides — мапа «ID моделі → {input, output, cacheRead, cacheWrite}», усі чотири обов’язкові, $ за MTok, 0–10000.
"modelPricing": { "multiplier": 0.85, "overrides": { "claude-sonnet-4-6": { "input": 2.4, "output": 12, "cacheRead": 0.24, "cacheWrite": 3 } } }
--settings і в HKCU. Для server-managed до підтвердження fetch сесія рахує за прайсом. Ряд з overrides використовується як є (без надбавки fast mode чи US-only), multiplier накладається зверху.Як довго prompt cache тримає розмову: "5m" або "1h". promptCacheTtl — головна розмова (інтерактив, -p, SDK та inline-помічники); subagentPromptCacheTtl — усе поза нею: субагенти, workflows, стиснення, назви сесій.
1h економить на довгих сесіях з паузами, але записи в кеш при цьому тарифікуються дорожче. Пріоритет: FORCE_PROMPT_CACHING_5M > CLAUDE_CODE_PROMPT_CACHE_TTL (для субагентів — CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL) > ключ > ENABLE_PROMPT_CACHING_1H.
"promptCacheTtl": "1h", "subagentPromptCacheTtl": "5m"
Показувати короткі підсумки extended thinking в інтерактивних сесіях. Default false.
Без ключа Anthropic API редагує thinking-блоки, і Claude Code показує згорнуту заглушку. Сторонні провайдери блоки не редагують, тож там різниці немає.
"showThinkingSummaries": true
Що робити, коли класифікатор безпеки позначив запит: перейти на запасну модель і продовжити, чи зупинитись і дати вибрати.
Не задано — перемикається автоматично (в інтерактиві може спитати). false — пауза з вибором; у -p позначений запит завершується помилкою.
"switchModelsOnFlag": false
Запускати сесії з увімкненим ultracode: Claude сам планує workflow для кожної суттєвої задачі, не чекаючи прохання. Default — вимкнено.
Працює лише коли динамічні workflows увімкнені й модель підтримує xhigh. Ключ не змінює рівень effort сесії; стеля maxEffortLevel знижує рівень, але ultracode не вимикає. Claude Code ключ лише читає, ніколи не пише.
"ultracode": true
/effort ultracode / /effort ultracode off; прапор --effort ultracode (v2.1.203+, на рівні xhigh). Поточна поведінка — з v2.1.284: раніше ultracode: true примусово ставив xhigh, а стеля нижче xhigh тримала ultracode вимкненим.hooks
Автоматичні дії на подіях сесії: 5 типів обробників, 33 події. Блокувати можна exit-кодом 2 або JSON-рішенням
Що таке хук і як він налаштовується
Хук — це ваш код, який Claude Code виконує детерміновано на певній події життєвого циклу: shell-команда, HTTP-запит, виклик MCP-інструмента, промпт до моделі або міні-агент. На відміну від рядка в CLAUDE.md, це не прохання, а гарантія: формат після кожної правки, заборона на .env, тести перед завершенням відповіді. Конфігурація має три рівні вкладеності: подія → група з matcher → обробники.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/format-py.sh",
"args": [],
"timeout": 30
}
]
}
]
}
}Тут PostToolUse — подія, об’єкт із matcher — група (фільтр за назвою інструмента), внутрішній масив hooks — обробники, що виконуються паралельно. Коментарі й зайві коми в справжньому settings.json не допускаються.
Де визначати хуки
| Місце | Охоплення | Коментар |
|---|---|---|
~/.claude/settings.json | усі ваші проєкти | локально, не в репозиторії |
.claude/settings.json | один проєкт | комітиться в репозиторій, спільний для команди |
.claude/settings.local.json | один проєкт | особистий, gitignored |
| managed policy settings | вся організація | керує адміністратор; не вимикається з user/project |
плагін hooks/hooks.json | поки плагін увімкнений | необов’язкове верхнє поле description |
| frontmatter skill | решта сесії після виклику skill | єдине місце, де працює once: true |
| frontmatter субагента | поки субагент працює | Stop автоматично стає SubagentStop |
Хуки з різних рівнів додаються, а не перезаписують один одного; однакові обробники з кількох файлів виконуються один раз. Усі хуки, що підійшли під подію, запускаються паралельно. Для PreToolUse при різних рішеннях діє пріоритет deny > defer > ask > allow; якщо кілька хуків повертають updatedInput, перемагає той, що завершився останнім (порядок недетермінований), тож не змінюйте один і той самий інструмент у двох хуках. Меню /hooks лише для читання, а правки файлів підхоплюються автоматично.
Усі 33 події, поля обробників, семантика matcher та if, exit-коди, JSON-вивід, змінні середовища, безпека й налагодження — у наступному розділі «hooks: довідник» (#hooks-ref). Готові рецепти для Django/Vue/GitLab-команди — наприкінці цього розділу.
Виконується до того, як Claude запускає інструмент (для будь-якого, крім EndConversation; @file-згадки не рахуються). matcher фільтрує за назвою інструмента, а if — за аргументами (синтаксис правил дозволів).
Єдина подія, де хук може дозволити, заборонити, запитати або відкласти виклик і переписати аргументи. Блокувати можна двома способами: exit 2 (stderr іде Claude як причина) або JSON hookSpecificOutput.permissionDecision = allow | deny | ask | defer. Хук спрацьовує до перевірки режиму дозволів, тож deny діє навіть у bypassPermissions. Prompt-хук з ok:false за замовчуванням завершує хід і показує причину в чаті; з continueOnBlock: true причина повертається Claude як помилка інструмента, і він може виправитися. Таке завершення ходу за замовчуванням — з v2.1.210; раніше причина завжди поверталася Claude як помилка інструмента.
"PreToolUse": [{ "matcher": "Bash", // тільки назва інструмента "hooks": [{ "type": "prompt", // модель оцінює через Claude "if": "Bash(git push *)", // фільтр за аргументами; збігається і з голим `git push` "prompt": "Чи безпечний цей push для main? Дані: $ARGUMENTS", "continueOnBlock": true, // ok:false -> Claude бачить причину і коригується "timeout": 30 }] }]
$ARGUMENTS = JSON-вхід хука (якщо його немає в промпті, JSON дописується в кінець). Модель відповідає {"ok": true|false, "reason": "...", "impossible": ...}; impossible діє лише на Stop/SubagentStop. Таймаут PreToolUse-хука не блокує виклик: інструмент піде далі звичайним потоком дозволів, тому на «зависання» як на ворота не покладайтеся.if — best-effort: для жорсткої заборони використовуйте permissions.deny.Виконується після успішного інструмента. Типи обробників: command, http, mcp_tool, prompt, agent (експериментальний). Дані події приходять JSON-ом у stdin.
Можна автоматично форматувати код, відправляти аудит-лог, запускати лінтер. Інструмент уже виконався, тож скасувати його хук не може, зате може повернути Claude зворотний зв’язок: exit 2 (stderr іде Claude), decision:"block" + reason, additionalContext або підмінити результат через updatedToolOutput. Без хука нічого автоматичного не відбувається.
"PostToolUse": [{ "matcher": "Edit|Write", "hooks": [{ "type": "command", "if": "Edit(*.py)", // лише Python-файли (правила Edit(...) охоплюють усі вбудовані інструменти редагування) "command": "jq -r '.tool_input.file_path' | xargs ruff format", "async": true, // не блокує Claude (лише command); timeout для async не діє "statusMessage": "Форматую код..." }] }]
$CLAUDE_FILE_PATH немає: шлях беремо зі stdin (jq -r '.tool_input.file_path'), він завжди абсолютний. Змінні середовища для хуків — див. таблицю в розділі «hooks: довідник». З async: true результат (additionalContext, systemMessage) надходить аж на наступному ході, а поля рішень не діють.HTTP-хук надсилає вхід події як POST (Content-Type: application/json) на ваш URL. Заголовки підтримують інтерполяцію $VAR / ${VAR}, але лише для змінних із allowedEnvVars.
Зручно для централізованого аудиту. HTTP-хук не може заблокувати дію кодом відповіді: блокування — лише 2xx з JSON-рішенням. Не-2xx, невалідне тіло чи збій з’єднання — неблокуюча помилка.
"PostToolUse": [{ "matcher": "Bash", "hooks": [{ "type": "http", "url": "https://audit.company.com/log", "headers": { "Authorization": "Bearer $AUDIT_TOKEN" }, "allowedEnvVars": ["AUDIT_TOKEN"] // ↑ лише ці змінні підставляються в headers; решта стає порожнім рядком }] }]
Спрацьовує коли задачу зі спільного task list позначають виконаною (agent teams, task-інструменти). Exit 2 = не закривати, stderr іде назад як фідбек.
Ідеально для pipeline: "перед закриттям — запусти тести". Тести впали → задача не закривається. Без хука — Claude закриває одразу.
"TaskCompleted": [{ "hooks": [{ "type": "command", "command": "cd "$CLAUDE_PROJECT_DIR" && python manage.py test --failfast 1>&2 || exit 2", // exit 2 = тести впали = задача не закривається "timeout": 120 }] }]
{"continue": false, "stopReason": "..."} (ігнорується, якщо подію спричинив виклик TaskUpdate).Stop — коли головний агент закінчив відповідь (не спрацьовує при перериванні користувачем; при помилці API замість нього спрацьовує StopFailure). SessionStart — при старті/відновленні сесії (matcher: startup, resume, clear, compact, fork); звичайний stdout потрапляє в контекст. SessionEnd — при завершенні сесії.
Stop + async = сповіщення Telegram/Slack після відповідей. Stop з decision:"block" або exit 2 не дає Claude зупинитись (наприклад, поки не пройдуть тести) — після 8 поспіль таких продовжень Claude Code сам завершує хід (ліміт піднімає CLAUDE_CODE_STOP_HOOK_BLOCK_CAP). SessionStart підтримує лише command і mcp_tool, причому mcp_tool при запуску пропускається (MCP-сервери ще не готові). SessionEnd має спільний бюджет ~1.5 с (піднімається власним timeout хука до 60 с або CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS) — тільки швидкі дії.
"Stop": [{ "hooks": [{ "type": "command", "command": "python3 ~/.claude/notify.py", "async": true, "statusMessage": "Відправляю сповіщення..." }] }]
stop_hook_active (true, якщо Claude вже продовжує через stop-хук), last_assistant_message (текст останньої відповіді; не читайте transcript_path, він може відставати), background_tasks[] і session_crons[].Спрацьовує щоразу як завантажується CLAUDE.md або файл з .claude/rules/. Тільки для аудиту — не може блокувати.
Дозволяє логувати які інструкції завантажуються — виявлення prompt injection атак через підкинуті CLAUDE.md файли.
"InstructionsLoaded": [{ "hooks": [{ "type": "command", "command": "jq -c . >> ~/.claude/audit.log", "async": true }] }]
Зараз — 33 події. Детальні таблиці для кожної події — у розділі «hooks: довідник».
Поле if працює лише на PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest, PermissionDenied — на інших подіях хук з if взагалі не запуститься. Переглянути активні хуки — /hooks (лише читання).
| сесія | SessionStart · Setup · SessionEnd · ConfigChange · CwdChanged · DirectoryAdded · FileChanged |
| промпт | UserPromptSubmit · UserPromptExpansion · InstructionsLoaded · MessageDisplay · Notification |
| інструменти | PreToolUse · PermissionRequest · PermissionDenied · PostToolUse · PostToolUseFailure · PostToolBatch |
| агенти | SubagentStart · SubagentStop · TaskCreated · TaskCompleted · TeammateIdle |
| завершення | Stop · StopFailure · PreCompact · PostCompact |
| інше | PreModelSwitch · PostModelSwitch · WorktreeCreate · WorktreeRemove · Elicitation · ElicitationResult |
| exit codes | 0 = успіх (JSON зі stdout читається на будь-якому коді) · 2 = блок (де подія це дозволяє; JSON його не скасує) · інше = неблокуюча помилка, але якщо stdout містить валідний JSON, рішення приймає саме він, а код ігнорується |
| timeout default | command/http/mcp_tool — 600 с (30 с для UserPromptSubmit, PreModelSwitch, PostModelSwitch; 10 с для MessageDisplay) · prompt — 30 с · agent — 60 с · SessionEnd — спільний бюджет 1.5 с |
disableAllHooks — вимикає хуки, а також кастомні statusLine і fileSuggestion (і моди плагінів). Діє з будь-якого файлу, але managed-хуки вимикає лише значення з managed settings. allowManagedHooksOnly (лише managed) — залишає тільки managed-хуки, хуки Agent SDK та хуки плагінів, примусово увімкнених у managed enabledPlugins.
disableAllHooks: true — для troubleshooting; береться значення після злиття пріоритетів, тому false у project-файлі перекриє true у user-файлі. Для одного запуску надійно: --settings '{"disableAllHooks": true}'. allowManagedHooksOnly: true — розробники не можуть додати власні хуки, через які могли б витікати дані.
"disableAllHooks": false, // default - хуки активні "allowManagedHooksOnly": true // лише managed settings
statusLine, fileSuggestion і subagentStatusLine до managed; вимикає плагіни з джерелом command та headersHelper маркетплейсів (якщо явно не задано disableCommandPluginSources: false); команда /goal при ньому недоступна.Allowlist URL-шаблонів (з *) для HTTP-хуків. Якщо ключ визначено, HTTP-хук виконується лише за збігом з об’єднаним списком; решта блокуються без запуску. Хост порівнюється без урахування регістру.
Діє на хуки з усіх джерел, включно з managed. Порожній масив [] блокує всі HTTP-хуки. Scope — будь-який файл, масиви зливаються (це не managed-only ключ).
"allowedHttpHookUrls": ["https://audit.company.com/*", "http://localhost:*"]
Зовнішня межа для allowedEnvVars усіх HTTP-хуків. Хук може підставити змінну в заголовок лише якщо її названо і в його власному allowedEnvVars, і в цьому ключі.
Не дає хуку прочитати секрет, навіть якщо його опис це просить. Не задано — діє лише власний список хука. Scope — будь-який файл, масиви зливаються.
"httpHookAllowedEnvVars": ["AUDIT_TOKEN", "HOOK_SECRET"]
allowedHttpHookUrls звужує, куди хуки можуть слати дані, httpHookAllowedEnvVars — які секрети можуть із ними піти. Розкладайте їх у managed settings.Рецепти для Django + Vue + GitLab
Шість робочих заготовок. Скрипти кладемо в .claude/hooks/, робимо виконуваними (chmod +x) і комітимо разом із .claude/settings.json, щоб вся команда мала однакові правила. Шлях до скрипта — через ${CLAUDE_PROJECT_DIR} і "args": [] (exec form: без shell і без проблем з лапками).
1. ruff + black (і prettier для Vue) після правки
PostToolUse на Edit|Write. Скрипт сам відфільтровує розширення, тож не залежить від тонкощів if. Якщо після автовиправлень лишились порушення ruff, скрипт завершується з кодом 2: stderr побачить Claude (інструмент уже виконано, але зворотний зв’язок він отримає) і виправить решту.
{
"hooks": {
"PostToolUse": [{
"matcher": "Edit|Write",
"hooks": [{
"type": "command",
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/format.sh",
"args": [],
"timeout": 60,
"statusMessage": "ruff + black / prettier..."
}]
}]
}
}#!/bin/bash f=$(jq -r '.tool_input.file_path // empty') f="${f//\\//}" # Windows: \ -> / cd "$CLAUDE_PROJECT_DIR" || exit 0 case "$f" in *.py) ruff check --fix --quiet "$f" black --quiet "$f" ruff check "$f" >&2 || exit 2 # залишились помилки -> Claude побачить stderr ;; *.vue|*.ts|*.js) npx prettier --write "$f" >/dev/null 2>&1 ;; esac exit 0
2. Заборона правок .env та вже закомічених міграцій
PreToolUse на Edit|Write, exit 2. «Вже застосована» хук знати не може, тому використовуємо практичне наближення: міграція, що вже є в git, — незмінна; нову міграцію (файл, якого ще немає в індексі) створювати дозволено.
#!/bin/bash f=$(jq -r '.tool_input.file_path // empty') f="${f//\\//}" case "$f" in */.env|*/.env.*|*/secrets/*) echo "Заблоковано: $f - секрети не редагуємо" >&2; exit 2 ;; esac if [[ "$f" == */migrations/0*.py ]] && \ git -C "$CLAUDE_PROJECT_DIR" ls-files --error-unmatch "$f" >/dev/null 2>&1; then echo "Міграція $f вже в git. Не правте її - створіть нову через makemigrations" >&2 exit 2 fi exit 0
{
"hooks": {
"PreToolUse": [{
"matcher": "Edit|Write",
"hooks": [{
"type": "command",
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/protect.sh",
"args": []
}]
}]
}
}Помилка в шляху до скрипта дає неблокуючу помилку (код 127), тобто ворота тихо відкриваються. Для справді критичного додайте дубль у permissions.deny: "Edit(.env)" діє на всі вбудовані інструменти редагування, і до того ж перевіряється самою системою дозволів, а не «best-effort» фільтром.
3. pytest на Stop
Stop-хук запускає тести, лише якщо змінено .py-файли. Якщо тести падають, exit 2 не дає Claude зупинитись, а хвіст виводу pytest іде йому як причина. Після 8 поспіль таких продовжень Claude Code сам завершить хід; ліміт піднімає CLAUDE_CODE_STOP_HOOK_BLOCK_CAP.
#!/bin/bash cd "$CLAUDE_PROJECT_DIR" || exit 0 [ -z "$(git status --porcelain -- '*.py')" ] && exit 0 # Python не чіпали out=$(python -m pytest -x -q 2>&1) && exit 0 { echo "pytest не пройшов, виправте перед завершенням:"; echo "$out" | tail -40; } >&2 exit 2
{
"hooks": {
"Stop": [{
"hooks": [{
"type": "command",
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/pytest-on-stop.sh",
"args": [],
"timeout": 300,
"statusMessage": "pytest..."
}]
}]
}
}4. Сповіщення, коли Claude чекає на вас
Подія Notification (matcher permission_prompt|idle_prompt). Варіант для Slack/Mattermost: webhook-URL береться зі змінної середовища, а не з репозиторію. Якщо потрібне лише системне сповіщення, скрипт може повернути terminalSequence (OSC 9/99/777 або BEL; працює тільки в інтерактивній сесії).
{
"hooks": {
"Notification": [{
"matcher": "permission_prompt|idle_prompt",
"hooks": [{
"type": "command",
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/notify.sh",
"args": [],
"async": true
}]
}]
}
}#!/bin/bash msg=$(jq -r '"Claude Code: " + (.message // "потрібна ваша увага")') curl -fsS -X POST -H 'Content-Type: application/json' \ --data "$(jq -nc --arg t "$msg" '{text: $t}')" "$SLACK_WEBHOOK_URL"
#!/bin/bash # варіант без мережі: OSC 777 (urxvt, Ghostty, Warp); для iTerm2/WezTerm - OSC 9, для Kitty - OSC 99 body=$(jq -r '.message // "Needs your attention"') seq=$(printf '\033]777;notify;%s;%s\007' "Claude Code" "$body") jq -nc --arg seq "$seq" '{terminalSequence: $seq}' # тоді без "async": true
5. Аудит-лог дій Claude
Два варіанти. Локальний JSONL (швидко, нічого не покидає машину) і HTTP-хук на внутрішній сервіс аудиту. Для HTTP обов’язково обмежте URL та змінні середовища на рівні організації. Matcher містить . і *, тому обчислюється як regex, а не як список точних назв.
{
"hooks": {
"PostToolUse": [{
"matcher": "Bash|Edit|Write|mcp__.*",
"hooks": [
{
"type": "command",
"command": "jq -c '{ts: (now|todate), session: .session_id, tool: .tool_name, input: .tool_input}' >> ~/.claude/audit.jsonl",
"async": true
},
{
"type": "http",
"url": "https://audit.company.com/claude",
"headers": { "Authorization": "Bearer $AUDIT_TOKEN" },
"allowedEnvVars": ["AUDIT_TOKEN"]
}
]
}]
}
}{
"allowedHttpHookUrls": ["https://audit.company.com/*"],
"httpHookAllowedEnvVars": ["AUDIT_TOKEN"]
}6. Ворота перед git push: детермінований скрипт + LLM
Спершу дешева детермінована перевірка (force push і push у main/master блокуємо exit 2), далі — prompt-хук, який оцінює решту (наприклад, чи не лишилось налагоджувального коду). Обидва мають if, тож для інших Bash-команд процеси навіть не стартують. Усі хуки групи йдуть паралельно, а при розбіжності діє пріоритет deny.
{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"if": "Bash(git push *)",
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/push-guard.sh",
"args": []
},
{
"type": "prompt",
"if": "Bash(git push *)",
"prompt": "Ти рев’юер перед push у GitLab. Дані події: $ARGUMENTS. Відхили (ok:false з коротким reason), якщо команда пушить гілку, яка схожа на main/master/release, або явно містить налагоджувальні артефакти. Інакше ok:true.",
"continueOnBlock": true,
"timeout": 30
}
]
}]
}
}#!/bin/bash cmd=$(jq -r '.tool_input.command') if grep -Eq -- '--force( |$)|(^| )-f( |$)' <<<"$cmd"; then echo "Force push заборонено. Використайте --force-with-lease у feature-гілці" >&2; exit 2 fi if grep -Eq '(^| |:)(main|master)( |$)' <<<"$cmd"; then echo "Push напряму в main/master заборонено - відкрийте Merge Request" >&2; exit 2 fi exit 0
if для Bash — best-effort: якщо Claude Code не може розібрати команду, хук запускається незалежно від шаблону, а для шаблонів, що уточнюють більше за ім’я команди, — також при $(), зворотних лапках чи $VAR. Захист рівня політики робіть через permissions.deny (наприклад, Bash(git push --force *)) і правила protected branches у GitLab.
hooks: довідник
Усі події, типи обробників, matcher та if, exit-коди, JSON-вивід, змінні середовища, безпека, налагодження
Повна довідка по хуках: усі події, обробники, matcher, коди завершення, JSON-вивід, змінні середовища, безпека й налагодження. Конфігурація й картки ключів — у попередньому розділі «hooks».
Події: сесія і середовище
| Подія | Коли спрацьовує | Блокує? | Matcher | Ключові поля input | Вихід / рішення |
|---|---|---|---|---|---|
SessionStart | старт або відновлення сесії | ні | startup, resume, clear, compact, fork | source, model?, agent_type?, session_title?; при resume/fork ще seconds_since_last_response, context_tokens, prompt_cache_likely_expired, estimated_cache_write_usd | additionalContext, initialUserMessage (лише -p), sessionTitle, watchPaths, reloadSkills; звичайний stdout стає контекстом |
Setup | --init-only, -p --init, -p --maintenance | ні | init, maintenance | trigger | немає (JSON відкидається); доступний CLAUDE_ENV_FILE |
SessionEnd | завершення сесії | ні | clear, resume, logout, prompt_input_exit, other | reason | немає; бюджет 1.5 с. (bypass_permissions_disabled прибрано у v2.1.234) |
ConfigChange | змінились файли settings, managed або skills | так (крім policy_settings) | user_settings, project_settings, local_settings, policy_settings, skills | source, file_path? | decision:"block"; причина нікому не показується (лише debug-лог) |
CwdChanged | cd в основній розмові | ні | немає | old_cwd, new_cwd | watchPaths; доступний CLAUDE_ENV_FILE |
DirectoryAdded | /add-dir або SDK register_repo_root (не --add-dir) | ні | slash_command, register_repo_root | directory, source | немає; працює у фоні |
FileChanged | файл зі списку спостереження змінився на диску | ні | літеральні імена через | (.envrc|.env), вони ж формують watch-list | file_path, event (change/add/unlink) | watchPaths; доступний CLAUDE_ENV_FILE |
Події: промпт і сповіщення
| Подія | Коли спрацьовує | Блокує? | Matcher | Ключові поля input | Вихід / рішення |
|---|---|---|---|---|---|
InstructionsLoaded | завантажено CLAUDE.md або .claude/rules/*.md | ні | session_start, nested_traversal, path_glob_match, include, compact | file_path, memory_type, load_reason, globs?, trigger_file_path?, parent_file_path?; memory_type: User/Project/Local/Managed | немає |
UserPromptSubmit | кожен промпт, у т.ч. заплановані задачі, звіти фонових субагентів, повідомлення з інших сесій | так | немає | prompt, session_title? | decision:"block" + reason (бачить лише користувач), additionalContext, sessionTitle, suppressOriginalPrompt; переписати промпт не можна; звичайний stdout стає контекстом |
UserPromptExpansion | розкриття введеної /команди | так | ім’я команди | expansion_type (slash_command/mcp_prompt), command_name, command_args, command_source, prompt | decision:"block", reason, additionalContext |
MessageDisplay | під час стрімінгу тексту асистента | ні | немає | turn_id, message_id, index, final, delta | displayContent (лише відображення; транскрипт і Claude бачать оригінал); типовий таймаут 10 с |
Notification | сповіщення Claude Code | ні | permission_prompt, idle_prompt, auth_success, elicitation_dialog, elicitation_url_dialog, elicitation_complete, elicitation_response, agent_needs_input, agent_completed, quota_auto_resume_fired, quota_auto_resume_stale, quota_auto_resume_disabled | message, title?, notification_type | діє лише terminalSequence. permission_prompt і elicitation-діалоги спрацьовують після ~6 с простою, idle_prompt — після ~60 с |
Події: інструменти і дозволи
| Подія | Коли спрацьовує | Блокує? | Matcher | Ключові поля input | Вихід / рішення |
|---|---|---|---|---|---|
PreToolUse | перед викликом інструмента | так | назва інструмента | tool_name, tool_input, tool_use_id, mcp_server? | hookSpecificOutput.permissionDecision allow/deny/ask/defer, permissionDecisionReason, updatedInput, additionalContext. defer працює лише в -p при одному виклику; AskUserQuestion/ExitPlanMode потребують allow + updatedInput |
PermissionRequest | ось-ось з’явиться запит дозволу (і коли виклик без UI був би авто-відхилений) | лише через JSON (exit 2 не діє) | назва інструмента | tool_name, tool_input, permission_suggestions, mcp_server? (без tool_use_id) | decision.behavior allow/deny, updatedInput, updatedPermissions, message, interrupt. Не запускається для мережевих запитів sandbox |
PermissionDenied | auto-режим відхилив виклик | ні | назва інструмента | tool_name, tool_input, tool_use_id, reason | hookSpecificOutput.retry: true (дозволяє моделі повторити) |
PostToolUse | після успішного інструмента | ні, але повертає фідбек Claude | назва інструмента | tool_input, tool_response, tool_use_id, duration_ms, mcp_server?; Bash може мати tool_response.bashEditDiff (бета, v2.1.269+) | decision:"block" + reason, additionalContext, updatedToolOutput, updatedMCPToolOutput, classifierContext (v2.1.236+, до 2000 символів) |
PostToolUseFailure | після невдалого інструмента | ні | назва інструмента | error, is_interrupt, duration_ms | additionalContext; decision:"block" |
PostToolBatch | після паралельного пакета викликів, до наступного запиту до моделі | так (зупиняє цикл) | немає | tool_calls[] (tool_name, tool_input, tool_use_id, tool_response) | additionalContext, decision:"block" |
Події: субагенти та задачі
| Подія | Коли спрацьовує | Блокує? | Matcher | Ключові поля input | Вихід / рішення |
|---|---|---|---|---|---|
SubagentStart | субагент запущено або відновлено; також щоразу, коли in-process тіммейт обробляє нове повідомлення | ні | тип агента (плагінні: ^plugin:name$) | agent_id, agent_type | additionalContext (іде в субагента) |
SubagentStop | субагент завершив роботу | так | тип агента | stop_hook_active, agent_id, agent_type, agent_transcript_path, last_assistant_message, background_tasks, session_crons | як у Stop |
TaskCreated | виклик TaskCreate | так | немає | task_id, task_subject, task_description?, teammate_name? | exit 2 або decision:"block" видаляє задачу; continue:false ігнорується |
TaskCompleted | задачу позначено виконаною через TaskUpdate, або тіммейт завершується з задачами в роботі | так | немає | як у TaskCreated | exit 2 або continue:false (ігнорується, якщо подію спричинив TaskUpdate) |
TeammateIdle | тіммейт збирається простоювати | так | немає | teammate_name, team_name | exit 2 або continue:false |
Події: завершення і компактування
| Подія | Коли спрацьовує | Блокує? | Matcher | Ключові поля input | Вихід / рішення |
|---|---|---|---|---|---|
Stop | головний агент закінчив відповідь | так | немає | stop_hook_active, last_assistant_message, background_tasks[], session_crons[] | decision:"block" + reason (обов’язково), hookSpecificOutput.additionalContext (фідбек без «помилки») |
StopFailure | хід закінчився помилкою API | ні | rate_limit, overloaded, authentication_failed, oauth_org_not_allowed, account_on_hold, billing_error, invalid_request, model_not_found, server_error, max_output_tokens, cloud_credential_error, unknown | error, error_details?, last_assistant_message? (тут це текст помилки API) | вивід ігнорується, окрім terminalSequence |
PreCompact | перед компактуванням | так | manual, auto | trigger, custom_instructions | decision:"block" |
PostCompact | після компактування | ні | manual, auto | trigger, compact_summary | немає |
Події: моделі, worktree, MCP
| Подія | Коли спрацьовує | Блокує? | Matcher | Ключові поля input | Вихід / рішення |
|---|---|---|---|---|---|
PreModelSwitch | перед перемиканням моделі користувачем/клієнтом (v2.1.251+) | так; таймаут теж блокує | канонічна назва моделі (claude-opus-5, .*opus.*) | from_model, to_model, requested_model, source (command/picker/sdk), context_tokens, prompt_cache_warm, cache_ttl, estimated_cache_write_usd, pricing | permissionDecision allow/deny/ask (без defer) або decision:"block". Типи: command/http/mcp_tool |
PostModelSwitch | після будь-якої зміни моделі | ні | канонічна назва моделі | як у PreModelSwitch, source також auto|resume | additionalContext; звичайний stdout стає контекстом |
WorktreeCreate | --worktree, isolation:"worktree" або фонова сесія | так (будь-який ненульовий код = помилка) | немає | name | command: шлях — останній непорожній рядок stdout; HTTP: hookSpecificOutput.worktreePath. Замінює git; .worktreeinclude пропускається |
WorktreeRemove | видалення worktree, створеного хуком | так (ненульовий код, якщо каталог ще існує) | немає | worktree_path | немає |
Elicitation | MCP-сервер просить ввід у користувача | так (відхиляє) | ім’я MCP-сервера | mcp_server_name, message, mode (form/url), url?, elicitation_id?, requested_schema? | hookSpecificOutput.action accept/decline/cancel + content, або decision:"block" |
ElicitationResult | користувач відповів на elicitation | так (стає decline) | ім’я MCP-сервера | mcp_server_name, action, mode?, elicitation_id?, content? | action + content (підміна або decline) |
Типи обробників
Є п’ять типів. Спільні поля:
| Поле | Обов’язкове | Опис |
|---|---|---|
type | так | command, http, mcp_tool, prompt або agent |
if | ні | одне правило дозволів, напр. Bash(git *) або Edit(*.py); лише на PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest, PermissionDenied (на інших подіях хук з if ніколи не запуститься) |
timeout | ні | секунди до скасування; значення за замовчуванням — у таблиці нижче |
statusMessage | ні | текст спінера, поки хук працює |
once | ні | true — прибрати хук після першого успішного запуску; працює лише у frontmatter skill (у settings і в агентах ігнорується) |
Специфічні поля:
| Тип | Обов’язкові поля | Додаткові поля та поведінка |
|---|---|---|
| command | command (обов’язково) | args — exec form: без shell, кожен елемент — один аргумент (рекомендовано зі шляхами-плейсхолдерами); async; asyncRewake — у фоні, а при exit 2 будить Claude (stderr іде як system reminder); shell = bash | powershell (ігнорується з args). Без args — shell form: sh -c, Git Bash або PowerShell на Windows |
| http | url (обов’язково) | headers (підтримують $VAR / ${VAR}), allowedEnvVars (без нього інтерполяція не працює, а невказані змінні стають порожніми). Тіло — POST із JSON-входом події. 2xx з порожнім тілом = успіх; 2xx з JSON = розбирається; інше (не-2xx, текст, збій) = неблокуюча помилка |
| mcp_tool | server, tool (обов’язкові) | input з підстановками ${tool_input.file_path}. Для плагінного сервера server = plugin:<plugin>:<server>. Текст результату читається як stdout команди; isError: true = неблокуюча помилка. OAuth не запускає; на SessionStart при запуску та Setup пропускається |
| prompt | prompt (обов’язково) | model (типово — «фонова» модель), timeout (30), continueOnBlock. $ARGUMENTS — JSON-вхід (\$ екранує); без нього JSON дописується в кінець. Відповідь: {"ok", "reason", "impossible"} |
| agent (експериментальний) | prompt (обов’язково) | як prompt, але timeout 60, до 50 ходів, може читати через Read/Grep/Glob; без continueOnBlock та impossible (ok:false обробляється як continueOnBlock: true) |
Які типи підтримує подія
| Група | Події |
|---|---|
| Усі п’ять типів | PermissionDenied, PostToolBatch, PostToolUse, PostToolUseFailure, PreToolUse, Stop, SubagentStop, TaskCreated, TaskCompleted, TeammateIdle, UserPromptExpansion, UserPromptSubmit |
Без agent | PermissionRequest |
| Лише command / http / mcp_tool | ConfigChange, CwdChanged, DirectoryAdded, Elicitation, ElicitationResult, FileChanged, InstructionsLoaded, MessageDisplay, Notification, PostCompact, PostModelSwitch, PreCompact, PreModelSwitch, SessionEnd, StopFailure, SubagentStart, WorktreeCreate, WorktreeRemove |
| Лише command / mcp_tool | SessionStart, Setup (mcp_tool на SessionStart при запуску й на Setup завжди пропускається) |
Таймаути за замовчуванням
| Тип / подія | Таймаут |
|---|---|
command, http, mcp_tool | 600 с |
prompt | 30 с |
agent | 60 с |
| command/http/mcp_tool на UserPromptSubmit, PreModelSwitch, PostModelSwitch | 30 с |
| command/http/mcp_tool на MessageDisplay | 10 с |
| SessionEnd (усі типи) | спільний бюджет 1.5 с; власний timeout піднімає його до 60 с; CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS задає явно |
async: true | таймаут не діє (для asyncRewake діє) |
Хук скасовується, а його вивід відкидається. На PreToolUse таймаут command/http/mcp_tool не блокує виклик (піде звичайний потік дозволів), на PreModelSwitch — блокує перемикання.
Фонові хуки: async і asyncRewake
| Параметр | Поведінка |
|---|---|
"async": true | лише command; Claude не чекає. Після завершення additionalContext і systemMessage з JSON надходять Claude на наступному ході (користувачу не показуються); поля рішень не діють. Якщо сесія бездіяльна — чекають наступної взаємодії. У -p усі ще запущені async-хуки вбиваються при завершенні |
"asyncRewake": true | у фоні; при exit 2 будить Claude одразу, навіть у бездіяльній сесії; stderr (або stdout, якщо stderr порожній) показується як system reminder. Таймаут діє |
| Сповіщення про завершення | за замовчуванням приховані; Ctrl+O або --verbose |
Matcher: як рахується збіг
| Значення matcher | Інтерпретація | Приклад |
|---|---|---|
"*", "" або поле відсутнє | усе | спрацьовує на кожну появу події |
лише літери, цифри, _, -, пробіли, ,, | | точний рядок або список точних рядків | Bash — лише Bash; Edit|Write і Edit, Write — або-або |
| будь-який інший символ | JavaScript-regex без якорів | ^Notebook; Edit.* збігається і з NotebookEdit — пишіть ^Edit$ |
FileChanged, StopFailure | вужчий точний набір: літери, цифри, _, | | дефіс, пробіл чи кома переводять на regex; розділювач лише | |
| MCP-інструменти | формат mcp__<server>__<tool> | mcp__memory не збігається ні з чим — потрібно mcp__memory__.*; плагінний сервер: mcp__plugin_<plugin>_<server>__.* |
Matcher чутливий до регістру. Що саме він фільтрує — див. колонку «Matcher» в таблицях подій. Для подій без підтримки matcher (UserPromptSubmit, PostToolBatch, Stop, TeammateIdle, TaskCreated, TaskCompleted, WorktreeCreate, WorktreeRemove, MessageDisplay, CwdChanged) поле тихо ігнорується.
Поле if: фільтр за аргументами
if — рівно одне правило в синтаксисі дозволів, без &&, || і списків; для кількох умов робіть окремі обробники. Обчислюється лише на tool-подіях (див. вище). Для файлових інструментів Edit(src/**) збігається лише з <cwd>/src (з v2.1.214); каталог src на довільній глибині — Edit(**/src/**). Правила Edit(...) в системі дозволів охоплюють усі вбудовані інструменти редагування файлів.
if | Bash-команда | Хук запуститься? | Чому |
|---|---|---|---|
Bash(git *) | FOO=bar git push | так | початкові присвоєння VAR= відкидаються |
Bash(git *) | npm test && git push | так | перевіряється кожна підкоманда |
Bash(rm *) | echo $(rm -rf /) | так | вміст $() і зворотних лапок перевіряється |
Bash(rm *) | echo $(date) | ні | жодна підкоманда не збігається |
Bash(git push *) | echo $(date) | так | шаблони, що уточнюють більше за ім’я команди, запускають хук на $(), зворотні лапки й $VAR |
Якщо Claude Code не може визначити, які команди містить Bash-вхід, він запускає хук незалежно від шаблону. Для жорсткого allow/deny користуйтеся системою дозволів, а не хуком із if.
Вхід (stdin / тіло POST)
Кожна подія додає до спільних полів свої (див. таблиці подій). Для command-хуків це JSON у stdin, для HTTP — тіло запиту. Моделі в спільних полях немає: змінної $CLAUDE_MODEL не існує, а поле model може прийти лише в SessionStart; для відстеження використовуйте PostModelSwitch.
| Поле | Опис |
|---|---|
session_id | ідентифікатор сесії |
prompt_id | UUID поточного промпта (збігається з prompt.id у OpenTelemetry); відсутній до першого вводу |
transcript_path | шлях до JSON розмови; файл пишеться асинхронно й може відставати — останній текст беріть з last_assistant_message |
cwd | поточний каталог на момент виклику (слідує за cd і за входом у worktree) |
scratchpad_dir | тека scratchpad сесії (v2.1.257+); може бути відсутня |
permission_mode | default, plan, acceptEdits, auto, dontAsk, bypassPermissions; режим Manual приходить як default |
effort.level | low / medium / high / xhigh / max; для подій у контексті інструмента; також як $CLAUDE_EFFORT |
hook_event_name | назва події |
agent_id, agent_type | лише всередині субагента або з --agent |
tool_name, tool_input, tool_use_id | події інструментів; для MCP додається mcp_server {name, source} (v2.1.274+). file_path завжди абсолютний (на Windows із зворотними слешами) |
Коди завершення
| Код | Що означає |
|---|---|
| 0 | успіх. Stdout розбирається як JSON, лише якщо починається з { і закінчується }. Звичайний текст стає контекстом лише для UserPromptSubmit, UserPromptExpansion, SessionStart, PostModelSwitch; на решті подій іде в debug-лог. Stderr при коді 0 — тільки в debug-лог |
| 2 | блокуюча помилка (де подія це дозволяє, див. таблицю нижче). Не скасовується JSON-ом: навіть permissionDecision:"allow" не допоможе. Причина — з JSON-рішення, інакше зі stderr. Якщо разом із кодом 2 виведено JSON, що не проходить схему, блок усе одно діє (з v2.1.214) |
| інші (1, 127...) | неблокуюча помилка: дія виконується, у транскрипті з’являється hook error з першим рядком stderr. Виняток: якщо stdout містить валідний JSON, код ігнорується, і рішення приймає лише JSON |
| невалідний JSON | stdout схожий на JSON, але не парситься або не проходить схему — неблокуюча помилка на будь-якому коді, крім 2 |
Що робить exit 2 на кожній події
| Результат | Події |
|---|---|
| Блокує дію | PreToolUse (виклик), UserPromptSubmit (промпт; stderr бачить користувач), UserPromptExpansion, Stop, SubagentStop, TeammateIdle, TaskCreated, TaskCompleted, PostToolBatch (зупиняє цикл), PreCompact, PreModelSwitch, Elicitation, ElicitationResult (decline), ConfigChange (крім policy_settings) |
| Будь-який ненульовий код = помилка | WorktreeCreate (створення падає), WorktreeRemove (падає, якщо каталог ще існує) |
| Не блокує, stderr бачить Claude | PostToolUse, PostToolUseFailure (інструмент уже відпрацював) |
| Не блокує, stderr бачить лише користувач | SessionStart, SubagentStart, SessionEnd, CwdChanged, FileChanged, PostCompact, PostModelSwitch |
| Exit 2 не діє | PermissionRequest (відхиляйте через JSON decision.behavior) |
| Усе ігнорується | Notification, Setup, StopFailure (крім terminalSequence), PermissionDenied, InstructionsLoaded, MessageDisplay; DirectoryAdded — stderr у debug-лог |
Код 1 (звичний «збій» в Unix) не блокує, якщо немає валідного JSON. Конвеєр на кшталт cmd | tail повертає код останньої команди, тобто 0. Обирайте одне: або лише коди, або exit 0 + JSON; при змішуванні exit 2 зберігає блокувальну дію.
JSON-вивід
Stdout повинен містити лише JSON-об’єкт. Універсальні поля приймає кожна подія (деякі їх відкидають):
| Поле | Типово | Опис |
|---|---|---|
continue | true | false повністю зупиняє Claude після хука; має пріоритет над рішеннями події |
stopReason | - | повідомлення користувачу при continue:false (залишається в розмові) |
suppressOutput | false | приймається, але не має жодного ефекту |
systemMessage | - | попередження користувачу; деякі події його відкидають |
terminalSequence | - | escape-послідовність для терміналу: лише OSC 0/1/2/9/99/777 і BEL; замінює недоступний /dev/tty; тільки в інтерактивній сесії |
decision / reason | - | верхньорівневе рішення для подій, що його використовують (єдине значення — "block") |
hookSpecificOutput | - | вкладений об’єкт; обов’язково містить hookEventName |
| Схема рішення | Події |
|---|---|
Верхньорівневий decision:"block" + reason | UserPromptSubmit, UserPromptExpansion, PostToolUse, PostToolUseFailure, PostToolBatch, Stop, SubagentStop, ConfigChange, PreCompact |
Exit 2 або continue:false | TeammateIdle, TaskCompleted; TaskCreated: exit 2 або decision:"block" |
hookSpecificOutput.permissionDecision | PreToolUse (allow/deny/ask/defer); PreModelSwitch (allow/deny/ask) |
hookSpecificOutput.decision.behavior | PermissionRequest (allow/deny) |
hookSpecificOutput.retry | PermissionDenied |
hookSpecificOutput.action + content | Elicitation, ElicitationResult (або decision:"block") |
displayContent | MessageDisplay |
Лише контекст (additionalContext) | SessionStart, SubagentStart, PostModelSwitch |
| Немає керування | Setup, Notification, SessionEnd, PostCompact, InstructionsLoaded, StopFailure, CwdChanged, DirectoryAdded, FileChanged |
Переписування та контекст
| Поле | Де | Нотатки |
|---|---|---|
updatedInput | PreToolUse (в hookSpecificOutput), PermissionRequest (в decision) | замінює весь об’єкт аргументів, тож повертайте й незмінені поля; права й авто-фон Bash оцінюються вже за новим входом |
updatedToolOutput | PostToolUse | замінює результат інструмента; форма має збігатися з виходом інструмента (для MCP — updatedMCPToolOutput) |
updatedPermissions | PermissionRequest | масив записів addRules/replaceRules/removeRules/setMode/addDirectories/removeDirectories; призначення: session, localSettings, projectSettings, userSettings |
additionalContext | більшість подій з контекстом | текст обгортається в system reminder; кілька хуків — усі значення; ліміт 10 000 символів (решта у файлі + прев’ю 2000) |
Для PreToolUse верхньорівневі decision/reason застарілі (approve/block відображаються на allow/deny). Рядки additionalContext, systemMessage, initialUserMessage і звичайний stdout обмежені 10 000 символами кожен, а надлишок іде у файл із прев’ю 2000 символів. Пишіть контекст як факти («цільове середовище — production»), а не як імперативні «системні» команди: так він сприймається як дані проєкту й не провокує захист від prompt injection.
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Міграції правити не можна: створіть нову"
}
}{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"updatedInput": { "command": "pytest -x -q" }
}
}{ "decision": "block", "reason": "Запустіть pytest і виправте помилки" }{ "continue": false, "stopReason": "Збірка впала, виправте помилки" }Змінні середовища хуків
Хук успадковує середовище батьківського процесу, окрім змінних OTEL_* (і тих, що вилучає CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1). Плейсхолдери ${CLAUDE_PROJECT_DIR}, ${CLAUDE_PLUGIN_ROOT}, ${CLAUDE_PLUGIN_DATA} підставляються в command і args і водночас експортуються як змінні. У shell-form обгортайте їх у лапки; у exec form (args) лапки не потрібні. Змінних $CLAUDE_FILE_PATH і $CLAUDE_MODEL немає.
| Змінна | Значення |
|---|---|
CLAUDE_PROJECT_DIR | корінь проєкту, де стартувала сесія; не змінюється і в worktree (поточний каталог — поле cwd у вході) |
CLAUDE_PLUGIN_ROOT | каталог встановленого плагіна |
CLAUDE_PLUGIN_DATA | постійний каталог даних плагіна (переживає оновлення) |
CLAUDE_PLUGIN_OPTION_<KEY> | опції плагіна для shell-form хуків (напр. CLAUDE_PLUGIN_OPTION_WEBHOOK_URL) |
CLAUDE_ENV_FILE | лише SessionStart, Setup, CwdChanged, FileChanged: допишіть рядки export VAR=..., і вони діятимуть у наступних Bash-командах |
CLAUDE_EFFORT | поточний рівень effort |
CLAUDE_CODE_REMOTE | "true" у віддалених (web) середовищах |
CLAUDE_CODE_BRIDGE_SESSION_ID | ID сесії Remote Control, поки з’єднання активне (v2.1.199+) |
CLAUDE_CODE_STOP_HOOK_BLOCK_CAP | піднімає ліміт 8 поспіль блокувань Stop |
CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS | бюджет SessionEnd; також стає таймаутом хуків без власного timeout (з v2.1.268) |
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB | 1 — з середовища підпроцесів вилучаються чутливі змінні |
CLAUDE_CODE_DEBUG_LOG_LEVEL | verbose — деталі збігу matcher у debug-лозі |
CLAUDE_CODE_DISABLE_PERMISSION_PROMPT_NOTIFY_HOOKS | 1 — вимикає Notification permission_prompt у сесіях із canUseTool (Claude Desktop, VS Code) |
Хуки в skills, субагентах і плагінах
| Де | Коли діють | Особливості |
|---|---|---|
| frontmatter skill | з виклику skill до кінця сесії | формат той самий, що в settings; once: true працює лише тут |
| frontmatter субагента | поки субагент працює | Stop перетворюється на SubagentStop; для проєктного субагента потрібна довіра до теки (workspace trust, з v2.1.218); блокуються під allowManagedHooksOnly |
плагін hooks/hooks.json | поки плагін увімкнений | об’єднуються з user/project; шляхи через ${CLAUDE_PLUGIN_ROOT}; MCP-сервер у mcp_tool — plugin:<plugin>:<server> |
| settings / managed / плагіни — в субагентах | завжди | tool-події у субагентах запускають ті самі хуки, а вхід містить agent_id та agent_type |
--- name: deploy-staging description: Деплой на staging з перевіркою hooks: PreToolUse: - matcher: "Bash" hooks: - type: command command: "${CLAUDE_PROJECT_DIR}/.claude/hooks/deploy-guard.sh" args: [] once: true --- Деплой виконуй лише після зеленого pipeline.
Безпека
Command-хук може змінювати, видаляти й читати будь-що, до чого має доступ ваш обліковий запис. Перевіряйте й тестуйте кожну команду перед додаванням.
| Тема | Що знати |
|---|---|
| Workspace trust | в інтерактивній сесії хуки з усіх settings-файлів (навіть ~/.claude/settings.json) чекають, поки ви приймете діалог довіри до теки. У -p/SDK діалогу немає, тека вважається довіреною, тож хуки з репозиторію .claude/settings.json запускаються |
| Чужий репозиторій у CI/скрипті | перегляньте .claude/; запускайте з --bare або --settings '{"disableAllHooks": true}'. Лише user-файла замало: project-налаштування мають вищий пріоритет |
| Frontmatter-хуки | проєктні skills реєструються і в непідтвердженій теці при -p; хуки проєктного субагента — лише після довіри (v2.1.218+) |
| Політика організації | allowManagedHooksOnly, allowedHttpHookUrls, httpHookAllowedEnvVars; PreToolUse-deny діє навіть у bypassPermissions, а allow хука не обходить deny-правила |
"$VAR", а не $VAR; шляхи до скриптів — абсолютні або через ${CLAUDE_PROJECT_DIR} з args.., нормалізуйте зворотні слеші Windows.env, .git/, ключіjq -n --arg, а не конкатенацією рядківif захистом: це best-effort фільтрallowedEnvVarsНалагодження
| Що | Як |
|---|---|
| Лог виконання | claude --debug-file /tmp/claude.log і tail -f; або /debug посеред сесії; --debug пише в ~/.claude/debug/<session-id>.txt, а не в термінал. Деталі збігів — CLAUDE_CODE_DEBUG_LOG_LEVEL=verbose |
| Результат запуску | Ctrl+O (транскрипт): успішний хук мовчить, блок показує причину, неблокуюча помилка — hook error + перший рядок stderr |
| Ручна перевірка | echo '{"tool_name":"Bash","tool_input":{"command":"ls"}}' | ./hook.sh; echo $? |
| Хук не спрацьовує | /hooks — чи є він під потрібною подією; matcher чутливий до регістру; чи не стоїть if на події без підтримки; чи виконуваний файл (chmod +x); чи JSON валідний (без коментарів і зайвих ком) |
| JSON «не діє» | зайвий вивід перед { (echo у ~/.zshrc — обгорніть у [[ $- == *i* ]]); поле не на тому рівні (permissionDecision має бути в hookSpecificOutput); у debug-лозі шукайте Hook JSON output had unrecognized keys. JSON краще збирати через jq -n --arg |
| Stop не відпускає | перевіряйте stop_hook_active; ліміт — 8 поспіль без викликів інструментів між ними |
| Тихо «відкриті ворота» | помилка у шляху (код 127) — неблокуюча; перевірте першу появу хука в транскрипті |
Що саме ізолює sandbox
Sandbox — межа на рівні ОС навколо shell-команд (Bash, PowerShell і Monitor) та їхніх дочірніх процесів. Вона вимкнена за замовчуванням: вмикається через /sandbox або sandbox.enabled. Побудований на відкритому пакеті @anthropic-ai/sandbox-runtime.
| Ресурс | Типово для команди в sandbox | Чим змінити |
|---|---|---|
| Запис | Робоча тека, тека тимчасових файлів користувача (для неї виставляється $TMPDIR) і додані директорії. Protected paths завжди під забороною запису | filesystem.allowWrite, filesystem.denyWrite |
| Читання | Майже вся машина, включно з ~/.ssh та ~/.aws/credentials | filesystem.denyRead / allowRead, credentials, permissions.blockReadsOutsideWorkingDirectories |
| Мережа | Прямого виходу немає — лише проксі на вашій машині, який звіряє хост зі списком. Дозволені домени спочатку порожні | network.allowedDomains, deniedDomains |
| Змінні середовища | Успадковуються від Claude Code, включно з секретами | credentials.envVars, CLAUDE_CODE_SUBPROCESS_ENV_SCRUB |
Вбудовані Read, Edit, Write, WebFetch, WebSearch керуються правилами дозволів, а не sandbox: denyRead не зупиняє інструмент Read, а allowedDomains не обмежує WebFetch. Поза межею також: хуки, локальні MCP-сервери, LSP, плагінні монітори, statusLine, apiKeyHelper, команди, які ви вводите через !, команди з excludedCommands та повтори поза sandbox. Щоб обгорнути все одним кордоном, запускайте весь Claude Code в контейнері/VM або в sandbox runtime.
Платформи
| Платформа | Механізм | Примітки |
|---|---|---|
| macOS | Seatbelt (вбудований) | Окремо нічого ставити не треба |
| Linux | bubblewrap + socat | sudo apt-get install bubblewrap socat (Ubuntu/Debian) або sudo dnf install bubblewrap socat (Fedora). Необов’язковий seccomp-фільтр додає блокування Unix-сокетів: npm install -g @anthropic-ai/sandbox-runtime. На Ubuntu 24.04+ потрібен AppArmor-профіль для bwrap (перевірка: sysctl kernel.apparmor_restrict_unprivileged_userns) |
| WSL2 | bubblewrap + socat | Те саме, що Linux. WSL1 не підтримується («Sandboxing requires WSL2») |
| Нативний Windows | немає | Команди виконуються без sandbox; запускайте Claude Code в WSL2 |
Якщо sandbox не може стартувати (бракує залежності, непідтримувана платформа), Claude Code типово запускає команди без sandbox; щоб натомість завершувати запуск з помилкою — failIfUnavailable: true. У контейнері без привілеїв bubblewrap не змонтує /proc: див. enableWeakerNestedSandbox.
Режими sandbox і взаємодія з дозволами
| Режим | Що відбувається | Налаштування |
|---|---|---|
| auto-allow | Команда, яка виконується всередині sandbox, схвалюється без запиту (навіть у Manual). Deny-правила, content-scoped ask-правила (Bash(git push *)) і rm/rmdir по критичних шляхах усе одно діють; голе Bash в ask для команд у sandbox пропускається, але не в plan-режимі | autoAllowBashIfSandboxed: true (default) |
| regular permissions | Усі команди проходять звичайні запити, навіть у sandbox: більше контролю, більше підтверджень | autoAllowBashIfSandboxed: false |
Auto-allow у sandbox і режим auto (класифікатор) — різні речі; вони незалежні й комбінуються. Правила дозволів та sandbox доповнюють одне одного: шляхи з Edit-allow, Read/Edit-deny та домени з WebFetch(domain:) зливаються в підсумкову конфігурацію sandbox.
Мережа: що з хостами поза allowedDomains
Команда лишається в sandbox і чекає рішення; воно залежить від режиму дозволів:
| Режим | Що станеться зі з’єднанням |
|---|---|
bypassPermissions (і plan, якщо bypass доступний) | Дозволено без запиту |
Manual, acceptEdits, plan | Запит |
auto | Відхилено, якщо команда не вказала хост у своєму списку (v2.1.271+) і класифікатор його не схвалив |
dontAsk | Відхилено |
З strictAllowlist або allowManagedDomainsOnly проксі відхиляє з’єднання в усіх режимах; deniedDomains — теж. «Yes» дозволяє хост до кінця сесії, «Yes, and don’t ask again» зберігає правило WebFetch(domain:…) у локальні налаштування.
- Інструменти без підтримки проксі (
ssh, більшість драйверів БД, UDP, QUIC,ping) не підключаться навіть до дозволеного хоста — їх виносять вexcludedCommands. - Хости, що резолвляться в loopback/link-local (
169.254.169.254), відхиляються;localhostдозволений. Корпоративний проксі задають черезHTTPS_PROXYвenv. - IPv6 пишіть у дужках:
"[::1]","[::1]:443"(v2.1.229+). Запис без порту дозволяє всі порти хоста. - Проксі вирішує за іменем хоста і за замовчуванням не розшифровує TLS, тож можливий domain fronting; не дозволяйте надто широкі домени на кшталт
github.com, якщо важливий ризик витоку.
Вихід із sandbox (escape hatch)
Коли команда не працює в sandbox, Claude може повторити її з параметром dangerouslyDisableSandbox. Хто це схвалює — залежить від режиму:
| Режим | Повтор поза sandbox |
|---|---|
bypassPermissions | Без запиту |
Manual, acceptEdits | Запит «Bash command (unsandboxed)» |
auto | Окремий класифікатор оцінює команду |
dontAsk | Відхилено |
- Збіжне allow-правило (наприклад
Bash(curl *)) схвалює й повтор поза sandbox без запиту. - Ask-правило
Bash(dangerouslyDisableSandbox:true)змушує питати завжди (навіть в auto і bypass) і має пріоритет над allow. allowUnsandboxedCommands: false(«strict sandbox mode») — параметр ігнорується, повтору немає.falseз user/managed/--settingsутримується навіть протиtrueз проєктного файлу (з v2.1.285).- Команди, які ви вводите вручну через
!, у більшості сесій ідуть поза sandbox.
Навіть у записуваних теках sandbox забороняє запис у файли, з яких Claude Code бере конфігурацію й код: .claude (settings, skills, agents, commands, hooks), .mcp.json, shell-rc файли (.bashrc, .zshrc), .gitconfig, .vscode, .idea, .git/hooks і .git/config, файли, що перетворили б теку на bare-репозиторій, а також більшу частину ~/.claude, ~/.claude.json і .credentials.json. Виняток зробити не можна — ні allowWrite, ні Edit-allow; лише filesystem.disabled знімає захист (разом з усією ізоляцією файлів).
Вмикає ізольоване середовище (Seatbelt на macOS, bubblewrap на Linux/WSL) для bash-команд з обмеженим доступом до файлів і мережі. Default — false.
true = bash команди виконуються в обмеженому просторі. З autoAllowBashIfSandboxed (default true) команди в пісочниці не потребують підтвердження — менше промптів без втрати безпеки.
"sandbox": { "enabled": true, "autoAllowBashIfSandboxed": true, // default; false = regular permissions "allowUnsandboxedCommands": false, // strict sandbox mode: ігнорувати dangerouslyDisableSandbox "failIfUnavailable": true // не стартувати без sandbox }
/sandbox відкриває панель: Mode (auto-allow або regular), Overrides (allowUnsandboxedCommands), Config (результуючі налаштування); вибір пишеться в .claude/settings.local.json. Для всіх проєктів ставте enabled у ~/.claude/settings.json. Перевірка, що sandbox працює: попросіть Claude виконати touch ~/sandbox-probe — має бути «Operation not permitted» / «Read-only file system».failIfUnavailable при збої запуску sandbox (немає bubblewrap/socat, WSL1, нативний Windows) Claude Code мовчки запускає команди без ізоляції.allowWrite — куди можна писати. denyWrite — заборона запису. denyRead / allowRead — читання з bash-команд (allowRead повторно відкриває частину області під denyRead; перемагає вужчий шлях). Масиви зливаються з усіх рівнів.
Це керує лише shell-командами та їхніми процесами: denyRead не зупиняє інструмент Read — для нього потрібні deny-правила Read(...) (вони, навпаки, автоматично потрапляють у denyRead). Запис поза дозволеними теками заблокований на рівні ОС. Типово можна писати в робочу теку, тимчасову теку й додані директорії, а читати — майже все, включно з ~/.ssh.
"filesystem": { "allowWrite": ["~/.cache/pip", "~/.npm"], // робоча тека і так записувана "denyWrite": ["./config/prod.json"], "denyRead": ["~/.ssh", "~/.aws"] }
~/.claude у user settings. Кінцеві / та /** прибираються*, ?, [ (після зняття кінцевого /**) в allowWrite/denyWrite пропускається й не діє — вказуй конкретні каталоги (це стосується й Edit-правил, які додаються до цих списків). У denyRead/allowRead wildcard-и працюють на всіх платформах. Захищені шляхи (.claude, .git/hooks, shell-rc…) не відкриваються жодним allowWrite.Allowlist / denylist доменів для мережевих запитів з bash-команд. Запис — домен, wildcard (*.example.com), IP, з необов’язковим :port; без порту — усі порти. Масиви зливаються між рівнями, а ще сюди додаються домени з правил WebFetch(domain:…).
Прямого виходу з sandbox немає, лише через проксі. Дозволені домени спочатку порожні, а що буде з іншими хостами — вирішує режим дозволів (запит у Manual/acceptEdits/plan, відмова в dontAsk, дозвіл у bypassPermissions; таблиця вище). Жорстка заборона — лише з strictAllowlist чи allowManagedDomainsOnly. deniedDomains блокує навіть усередині ширшого wildcard-а й діє в усіх режимах. allowLocalBinding і allowUnixSockets працюють лише на macOS; на Linux для сокетів — allowAllUnixSockets.
"network": { "allowedDomains": ["*.github.com", "registry.npmjs.org", "pypi.org"], "deniedDomains": ["uploads.github.com"], "allowLocalBinding": true, // localhost:8000 — ok (macOS) "allowUnixSockets": ["/var/run/docker.sock"] // docker (macOS) }
allowManagedDomainsOnly — враховувати лише домени з managed (див. картку нижче). strictAllowlist (user/managed, v2.1.219+) — відхиляти хости поза allowlist замість запиту.allowedDomains не обмежує інструмент WebFetch. Дозвіл на /var/run/docker.sock через allowUnixSockets фактично віддає хост-систему. Широкі домени (github.com) лишають шляхи для витоку даних.Команди, які виконуються поза sandbox — без файлових обмежень і без проксі (але зі звичайною перевіркою дозволів). Записи мають синтаксис правил Bash(...): шаблон без wildcard — точний збіг, тож docker збігається лише з голим docker без аргументів, а docker * — з викликом з аргументами чи без.
Для інструментів, несумісних з ізоляцією (docker, клієнти БД без проксі). Якщо інструменту потрібна ще одна тека чи хост — краще allowWrite/allowedDomains, що лишають його в sandbox. Виключена команда має повний доступ: ширший шаблон (docker *) охоплює все, що вміє інструмент.
"excludedCommands": ["docker compose *", "python manage.py migrate *"]
npm ci && docker compose build лишається в sandbox, поки не покритий і npm ci. Збіг іде за текстом виклику: скрипт, що всередині викликає docker, і /usr/local/bin/docker не збігаються.cd/pushd/popd, $() чи підоболонкою, if/for, перенаправленням у файл, sudo/eval/xargs на початку, іменем команди зі змінної, а також git clone/init/worktree add із шляхом, що абсолютний, починається з ~ або містить ... У bypassPermissions виключена команда виконується без запиту, якщо не збігається ask-правило..claude/settings.json і settings.local.json ігноруються — клонований репозиторій не виведе команди з sandbox.Захищає файли з секретами та змінні середовища від команд у пісочниці: deny — приховати, mask — показати плейсхолдер, а справжнє значення підставить sandbox-проксі у вихідних запитах (для файлів mask — з v2.1.221).
Навіть якщо Claude запустить env чи cat ~/.aws/credentials — секрет не потрапить у контекст. Вбудованого списку немає: захищається лише те, що перелічено (типово секрети читаються, зокрема ~/.aws/credentials). mask, allowPlaintextInject, awsPairs, sigv4 діють лише з user, managed і --settings; з проєктних файлів mask-записи відкидаються. mask потребує network.tlsTerminate (або allowPlaintextInject для HTTP).
"credentials": { "files": [{ "path": "~/.aws/credentials", "mode": "deny" }], "envVars": [{ "name": "GITHUB_TOKEN", "mode": "deny" }] }
mask для змінної: { "name": "GITHUB_TOKEN", "mode": "mask", "injectHosts": ["api.github.com"] } — команда бачить заповнювач, а справжнє значення підставляється лише в запитах до api.github.com (без injectHosts — до всіх хостів з allowedDomains).| extract | Регулярний вираз з групою захоплення: маскується лише група 1 (напр. пароль у DATABASE_URL) |
| decode: "jwt" | Підміняє JWT структурно коректною підробкою; з maskClaims маскує лише названі claims (v2.1.224+; не поєднується з extract для змінних) |
| onExtractNoMatch | warn (default) · deny · error — що робити, коли нічого маскувати |
| injectHosts | Хости, де проксі підставляє справжнє значення (мають бути також у allowedDomains) |
| maskDuplicates | Лише для файлів: маскувати також дослівні копії значення в тому самому файлі |
mask застосовується як deny; для каталогів, glob-ів, файлів понад 8 MiB і не-UTF-8 — теж fallback на deny. Файловий deny не діє, якщо вимкнено ізоляцію файлів (filesystem.disabled); захист змінних працює і тоді.Чи виконувати команди, що працюють усередині sandbox, без запиту підтвердження.
Default true — auto-allow режим: менше запитів без втрати безпеки (межу тримає ОС). false — «regular permissions»: команди в sandbox проходять звичайні allow/ask правила і режим дозволів. CLAUDE_CODE_SUBPROCESS_ENV_SCRUB вимикає auto-allow.
"sandbox": { "enabled": true, "autoAllowBashIfSandboxed": false // хочу бачити запити навіть у sandbox }
rm по критичних шляхах діють і в auto-allow. Поза sandbox (виключені команди, повтори) команда йде звичайним шляхом дозволів.Чи може Claude повторити заблоковану в sandbox команду поза нею з параметром dangerouslyDisableSandbox.
Default true. З false параметр ігнорується, і доки sandbox працює, усі команди Claude виконуються в ньому (крім збігів з excludedCommands) — «strict sandbox mode» у вкладці Overrides /sandbox. false з managed чи --settings робить sandbox «admin-required».
"sandbox": { "enabled": true, "allowUnsandboxedCommands": false, "failIfUnavailable": true }
failIfUnavailable, інакше при збої sandbox команди підуть без нього. Хто схвалює повтор у кожному режимі — у таблиці вище.Повторно відкриває читання для шляхів усередині області, яку закрив denyRead. Коли правила перетинаються, перемагає вужчий шлях.
denyRead: ["~/"] + allowRead: ["."] дає читання лише проєкту. Точний або wildcard denyRead лишається заблокованим усередині ширшого allowRead (напр. ~/**/.env), тож широкий allow не відкриє секрет випадково.
"sandbox": { "filesystem": { "denyRead": ["~/"], "allowRead": ["."] // у project settings "." = корінь проєкту } }
~/.claude/settings.json той самий "." означає ~/.claude, а не проєкт — файли проєкту лишилися б заблокованими. Простіший шлях закрити читання поза проєктом — permissions.blockReadsOutsideWorkingDirectories.Вимикає ізоляцію файлової системи, залишаючи мережеву. Команди отримують необмежені читання й запис на хості, а вихід у мережу лишається в межах allowedDomains. Потребує v2.1.216+.
Для сценаріїв, де важливо контролювати куди з’єднуються команди, а не що вони пишуть. denyRead і credentials.files (deny) тоді не діють, а credentials.envVars та застосовані mask — працюють. autoAllowBashIfSandboxed за замовчуванням лишається true — поставте false, щоб бачити запити.
"sandbox": { "enabled": true, "filesystem": { "disabled": true }, "network": { "allowedDomains": ["github.com", "*.npmjs.org"] } }
sandbox.filesystem або credentials.files з режимом deny, ключ може встановити лише managed. Без ізоляції файлів уже не діє й захист protected paths.Враховувати лише ті allowRead, що прийшли з managed-налаштувань, щоб розробники не могли знову відкрити читання шляхів, які закрила організація.
denyRead усе одно зливається з усіх рівнів — розробник завжди може лише додати заборони.
"sandbox": { "filesystem": { "denyRead": ["~/"], "allowRead": ["~/work"], "allowManagedReadPathsOnly": true } }
Відхиляти хости поза allowlist замість запиту. Allowlist = allowedDomains + домени з allow-правил WebFetch(domain:…) (або лише managed, якщо задано allowManagedDomainsOnly). Потребує v2.1.219+.
Перетворює «запит залежно від режиму» на жорстку заборону в усіх режимах, включно з bypassPermissions. Стосується лише команд у sandbox: WebFetch далі підкоряється своїм правилам. Репозиторій увімкнути/вимкнути його не може.
"sandbox": { "network": { "allowedDomains": ["pypi.org", "registry.npmjs.org"], "strictAllowlist": true } }
Фіксує мережевий allowlist на тому, що задано в managed: враховуються лише allowedDomains і allow-правила WebFetch(domain:) з managed-налаштувань, інші джерела ігноруються, а непрописані домени блокуються без запиту.
Робить sandbox «admin-required»: репозиторні ключі, що послаблюють sandbox (excludedCommands, allowedDomains, allowWrite, WebFetch-allow), ігноруються (v2.1.285+), а порт власного проксі може задати лише managed. deniedDomains усе одно зливаються з усіх рівнів.
"sandbox": { "network": { "allowManagedDomainsOnly": true, "allowedDomains": ["github.com", "*.npmjs.org", "pypi.org"] } }
Дозволяє командам у sandbox підключатися до будь-яких Unix-сокетів. На Linux і WSL2 це єдиний спосіб дозволити Unix-сокети (seccomp-фільтр інакше блокує socket(AF_UNIX, …)).
Default false. На WSL2 true також відкриває interop-сокет, що запускає Windows-бінарники (cmd.exe, powershell.exe). Якщо seccomp-фільтра немає, Unix-сокети й так не блокуються.
"sandbox": { "network": { "allowAllUnixSockets": true } }
/var/run/docker.sock фактично віддає хост. Для macOS є вужчий allowUnixSockets, який у картці sandbox.network вище.Додаткові імена XPC/Mach-сервісів, які macOS-sandbox може шукати. Потрібно інструментам на XPC: iOS Simulator, Playwright.
Один кінцевий * — префікс; лише "*" — усі сервіси. Без ключа список порожній. Лише macOS.
"sandbox": { "network": { "allowMachLookup": ["com.apple.coresimulator.*"] } }
Спрямовує HTTP-трафік sandbox на ваш проксі (локальний TCP-порт) замість вбудованого — щоб інспектувати HTTPS, застосовувати власну фільтрацію чи логувати.
Ваш проксі бере фільтрацію на себе: Claude Code припиняє застосовувати свої списки доменів і мережеві запити до цього трафіку. Якщо задано лише один із двох портів, для іншого протоколу лишається вбудований проксі. Під allowManagedDomainsOnly порт може задати лише managed.
"sandbox": { "network": { "httpProxyPort": 8080 } }
gh, gcloud, terraform) за MITM-проксі на macOS потребують ще й enableWeakerNetworkIsolation.Те саме, що httpProxyPort, але для SOCKS5-проксі.
Власний SOCKS-проксі бере фільтрацію на себе; для HTTP лишається вбудований, якщо не задано й httpProxyPort.
"sandbox": { "network": { "socksProxyPort": 8081 } }
Експериментально. Змушує проксі sandbox термінувати TLS, щоб бачити вміст HTTPS-запитів. Потрібно для підстановки mask-облікових даних.
{} створює тимчасовий центр сертифікації на сесію; або вкажіть свої caCertPath і caKeyPath. Без ключа TLS не інспектується. З кількох джерел береться значення з найвищим пріоритетом: managed → --settings → user.
"sandbox": { "network": { "tlsTerminate": {} // або { "caCertPath": "...", "caKeyPath": "..." } } }
Дозволяє підстановку mask також для звичайних HTTP-запитів, а не лише для HTTPS з термінацією TLS.
На plain HTTP особа сервера не перевіряється, а секрет іде відкритим текстом — залишайте false поза довіреними тестовими мережами.
"sandbox": { "credentials": { "allowPlaintextInject": true } }
Групує замасковані змінні середовища, що утворюють одні AWS-облікові дані, для перепідпису запитів SigV4, коли змінні мають нестандартні імена. Потребує v2.1.224+.
Стандартна трійка AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_SESSION_TOKEN зв’язується автоматично, якщо їх замасковано цілком. Кожна названа змінна має бути mask-записом у credentials.envVars (без extract/decode) і займати лише один слот. Згадка стандартних імен у парі вимикає автозв’язування.
"sandbox": { "credentials": { "awsPairs": [ { "accessKeyIdVar": "MY_KEY_ID", "secretAccessKeyVar": "MY_SECRET_KEY" } ] } }
Що робить проксі з формами AWS-запитів, які він не може перепідписати: streaming (aws-chunked), presigned (presigned URL), sigv4a (асиметричний підпис). Потребує v2.1.224+.
Кожне поле: "deny" — проксі відхиляє запит (типово для всіх), "passthrough" — пересилає з підписом від замаскованого заповнювача, тож AWS поверне власну відмову. Стосується запитів, підписаних заповнювачем замаскованої пари.
"sandbox": { "credentials": { "sigv4": { "streaming": "passthrough" } } }
Приглушує звіти про порушення sandbox для шляхів, які команда очікувано пробує і їй відмовляють (наприклад, перевірка /etc/hosts на старті). Блокування лишається; зникає лише сповіщення.
Ключ — підрядок команди ("*" — будь-яка), значення — масив підрядків порушення (зазвичай шляхи). Зменшує шум у виводі, який бачить Claude.
"sandbox": { "ignoreViolations": { "*": ["/etc/hosts"], "npm": ["~/.npmrc"] } }
Linux/WSL2: запуск sandbox усередині непривілейованого Docker-контейнера, де bubblewrap не може змонтувати свіжий /proc. Внутрішній sandbox тоді монтує наявний /proc контейнера.
Знижує безпеку (відкриває інформацію про процеси). Вмикайте лише коли зовнішній контейнер сам дає потрібну ізоляцію; типова помилка без нього — Can't mount proc on /newroot/proc: Operation not permitted.
"sandbox": { "enabled": true, "enableWeakerNestedSandbox": true }
macOS: дозволяє командам у sandbox звертатися до системного сервісу довіри TLS com.apple.trustd.agent.
Go-інструменти (gh, gcloud, terraform) потребують його для перевірки сертифікатів при httpProxyPort з MITM-проксі та власним CA. Знижує безпеку (потенційний канал витоку). Без MITM-проксі краще винести такі інструменти в excludedCommands.
"sandbox": { "enabled": true, "enableWeakerNetworkIsolation": true }
macOS: дозволяє командам у sandbox надсилати Apple Events — без цього open, osascript та інструменти, що відкривають URL у браузері, падають з помилкою -600.
Прибирає ізоляцію виконання коду: команда зможе без запиту запускати інші програми поза sandbox і слати AppleScript до запущених програм (за згодою TCC). Задається лише в user, managed чи CLI; проєктний файл не може. Безпечніше винести одну потрібну команду в excludedCommands.
"sandbox": { "enabled": true, "allowAppleEvents": true }
Вказує sandbox власний бінарник ripgrep замість того, що використовує сам Claude Code.
Поля: command — шлях до rg, необов’язковий args — масив аргументів, що додаються попереду. Без ключа використовується вбудований ripgrep (якщо не USE_BUILTIN_RIPGREP=0).
"sandbox": { "ripgrep": { "command": "/usr/local/bin/rg", "args": ["--no-config"] } }
Linux/WSL2: шлях до бінарника bubblewrap, встановленого поза PATH (наприклад, вендорська копія на ізольованому хості). Використовується і для перевірки залежностей, і для обгортання кожної команди.
Лише абсолютний шлях (відносний відкидається, і береться bwrap з PATH). Читається лише з managed, щоб user/project файл не міг підмінити бінарник.
"sandbox": { "enabled": true, "bwrapPath": "/opt/admin/bwrap" }
Linux/WSL2: шлях до бінарника socat поза PATH для мережевого проксі sandbox.
Абсолютний шлях; відносний відкидається. Лише managed.
"sandbox": { "enabled": true, "socatPath": "/opt/admin/socat" }
Реальний приклад sandbox для Django + Vue
Проєктні налаштування для команди: Python і npm встановлюють пакети лише з реєстрів та внутрішнього GitLab, секрети домашньої теки закриті, dev-сервери (Django :8000, Vite :5173) працюють на macOS. Команди, що ходять у PostgreSQL (драйвер не користується проксі), виносимо в excludedCommands з ask-правилом.
{
"sandbox": {
"enabled": true,
"failIfUnavailable": true,
"allowUnsandboxedCommands": false, // без 'dangerouslyDisableSandbox'
"excludedCommands": [
"docker compose *", // docker несумісний із sandbox
"python manage.py migrate *" // psycopg не бачить проксі
],
"filesystem": {
"allowWrite": ["~/.cache/pip", "~/.npm"],
"denyWrite": ["./.env", "./.env.production"],
"denyRead": ["~/.ssh", "~/.aws"]
},
"network": {
"allowedDomains": [
"pypi.org", "files.pythonhosted.org",
"registry.npmjs.org", "*.npmjs.org",
"github.com", "gitlab.example.com"
],
"allowLocalBinding": true // macOS: runserver і vite dev
},
"credentials": {
"files": [{ "path": "~/.aws/credentials", "mode": "deny" }],
"envVars": [{ "name": "NPM_TOKEN", "mode": "deny" }]
}
},
"permissions": {
"ask": ["Bash(python manage.py migrate *)", "Bash(docker compose *)"]
}
}- Пакети pip/npm ставляться через проксі, тож
pypi.orgтаregistry.npmjs.orgмають бути вallowedDomains;strictAllowlist(лише user/managed) зробить список жорстким. - Виключена команда має повний доступ, а Claude може змінити скрипт у робочій теці й запустити його поза sandbox — тримайте шаблони вузькими (
python manage.py migrate *, а неpython *) і залишайте ask-правило. - На Linux/WSL2
allowLocalBindingне діє: у кожної команди свій loopback; щоб дістатися сервера на хості (БД у контейнері), виносьте команду вexcludedCommands. jest:watchmanнесумісний із sandbox — запускайтеjest --no-watchman. Go-CLI (gh,terraform) на macOS можуть не пройти перевірку TLS — винесіть їх вexcludedCommands(enableWeakerNetworkIsolation— лише для MITM-проксі з власним CA).gitчерез SSH на macOS у sandbox не працює — переведіть remote на HTTPS.
MCP-сервер — це локальний процес або віддалений ендпоінт, який дає Claude додаткові інструменти, ресурси та промпти (GitLab, база даних, Sentry тощо). Нижче: де зберігається конфігурація, як додати сервер, як налаштувати авторизацію, як організація обмежує доступ і які ключі settings за це відповідають.
Області (scopes) та файли конфігурації
| Область | Де завантажується | Спільна з командою | Де зберігається |
|---|---|---|---|
local (за замовчуванням) | лише поточний проєкт | ні | ~/.claude.json, у projects["<шлях>"].mcpServers |
project | лише поточний проєкт | так, через git | .mcp.json у корені проєкту |
user | усі ваші проєкти | ні | ~/.claude.json, верхній рівень mcpServers |
Managed: managed-mcp.json | усі користувачі машини (ексклюзивний контроль) | розгортає адмін | системний шлях (таблиця нижче) |
Managed: managedMcpServers | усі користувачі, поверх власних серверів | розгортає адмін | managed settings (див. картку нижче) |
«Local scope» для MCP — це не .claude/settings.local.json. MCP-сервери локальної області лежать у ~/.claude.json (у домашній теці), а загальні локальні settings — у .claude/settings.local.json проєкту.
Пріоритет, коли один сервер визначено в кількох місцях: managedMcpServers > local > project > user > сервери плагінів > конектори claude.ai. Claude Code підключається один раз, використовуючи визначення з найвищого джерела; запис береться цілком, поля між областями не зливаються. Області дедуплікуються за іменем, плагіни та конектори — за ендпоінтом (той самий URL або команда). Якщо одне ім’я має різні ендпоінти в кількох областях, claude mcp list і /mcp покажуть попередження (OAuth-вхід зберігається окремо для кожного ендпоінта).
| Платформа | Шлях до managed-mcp.json |
|---|---|
| macOS | /Library/Application Support/ClaudeCode/managed-mcp.json |
| Linux / WSL | /etc/claude-code/managed-mcp.json |
| Windows | C:\Program Files\ClaudeCode\managed-mcp.json |
Файл має той самий формат, що й .mcp.json. Його не можна доставити через server-managed settings — лише як файл на диску (Jamf, Intune, GPO тощо). Не клади ключі й паролі в env такого файлу: його читає будь-який користувач машини; використовуй ${VAR}, OAuth або headersHelper.
Транспорти
| Транспорт | type | Як додати | Нотатки |
|---|---|---|---|
| HTTP | http (синонім streamable-http) | claude mcp add --transport http <name> <url> | Рекомендований для віддалених серверів. Підтримує OAuth і заголовки. |
| SSE | sse | claude mcp add --transport sse <name> <url> | Застарілий. З v2.1.265 --transport http сам перемикається на SSE, якщо сервер не приймає HTTP. |
| stdio | stdio | claude mcp add [опції] <name> -- <команда> [args] | Локальний процес. -- відділяє власні прапорці Claude (--transport, --env, --scope) від команди сервера. Сервер отримує змінну CLAUDE_PROJECT_DIR; на roots/list Claude Code відповідає робочими директоріями сесії. |
| WebSocket | ws | лише через .mcp.json або claude mcp add-json | Постійне двостороннє з’єднання. Автентифікація тільки заголовками (статичний токен або headersHelper), OAuth немає. Прапорець --transport значення ws не приймає. |
| SDK | sdk | — | Реєструється лише SDK-хостом (Agent SDK, desktop). У .mcp.json пропускається з повідомленням. |
JSON-запис із url, але без type вважається stdio-сервером і дає помилку конфігурації (сервер пропускається). Завжди пиши "type": "http" (або sse / ws).
Ім’я сервера в командах claude mcp — лише літери, цифри, - та _. Зарезервовані імена: workspace, claude-in-chrome, computer-use, Claude Preview, Claude Browser (сервер із таким іменем пропускається, claude mcp add відхиляє ім’я).
Команди claude mcp add та керування
# Віддалений HTTP-сервер (область за замовчуванням — local, лише для вас у цьому проєкті) claude mcp add --transport http sentry https://mcp.sentry.dev/mcp # Спільний для команди сервер: запис потрапляє у .mcp.json (комітиться в git) # УВАГА: адреса GitLab MCP — плейсхолдер; точний шлях ендпоінта звір із документацією свого GitLab claude mcp add-json --scope project gitlab \ '{"type":"http","url":"https://gitlab.acme.example/api/v4/mcp","headers":{"Authorization":"Bearer ${GITLAB_TOKEN}"}}' # Локальний stdio-сервер для PostgreSQL (--scope user = усі ваші проєкти). Після -- іде команда сервера claude mcp add --transport stdio --scope user db \ -- npx -y @bytebase/dbhub --dsn "postgresql://readonly:PASSWORD@db.acme.example:5432/analytics" # Секрет у змінній середовища сервера (між --env і іменем має бути інша опція, напр. --transport) claude mcp add --env AIRTABLE_API_KEY=YOUR_KEY --transport stdio airtable -- npx -y airtable-mcp-server # Керування claude mcp list # статус: Connected / Needs authentication / Failed / Pending approval claude mcp get sentry # деталі одного сервера claude mcp remove sentry --scope local # також видаляє OAuth-токени та реєстрацію клієнта claude mcp login sentry [--no-browser] # OAuth з терміналу claude mcp logout sentry claude mcp reset-project-choices # скинути схвалення серверів з .mcp.json claude mcp add-from-claude-desktop # імпорт із Claude Desktop (macOS і WSL) claude mcp serve # запустити сам Claude Code як stdio MCP-сервер
У сесії: /mcp — панель статусів, авторизація, вмикання/вимикання серверів, список інструментів. Промпти MCP-сервера з’являються як команди /server:prompt (MCP) (також працює /mcp__server__prompt).
Реалістичний .mcp.json: GitLab + PostgreSQL + Sentry
Файл комітиться в репозиторій. Секрети не пишемо у файл — тільки посилання ${VAR}, кожен розробник задає змінні у своєму середовищі. Шлях /api/v4/mcp для GitLab — плейсхолдер: точну адресу MCP-ендпоінта звір із документацією свого інстансу GitLab; хости acme.example і адреса БД — теж приклади.
{
"mcpServers": {
"gitlab": {
"type": "http",
"url": "${GITLAB_URL:-https://gitlab.acme.example}/api/v4/mcp",
"headers": {
"Authorization": "Bearer ${GITLAB_TOKEN}"
}
},
"db": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@bytebase/dbhub", "--dsn", "${DATABASE_URL_READONLY}"],
"env": {
"PGCONNECT_TIMEOUT": "10"
},
"timeout": 60000
},
"sentry": {
"type": "http",
"url": "https://mcp.sentry.dev/mcp"
}
}
}Для БД бери користувача лише з правом читання. Sentry без заголовків авторизується через OAuth: /mcp або claude mcp login sentry.
Підстановка змінних середовища у .mcp.json
- Синтаксис:
${VAR}та${VAR:-значення за замовчуванням}. - Підставляється в полях
command,args,env,url,headers. - Якщо змінна не задана й немає
:-default, конфіг усе одно завантажується: Claude Code показує попередження у виводіclaude mcp listі лишає текст${VAR}як є. - У
claude mcp list,claude mcp getі деталях/mcp(v2.1.268+) посилання показуються за іменем, а не розкритим значенням. CLAUDE_PROJECT_DIRвиставляється в оточенні сервера, а не Claude Code, тому вcommand/argsпоза плагінами пиши${CLAUDE_PROJECT_DIR:-.}. У плагінах${CLAUDE_PROJECT_DIR}підставляється напряму.
У url і headers віддалених серверів Claude Code читає облікові змінні як порожні: ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN, AWS_BEARER_TOKEN_BEDROCK, HTTPS_PROXY, NPM_TOKEN тощо — навіть якщо вони задані, а :-default для них ігнорується. Так репозиторій або плагін не можуть вислати ваші облікові дані на чужий сервер. Результат — Bearer без токена та 401. Лайфхак: скопіюй значення у змінну зі своїм іменем (наприклад GITLAB_TOKEN) і посилайся на неї. Ім’я поза списком (API_KEY) підставляється як звичайно.
Поля запису сервера
| Поле | Для | Що робить |
|---|---|---|
type | усі | http | sse | stdio | ws |
command, args, env | stdio | команда запуску, її аргументи, змінні оточення процесу |
url | http / sse / ws | адреса ендпоінта (для remote обов’язково) |
headers | http / sse / ws | статичні HTTP-заголовки |
headersHelper | http / sse / ws | команда, що друкує JSON-об’єкт заголовків (див. нижче) |
timeout | усі | тайм-аут інструментів цього сервера в мс; перекриває MCP_TOOL_TIMEOUT |
alwaysLoad | усі | true — інструменти завжди в контексті (без tool search); false — завжди відкладені (v2.1.287+) |
oauth | http / sse | об’єкт clientId, callbackPort, authServerMetadataUrl, scopes |
Схвалення project-серверів та довіра до папки
- Сервери з
.mcp.jsonв інтерактивній сесії потребують схвалення (діалог). Скинути вибір —claude mcp reset-project-choices. - У
claude -p, Agent SDK та cloud-сесіях діалогу немає, тому project-сервери завантажуються без запиту. Щоб тримати їх осторонь:disabledMcpjsonServers(працює в усіх режимах),--setting-sourcesбез project, або--strict-mcp-config(тільки сервери з--mcp-config). - Клонований репозиторій не може схвалити сам себе:
enableAllProjectMcpServers/enabledMcpjsonServers - з закоміченого
.claude/settings.jsonігноруються, доки ти не прийняв діалог довіри до папки (діє й дляclaude mcp list/getз v2.1.196). Схвалення з user settings, managed та--settingsпрацюють і в недовіреній папці. /mcp-перемикачі «вимкнути сервер» пишуть per-project у~/.claude.jsonспискиdisabledMcpServers(вимкнути звичайний сервер, плагінний, claude.ai-конектор) іenabledMcpServers(увімкнути вбудований сервер, вимкнений за замовчуванням, напр.computer-use). Це не ті самі ключі, що*Mcpjson*.
Авторизація віддалених серверів
- OAuth 2.0 для HTTP/SSE: відповідь 401/403 позначає сервер у
/mcpяк такий, що потребує входу. Увійти —/mcpабоclaude mcp login <name> [--no-browser]. Токени зберігаються безпечно й оновлюються автоматично; «Clear authentication» у/mcpвідкликає доступ. - Якщо ти сам задав заголовок
Authorization(уheadersчи черезheadersHelper) і сервер його відхилив, Claude Code повідомить про помилку з’єднання й не перейде на OAuth. --callback-portфіксує redirect URIhttp://localhost:PORT/callback(також зміннаMCP_OAUTH_CALLBACK_PORT).- Немає Dynamic Client Registration — передай
--client-idі--client-secret(маскований запит або зміннаMCP_CLIENT_SECRET). Секрет можна задати лише при додаванні сервера; зберігається в keychain (macOS) або credentials-файлі. Підтримується також CIMD. oauth.authServerMetadataUrl(лишеhttps://) перекриває стандартне виявлення метаданих;oauth.scopes— рядок scope через пробіл, що фіксує потрібний набір (спосіб обмежити сервер підмножиною прав, схваленою службою безпеки).- У
claude -pсам OAuth пройти не можна: потрібен попередній вхід через/mcpчиclaude mcp login.
{
"mcpServers": {
"internal-api": {
"type": "http",
"url": "https://mcp.internal.acme.example",
"headersHelper": "/opt/bin/get-mcp-auth-headers.sh"
},
"slack": {
"type": "http",
"url": "https://mcp.slack.com/mcp",
"oauth": { "scopes": "channels:read chat:write search:read" }
}
}
}headersHelper — команда, яка друкує у stdout JSON-об’єкт рядкових заголовків. Запускається через shell, тайм-аут 10 с, на кожне підключення/перепідключення та після 401/403; результат не кешується. Динамічні заголовки перекривають статичні. Змінні середовища для скрипта: CLAUDE_CODE_MCP_SERVER_NAME, CLAUDE_CODE_MCP_SERVER_URL, CLAUDE_PLUGIN_ROOT (лише для серверів плагіна). Для серверів із project .mcp.json та плагінів змінні з «обліковими» іменами (TOKEN, SECRET, KEY, AUTH …) з оточення прибираються; для project/local-серверів скрипт виконується лише після діалогу довіри до папки.
Конектори claude.ai
- Якщо ти увійшов через підписку claude.ai, конектори з claude.ai/customize/connectors автоматично доступні в Claude Code й у
/mcp. - Вони не завантажуються, якщо активні
ANTHROPIC_API_KEY,ANTHROPIC_AUTH_TOKENчиapiKeyHelper, сторонній провайдер (Bedrock, Vertex …) або токен ізclaude setup-token. - Сервер, доданий у Claude Code, має пріоритет над конектором з тим самим URL. Вимкнути всі —
disableClaudeAiConnectorsабоENABLE_CLAUDEAI_MCP_SERVERS=false; поодинці —deniedMcpServersабо перемикач у/mcp. - Організація може задати для інструментів конектора режими
ask(запит на кожен виклик, навіть вbypassPermissions; уdontAsk— відмова) таblocked(інструмент для Claude прихований).
Settings-ключі MCP
Ці ключі діють у файлах settings (settings.json); конфігурація самих серверів — у .mcp.json / ~/.claude.json / managed-mcp.json.
Whitelist MCP серверів. Кожен запис — об’єкт з одним ключем: serverName, serverUrl (з * wildcard) або serverCommand (точний масив). Denylist має пріоритет.
Не задано = дозволені всі сервери. Порожній [] = не дозволено жоден, крім серверів, що пропускають allowlist (managedMcpServers, записи managed-mcp.json без ${VAR}, вбудовані: Claude in Chrome, ide). Без allowManagedMcpServersOnly allowlist-и з усіх рівнів зливаються, тож користувач може розширити ваш список власним.
"allowedMcpServers": [ { "serverName": "github" }, { "serverName": "trello" }, { "serverUrl": "https://*.company.com/*" }, { "serverCommand": ["npx", "-y", "@company/mcp-server"] } ]
serverName — не засіб безпеки: це просто мітка, яку користувач дає серверу, і будь-який сервер можна назвати github. У allowlist serverName — лише літери, цифри, - та _. Для реального контролю використовуй serverUrl / serverCommand.serverUrl: * — wildcard, можна навіть замість схеми; регістр хоста не важливий, шлях чутливий до регістру. Хост, записаний повністю й без порту, збігається лише з портом за замовчуванням (443/80); хост із * — з будь-яким портом; :* — будь-який порт. serverCommand — точний масив: кожен аргумент по порядку; env не порівнюється. У serverUrl / serverCommand розкриваються ${VAR} з «закріпленого» оточення (v2.1.219+), тому для enforcement краще писати літеральні значення.serverUrl (serverName рахується, тільки якщо в списку немає жодного serverUrl); stdio — за serverCommand. Allowlist не поширюється на managed-mcp.json (з 2.1.259), крім записів із ${VAR}. Обидва списки фільтрують і сервери з --mcp-config (крім type: "sdk").Blacklist — має пріоритет над allowedMcpServers. Зливається з усіх рівнів. У serverName можна вказати і назву claude.ai-конектора.
Блокує потенційно небезпечні MCP сервери з доступом до файлів або інтернету що можуть витікати дані з проєкту.
"deniedMcpServers": [ { "serverName": "filesystem" }, { "serverUrl": "https://untrusted-mcp.io/*" }, { "serverName": "claude.ai Slack" } ]
serverName — будь-який непорожній рядок без пробілів на краях, зокрема з пробілами: так блокується конектор claude.ai за назвою ("claude.ai Slack"). Назва конектора може змінитися або отримати суфікс (N), тому надійніше — serverUrl.managed-mcp.json, managedMcpServers і --mcp-config; власний denylist користувача зливається з вашим — він може заблокувати managed-сервер лише для себе. Ніщо не перекриває збіг із denylist.Керує схваленням серверів з .mcp.json проєкту — дозволяє або забороняє без зміни самого файлу репо. enableAllProjectMcpServers схвалює всі одразу (за замовчуванням не задано — питати про кожен). При конфлікті виграє заборона.
Якщо .mcp.json містить сервери що не потрібні всій команді — вибірково увімкни тільки потрібні без редагування файлу.
"enabledMcpjsonServers": ["github", "trello"], "disabledMcpjsonServers": ["filesystem"], "enableAllProjectMcpServers": false // false = не авто-схвалювати всі MCP з .mcp.json // у недовіреній папці true діє з user, managed та --settings (не з project-файлу)
.claude/settings.local.json. Закомічені в репозиторій enableAllProjectMcpServers/enabledMcpjsonServers ігноруються, доки папка не стала довіреною — клонований репо не може схвалити власні сервери. disabledMcpjsonServers з будь-якого файлу працює завжди й виграє над обома.claude -p, SDK та cloud-сесіях діалогу схвалення немає — project-сервери завантажуються без запиту, якщо їх не відхилено через disabledMcpjsonServers.allowManagedMcpServersOnly: true робить allowlist авторитетним: враховується лише allowedMcpServers із managed-джерела (потрібен саме там; з v2.1.273 замок і список читаються з усіх адмін-джерел). Не плутати з allowManagedPermissionRulesOnly — той блокує лише permission rules. managedMcpServers (v2.1.259+) — об’єкт «ім’я сервера → запис»: роздати віддалені HTTP/SSE сервери всім користувачам, не забираючи в них власні.
true = розробники можуть підключити лише те, що дозволяє managed allowlist. Denylist при цьому все одно зливається з усіх рівнів. Записи managedMcpServers не потребують allowlist, мають пріоритет над серверами local/project/user, плагінів і конекторів (при збігу імені з managed-mcp.json виграє файл), їх не можна видалити (лише вимкнути для себе в /mcp, розділ Managed MCPs) і вони лишаються при strictPluginOnlyCustomization.
"allowManagedMcpServersOnly": true, "allowedMcpServers": [ { "serverUrl": "https://mcp.sentry.dev/*" }, { "serverCommand": ["npx", "-y", "@bytebase/dbhub", "--dsn", "postgresql://readonly@db.acme.example:5432/analytics"] } ], "managedMcpServers": { "gitlab": { "type": "http", "url": "https://gitlab.acme.example/api/v4/mcp" // плейсхолдер — підстав свій ендпоінт } }
managedMcpServers завантажується, лише якщо: type = http/sse; url — https:// (навіть localhost по http:// не можна); немає command, args, env, headersHelper; ніде немає ${VAR} (змінні не розкриваються); ім’я містить лише літери, цифри, -, _. Інакше запис відкидається, а причину видно в /status.headers — клади туди лише облікові дані, видані всій аудиторії, або дай кожному користувачу увійти через OAuth. Ключ читається лише з managed-джерел (з user/project/local відкидається з попередженням). Desktop-ключ з такою самою назвою має інший формат (масив) — не копіюй.Вимикає конектори claude.ai, які Claude Code підтягує сам (сервери, додані у claude.ai/customize/connectors).
Конектори не з’являються в /mcp і не підключаються. Семантика «будь-яке джерело true»: true у будь-якому файлі (user, managed, навіть project) перемагає; false у project не поверне те, що вимкнув user чи політика. Не зачіпає сервери з --mcp-config.
"disableClaudeAiConnectors": true
ENABLE_CLAUDEAI_MCP_SERVERS=false робить те саме на одну сесію; якщо хоч одне з двох вимикає конектори, інше не може їх увімкнути. Діє лише для конекторів, які Claude Code отримує сам (термінал, VS Code, JetBrains, Agent SDK), але не для cloud-сесій і desktop-сесій — там конектори приходять інакше.Дозволяє завантажувати конектори claude.ai поруч із розгорнутим managed-mcp.json. За замовчуванням false.
Без цього ключа managed-mcp.json бере ексклюзивний контроль і приховує конектори claude.ai. З true вони завантажуються як без файлу (allow/deny-списки до них усе одно застосовуються; сервери плагінів лишаються заблокованими).
"allowAllClaudeAiMcps": true
managed-settings.json); у user/project не діє.Дозволяє вбудованому серверу Claude in Chrome працювати поруч із розгорнутим managed-mcp.json (v2.1.282+).
За замовчуванням при managed-mcp.json Claude Code блокує Claude in Chrome у терміналі, а claude --chrome завершується з помилкою, що називає цей ключ. З true розширення працює. Запис deniedMcpServers для claude-in-chrome усе одно блокує.
"allowClaudeInChromeWithManagedMcp": true
Per-project списки, які Claude Code сам веде у ~/.claude.json, коли ти вмикаєш/вимикаєш сервер перемикачем у /mcp. disabledMcpServers — opt-out для звичайних серверів, плагінних, managed-серверів, конекторів claude.ai (за display-іменем, напр. "claude.ai Slack") та вбудованих серверів, увімкнених за замовчуванням. enabledMcpServers — opt-in для вбудованих серверів, вимкнених за замовчуванням (напр. computer-use).
Сервер із disabledMcpServers не підключається, але лишається в конфігурації й у /mcp (позначений вимкненим). Для кожного сервера діє рівно один список: звичайний сервер у enabledMcpServers або default-off вбудований у disabledMcpServers ігноруються.
"projects": { "/Users/me/work/shop": { "disabledMcpServers": ["sentry", "claude.ai Slack"], "enabledMcpServers": ["computer-use"] } }
enabledMcpjsonServers / disabledMcpjsonServers (вони керують лише схваленням серверів з .mcp.json).Шаблони керування MCP в організації
| Мета | Що налаштувати |
|---|---|
| Вимкнути MCP повністю | managed-mcp.json з {"mcpServers": {}}. claude mcp add тоді падає з помилкою політики. Не задавай managedMcpServers та allowAllClaudeAiMcps: сервери з них продовжать завантажуватися навіть при порожньому наборі. |
| Фіксований набір серверів | managed-mcp.json із потрібними серверами: користувачі не можуть додавати/міняти інші, у тому числі плагінні й --mcp-config (з ним Claude Code на робочій станції завершується з помилкою). |
| Видати сервери всім, але не забирати власні | managedMcpServers у managed settings (v2.1.259+). |
| Затверджений каталог | allowedMcpServers + allowManagedMcpServersOnly: true. Вбудованого реєстру серверів у Claude Code немає — розповсюджуй команди claude mcp add у wiki або видавай сервери плагінами через корпоративний marketplace. |
| Лише сервери з плагінів | strictPluginOnlyCustomization зі значенням "mcp" у масиві: ~/.claude.json та .mcp.json ігноруються, плагінні й managed-сервери лишаються. |
| М’який allowlist | allowedMcpServers без allowManagedMcpServersOnly: користувачі можуть його розширити. |
| Тільки чорний список | deniedMcpServers. |
Перевірка на керованій машині: claude mcp list показує лише сервери з managed-mcp.json (плюс managedMcpServers); claude mcp add --transport http test https://example.com/mcp має впасти з «enterprise MCP configuration is active …».
До v2.1.259 кожен сервер з managed-mcp.json мав проходити allowlist. Тепер allowlist до них не застосовується (крім записів з ${VAR}), тож сервери, які ти раніше «відсікав» allowlist-ом, почнуть завантажуватися без повідомлення — додай для них записи в deniedMcpServers.
Ліміти виводу MCP та змінні середовища
| Параметр | Значення | Що робить |
|---|---|---|
| Попередження | 10 000 токенів | Claude Code показує попередження, якщо вивід інструмента перевищив поріг. |
MAX_MCP_OUTPUT_TOKENS | за замовчуванням 25 000 | Максимум токенів у відповіді MCP-інструмента. Успішний результат (без зображень) понад ліміт зберігається у файл у теці tool-results сесії (під ~/.claude/projects/), а в розмову потрапляє шлях до файлу. Зображення цим лімітом обмежуються завжди. |
| Ліміт символів тексту | 50 000 символів | Успішний текстовий результат довший за це зберігається у файл незалежно від токенів і від MAX_MCP_OUTPUT_TOKENS. Автор сервера може підняти ліміт для свого інструмента через _meta["anthropic/maxResultSizeChars"] (стеля 500 000). |
| Відповідь HTTP/SSE | 16 МБ | Claude Code перестає читати відповідь (чи подію потоку) після 16 МБ після розпакування; запит завершується помилкою. |
| Текст помилки | ≈ 11 000 символів | Довший текст обрізається посередині: лишаються перші й останні 5 000 символів. |
MCP_TIMEOUT | за замовчуванням 30 000 мс | Тайм-аут запуску сервера. |
MCP_TOOL_TIMEOUT | за замовчуванням 100 000 000 мс (≈ 28 год) | Тайм-аут виконання інструмента; для HTTP/SSE кожен запит окремо обмежений 60 с, поки значення (або timeout сервера) не більше 60 000. Поле timeout у конфігу сервера перекриває змінну. |
CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT | мс; 0 = вимкнути | Скасувати виклик, якщо сервер не відповідає і не шле progress. Типові значення: 300 000 (мережеві) і 1 800 000 (stdio). |
CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS | за замовчуванням 120 000 | Виклик MCP-інструмента в основній розмові, що триває довше, стає фоновою задачею (v2.1.212+); 0 вимикає. |
MCP_CONNECTION_NONBLOCKING | 0 = чекати | За замовчуванням запуск не чекає на підключення серверів; 0 змушує чекати перед першим запитом. Сервери з alwaysLoad: true чекають завжди. |
MCP_CONNECT_TIMEOUT_MS | за замовчуванням 5 000 | Скільки блокуючий старт чекає на пачку підключень. |
MCP_SERVER_CONNECTION_BATCH_SIZE / MCP_REMOTE_SERVER_CONNECTION_BATCH_SIZE | 3 / 20 | Скільки локальних (stdio) / віддалених серверів підключати паралельно на старті. |
MCP_DISCOVERY_CACHE | 1 / 0 | Кеш списку інструментів віддалених серверів (статус «cached», підключення при першому виклику). Типово вимкнений, якщо його не вмикає поступовий rollout. |
MCP_SDK_GENERATION | v1 | v2 | Обрати MCP-клієнт: на TypeScript SDK 1.x чи 2.0. |
MCP_PROTOCOL_NEGOTIATION | auto | legacy | Лише для v2: чи пробувати протокол 2026-07-28. |
MCP_CLIENT_SECRET | рядок | OAuth client secret без інтерактивного запиту при claude mcp add --client-secret. |
MCP_OAUTH_CALLBACK_PORT | порт | Фіксований порт OAuth-callback (альтернатива --callback-port). |
ENABLE_CLAUDEAI_MCP_SERVERS | false | Не підтягувати конектори claude.ai. |
CLAUDE_CODE_MAX_MCP_DESCRIPTION_LENGTH | за замовчуванням 2 048 символів | Обмеження довжини опису кожного інструмента й інструкцій кожного сервера (v2.1.280+). |
CLAUDE_CODE_MCP_ALLOWLIST_ENV | 1 | stdio-сервери запускаються лише з безпечним базовим оточенням + власним env, а не з усім середовищем оболонки. |
Змінні можна задати в оболонці або в блоці env settings. Приклад: export MAX_MCP_OUTPUT_TOKENS=50000 перед запуском claude.
Tool search: відкладене завантаження інструментів
За замовчуванням визначення MCP-інструментів відкладаються: на старті в контекст потрапляють лише назви інструментів та інструкції серверів, повні схеми підтягуються за потреби (інструмент ToolSearch). Тому додавання серверів майже не з’їдає контекст. Потрібна модель з підтримкою tool_reference (Sonnet/Haiku/Opus 4.5 і новіші).
| ENABLE_TOOL_SEARCH | Поведінка |
|---|---|
| не задано | Усі MCP-інструменти відкладені. Автоматично вимикається (усе вантажиться наперед) при нестандартному ANTHROPIC_BASE_URL, на моделях раніше 4.5 у Google Cloud Agent Platform та на Foundry, розміщеному в Azure. |
true | Завжди відкладати (і слати beta-заголовок через проксі; на проксі без підтримки tool_reference запити падатимуть). |
auto | Поріг 10% контексту: поки визначення займають менше — вантажаться наперед, від 10% — відкладаються. |
auto:N | Те саме з власним порогом у відсотках (0–100), напр. auto:5. |
false | Усі інструменти завантажуються наперед. |
- Інструмент можна вимкнути політикою:
permissions.deny: ["ToolSearch"]. CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETASтримає tool search вимкненим, і перекрити це змінноюENABLE_TOOL_SEARCHнеможливо; організація може залишити його ввімкненим через managed settings (v2.1.227+).- На сервер:
"alwaysLoad": true— інструменти завжди в контексті (старт чекає на сервер до 5 с);"alwaysLoad": false— завжди відкладені, навіть якщо автор позначив інструмент_meta["anthropic/alwaysLoad"](v2.1.287+). На рівні інструмента автор сервера може виставити_meta["anthropic/alwaysLoad"].
Імена інструментів та дозволи
- Інструмент:
mcp__<server>__<tool>; для плагінного сервера —mcp__plugin_<plugin>_<server>__<tool>. Правила permissions приймають іmcp__server, іmcp__server__*. - Правила з параметрами (дужки) для MCP-інструментів працюють лише через
--disallowedTools; settings-файли пропускають такі правила. - У matcher хуків потрібно
.*:mcp__memoryнічого не збігається, аmcp__memory__.*— так. - Сервер може вимагати підтвердження кожного виклику:
_meta["anthropic/requiresUserInteraction"]: trueуtools/list— запит показується в будь-якому режимі (навітьbypassPermissions, а уdontAskвиклик відхиляється). - Сервер може запитувати введення у користувача посеред задачі (elicitation): діалог у режимі форми або URL; автовідповідь — хук
Elicitation.
Плагін — це тека з компонентами, які Claude Code вантажує разом: скіли, агенти, хуки, MCP- та LSP-сервери, теми, монітори. Плагіни поширюються через marketplace — каталог (marketplace.json) у git-репозиторії, за URL або в локальній теці. Нижче — будова плагіна та marketplace, ключі settings, команди CLI і готовий рецепт для команди.
Що може містити плагін та структура теки
| Компонент | Типове розташування | Нотатки |
|---|---|---|
| Маніфест | .claude-plugin/plugin.json | Необов’язковий. Без нього компоненти беруться зі стандартних місць, ім’я — з marketplace або з назви теки. |
| Скіли | skills/<name>/SKILL.md | Основний спосіб додавати команди. Плагін із SKILL.md у корені (без skills/) завантажується як один скіл. |
| Команди | commands/*.md | Плоскі Markdown-файли; для нового краще використовувати скіли. |
| Агенти | agents/*.md | Підтеки входять до імені агента. |
| Хуки | hooks/hooks.json | Формат як у hooks у settings. |
| MCP-сервери | .mcp.json | Або вбудовано в mcpServers у plugin.json. Зареєстроване ім’я сервера: plugin:<plugin>:<server>. |
| LSP-сервери | .lsp.json | Підсвітка/діагностика коду. |
| Стилі виводу | output-styles/ | — |
| Workflow | workflows/ | JS-файли воркфлоу. |
| Теми | themes/ | JSON-файли тем. |
| Монітори | monitors/monitors.json | Працюють лише в інтерактивних сесіях і не на Bedrock / Vertex / Foundry. |
| Виконувані файли | bin/ | Додаються в PATH Bash-інструмента, поки плагін увімкнений. |
| Settings плагіна | settings.json | Діють лише ключі agent та subagentStatusLine. |
deploy-tools/ ├── .claude-plugin/ │ └── plugin.json ├── skills/ │ └── deploy/ │ └── SKILL.md ├── agents/ │ └── reviewer.md ├── hooks/ │ └── hooks.json ├── bin/ │ └── deploy-tool ├── scripts/ │ └── format.sh ├── settings.json ├── .mcp.json └── .lsp.json
Усі компоненти лежать у корені плагіна, а не всередині .claude-plugin/ (там лише plugin.json). CLAUDE.md у корені плагіна не завантажується в контекст (валідатор попереджає) — інструкції кладіть у скіл. Компоненти мають простір імен за іменем плагіна: скіл /my-plugin:review, агент my-plugin:reviewer.
plugin.json: приклад
{
"name": "django-review",
"displayName": "Django Review",
"version": "1.2.0",
"description": "Рев’ю Django-коду: міграції, ORM-запити, DRF-серіалізатори",
"author": { "name": "Acme Platform Team", "email": "platform@acme.example" },
"license": "MIT",
"keywords": ["django", "review"],
"mcpServers": {
"gitlab": {
"type": "http",
"url": "${user_config.gitlab_url}/api/v4/mcp",
"headers": { "Authorization": "Bearer ${user_config.gitlab_token}" }
}
},
"userConfig": {
"gitlab_url": {
"type": "string",
"title": "GitLab URL",
"description": "Адреса інстансу GitLab",
"default": "https://gitlab.acme.example"
},
"gitlab_token": {
"type": "string",
"title": "GitLab token",
"description": "Personal access token з правом read_api",
"sensitive": true,
"required": true
}
}
}Адреса ${user_config.gitlab_url}/api/v4/mcp — плейсхолдер для GitLab MCP-ендпоінта; підстав реальний шлях свого інстансу.
Перевірка: claude plugin validate ./django-review (з --strict попередження стають помилками — зручно для CI). Невідомий ключ верхнього рівня відкидається з попередженням; невідомий ключ усередині userConfig / channels / lspServers / monitors — помилка, і плагін не завантажується.
Поля plugin.json
| Поле | Тип | Що робить |
|---|---|---|
name | string, обов’язкове | Ідентифікатор у kebab-case, без пробілів, @ та :. Усі компоненти отримують його як префікс. Імена з префіксами claude-, anthropic-, anthropics-, cc-plugin- — помилка claude plugin validate (і відмова init/tag). |
displayName | string | Назва в UI замість name; не використовується для простору імен і пошуку. displayName запису marketplace має пріоритет. |
version | string | Фіксує версію: користувачі лишаються на ній, доки не змінити. Не перевіряється як semver. |
description, author, homepage, repository, license, keywords | string / object / array | Метадані для UI та marketplace; author = {name, email, url}, license — SPDX-ідентифікатор. homepage має бути валідним URL, інакше плагін не завантажиться. |
metadata | object | Довільні ваші дані; Claude Code не читає (v2.1.222+). |
icon, documentationUrl, supportUrl, privacyPolicyUrl, termsOfServiceUrl | string | Для лістингу в каталозі Anthropic; Claude Code ігнорує. Задаються лише в plugin.json. |
defaultEnabled | boolean (true) | Чи вмикається плагін, якщо користувач не задав у enabledPlugins. Значення в запису marketplace перекриває. |
dependencies | array | Плагіни, які мають бути ввімкнені: "name", "name@marketplace" або об’єкт {name, marketplace, version}. |
settings | object | Settings при увімкненому плагіні; діють лише agent і subagentStatusLine. settings.json у корені має пріоритет. |
userConfig | object | Значення, які Claude Code запитує при вмиканні (див. нижче). |
channels | array | Канали повідомлень, кожен прив’язаний до MCP-сервера плагіна. |
types | path | .d.ts для «модів» (плагінів із обробниками подій). |
skills | path | array | Додаткові теки скілів — додаються до стандартного skills/. "." = корінь плагіна. |
commands | path | array | object | Замінює стандартну commands/. Об’єкт: ключ — ім’я команди, значення — source або content (+ description, argumentHint, model, allowedTools). |
agents | path | array | Файли .md (теки не приймаються); замінює agents/. |
hooks | path | object | array | Шлях до .json або inline-конфіг; зливається з hooks/hooks.json. |
mcpServers | path | object | array | .json, пакети .mcpb/.dxt або inline-сервери; зливається з .mcp.json (пізніше ім’я замінює раніше). |
lspServers | path | object | array | Як mcpServers, для .lsp.json. |
outputStyles, workflows | path | array | Замінюють стандартні output-styles/ і workflows/. |
experimental.themes, experimental.monitors, experimental.evals | path | array | Теми й монітори (замінюють стандартні themes/ і monitors/monitors.json) та тека eval-кейсів (за замовчуванням evals/). |
Усі шляхи компонентів відносні до кореня плагіна, починаються з ./, не виходять за корінь (без ..) і мають існувати. Якщо ключ замінює стандартну теку, а тека існує, claude plugin list покаже попередження «Default … folder is ignored».
userConfig та змінні середовища плагіна
| Поле userConfig | Обов’язкове | Опис |
|---|---|---|
type | так | string, number, boolean, directory, file |
title, description | так | Підпис і підказка в діалозі конфігурації |
required, default | ні | Не приймати порожнє значення / значення за замовчуванням |
options | ні | Для string: фіксований список (вибір у /config; v2.1.271+; якщо оголошено, старіші клієнти плагін не завантажать) |
multiple, sensitive, min/max | ні | Масив рядків; маскування й зберігання в сховищі секретів; межі для number |
- Значення посилаються як
${user_config.KEY}(у конфігах MCP/LSP, exec-form хуках, змісті скілів і агентів — секретні там стають плейсхолдером) та як зміннаCLAUDE_PLUGIN_OPTION_<KEY>у процесах хуків. Не дозволено в shell-form хуках, командах моніторів іheadersHelper(там — помилка). - Несекретні значення зберігаються в
pluginConfigs(user/managed), секретні — у системному keychain (або~/.claude/.credentials.json). ${CLAUDE_PLUGIN_ROOT}— абсолютний шлях встановленої версії плагіна (змінюється при оновленні, стан тут не зберігай).${CLAUDE_PLUGIN_DATA}—~/.claude/plugins/data/<id>/: зберігається між оновленнями (node_modules, кеші); видаляється при видаленні останньої інсталяції, якщо не--keep-data.${CLAUDE_PROJECT_DIR}— корінь проєкту. Ці змінні не експортуються в команди, які Claude виконує через Bash-інструмент.
marketplace.json
Файл лежить у .claude-plugin/marketplace.json кореня каталогу; відносні шляхи плагінів рахуються від цього кореня (не від .claude-plugin/). Якщо файл лежить деінде, користувачі мають оголосити marketplace в extraKnownMarketplaces із path у джерелі.
{
"name": "acme-plugins",
"owner": { "name": "Acme Platform Team", "email": "platform@acme.example" },
"description": "Плагіни команди Django + Vue",
"metadata": { "pluginRoot": "./plugins" },
"plugins": [
{
"name": "django-review",
"source": "django-review",
"description": "Рев’ю Django-коду",
"version": "1.2.0",
"category": "code-review",
"tags": ["django", "python"]
},
{
"name": "vue-tools",
"source": {
"source": "git-subdir",
"url": "https://gitlab.acme.example/platform/claude-tools.git",
"path": "plugins/vue-tools",
"ref": "v0.4.0"
}
},
{
"name": "deploy-helper",
"source": {
"source": "url",
"url": "https://gitlab.acme.example/platform/deploy-helper.git",
"ref": "main"
}
}
]
}Тут "source": "django-review" — «голе» ім’я, що розкривається в ./plugins/django-review завдяки metadata.pluginRoot (v2.1.239+).
| Поле верхнього рівня | Опис |
|---|---|
name | обов’язкове. Літери, цифри, ., _, -; користувачі пишуть його після @ (django-review@acme-plugins). Один користувач — один marketplace з цим іменем. |
owner | обов’язкове: name, необов’язково email, url |
plugins | обов’язкове: масив записів; кожен запис валідується окремо |
description, version, $schema | метадані; metadata.description/metadata.version — альтернатива |
metadata.pluginRoot | тека, в якій розкриваються «голі» імена джерел |
forceRemoveDeletedPlugins | true — плагін, видалений зі списку, видаляється й на машинах користувачів |
allowCrossMarketplaceDependenciesOn | імена marketplace, плагіни яких можуть бути залежностями |
renames | мапа «старе ім’я → нове» (або null для видаленого плагіна) |
Не можна називати marketplace так, як офіційні: claude-plugins-official, claude-code-plugins, anthropic-plugins, claude-community тощо (резерв знімається лише для репозиторіїв під github.com/anthropics/), іменами-імітаціями, префіксом claudeai- (marketplace на claude.ai) та системними inline, builtin, skills-dir, synced, npm, github тощо.
Запис плагіна у marketplace: поля та джерела
| Поле запису | Опис |
|---|---|
name, source | обов’язкові. name — те, що вводять до @ при встановленні. |
description, version, category, tags | каталог і пошук. Якщо version є й у plugin.json — виграє plugin.json (валідатор попереджає). |
strict | true за замовчуванням: plugin.json — авторитет, компоненти запису (commands, agents, skills, hooks, outputStyles, themes) додаються до нього (hooks — замінюють по подіях). false + компоненти і в plugin.json, і в записі = конфлікт, плагін не завантажиться. |
relevance, dependencies, defaultEnabled, displayName, metadata | підказки для рекомендацій, залежності, увімкнення за замовчуванням (запис перекриває plugin.json), назва в UI |
headers, headersHelper | заголовки для завантаження архіву (v2.1.238+); headersHelper вимагає "strict": false |
| будь-яке поле plugin.json | крім полів лістингу каталогу. Якщо в плагіна немає власного plugin.json — запис і є маніфест. |
| Тип джерела плагіна | Поля | Нотатки |
|---|---|---|
| Відносний шлях | "./plugins/x" | Тека всередині marketplace. Лише для джерел github / git / file / directory; для marketplace типу url шляхи не розкриваються. |
github | repo, ref, sha | Репозиторій owner/repo. |
url | url, ref, sha | Будь-який git-репозиторій за повним URL (GitLab, Azure DevOps …); скорочення owner/repo не підтримується. |
git-subdir | url, path, ref, sha | Одна тека монорепо (sparse checkout, partial clone). |
npm | package, version, registry | Пакет npm; скрипти встановлення не виконуються. |
archive | url, sha256 | zip за HTTPS (v2.1.224+); якщо задано sha256 — розбіжність відхиляється. |
command | command, timeout, mode | Каталог, який друкує команда на машині користувача (v2.1.229+). Користувач бачить команду і підтверджує її. Блокується disableCommandPluginSources. |
ref — гілка чи тег; sha — повний 40-символьний SHA коміту (якщо задано обидва, береться sha). Для production-плагінів зі стороннього джерела фіксуй sha.
Джерела marketplace (куди вказує extraKnownMarketplaces)
| Тип | Поля | Що вводиш у marketplace add |
|---|---|---|
github | repo, ref, path, sparsePaths | owner/repo, owner/repo@ref або owner/repo#ref |
git | url, ref, path, sparsePaths | user@host:path або https-URL, що закінчується на .git / містить /_git/ / веде на github.com чи gitlab.com |
url | url, headers, headersHelper | будь-який інший http(s)-URL — це пряме посилання на marketplace.json (завантажується лише він) |
file / directory | path | шлях до .json-файлу / теки |
settings | name, plugins, owner | inline-каталог просто в settings; лише об’єктні джерела плагінів; name має збігатися з ключем |
Лише в політиках (strictKnownMarketplaces / blockedMarketplaces): hostPattern, pathPattern, skills-dir та owner/* у github.repo. Джерело npm для marketplace не реалізоване (завантаження падає з «NPM marketplace sources not yet implemented»).
Settings-ключі плагінів
Спочатку ключі, що реєструють marketplace і вмикають плагіни, потім політики адміністратора.
Вмикає (true) або вимикає (false) плагіни у форматі "plugin@marketplace". Плагіни додають скіли, агентів, хуки, MCP/LSP-сервери. Без запису плагін береться зі свого defaultEnabled. Ключ пишуть для вас /plugin і claude plugin enable.
Автоматично на всіх машинах плагін з’являється лише з managed enabledPlugins + managed extraKnownMarketplaces. Запис у .claude/settings.json репозиторію для плагіна із зовнішнім джерелом (GitHub, npm) нікому нічого не встановлює: кожен бачить «is enabled in project settings but isn’t installed», доки не виконає claude plugin install <name>@<marketplace> --scope project. Автоматично вантажаться лише плагіни з відносним шляхом у marketplace, зареєстрованому репозиторієм. false у managed блокує плагін на всіх рівнях і ховає його.
"enabledPlugins": { "code-review@claude-plugins-official": true, "deploy-tools@acme-plugins": true, "experimental-ui@personal": false }
false у .claude/settings.local.json (false у ~/.claude/settings.json не допоможе). Один синхронізований із claude.ai плагін вимикається записом "<name>@synced": false.Реєструє маркетплейси за ім’ям, щоб люди, які відкрили репозиторій (або всі, до кого доходять managed settings), могли ставити плагіни. Джерела (source.source): github, git, url, file, directory, settings (inline-каталог). Необов’язкове поле autoUpdate (boolean): для claude-plugins-official і більшості офіційних маркетплейсів Anthropic за замовчуванням true, для сторонніх false. Alias — additionalMarketplaces (v2.1.232+).
Новий учасник команди відкриває репозиторій — і після довіри до папки маркетплейс уже підключений (в недовіреній папці запис мовчки ігнорується, і в -p теж). Плагіни з enabledPlugins підхоплюються самі лише якщо вони в цьому маркетплейсі вказані відносним шляхом; плагін із зовнішнім джерелом кожен ставить сам (claude plugin install … --scope project). Запис з тим самим ім’ям із файлу вищого пріоритету замінює нижчий цілком — поля не зливаються (з v2.1.228).
"extraKnownMarketplaces": { "acme-plugins": { "source": { "source": "github", "repo": "acme-corp/claude-plugins" }, "autoUpdate": true }, "gitlab-plugins": { "source": { "source": "git", "url": "https://gitlab.acme.example/platform/claude-plugins.git", "ref": "main" } } }
github — repo, ref, path, sparsePaths; git — url, ref, path, sparsePaths; url — прямий лінк на marketplace.json з headers і headersHelper (v2.1.238+); file/directory — path; settings — name (= ключ), plugins, owner. Джерело npm не реалізоване (завантаження падає). headersHelper з .claude/settings*.json теки, доданої через --add-dir, ігнорується..git (наприклад AWS CodeCommit), додавай записом git у цьому ключі, а не командою marketplace add.Allowlist джерел маркетплейсів, з яких можна встановлювати плагіни (не плагінів усередині них). [] = повне блокування, включно з офіційним маркетплейсом. Джерела: github, git, url, file, directory, hostPattern, pathPattern, settings (збіг за ім’ям і ідентичними plugins) та skills-dir. Alias — allowedMarketplaces (v2.1.232+).
Розробники зможуть встановлювати плагіни тільки з корпоративного GitHub чи внутрішнього git-хоста. Співставлення точне, включно з ref і path.
"strictKnownMarketplaces": [ { "source": "github", "repo": "acme-corp/approved-plugins" }, { "source": "github", "repo": "acme-corp/*" }, { "source": "hostPattern", "hostPattern": "^git\\.acme\\.com$" }, { "source": "skills-dir" } ]
~/.claude/skills/, .claude/skills/ з .claude-plugin/plugin.json) перестають вантажитися, доки не додано { "source": "skills-dir" }. Звичайні скіли (просто SKILL.md) не страждають.github/git мусять збігатися repo або url, ref та path (або бути відсутніми з обох боків). Запис без ref не покриває джерело з ref: "main"; запис github не покриває той самий репозиторій як git-URL; суфікс .git, слеш у кінці чи ssh:// замість https:// — інше значення. github з "repo": "acme-corp/*" — wildcard на власника (v2.1.223+; лише * замість усієї назви репо). hostPattern/pathPattern — регулярні вирази, що збігаються будь-де, тож прив’язуй їх ^…$. У JSON зворотний слеш подвоюється: "^git\\.acme\\.com$".Кастомне повідомлення що додається до попередження безпеки при встановленні плагінів.
Розробники бачитимуть твій текст при кожній спробі встановити плагін. Корисно для посилання на internal policy або контакт для схвалення.
"pluginTrustMessage": "Схвалюйте тільки з корпоративного реєстру. Питання: security@company.com"
Managed-ключі. Перший: true (усі чотири типи) або масив із "skills" / "agents" / "hooks" / "mcp" — відповідні кастомізації дозволені лише з плагінів, managed-налаштувань та вбудованих (не з .claude/ і не з ~/.claude.json / .mcp.json). Другий — blocklist джерел маркетплейсів; перевіряється раніше за allowlist, тому джерело в обох списках блокується; збіг ширший, ніж в allowlist (канонізація git-URL, github блокує й еквівалентний git).
Кастомізація Claude Code проходить через перевірені плагіни — не можна просто покласти скіл у ~/.claude/skills. MCP-сервери з managedMcpServers і managed-mcp.json продовжують працювати. Ключ не обмежує, які саме плагіни ставлять — поєднуй зі strictKnownMarketplaces.
"strictPluginOnlyCustomization": ["hooks", "mcp"], "blockedMarketplaces": [{ "source": "github", "repo": "random/plugins" }]
Забороняє плагіни з джерелом типу command — коли каталог плагіна генерується командою, що виконується на машині користувача.
Такі плагіни не встановлюються, не оновлюються й не завантажуються. Якщо ключ не задано, береться значення allowManagedHooksOnly. На інші типи джерел не впливає. (v2.1.229+)
"disableCommandPluginSources": true
Імена маркетплейсів, плагіни яких можуть з’являтися як контекстні підказки встановлення (у spinner-підказках та закріплені вгорі вкладки Discover в /plugin).
Підказка з’являється лише якщо маркетплейс зареєстрований на машині, його ім’я є в цьому списку, а його джерело оголошене в тій самій політиці (запис extraKnownMarketplaces або allowlist). Для офіційного маркетплейсу достатньо імені. Збіг із проєктом задають через relevance у записі marketplace.
"pluginSuggestionMarketplaces": ["acme-plugins"]
Керує завантаженням плагінів, увімкнених для твого акаунта claude.ai, у ~/.claude/plugins/synced/; вантажаться як <name>@synced. Має сенс лише значення false (v2.1.273+).
false зупиняє завантаження і припиняє вантажити вже синхронізовані (у user/managed вони ще й переміщуються в .trash). true = не задано. Один синхронізований плагін вимикають записом "<name>@synced": false в enabledPlugins. Блокування всіх джерел через strictKnownMarketplaces: [] синхронізовані плагіни не зачіпає — їх вимикає саме цей ключ.
"syncClaudeAiPlugins": false
--settings; репозиторій не може вимкнути синхронізацію за користувача. Для скілів є аналог syncClaudeAiSkills (тека ~/.claude/skills/synced/).Керує завантаженням скілів, увімкнених для акаунта claude.ai, у ~/.claude/skills/synced/. Має сенс лише false.
false зупиняє синхронізацію й припиняє вантажити вже синхронізовані скіли (у user/managed — ще й переміщує їх у .trash). true = не задано.
"syncClaudeAiSkills": false
--settings; репозиторій вимкнути не може.Зберігає несекретні відповіді з діалогу userConfig плагіна, ключ — ID плагіна (name@marketplace). Claude Code пише його сам, коли заповнюєш діалог.
Значення підставляються у конфіги хуків, MCP та LSP плагіна. Секретні опції сюди не потрапляють — вони йдуть у keychain macOS (або ~/.claude/.credentials.json). Проєктні та локальні записи ігноруються (репозиторій не повинен підсовувати такі значення), читається лише з user та managed.
"pluginConfigs": { "deployer@acme-plugins": { "options": { "api_endpoint": "https://api.acme.example" } } }
@builtin. Опцію можна задати й командою claude plugin install … --config api_endpoint=… або claude plugin configure.Вимикає виконання inline-shell у блоках !`…` та ```! у скілах і custom-командах із user, project, plugin та additional-directory джерел.
Замість виводу команди підставляється [shell command execution disabled by policy]. true у managed не можна перекрити. Вбудовані скіли та скіли з managed settings не зачіпаються.
"disableSkillShellExecution": true
Вимикає скіли та workflow, що йдуть у комплекті з Claude Code. Також змінна CLAUDE_CODE_DISABLE_BUNDLED_SKILLS.
Вбудовані команди на кшталт /init можна набрати, але модель їх не бачить.
"disableBundledSkills": true
Ховає чи згортає скіл без редагування його SKILL.md: ключ — ім’я скіла, значення — "on", "name-only", "user-invocable-only" або "off".
name-only — Claude бачить лише ім’я без опису; user-invocable-only — Claude скіл не бачить, але /name працює; off — не бачить ні Claude, ні автодоповнення. Меню /skills пише сюди в .claude/settings.local.json.
"skillOverrides": { "legacy-context": "name-only", "deploy": "off" }
/plugin.Списки plugin@marketplace керованих плагінів, чиї «моди» (обробники подій у коді плагіна) запускаються до / після усіх модів, які встановив користувач, у вказаному порядку. У managed додай sec-default@builtin, щоб зберегти вбудований захист.
Ідентифікатор, указаний в обох списках, виконується як prepend. У managed пропускаються id, чий плагін не належить організації. Читається з managed, а з user — лише на машині без managed settings і без входу через Team/Enterprise; у project, local і --settings ігнорується.
"enabledPlugins": { "acme-guard@acme-tools": true, "acme-audit@acme-tools": true }, "prependPlugins": ["acme-guard@acme-tools", "sec-default@builtin"], "appendPlugins": ["acme-audit@acme-tools"]
channelsEnabled дозволяє «канали» (плагіни, що можуть пушити повідомлення в сесію). allowedChannelPlugins замінює типовий список дозволених канальних плагінів: масив {marketplace, plugin} або рядків "plugin@marketplace" (рядкова форма — v2.1.267+, старіші версії відхиляють усе значення).
Без channelsEnabled канали заблоковані на Team/Enterprise і на Console-акаунтах з managed settings; на Pro/Max і Console без managed — дозволені. allowedChannelPlugins працює лише при channelsEnabled: true.
"channelsEnabled": true, "allowedChannelPlugins": [ { "marketplace": "claude-plugins-official", "plugin": "telegram" } ]
Як працюють enabledPlugins та extraKnownMarketplaces разом
- Область: пріоритет
local>project>user, а managed перекриває все. Щоб вимкнути для себе плагін, увімкнений у проєкті, поставfalseу.claude/settings.local.json:falseу user-файлі не допоможе. - Managed
falseблокує плагін у всіх областях і ховає його з marketplace. - Автоматично встановлюються лише плагіни, ввімкнені в managed
enabledPluginsразом із managedextraKnownMarketplaces. У репозиторії (.claude/settings.json) плагін із відносним шляхом у marketplace, зареєстрованому цим репозиторієм, завантажується сам, але плагін із зовнішнім джерелом (GitHub, npm …) ні — кожен користувач бачить «Plugin "<name>" is enabled in project settings but isn’t installed», доки не виконаєclaude plugin install <name>@<marketplace> --scope project. extraKnownMarketplacesу файлах репозиторію враховується лише після діалогу довіри до папки (у недовіреній — тихо ігнорується, у тому числі в-p).- Запис із тим самим іменем marketplace з файлу вищого пріоритету замінює нижчий цілком, без злиття полів (з v2.1.228).
- Офіційний
claude-plugins-officialреєструється сам при першій інтерактивній сесії; у скриптах спершуclaude plugin marketplace add anthropics/claude-plugins-official. Вимкнути авто-реєстрацію —CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALL=1.
Матриця політик плагінів
| Ключ | Що забезпечує | Чого не робить |
|---|---|---|
strictKnownMarketplaces | allowlist джерел marketplace; [] блокує все, навіть офіційний | не реєструє marketplace, не обмежує плагіни всередині дозволеного, не блокує --plugin-dir |
blockedMarketplaces | blocklist, перевіряється до allowlist | не відключає marketplace, уже зареєстрований із джерела, що не збігається |
enabledPlugins | true — примусове вмикання, false — блок у всіх областях | не встановить плагін із незареєстрованого/недозволеного marketplace |
disableSideloadFlags | відхиляє --plugin-dir, --plugin-url, --agents, plugins в SDK, не-SDK --mcp-config, CLAUDE_CODE_PLUGIN_DIRS (v2.1.193+) | не обмежує .mcp.json, claude mcp add — поєднуй з allowedMcpServers |
strictPluginOnlyCustomization | скіли/агенти/хуки/MCP лише з плагінів, managed і вбудованих | не обмежує, які саме плагіни ставлять |
pluginTrustMessage | додає ваш текст до попередження довіри в /plugin | не змінює саме попередження |
Allow/block-списки застосовуються перед завантаженням (додавання, встановлення, оновлення, auto-update) і ще раз на старті сесії: уже встановлений плагін, чий marketplace більше не підходить, не завантажується, а /plugin показує «is not in the allowed marketplace list» або «is blocked by enterprise policy». Поки діє будь-який allowlist, плагін із marketplace, якого Claude Code не знайшов, теж не вантажиться.
Змінні середовища для плагінів
| Змінна | Що робить |
|---|---|
CLAUDE_CODE_PLUGIN_CACHE_DIR | Коренева тека плагінів (за замовчуванням ~/.claude/plugins) — marketplace та кеш лежать у піддиректоріях. Корисна для побудови seed. |
CLAUDE_CODE_PLUGIN_SEED_DIR | Тека(и) з уже готовими marketplace та кешем плагінів, лише для читання (розділювач : або ; на Windows). Для образів контейнерів і CI. Плагіни зі seed потрібно ще ввімкнути в enabledPlugins. |
CLAUDE_CODE_SYNC_PLUGIN_INSTALL | 1: у -p чекати завершення встановлення плагінів до першого запиту (інакше вони ставляться у фоні). Тайм-аут — CLAUDE_CODE_SYNC_PLUGIN_INSTALL_TIMEOUT_MS. |
CLAUDE_CODE_PLUGIN_DIRS | Теки плагінів на сесію (як --plugin-dir), абсолютні шляхи або з ~ (v2.1.280+). |
CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS | Тайм-аут клонування/оновлення marketplace (за замовчуванням 120 000 мс). |
CLAUDE_CODE_PLUGIN_PREFER_HTTPS | 1: клонувати скорочення owner/repo по HTTPS, а не SSH (CI, контейнери). |
CLAUDE_CODE_PLUGIN_KEEP_MARKETPLACE_ON_FAILURE | 1: не переклоновувати marketplace, якщо оновлення не може дістатися до remote (офлайн / airgap). |
DISABLE_AUTOUPDATER / FORCE_AUTOUPDATE_PLUGINS | Вимкнути auto-update (разом із оновленнями самого Claude Code) / залишити авто-оновлення плагінів попри це. |
Команди керування плагінами
У сесії: /plugin (вкладки Discover, Installed, Marketplaces та Errors) і /reload-plugins (підхопити зміни без перезапуску). З оболонки — claude plugin (псевдонім claude plugins). Код виходу: 0 — успіх, 1 — помилка; у validate 2 — збій самого валідатора.
| Команда | Що робить |
|---|---|
claude plugin install <plugin>[@marketplace] [-s user|project|local] [--config k=v] [-y] [--json] [--marketplace <source>] | Встановити плагін (псевдонім i). Область за замовчуванням — user (~/.claude/settings.json); project — .claude/settings.json (кожен колега все одно ставить сам); local — .claude/settings.local.json. --config задає userConfig |
claude plugin uninstall <plugin> [-s …] [--keep-data] [--prune] | Видалити (remove / rm). Дані ${CLAUDE_PLUGIN_DATA} видаляються з останньою інсталяцією, якщо не --keep-data. |
claude plugin enable|disable <plugin> [-s …], disable --all | Увімкнути/вимкнути; область визначається автоматично (local, project, user). Синхронізований з claude.ai плагін — <name>@synced. |
claude plugin update <plugin> [-s user|project|local|managed] | Оновити до версії з marketplace; застосується в наступній сесії або після /reload-plugins. |
claude plugin list [--json], claude plugin details <name> | Список встановлених із версіями/областями/статусом; склад плагіна та проєктована вартість токенів. |
claude plugin configure <plugin@marketplace> [--values-stdin] [--json] | Показати або зберегти значення userConfig (JSON зі stdin); v2.1.285+. |
claude plugin prune | Прибрати автовстановлені залежності, які більше нікому не потрібні. |
claude plugin init <name> [--with skills hooks …] | Створити каркас у ~/.claude/skills/<name>/ (завантажується як <name>@skills-dir). |
claude plugin validate <path> [--strict] [--json] | Перевірити plugin.json, marketplace.json або компоненти в теці; для CI. |
claude plugin tag [path] [--push] [--dry-run] | Створити git-тег <name>--v<version> (перед цим звіряє версії в plugin.json і marketplace). |
claude plugin eval [target] [--threshold 0..1] [--runs n] [--json], eval init | Прогнати eval-кейси плагіна з оцінкою (v2.1.269+); порівнює з/без плагіна; коди виходу 0/1/2. |
claude plugin marketplace add <source> [--scope …] [--sparse …] [--claudeai] | Додати marketplace і оголосити його в settings. Джерело: owner/repo[@ref], git-URL, URL на marketplace.json, локальний шлях. |
claude plugin marketplace list|remove|update | Список / видалення (видаляє й його плагіни та дані) / оновлення каталогу. |
claude --plugin-dir <path|.zip>, claude --plugin-url <url> | Завантажити плагін лише на цю сесію (з’являється як <name>@inline). Блокується disableSideloadFlags. |
Рецепт: роздати плагіни команді Django + Vue на GitLab
- Репозиторій marketplace. Створи в GitLab репо
platform/claude-pluginsз.claude-plugin/marketplace.jsonі теками плагінів уplugins/. Для кожного плагіна —.claude-plugin/plugin.jsonізversion. - Перевір і познач реліз:
claude plugin validate . --strictу CI, потімclaude plugin tag plugins/django-review --push. Для зовнішніх джерел фіксуйrefіsha. - Підключи в проєкті. У репозиторії застосунку закоміть
.claude/settings.json(нижче). У нашому прикладіdjango-review(відносний шлях) підхопиться після довіри до папки, аvue-tools(git-subdir, зовнішнє джерело) кожен колега ставить командоюclaude plugin install vue-tools@acme-plugins --scope project. - Приватний репозиторій. Клонування йде через git на машині користувача (credential helper / SSH-ключі, без запитів). Для CI налаштуй git credential helper з токеном із правом читання репозиторію (у документації — приклад для GitHub Actions:
GH_TOKEN+gh auth setup-git), або зроби seed-образ:CLAUDE_CODE_PLUGIN_CACHE_DIR=/opt/claude-seed claude plugin marketplace add …на збірці,CLAUDE_CODE_PLUGIN_SEED_DIR=/opt/claude-seedу рантаймі. - Жорстка політика на рівні компанії. У managed settings (див. другий приклад): те саме
extraKnownMarketplaces+enabledPlugins— і плагіни ставляться самі на кожній машині, плюсstrictKnownMarketplacesлише з вашого GitLab-хоста таdisableSideloadFlags. - Перевір.
/pluginпоказує marketplace і плагіни; у CI —claude -p --output-format stream-json --verbose: подіяinitмістить масивplugins. У-pдодайCLAUDE_CODE_SYNC_PLUGIN_INSTALL=1, щоб плагін був доступний уже на першому ході.
{
"extraKnownMarketplaces": {
"acme-plugins": {
"source": {
"source": "git",
"url": "https://gitlab.acme.example/platform/claude-plugins.git",
"ref": "main"
},
"autoUpdate": true
}
},
"enabledPlugins": {
"django-review@acme-plugins": true,
"vue-tools@acme-plugins": true
}
}{
"extraKnownMarketplaces": {
"acme-plugins": {
"source": {
"source": "git",
"url": "https://gitlab.acme.example/platform/claude-plugins.git"
},
"autoUpdate": true
}
},
"enabledPlugins": {
"django-review@acme-plugins": true,
"vue-tools@acme-plugins": true
},
"strictKnownMarketplaces": [
{ "source": "hostPattern", "hostPattern": "^gitlab\\.acme\\.example$" },
{ "source": "skills-dir" }
],
"disableSideloadFlags": true,
"pluginTrustMessage": "Плагіни лише з acme-plugins. Питання: security@acme.example"
}- Офіційний marketplace при allowlist із вашого хоста не працюватиме — додай його в
strictKnownMarketplaces(anthropics/claude-plugins-official) і вextraKnownMarketplaces, якщо він потрібен. - Записи
extraKnownMarketplacesмають самі проходити allowlist, інакше Claude Code відмовиться їх реєструвати. autoUpdate: дляclaude-plugins-officialі більшості офіційних marketplace Anthropic за замовчуваннямtrue, для сторонніхfalse. Якщо managed-запис задає поле, користувач не може його перемкнути в/plugin.- Фіксований реліз: у plugin.json поле
version«приколює» плагін до цієї версії, доки ти його не змінив; безversionверсію обчислює сам Claude Code.
Джерела managed за пріоритетом: server-managed (консоль claude.ai або self-hosted Claude apps gateway) → MDM (plist / HKLM) → файл + drop-in каталог managed-settings.d/*.json → резервний HKCU (Windows; user-writable, тому не вважається admin-джерелом).
Різні команди безпеки можуть класти свої фрагменти в managed-settings.d/ — файли зливаються за алфавітом. За замовчуванням ("first-wins") діє лише найвище джерело з ключем політики — плюс невеликий набір ключів, які читаються з усіх admin-джерел. managedSourcesBehavior: "merge" (v2.1.242+) поєднує всі. Деталі — у розділі файли і пріоритети.
| macOS | /Library/Application Support/ClaudeCode/ (managed-settings.json, managed-settings.d/, managed-mcp.json) |
| Linux / WSL | /etc/claude-code/ (ті самі файли) |
| Windows | C:\Program Files\ClaudeCode\ (ті самі файли; стара C:\ProgramData\ClaudeCode\managed-settings.json не читається) |
| macOS MDM | plist-домен com.anthropic.claudecode |
| Windows MDM | HKLM\SOFTWARE\Policies\ClaudeCode → Settings (REG_SZ або REG_EXPAND_SZ); перевірка кожні 30 хв |
| Windows HKCU | HKCU\SOFTWARE\Policies\ClaudeCode → Settings: user-writable, тому застосовується лише коли вище немає жодного admin-документа |
Від найвищого: managed → --settings → .claude/settings.local.json → .claude/settings.json → ~/.claude/settings.json.
Масиви (allow, deny...) зливаються між файлами, скаляри — перевизначаються; hooks зливаються, а managed-hooks видалити не можна. Змінні середовища не є рівнем стека — пріоритет вирішується для кожної пари окремо. settings.local.json з v2.1.211 читається з кореня git-репозиторію і додається в global git excludes.
| 1 · managed | не перевизначається нічим |
| 2 · --settings | файл або JSON у CLI |
| 3 · local | .claude/settings.local.json — особисте, не комітиться |
| 4 · project | .claude/settings.json — спільне для команди |
| 5 · user | ~/.claude/settings.json |
disableClaudeAiConnectors (true з будь-якого рівня), enableArtifact / disableArtifact (false / true з будь-якого, v2.1.242+), isolatePeerMachines (true), permissions.blockReadsOutsideWorkingDirectories (true, v2.1.257+), autoMode.classifyAllShell (true з user чи --settings), remoteControlAtStartup (false з project/local), crossSessionInbound (суворіше значення з project/local), useAutoModeDuringPlan, syncClaudeAiSkills, syncClaudeAiPlugins (false з managed, --settings, user чи local), maxEffortLevel (найнижча стеля, v2.1.267+). Повна таблиця — у розділі файли і пріоритети.Обмежує, яким акаунтом можна логінитись: "claudeai", "console" або "gateway" (хмарний gateway замість першопартійного входу). forceLoginOrgUUID — один UUID або масив UUID організацій.
"claudeai" = через підписки Claude Pro/Max/Team/Enterprise. "console" = через Anthropic Console API — командний billing. forceLoginMethod "claudeai"/"console" обмежує вхід з будь-якого файлу налаштувань (діє у VS Code, SDK, claude setup-token, /install-github-app); єдиний виняток — інтерактивний екран входу в терміналі (/login або онбординг першого запуску), який лише попередньо обирає метод (до v2.1.212 застосовувався лише у терміналі). "gateway" береться лише з managed-джерела на машині (файл, plist, HKLM, policyHelper) — не з server-managed, HKCU чи user-файлів. forceLoginOrgUUID примусово діє лише з managed; в інших файлах один UUID лише попередньо обирає організацію, масив — нічого. Порожній масив або нерозбірливе managed-значення блокує усі входи.
"forceLoginMethod": "console", "forceLoginOrgUUID": ["xxxx-xxxx-xxxx-xxxx"] // UUID організації (можна кілька)
Shell-команда (будь-який командний рядок: /bin/sh на macOS/Linux, cmd на Windows), що динамічно віддає облікові дані. Вивід іде як X-Api-Key і Authorization: Bearer. Кеш — 5 хв за замовчуванням; команда перезапускається також при 401/403 та (з v2.1.246) коли кешований вивід — JWT, що вже прострочився.
Без нього — ключ статичний. З ним — інтегрується HashiCorp Vault, AWS IAM, або будь-яка ротація токенів. Ключ ніколи не зберігається на диску розробника. Останні два випадки перезапуску діють лише коли вивід — це справжній credential і не задано ANTHROPIC_AUTH_TOKEN. В інтерактивних сесіях хелпер із project/local settings не виконується, доки не прийнято діалог довіри до робочої теки. У managed-merge ключ читається лише з найвищого джерела.
"apiKeyHelper": "/opt/company/get-claude-key.sh" // Команда виводить ключ в stdout; йде як X-Api-Key і Bearer // TTL кешу — CLAUDE_CODE_API_KEY_HELPER_TTL_MS
Масив рядків — одне рандомно показується при старті кожної сесії (при першому запуску — перше). Власний "message of the day" для команди.
Розробники бачитимуть оголошення щоразу при запуску. Корисно для нагадувань про security policy, нові інструменти, планові роботи.
"companyAnnouncements": [ "🔒 Нагадування: секрети — тільки у Vault!", "📋 Новий MCP для Jira — деталі в Confluence", "🚀 Оновлено managed settings v2.4 — changelog" ]
Скільки днів зберігати локальні транскрипти сесій (~/.claude/projects/). Після — автоматично видаляються. Мінімум 1, default 30.
Менше — швидше видалення, менше місця, краща приватність. Важливо для compliance вимог (GDPR, SOC2). Для довгого зберігання — велике значення.
"cleanupPeriodDays": 7 // тиждень — для compliance "cleanupPeriodDays": 30 // default "cleanupPeriodDays": 3650 // ≈ ніколи не видаляти
Managed-ключі (з v2.1.163). Claude Code виходить на старті, якщо його версія нижча (requiredMinimumVersion) або вища (requiredMaximumVersion) за дозволену. Перевірка лише на старті — уже запущені сесії працюють далі; claude update, claude install і claude doctor лишаються доступними для відновлення. Невалідне значення ігнорується.
Гарантує, що в команді немає старих CLI з відомими вразливостями, і що ніхто не обганяє перевірену версію. minimumVersion — інше: він не блокує запуск, а лише не дає автооновленню та claude update встановити версію нижче (корисно при переході на канал stable).
"requiredMinimumVersion": "2.1.280", // потрібна для Opus 5.5 "requiredMaximumVersion": "2.1.295"
Скрипт що виводить OpenTelemetry headers. Прокидає телеметрію Claude Code в корпоративну observability систему.
Метрики й події Claude Code потрапляють у Datadog/Grafana поряд з іншими сервісами компанії. Частоту оновлення задає CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS.
"otelHeadersHelper": "/opt/company/otel-headers.sh"
Список сервісів, через які машина може ходити до Claude. Сесія на провайдері поза списком відхиляється на старті, при логіні й при наступному зверненні до API — перемкнутись посеред сесії теж не вийде.
Гарантує, що код не піде в непередбачений хмарний сервіс. Server-managed список може лише звузити перелік машини, ніколи не розширити. Невідомі записи відкидаються з повідомленням; порожній список або такий, де всі записи нерозпізнані, забороняє всіх провайдерів — Claude Code не запуститься.
"allowedProviders": ["anthropic", "bedrock"]
anthropic | Anthropic API на власному хості (вхід claude.ai/Console або ключ); для обмеження входу додай forceLoginMethod / forceLoginOrgUUID |
bedrock / mantle | Amazon Bedrock / його Mantle endpoint (для сесії, що використовує обидва, вкажи обидва) |
vertex / foundry / anthropicAws | Google Cloud Agent Platform / Microsoft Foundry / Claude Platform on AWS |
customEndpoint | API Anthropic або хмарного провайдера на інший хост (LLM gateway через ANTHROPIC_BASE_URL тощо); допускається лише для точного значення, закріпленого в managed env |
gateway | вхід через Cloud gateway |
Власна команда (напр. aws sso login), що оновлює облікові дані в каталозі .aws, коли ті, що має Claude Code для Amazon Bedrock, перестали працювати.
Команда запускається лише після того, як перевірка через STS не пройшла; потім Claude Code перечитує .aws. Якщо кілька процесів (термінали, вікна IDE) впали одночасно, команду запускає один, інші чекають; той, хто чекає 60 с, запускає сам. Блокування вимикає CLAUDE_CODE_DISABLE_AUTH_REFRESH_LOCK=1.
"awsAuthRefresh": "aws sso login --profile myprofile"
.aws, а друкує креди — використовуй awsCredentialExport.Команда, що друкує AWS-креди у JSON (формат виводу aws sts або плаский aws configure export-credentials), коли вони не лежать в .aws.
Креди обмежені власним Bedrock-клієнтом Claude Code: shell-команди, які запускає Claude, бачать твої звичайні змінні. На відміну від awsAuthRefresh, команда виконується завжди, коли задана, без попередньої перевірки.
"awsCredentialExport": "/bin/generate_aws_grant.sh"
Команда, що оновлює Google Cloud Application Default Credentials, коли вони прострочені або не завантажуються.
Запити до Google Cloud Agent Platform продовжують працювати без ручного перелогіну. Без ключа помилка просто підказує виконати gcloud auth application-default login. Спільне блокування як у awsAuthRefresh.
"gcpAuthRefresh": "gcloud auth application-default login"
URL, до якого підключається екран /login → Cloud gateway. Повна адреса зі схемою.
Люди потрапляють на ваш gateway, не вводячи адреси. Без ключа екран просить звернутись до IT. Цей ключ або forceLoginMethod: "gateway" робить машину gateway-only (крім сесій з CLAUDE_CODE_USE_*); задай обидва, щоб екран підключався, а не показував помилку.
"forceLoginGatewayUrl": "https://claude-gateway.example.com"
Публічні IPv4-блоки, з яких організація нумерує внутрішню мережу, щоб /login приймав cloud gateway і там.
Без ключа /login підключається лише до gateway на приватних адресах. З ключем приймає ще й gateway усередині вказаного блоку, лише прямим з’єднанням, і адреса самої машини має бути в тому ж блоці. До 4 CIDR (/8–/32), без перетину між собою та з приватним простором. Невалідний запис блокує усі нові gateway-входи на машині, доки не виправиш.
"gatewayInternalNetworks": ["203.0.113.0/24"]
Відхиляє прапори --plugin-dir, --plugin-url, --agents і --mcp-config на старті. Default false.
Закриває обхід strictKnownMarketplaces через підвантаження плагінів, агентів чи MCP з командного рядка. У cloud-сесіях замість відмови відкидаються server-delivered записи --mcp-config.
"disableSideloadFlags": true
Блокує старт CLI, доки свіжо не отримано server-managed settings. Якщо fetch не вдався — Claude Code завершується. Default false.
Політика не «застаріє» з кешу. Значення true береться з будь-якого admin-джерела; перевірка йде до запуску policyHelper. Зміна діє з наступного запуску сесії.
"forceRemoteSettingsRefresh": true
Чи застосовувати managed-налаштування від процесу-хоста (Agent SDK, розширення IDE, Claude Desktop), коли на машині є і admin-managed рівень: "first-wins" (default) або "merge".
first-wins відкидає налаштування хоста. merge застосовує їх під admin-рівнем через фільтр «лише обмеження» — хост може передати власні обмеження сесіям, які запускає (наприклад, egress allowlist gateway). Читається з найвищого admin-джерела.
"parentSettingsBehavior": "merge"
Виконуваний файл, який ви розгортаєте і який обчислює managed-налаштування на старті — з позиції пристрою, ідентичності чи віддаленого сервісу — замість статичного файлу. Запускається до першого промпту, його вивід стає managed-налаштуваннями сесії.
Політику можна рахувати динамічно. Хелпер без аргументів друкує у stdout один JSON-об’єкт (до 1 МіБ) з ключем managedSettings — «голий» об’єкт без цього ключа не застосує нічого й не дасть помилки. У середовищі є CLAUDE_CODE_VERSION. Якщо видано managedSettings, це єдине managed-джерело сесії: MDM, файл і HKCU ігноруються.
"policyHelper": { "path": "/usr/local/bin/claude-policy", "timeoutMs": 5000, "refreshIntervalMs": 300000 }
path | обов’язковий; абсолютний нормалізований шлях без ./..; у Windows — диск або UNC, кінчається .exe |
timeoutMs | ціле, мінімум 1000, default 10000. Таймаут на старті = Claude Code відмовляється запускатися |
refreshIntervalMs | 0 = вимкнено, інакше ≥60000; без ключа хелпер запускається один раз. Збій фонового оновлення залишає останню успішну політику, /status показує причину |
Змушує Claude Code у WSL читати managed-налаштування з ланцюга політик Windows: HKLM і Windows-файл мають пріоритет над /etc/claude-code та HKCU. Default false (WSL читає лише /etc/claude-code).
Одна політика Windows діє і на сесії WSL тієї ж машини. Поки ланцюг увімкнено, /etc/claude-code читається лише якщо у HKLM чи в C:\Program Files\ClaudeCode\ немає admin-документа. Визнається лише з HKLM або з файлу/drop-in у C:\Program Files\ClaudeCode\; на нативному Windows не діє.
"wslInheritsWindowsSettings": true
true.Віковий ліміт (дні, ≥0) для транскриптів сесій, які ти починав або востаннє продовжував у Claude Desktop чи Cowork. Default 0 — без ліміту.
Транскрипт видаляється лише коли він старший і за цей ключ, і за cleanupPeriodDays. Корисно для окремої політики зберігання десктопних сесій.
"desktopSessionCleanupPeriodDays": 90
--settings).Керує чернетками відгуків, які пише Claude: "notify" (default), "quiet" або "off".
Визначає, чи може Claude ставити чернетки відгуків у чергу для твого перегляду і чи показує Claude Code картку. "off" прибирає інструмент SendFeedback; те саме дає CLAUDE_CODE_SEND_FEEDBACK=0.
"feedbackDrafts": "quiet"
Імовірність (0–1) показати опитування якості сесії, коли сесія до нього придатна. 0 — не показувати ніколи.
Без ключа діє віддалена частота (або 0.005 на Bedrock/Vertex/Foundry). Повністю вимкнути опитування можна й змінною CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY=1.
"feedbackSurveyRate": 0
Пропускає перевірку безпеки домену перед WebFetch, яка надсилає запитану назву хоста на api.anthropic.com.
Для середовищ, що блокують трафік до Anthropic: Bedrock, Google Cloud Agent Platform чи Foundry з обмеженим egress. Без ключа перевірка виконується перед першим запитом до кожного хоста в сесії.
"skipWebFetchPreflight": true
WebFetch у permissions.Встановлює мову відповідей Claude незалежно від мови запиту. Також мову голосової диктовки та назв сесій.
"ukrainian" = Claude відповідатиме українською навіть якщо запит англійською. Корисно для стандартизації мови в команді.
"language": "ukrainian"
Claude автоматично зберігає корисний контекст у ~/.claude/projects/<проєкт>/memory/ (індекс MEMORY.md) — рішення, патерни, уподобання. Default true.
true = Claude "навчається" від сесії до сесії. false = кожна сесія ізольована, нічого не пишеться. Для compliance (GDPR) — false. autoMemoryDirectory — перенести пам’ять в інше місце.
"autoMemoryEnabled": true // зберігає контекст між сесіями "autoMemoryEnabled": false // кожна сесія з нуля "autoMemoryDirectory": "~/work/claude-memory"
З якого каналу отримувати автооновлення Claude Code CLI: "latest" (default) або "stable". Homebrew-інсталяції ігнорують.
"stable" відстає від latest і містить перевірені збірки (зараз 2.1.286 проти 2.1.295). Для команд краще "stable" — менше сюрпризів.
"autoUpdatesChannel": "stable" // ✓ рекомендовано для команд "minimumVersion": "2.1.280"
Задає стиль відповідей Claude. Вбудовані: Default, Proactive, Concise, Explanatory, Learning, або власний з .claude/output-styles/.
"Explanatory" = пояснює рішення. "Learning" = залишає частину коду тобі. "Concise" = мінімум тексту. Зміна діє з наступного повідомлення.
"outputStyle": "Explanatory" // onboarding junior розробників
Де зберігати план-файли що Claude Code створює в режимі планування. Шлях відносно кореня проєкту.
Default ~/.claude/plans. Перемістивши в ./plans/ — плани в репозиторії, доступні всій команді через git і code review. Шлях поза проєктом ігнорується.
"plansDirectory": "./plans" // в репо поряд з CLAUDE.md
Нові ключі. autoCompactWindow (100000–1000000) — розмір вікна, після якого стискається контекст; значення обмежене вікном моделі. bashOutputMaxChars (4000–128000, default 30000) — скільки виводу успішної Bash/PowerShell-команди Claude отримує одразу; понад ліміт вивід зберігається у файл, Claude бачить прев’ю і шлях.
Менше вікно = дешевші запити на 1M-моделях, але частіше стиснення. Менший bash-вивід = економія токенів на шумних тестах і білдах. bashOutputMaxChars потребує v2.1.261+ і має пріоритет над BASH_MAX_OUTPUT_LENGTH: якщо ключ задано, змінна ігнорується. Пріоритет autoCompactWindow: CLAUDE_CODE_AUTO_COMPACT_WINDOW > --autocompact > ключ; modelSettings.<модель>.autoCompactWindow (його пише /autocompact) у тому ж файлі сильніший за ключ.
"autoCompactWindow": 400000, "bashOutputMaxChars": 15000
Чи стискати розмову автоматично, коли контекст наближається до межі. Default true.
false — контекст не стискається сам, лишається ручний /compact. Змінна DISABLE_AUTO_COMPACT теж вимикає авто-стиснення, і жоден із двох способів не може повернути те, що вимкнув інший.
"autoCompactEnabled": false
Вставляє інструкції у стилі CLAUDE.md як організаційну managed-пам’ять без розгортання окремого файлу. Це текст Markdown, переноси — \n.
Завантажується раніше за user- і project-CLAUDE.md, тож базові правила інженерії діють у кожному проєкті. Підходить для політик, які мають бути в контексті завжди.
"claudeMd": "# Engineering rules\n\n- Перед комітом запускай make lint.\n- Міграції Django — лише через makemigrations."
Glob-шаблони або абсолютні шляхи CLAUDE.md-файлів, які треба пропустити під час завантаження пам’яті. Шаблони зіставляються з абсолютними шляхами.
Корисно в монорепо: чужі CLAUDE.md сусідніх команд або вендорні каталоги не засмічують контекст.
"claudeMdExcludes": ["**/vendor/**/CLAUDE.md", "**/node_modules/**/CLAUDE.md"]
Робити знімок файлів перед кожною правкою, щоб /rewind міг відновити їх. Default true; у /config — «Rewind code (checkpoints)».
false — знімків немає, /rewind не поверне код. CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING=1 вимикає те саме на сесію; що вимкнуло — те й лишається вимкненим.
"fileCheckpointingEnabled": false
-p та Agent SDK ключ ігнорується: SDK вмикає опцією enableFileCheckpointing, а «голий» -p потребує CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING=true.Частка вікна контексту (0 < x ≤ 1, default 0.01), яку може займати щоходовий перелік скілів.
Понад ліміт Claude Code «скидає описи найменш вживаних скілів». Піднімай, якщо скілів багато і Claude перестає їх помічати.
"skillListingBudgetFraction": 0.02
Скільки символів тексту (description + when_to_use) показувати на один скіл у переліку. Default 1536.
Довші описи обрізаються. Збільшуй, якщо критичні умови запуску скіла стоять наприкінці опису.
"skillListingMaxDescChars": 2048
Застарілі ключі
Ці ключі вже не мають ефекту або замінені новими. Старі файли з ними не ламаються, але прибери їх під час наступної ревізії.
| Ключ | Статус | Що робити |
|---|---|---|
taskOutputMaxChars | видалено у v2.1.277 разом з інструментом TaskOutput; не діє | Прибрати. |
permissionExplainerEnabled | видалено у v2.1.257 (разом з поясненням Ctrl+E); не діє | Прибрати. |
teammateDefaultModel | видалено у v2.1.234; не діє | Прибрати. |
keybindingFlavor | deprecated з v2.1.261; не діє — клавіші редагування слів завжди за readline | Прибрати. |
voiceEnabled | deprecated з v2.1.92, ще читається | Замінити на voice.enabled. |
disableArtifact | deprecated, ще читається: true = enableArtifact: false, false ігнорується | Замінити на enableArtifact: false. |
includeCoAuthoredBy | deprecated з v2.0.62, ще читається (див. розділ git) | Замінити на attribution. |
Кастомізує текст атрибуції що Claude додає до git комітів як co-author trailer та в описи Pull Request. Нове поле sessionUrl — посилання на сесію.
"" = прибрати конкретний підпис. false (v2.1.281+) = сховати всю атрибуцію. Корисно якщо internal policy не дозволяє AI-атрибуцію в комітах.
"attribution": { "commit": "", "pr": "", "sessionUrl": false } // або все одразу: "attribution": false // або кастомний текст: "attribution": { "commit": "Co-authored-by: AI Dev <ai@company.com>" }
Вмикає/вимикає вбудовані git-інструкції та знімок git status у system prompt Claude. Default true.
false = Claude не використовує стандартні git інструкції. Корисно якщо є власний CLAUDE.md з кастомними git конвенціями — уникнення конфлікту інструкцій. Env-аналог: CLAUDE_CODE_DISABLE_GIT_INSTRUCTIONS.
"includeGitInstructions": false // є свій CLAUDE.md з git правилами
Нові ключі. prUrlTemplate — шаблон посилання на PR для не-GitHub хостингів. worktree — об’єкт з підключами baseRef, symlinkDirectories, sparsePaths, bgIsolation: як Claude створює git worktree для --worktree, EnterWorktree, ізольованих субагентів і фонових сесій.
Посилання на PR ведуть у твій внутрішній code-review інструмент. baseRef: "fresh" (default) — від origin/<default-branch>, "head" — від поточного HEAD з незапушеними комітами.
"prUrlTemplate": "https://reviews.company.com/{owner}/{repo}/pull/{number}", "worktree": { "baseRef": "head" }
Каталоги (шляхи від кореня репозиторію), які символічно лінкуються з основного репо в кожен worktree.
Не дублюєш на диску важкі каталоги: у Django + Vue проєкті — node_modules або кеші. Без ключа нічого не лінкується.
"worktree": { "symlinkDirectories": ["node_modules", ".cache"] }
.env, поклади в корінь проєкту файл .worktreeinclude — окремого ключа для цього немає.Каталоги від кореня репо, які git sparse-checkout вивантажує в кожен worktree. На диск записуються лише вони та файли з кореня.
Швидше у великих монорепо: у worktree з’являється лише потрібна частина дерева. Без ключа береться все дерево.
"worktree": { "sparsePaths": ["packages/my-app", "shared/utils"] }
extensions.worktreeConfig у спільному .git/config.Як фонові сесії ізолюють правки файлів: "worktree" (default) або "none".
З "worktree" Claude Code блокує Edit і Write в основному checkout, доки сесія не викличе EnterWorktree. З "none" фонові завдання правлять робочу копію напряму — для репо, де worktree незручні. Сесія, яку ти сам перевів у фон (← чи /background), редагує на місці за будь-якого значення.
"worktree": { "bgIsolation": "none" }
WorktreeCreate знімає блокування, і сесія редагує каталог на місці (з v2.1.203).Ключі нижче лежать у settings.json, якщо не сказано інше. Бейдж біля ключа показує, звідки він діє: без бейджа ключ читається з будь-якого файла (user, project, local, managed); «user або managed» означає, що project і local ігноруються (репозиторій не може вмикати такі речі за тебе). Деякі ключі (theme, verbose, terminalProgressBarEnabled, respectGitignore, teammateMode, ключі сповіщень) за відсутності в settings читаються ще й з ~/.claude.json, куди їх писали старіші версії.
Рядок статусу, спінер і файли
Кастомний рядок статусу внизу терміналу. Скрипт читає JSON зі stdin (модель, контекст, cost, git) і виводить рядок. subagentStatusLine — окремий рядок для субагентів.
Без цього — стандартний статус. З скриптом — показуй що завгодно: git branch, витрачені токени, час сесії. padding — горизонтальний відступ у символах. refreshInterval — оновлення за таймером, у секундах, мінімум 1. hideVimModeIndicator: true ховає вбудований індикатор vim-режиму, коли скрипт сам малює vim.mode. Якщо ввімкнено allowManagedHooksOnly (або disableAllHooks стоїть поза managed), працює лише значення з managed.
"statusLine": { "type": "command", "command": "~/.claude/statusline.sh", "padding": 2, // відступ, символів "refreshInterval": 5, // кожні 5 с (мінімум 1) "hideVimModeIndicator": true }
Кастомізує анімований спінер: текст дій (append або replace), підказки, тривалість ходу, анімації. Чисто косметично.
spinnerTipsEnabled false = без підказок (або свої через spinnerTipsOverride). showTurnDuration false = не показувати "Cooked for 1m 6s". prefersReducedMotion true = вимкнути анімацію (accessibility).
"spinnerVerbs": { "mode": "replace", "verbs": ["Думаю...", "Пишу..."] }, "spinnerTipsEnabled": false, "showTurnDuration": true, "prefersReducedMotion": false
Власний скрипт для автокомпліту файлів при наборі "@filename". Отримує {"query": "..."} у stdin, виводить до 15 шляхів. Таймаут 5 с.
Дозволяє інтегрувати fd, ripgrep, або кастомний індекс великого монорепо. Без цього — стандартний пошук по директорії.
"fileSuggestion": { "type": "command", "command": "~/.claude/file-suggest.sh" } // file-suggest.sh: q=$(jq -r .query); fd --type f | fzf --filter "$q" | head -15
Нові ключі інтерфейсу: рендерер tui ("fullscreen" — без мерехтіння, або "default"), формат часу та часовий пояс (v2.1.257), а також ширина тексту maxProseWidth (з v2.1.282, число колонок, мінімум 40; інші значення ігноруються). Параграфи, заголовки, списки й цитати переносяться в межах цієї ширини, а таблиці та блоки коду лишаються на всю ширину терміналу. Без tui Claude Code сам обирає рендерер; /tui fullscreen або /tui default записують ключ за тебе.
Однаковий вигляд терміналу в команді, коректний час у статусах для розподілених команд.
"tui": "fullscreen", "timeFormat": "24-hour", "timeZone": "Europe/Kyiv", "maxProseWidth": 80
Термінал і відображення
Колірна тема інтерфейсу. Зазвичай її міняють через /theme або /config, але ключ дозволяє зафіксувати тему у файлі.
Без ключа діє "dark". "auto" слідує за темою терміналу; daltonized-теми — для дальтонізму; ansi-теми використовують лише 16 кольорів терміналу.
{
"theme": "light-daltonized"
}"auto" | за темою терміналу |
"dark" / "light" | стандартні (default — dark) |
"dark-daltonized" / "light-daltonized" | для дальтонізму |
"dark-ansi" / "light-ansi" | лише ANSI-кольори терміналу |
"custom:<slug>", "custom:<plugin>:<slug>" | власна тема або тема з плагіна |
У якому вигляді транскрипту стартує Claude Code: default (звичайний, вивід інструментів скорочено), verbose (повний вивід інструментів) або focus (лише твій останній промпт, однорядкове зведення викликів інструментів і фінальна відповідь).
Якщо ключ заданий, він перекриває і запам’ятований вибір /focus, і ключ verbose. Режим focus працює лише з fullscreen-рендерером (tui). Без ключа діють ключ verbose і твій останній вибір /focus. Прапорець --verbose перекриває ключ на одну сесію.
{
"viewMode": "focus"
}Показувати повний вхід і вихід кожного виклику інструмента просто в розмові, у міру того як він відбувається. Типово false.
Корисно, коли треба дебажити, що саме запускає Claude (повні аргументи Bash, вміст читаних файлів). Прапорець --verbose перекриває ключ на одну сесію. Шумно для щоденної роботи.
{
"verbose": true
}Вимикає підсвічування синтаксису: diff-и, блоки коду й прев’ю показуються простим текстом. Типово false.
Корисно в терміналах із поганою передачею кольору або коли підсвічування заважає читати diff. Функціональних наслідків немає.
{
"syntaxHighlightingDisabled": true
}У fullscreen-рендерінгу вікно слідує за новим виводом до низу розмови. Типово true.
З false позиція прокрутки залишається там, де ти її лишив, і нові рядки не відкидають тебе вниз. Зручно, коли перечитуєш довгу відповідь, поки Claude ще пише.
{
"autoScrollEnabled": false
}У fullscreen-рендерінгу прискорює прокрутку колесом миші під час швидкого скролу. Типово true.
З false швидкість скролу постійна: передбачувано на трекпадах і в мишах із власною акселерацією.
{
"wheelScrollAccelerationEnabled": false
}Повідомляє терміналу про стан «виконується», якщо той уміє показувати індикатор прогресу на вкладці чи в панелі завдань. Типово true.
З false індикатор у вкладці не з’являється. Якщо ключа немає в settings, береться значення з ~/.claude.json.
{
"terminalProgressBarEnabled": false
}Керує тим, чи заголовок вкладки терміналу оновлюється, коли ти перейменовуєш сесію. Типово true.
З false на вкладці лишається згенерований заголовок навіть після того, як ти дав сесії ім’я.
{
"terminalTitleFromRename": false
}Ввід і взаємодія
Режим клавіш у полі вводу: "normal" (за замовчуванням) або "vim".
З "vim" поле вводу працює як vim (INSERT / NORMAL). Разом із vimInsertModeRemaps можна повісити вихід з INSERT на jj.
{
"editorMode": "vim"
}У vim-режимі перетворює двосимвольні послідовності в INSERT на Escape. Єдине допустиме значення — "<Esc>". Потребує v2.1.208+.
Без ключа вихід з INSERT лише справжнім Esc. Працює тільки при editorMode: "vim".
{
"editorMode": "vim",
"vimInsertModeRemaps": { "jj": "<Esc>" }
}Підкреслює слова з помилками у полі вводу під час набору через spell checker, який ти встановив сам (aspell, hunspell, ispell). Перевіряється лише текст у полі вводу. Потребує v2.1.235+.
Типово вимкнено. Поля: enabled, checker ("aspell", "hunspell", "ispell" або "auto" — перший знайдений у PATH), language (назва словника для checker) і color (ім’я кольору, #rrggbb, rgb(r,g,b), ansi256(n), ansi:<name>; типово колір помилки з теми).
{
"spellcheck": {
"enabled": true,
"checker": "hunspell",
"language": "uk_UA"
}
}Голосова диктовка: вмикає її та задає поведінку клавіші диктовки. Поля: enabled, mode — "hold" (тримаєш клавішу, відпускаєш — стоп) або "tap" (тап — старт, тап — відправити), autoSubmit (відправити промпт при відпусканні, лише в hold).
Без ключа диктовка вимкнена; якщо enabled: true, а mode не задано, використовується "hold". Ключ пише за тебе команда /voice. Потрібен акаунт claude.ai.
{
"voice": {
"enabled": true,
"mode": "tap"
}
}Показує підказки емодзі після : і замінює шорткоди на кшталт :heart: на символи. Типово true. Потребує v2.1.217+.
З false двокрапка у промпті не викликає підказок: зручно, якщо часто пишеш : у коді чи YAML.
{
"emojiCompletionEnabled": false
}Показує або ховає підказки промпту: сірі передбачення, що з’являються у полі вводу. Типово true.
З false поле вводу залишається порожнім, поки ти не почнеш писати. Змінна оточення CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION робить те саме.
{
"promptSuggestionEnabled": false
}Чи пропускає файловий вибір @ файли, що збігаються з патернами .gitignore. Типово true.
З false у списку @ з’являються й ігноровані файли (node_modules, dist, .env). Якщо ключа немає в settings, береться значення з ~/.claude.json.
{
"respectGitignore": false
}Який шел виконує команди, які ти вводиш через префікс !: "bash" або "powershell".
Типово "bash" (або "powershell" на Windows без Bash). Команди, що їх запускає сам Claude, цим ключем не змінюються.
{
"defaultShell": "powershell"
}Чи відповідає Claude на команду, введену через !. Типово true.
З false вивід команди просто додається в контекст без відповіді Claude: економить токени, коли ти збираєш дані для наступного промпту.
{
"respondToBashCommands": false
}Чи записує Claude Code, які файли в Git-репозиторії змінила Bash-команда, поки вона виконувалась. Показує diff і передає його у PostToolUse-хуки на Bash. Потребує v2.1.269+.
Без ключа запис ведеться лише в режимах auto і bypassPermissions. true рахується тільки з user, --settings чи managed. Змінна оточення: CLAUDE_CODE_BASH_EDIT_DIFF.
{
"bashEditDiffEnabled": true
}Додає першим пунктом у меню схвалення плану варіант «Yes, clear context and …». Типово false.
З true схвалити план можна одразу з очищенням контексту: корисно, коли дослідження забило вікно, а виконанню потрібен чистий старт.
{
"showClearContextOnPlanAccept": true
}Діалоги, таймаути й сповіщення
Дозволяє діалогу AskUserQuestion, на який ніхто не відповів, автоматично продовжити після періоду бездіяльності: Claude Code відправляє варіанти, які ти вже встиг вибрати.
Значення: "60s", "5m", "10m", "never" (типово). Корисно для довгих сесій, які ти залишаєш без нагляду. Змінна CLAUDE_AFK_TIMEOUT_MS перекриває ключ.
{
"askUserQuestionTimeout": "5m"
}Дедлайн для діалогів, які Claude Code пересилає віддаленому клієнту: Remote Control або хосту SDK. Потребує v2.1.224+.
Значення: "60s", "5m" (типово), "10m", "never". Змінна оточення: CLAUDE_CODE_USER_DIALOG_TIMEOUT_MS.
{
"dialogExpiry": "10m"
}Коли ліміт використання claude.ai зупиняє сесію, Claude Code чекає в цій самій відкритій сесії й сам продовжує задачу після скидання ліміту. Типово true. Потребує v2.1.234+.
З false сесія просто зупиняється, і продовжувати треба вручну. Значення з project чи local може лише вимкнути функцію, і то лише якщо не задано значення в user, --settings чи managed.
{
"autoContinueAtUsageLimit": false
}Доступність
Режим для скрінрідерів: плоский текст без декоративних рамок і анімацій. Працює на класичному рендерері, тому ключ tui під час його дії ігнорується.
Типово вимкнено. Пріоритет: прапорець --ax-screen-reader, потім змінна CLAUDE_AX_SCREEN_READER, потім ключ. Разом із prefersReducedMotion (див. вище) дає мінімально рухливий інтерфейс.
{
"axScreenReader": true,
"prefersReducedMotion": true
}Застарілі ключі
Ці ключі не потрібно додавати в нові конфіги.
| Ключ | Стан | Що робити |
|---|---|---|
voiceEnabled | застарілий з v2.1.92, ще читається | Заміни на voice.enabled (див. картку voice вище) |
keybindingFlavor | застарілий з v2.1.261, не має ефекту | Видали. Клавіші редагування слів завжди працюють за readline |
Агенти, сесії й workflows
Ключі для головного агента, фонових сесій, agent teams і динамічних workflows
Ключі, що вирішують, ким працює головний потік, як сесії спілкуються між собою і чи доступні динамічні workflows. Самі поняття — субагенти, agent teams, workflows — пояснені на сторінці Команди та агенти; тут лише налаштування. Усі ключі читаються з будь-якого файла, якщо не вказано інакше.
Головний потік і фонові агенти
Запускає головний потік як іменований субагент: Claude Code застосовує до сесії системний промпт, обмеження інструментів і модель цього субагента (вбудованого чи власного). Також задає типове значення для диспетчеризації через claude agents.
Без ключа працює звичайна сесія. Прапорець --agent перекриває ключ. Зручно закріпити за репозиторієм, скажімо, рев’юера чи агента міграцій Django.
{
"agent": "code-reviewer"
}Вимикає фонових агентів і agent view: claude agents, --bg, /background і супервізор на вимогу.
Для середовищ, де фонові процеси заборонені політикою. Змінна оточення: CLAUDE_CODE_DISABLE_AGENT_VIEW.
{
"disableAgentView": true
}На macOS і Linux ставить корпоративний launcher перед фоновими процесами, які запускає Claude Code. Значення — префікс argv; launcher мусить виконати exec у Claude Code. Потребує v2.1.210+.
Дозволяє пропускати фонові процеси через аудит чи профілювання. Змінна оточення: CLAUDE_CODE_PROCESS_WRAPPER (з project і local settings її задати не можна).
{
"processWrapper": "/opt/corp/launcher --profile claude"
}Де Claude Code показує teammates з agent teams: у твоїй основній панелі терміналу чи в окремих split-панелях.
Значення: "in-process" (типово), "auto", "tmux", "iterm2". Прапорець --teammate-mode перекриває ключ на одну сесію.
{
"teammateMode": "auto"
}Зв’язок між сесіями
Що ця сесія робить із повідомленнями, які надходять від твоїх інших сесій Claude Code. Потребує v2.1.224+.
Значення: "accept", "hold" (показати сповіщення, не доставляючи повідомлення), "refuse". Без ключа рішення приймається для кожного повідомлення окремо. Значення з project чи local застосовується лише якщо воно суворіше.
{
"crossSessionInbound": "hold"
}Вимагає твого явного схвалення, перш ніж SendMessage від Claude дійде до сесії поза цією машиною. Потребує v2.1.224+.
Захист від того, щоб агент розсилав повідомлення між твоїми машинами без відома. true з будь-якого рівня застосовується.
{
"isolatePeerMachines": true
}Динамічні workflows
Вмикає або вимикає динамічні workflows для тебе особисто.
Без ключа workflows увімкнені, крім плану Pro, де вони вимкнені типово. Для вимкнення для всіх, кого зачіпають settings, дивись disableWorkflows.
{
"enableWorkflows": true
}Вимикає динамічні workflows і вбудовані команди workflows для всіх, кого досягають ці settings. Типово false.
Власнику репозиторію чи адміну достатньо виставити true у спільному файлі. Змінна оточення: CLAUDE_CODE_DISABLE_WORKFLOWS.
{
"disableWorkflows": true
}Чи запускає динамічний workflow слово ultracode, набране у промпті. Типово true.
З false слово у промпті лишається звичайним текстом і workflow не запускає; режим ultracode все одно вмикається ключем ultracode чи /effort ultracode.
{
"workflowKeywordTriggerEnabled": false
}Орієнтир для кількості агентів у динамічних workflows, які пише Claude. Це порада, а не жорсткий ліміт. Потребує v2.1.219+.
Типово "medium", на плані Pro — "small" (з v2.1.271).
{
"workflowSizeGuideline": "small"
}"small" | менше 5 агентів |
"medium" | менше 10 агентів (типово) |
"large" | менше 50 агентів |
"unrestricted" | без орієнтира |
Remote, Desktop і сповіщення
Remote Control, хмарні сесії, Desktop-застосунок, push-сповіщення, Artifact
Remote Control, хмарні сесії, desktop-застосунок, сповіщення та Artifact. Багато ключів тут для адміністраторів: вони читаються лише з managed settings (файл, MDM, server-managed) і ігноруються в user, project та local. Для managed-ключів приклади показано у managed-settings.json.
Сповіщення
Як Claude Code повідомляє тебе, що задача завершена або чекає дозволу.
Типово "auto".
{
"preferredNotifChannel": "terminal_bell"
}"auto" | десктоп-сповіщення в iTerm2, Ghostty і Kitty; у Terminal.app дзвінок, лише якщо його звуковий дзвінок вимкнено; в інших терміналах нічого (типово) |
"terminal_bell" | символ дзвінка в будь-якому терміналі |
"iterm2", "iterm2_with_bell" | сповіщення iTerm2 (з дзвінком чи без) |
"kitty", "ghostty" | нативні сповіщення цих терміналів |
"notifications_disabled" | без сповіщень |
Push-сповіщення на телефон, коли permission-запит або питання чекає на твою відповідь. Типово false.
Дозволяє піти від терміналу й повернутися лише тоді, коли Claude справді застряг. Потрібне підключення Remote Control.
{
"inputNeededNotifEnabled": true
}Дозволяє Claude самому надсилати push на телефон, коли він вважає, що це варто зробити. Типово false.
Відрізняється від inputNeededNotifEnabled: тут рішення приймає модель (наприклад, довгий прогін завершився). Потребує підключеного Remote Control.
{
"agentPushNotifEnabled": true
}Однорядковий підсумок сесії, коли ти повертаєшся до терміналу після кількох хвилин відсутності.
Без ключа підсумок показується. З false вимикається. Змінна оточення: CLAUDE_CODE_ENABLE_AWAY_SUMMARY.
{
"awaySummaryEnabled": false
}Remote Control і хмарні сесії
Автоматично підключає Remote Control на старті кожної інтерактивної сесії.
Без ключа діє адмінський дефолт організації, якщо він є; інакше Remote Control вмикається вручну (/remote-control, --remote-control). Значення false з project чи local перекриває навіть true з managed, а true з project чи local ігнорується: репозиторій може відмовитися від автопідключення, але не ввімкнути його.
{
"remoteControlAtStartup": true
}Повністю вимикає Remote Control: Claude Code відмовляється від claude remote-control, прапорця --remote-control, автозапуску й перемикача в сесії. Типово false.
Ключ читається з будь-якого файла; щоб примусово заборонити Remote Control в організації, клади його в managed settings (наприклад, через MDM).
{
"disableRemoteControl": true
}Типове хмарне середовище для сесій, які ти створюєш з CLI, наприклад через claude --cloud. Значення виду env_… або ccpool_…. Ключ пише команда /remote-env.
Без ключа береться середовище, яке хостить Anthropic (якщо воно є у твоєму списку), інакше перше середовище, що не є bridge-середовищем Remote Control. Прапорець --environment перекриває ключ для однієї сесії. ID self-hosted середовищ (ccpool_…) приймаються лише з user, managed або --settings.
{
"remote": {
"defaultEnvironmentId": "env_0123abcd"
}
}Забороняє Claude Code реєструвати в операційній системі обробник протоколу claude-cli://. Єдине значення — "disable".
Після цього посилання claude-cli:// не відкриватимуть Claude Code.
{
"disableDeepLinkRegistration": "disable"
}Artifact
Керує інструментом Artifact, що публікує вивід сесії як приватну веб-сторінку на claude.ai. Практично має сенс лише false: це вимикає інструмент. Потребує v2.1.196+.
false з будь-якого файла перемагає, і жодним іншим значенням його вже не ввімкнути. Для середовищ, де вивід сесії не можна публікувати назовні.
{
"enableArtifact": false
}Desktop-застосунок: SSH, браузер, симулятор
Додає SSH-підключення у випадаючий список середовищ Desktop. Кожен елемент: id, name, sshHost, необов’язково sshPort та sshIdentityFile.
Розробники одразу бачать dev-машини команди. Записи з managed доступні лише для читання.
{
"sshConfigs": [
{
"id": "dev-vm",
"name": "Dev VM (Django)",
"sshHost": "deploy@dev.example.com",
"sshPort": 22
}
]
}Обмежує хости, до яких Desktop може підключитися по SSH. Шаблони без урахування регістру: точне ім’я, * або на кшталт *.example.com (сам домен і всі піддомени). Порожній масив вимикає SSH-сесії. Читає лише Desktop-застосунок (Claude Desktop v2.26454.0+).
Без ключа дозволені будь-які хости.
{
"sshHostAllowlist": ["*.devboxes.example.com"]
}Вимикає Code-сесії, що виконуються на самому пристрої в Desktop. Для розгортань, де розробники мають працювати на віддалених машинах по SSH. Враховується лише JSON true. Claude Desktop v1.37937.0+.
Локальні сесії в Desktop недоступні; лишаються SSH і хмарні.
{
"disableDesktopLocalSessions": true
}Забороняє Claude використовувати свої інструменти, щоб читати чи керувати зовнішніми сторінками в панелі Browser Desktop-застосунку. Значення — "disabled" (також приймається "disable"). CLI ключ ігнорує.
Claude не читає зовнішні сторінки й не діє на них у панелі Browser.
{
"browserExternalPageTools": "disabled"
}Блокує інструменти Claude для панелі iOS Simulator у Desktop-застосунку. Враховується лише true.
Claude не отримує інструментів для керування iOS Simulator.
{
"disableMobileSimulatorTools": true
}Застарілі ключі
| Ключ | Стан | Що робити |
|---|---|---|
disableArtifact | застарілий, замінений на enableArtifact | true дорівнює enableArtifact: false, а false ігнорується. Використовуй enableArtifact: false |
Глобальний конфіг: ~/.claude.json
Ключі, які працюють лише в ~/.claude.json, а не в settings.json
Окрім settings.json, Claude Code веде файл ~/.claude.json. Він його пише сам: там лежать сесія входу, конфігурації MCP-серверів, стан по проєктах (наприклад, рішення про довіру до папки) і «глобальні» ключі, які змінює /config. Ключі нижче працюють лише в ~/.claude.json; в будь-якому з settings-файлів Claude Code їх ігнорує.
settings.json | ~/.claude.json | |
|---|---|---|
| Хто пише | ти (або команда через /config, /model тощо) | Claude Code; можна й вручну |
| Рівні | user, project, local, managed | один файл у домашній директорії |
| Що там | permissions, hooks, env, sandbox, модель, UI | вхід, MCP-сервери, довіра до проєктів, ключі нижче |
| У git | project / local можна комітити чи ігнорувати | ніколи не комітиться |
Якщо ~/.claude.json не парситься, Claude Code копіює зламаний файл у ~/.claude/backups/.claude.json.corrupted.<timestamp> і питає, вийти й виправити руками чи скинути конфіг. Перед кожним записом зберігаються резервні копії; відновити стан можна з однієї з п’яти останніх .claude.json.backup.<timestamp> у ~/.claude/backups/.
IDE
Автоматично підключається до запущеної IDE (VS Code чи JetBrains), коли ти стартуєш Claude Code із зовнішнього терміналу. Типово false.
У /config з’являється, лише якщо ти працюєш поза терміналом VS Code чи JetBrains. Змінна CLAUDE_CODE_AUTO_CONNECT_IDE має вищий пріоритет.
{
"autoConnectIde": true
}Автоматично встановлює розширення Claude Code для IDE, коли ти запускаєш його з терміналу VS Code. Типово true.
З false розширення не ставиться саме. Змінна оточення: CLAUDE_CODE_IDE_SKIP_AUTO_INSTALL.
{
"autoInstallIdeExtension": false
}Де показувати diff для змін від Edit або Write, коли підключено IDE VS Code чи JetBrains: у diff-в’ювері IDE ("auto", типово) чи в терміналі ("terminal").
З "terminal" схвалюєш правки, не переключаючись у IDE.
{
"diffTool": "terminal"
}Стартує кожну інтерактивну CLI-сесію з увімкненою інтеграцією з Chrome, без прапорця --chrome. Підтримка в розширенні VS Code з v2.1.287.
Без ключа інтеграція вимкнена, поки не передати --chrome.
{
"claudeInChromeDefaultEnabled": true
}Редагування й буфер обміну
Змушує /copy щоразу копіювати всю відповідь, без вибору блоку коду. Типово false.
Без ключа /copy показує вибір (відповідь чи окремий блок коду).
{
"copyFullResponse": true
}Копіює виділений мишею текст у буфер обміну одразу після виділення, у fullscreen-рендерінгу та agent view. Типово true.
З false копіювати треба вручну.
{
"copyOnSelect": false
}Коли Ctrl+G відкриває зовнішній редактор, буфер починається з попередньої відповіді Claude у вигляді рядків-коментарів із #. Типово false.
Зручно, коли пишеш довгу відповідь у $EDITOR і хочеш бачити, на що відповідаєш.
{
"externalEditorContext": true
}Agent view і pull request
Команда claude без аргументів відкриває agent view замість нової розмови. Типово false.
Підходить, якщо ти працюєш переважно з фоновими агентами. Про agent view — на сторінці агентів.
{
"defaultToAgentsView": true
}Стрілка ← на порожньому промпті переводить сесію у фон і відкриває agent view. Типово true.
З false комбінація вимкнена: корисно, якщо випадково тиснеш ← у порожньому полі.
{
"leftArrowOpensAgents": false
}Видалені ключі
| Ключ | Видалено | Примітка |
|---|---|---|
permissionExplainerEnabled | v2.1.257 | Разом із поясненням команди по Ctrl+E на shell-запитах дозволу. Ефекту немає |
teammateDefaultModel | v2.1.234 | Ефекту немає. Як Claude Code обирає модель teammate, див. розділ про agent teams |
Приклад фрагмента ~/.claude.json (решта файла — вхід, MCP, проєкти — лишається як є):
{
"autoConnectIde": true,
"diffTool": "terminal",
"copyOnSelect": false,
"prStatusFooterEnabled": true
}{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
// схема може відставати від найновіших ключів CLI
// Модель і рівень thinking
"model": "sonnet",
"availableModels": ["sonnet", "opus", "haiku"],
"effortLevel": "high",
"maxEffortLevel": "xhigh",
"fallbackModel": ["claude-haiku-5-5"],
"fastModePerSessionOptIn": true,
// Мова відповідей
"language": "ukrainian",
// Дозволи
"permissions": {
"defaultMode": "default",
"disableBypassPermissionsMode": "disable",
"allow": [
"Bash(git status)", "Bash(git diff *)", "Bash(git log *)",
"Bash(git add *)",
"Bash(python manage.py showmigrations)",
"Bash(npm run lint)", "Bash(npm run test:unit)",
"Bash(docker compose ps)", "Bash(docker compose logs *)"
],
"ask": [
"Bash(git commit *)", "Bash(git push *)",
"Bash(python manage.py migrate)",
"Bash(docker compose up *)", "Bash(docker compose down *)"
],
"deny": [
"Read(**/.env)", "Read(**/.env.*)",
"Read(~/.ssh/**)", "Read(~/.aws/**)",
"Bash(sudo *)", "Bash(su *)",
"Bash(rm -rf /)", "Bash(dd *)"
]
},
// Змінні середовища
"env": {
"DISABLE_TELEMETRY": "1",
"BASH_DEFAULT_TIMEOUT_MS": "300000"
},
// Хуки
"hooks": {
"PostToolUse": [{
"matcher": "Edit|Write",
"hooks": [{ "type": "command", "command": "~/.claude/format.sh", "async": true }]
}],
"TaskCompleted": [{
"hooks": [{ "type": "command", "command": "cd "$CLAUDE_PROJECT_DIR" && python manage.py test --failfast 1>&2 || exit 2", "timeout": 120 }]
}],
"Stop": [{
"hooks": [{ "type": "command", "command": "python3 ~/.claude/notify-telegram.py", "async": true }]
}]
},
// Enterprise
"forceLoginMethod": "console",
"autoUpdatesChannel": "stable",
"requiredMinimumVersion": "2.1.280",
"cleanupPeriodDays": 14,
"allowManagedPermissionRulesOnly": true,
"allowManagedHooksOnly": true,
"companyAnnouncements": ["🔒 Секрети — тільки у Vault, не в .env!"],
// Git
"attribution": { "commit": "", "pr": "" },
"includeGitInstructions": false
}