Поля hooks, которые переписывают команды на лету, постоянная память агентов, правила auto-mode на обычном английском, фоновые циклы самообучения — и готовые примеры.
Внутри Claude Code система разрешений для auto-mode называется «YOLO Classifier». Именно так и называется переменная в yoloClassifier.ts. И настраивать её можно обычными английскими описаниями окружения — например, «это staging-сервер, разрушающие операции допустимы» — которые классификатор читает, чтобы решить, что можно автоматически одобрять. В документации этого нет.
Это лишь одна из десятков недокументированных возможностей, закопанных в исходниках Claude Code, которые лежат прямо у вас в node_modules как публично распространяемый npm-пакет. Официальная документация неплохо описывает базовые вещи. Но исходники раскрывают поля, форматы ответов и настройки, которые сильно расширяют то, что можно собрать. Всё, что описано ниже, работает прямо сейчас, и каждый пример можно вставлять в проект как есть.
Замечание про версии: всё это найдено в @anthropic-ai/claude-code@2.1.87. Недокументированные возможности могут меняться от релиза к релизу, так что воспринимайте материал как снимок того, что доступно сегодня. Поля со словом «EXPERIMENTAL» в имени сами инженеры Anthropic явно помечают как нестабильные — такие я буду отмечать отдельно.
Перед началом
Краткая шпаргалка, где что лежит:
- Настройки:
~/.claude/settings.json(личные) или.claude/settings.json(проектные, шарятся через git) - Skills:
~/.claude/skills/<name>/SKILL.md(личные) или.claude/skills/<name>/SKILL.md(проектные) - Агенты:
~/.claude/agents/<name>.md(личные) или.claude/agents/<name>.md(проектные) - Скрипты hooks:
~/.claude/hooks/— удобное соглашение. Не забудьте сделатьchmod +xсвоим скриптам.
Проектные файлы в .claude/ можно коммитить в git и делиться с командой. Личные файлы в ~/.claude/ — только ваши.
Hooks могут возвращать ответы, и никто не объяснил как
Это самый большой пробел в документации. В документации сказано, что hooks получают JSON на stdin и что код возврата 2 блокирует операцию. О чём не сказано: hooks могут возвращать JSON в stdout со специфичными для события полями, которые меняют поведение Claude Code в реальном времени. Исходники показывают, что именно принимает каждый тип события.
Hook PreToolUse может вернуть:
updatedInput— переписать вход инструмента до выполнения. Можно менять команды на лету.permissionDecision— принудительно «allow» или «deny» без запроса у пользователя.permissionDecisionReason— объяснение решения (показывается в UI).additionalContext— добавить текст в контекст беседы.
Hook SessionStart может вернуть:
watchPaths— настроить автоматическое слежение за файлами, которое триггерит события FileChanged.initialUserMessage— дописать содержимое в начало первого пользовательского сообщения в сессии.additionalContext— добавить контекст, который держится всю сессию.
Hook PostToolUse может вернуть:
updatedMCPToolOutput— изменить то, что Claude видит в ответе MCP-инструмента.additionalContext— добавить контекст после запуска инструмента.
Hook PermissionRequest может вернуть:
decision— программно разрешить или запретить сupdatedInputилиupdatedPermissions.
Это серьёзный инструмент. Вот hook PreToolUse, который автоматически добавляет --dry-run к любой команде git push до того, как Claude её выполнит.
В вашем settings.json:
{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "~/.claude/hooks/dry-run-pushes.sh"
}]
}]
}
}
И скрипт в ~/.claude/hooks/dry-run-pushes.sh:
#!/bin/bash
INPUT=$(jq -r '.tool_input.command' < /dev/stdin)
if echo "$INPUT" | grep -q 'git push'; then
jq -n --arg cmd "$INPUT --dry-run" '{"updatedInput": {"command": $cmd}}'
fi
Claude думает, что запускает git push origin main, а ваш hook тихо переписывает команду в git push origin main --dry-run до выполнения. Поля updatedInput нет ни в какой документации.
Вот hook SessionStart, который следит за конфигурационными файлами и добавляет git-контекст в каждую сессию.
settings.json:
{
"hooks": {
"SessionStart": [{
"hooks": [{
"type": "command",
"command": "~/.claude/hooks/session-context.sh",
"statusMessage": "Loading project context..."
}]
}]
}
}
~/.claude/hooks/session-context.sh:
#!/bin/bash
BRANCH=$(git branch --show-current 2>/dev/null)
CHANGES=$(git status --porcelain 2>/dev/null | wc -l | tr -d ' ')
jq -n \
--arg branch "$BRANCH" \
--arg changes "$CHANGES" \
'{
"watchPaths": ["package.json", ".env", "tsconfig.json"],
"additionalContext": "Current branch: \($branch). Uncommitted changes: \($changes) files."
}'
Теперь Claude Code автоматически следит за package.json, .env и tsconfig, и заранее знает, на какой вы ветке и сколько у вас незакоммиченных файлов — ещё до того, как вы хоть что-то напечатаете.
А вот этот hook автоматически одобряет read-only команды bash без запроса.
settings.json:
{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "~/.claude/hooks/auto-approve-readonly.sh"
}]
}]
}
}
~/.claude/hooks/auto-approve-readonly.sh:
#!/bin/bash
CMD=$(jq -r '.tool_input.command' < /dev/stdin)
if echo "$CMD" | grep -qE '^(ls|cat|echo|pwd|whoami|date|git status|git log|git diff)'; then
echo '{"permissionDecision": "allow", "permissionDecisionReason": "Safe read-only command"}'
fi
По сути, вы собираете собственный классификатор разрешений из shell-скриптов. Поля permissionDecision нет ни в какой документации.
Три поля hook, о которых документация умолчала
Документированные поля hook — это type, command, matcher, timeout, if и statusMessage. Парсер в исходниках принимает ещё три, и они принципиально меняют поведение hooks.
once: true запускает hook ровно один раз, потом удаляет его автоматически. Идеально для разовой настройки в первой сессии:
{
"hooks": {
"SessionStart": [{
"hooks": [{
"type": "command",
"command": "[ -f .env ] || cp .env.example .env && echo 'Created .env from template'",
"once": true,
"statusMessage": "First-time setup..."
}]
}]
}
}
Достаточно простой, чтобы написать прямо инлайном. Проверяет, есть ли .env, копирует шаблон, если нет, и больше никогда не запускается.
async: true запускает hook в фоне, не блокируя Claude. Fire and forget:
{
"hooks": {
"PostToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "jq '{timestamp: now, command: .tool_input.command, session: .session_id}' < /dev/stdin >> ~/.claude/audit.jsonl",
"async": true
}]
}]
}
}
Это пишет каждую bash-команду в аудит-файл, не добавляя задержки в сессию.
asyncRewake: true — самое необычное поле. Hook работает в фоне как async и не блокирует обычный сценарий. Но если он завершается с кодом 2, управление возвращается к модели, а операция блокируется. Не мешает, когда всё хорошо, и останавливает выполнение, когда что-то не так:
settings.json:
{
"hooks": {
"PostToolUse": [{
"matcher": "Write|Edit",
"hooks": [{
"type": "command",
"command": "~/.claude/hooks/scan-secrets.sh",
"asyncRewake": true,
"statusMessage": "Scanning for secrets..."
}]
}]
}
}
~/.claude/hooks/scan-secrets.sh:
#!/bin/bash
FILE=$(jq -r '.tool_input.file_path // .tool_response.filePath' < /dev/stdin)
if grep -qE '(password|secret|api_key)\s*=' "$FILE" 2>/dev/null; then
exit 2 # Block: secrets detected
fi
exit 0 # Clean: carry on
Этот скрипт сканирует каждый файл, который пишет Claude, на захардкоженные секреты. Если находит — блокирует и сообщает Claude. Если нет — вы даже не заметите, что он работал.
Поля frontmatter в skills, которых нет в документации
Документация описывает name, description, allowed-tools, argument-hint, when_to_use и context. Реальный парсер frontmatter в исходниках принимает ещё шесть.
model позволяет переопределить, какая модель запускает skill. Используйте haiku для дешёвых быстрых задач и opus для сложного анализа:
---
name: quick-lint
description: Fast lint check using the cheapest model
model: haiku
effort: low
allowed-tools: Bash, Read
argument-hint: "[file]"
---
Run the project linter on: $ARGUMENTS
Detect the linter from config (eslint, ruff, clippy) and run it. Report only errors, not warnings.
Это запускается на Haiku с низким effort — быстро и дёшево. Для глубокого ревью архитектуры лучше взять model: opus и effort: max.
effort управляет тем, насколько глубоко модель думает. low, medium, high или max. Это та же самая система effort, которая внутри управляет глубиной рассуждений на ответ.
hooks задаёт hooks, ограниченные временем работы skill. Они регистрируются, когда skill запускается, и снимаются с регистрации, когда он завершается:
---
name: strict-typescript
description: Write TypeScript with type checking on every save
allowed-tools: Bash, Read, Write, Edit, Grep, Glob
hooks:
PostToolUse:
- matcher: "Write|Edit"
hooks:
- type: command
command: "~/.claude/hooks/typecheck-on-save.sh"
statusMessage: "Type checking..."
- type: command
command: "~/.claude/hooks/lint-on-save.sh"
async: true
---
Write TypeScript with strict enforcement. Every file you touch gets type-checked and linted automatically.
$ARGUMENTS
~/.claude/hooks/typecheck-on-save.sh:
#!/bin/bash
FILE=$(jq -r '.tool_input.file_path // .tool_response.filePath' < /dev/stdin)
[[ "$FILE" == *.ts ]] && npx tsc --noEmit 2>&1 || true
~/.claude/hooks/lint-on-save.sh:
#!/bin/bash
FILE=$(jq -r '.tool_input.file_path // .tool_response.filePath' < /dev/stdin)
[[ "$FILE" == *.ts ]] && npx eslint --fix "$FILE" 2>&1 || true
Пока этот skill работает, каждый файл TypeScript, который пишет Claude, синхронно проходит type-check и линтуется в фоне. Когда skill завершается, эти hooks исчезают. Изоляция аккуратная.
agent делегирует skill пользовательскому агенту:
---
name: deep-review
description: Thorough security review delegated to the review agent
agent: security-review
---
Review the following: $ARGUMENTS
disable-model-invocation: true запрещает автоматический вызов. Работает только явный /skill-name. Полезно для разрушительных skills, которые не должны запускаться случайно.
shell: bash указывает, какую оболочку использовать для выполнения.
Поля агентов, которых вы не найдёте ни в какой документации
Пользовательские агенты в .claude/agents/ поддерживают поля frontmatter, не упомянутые в документации.
color задаёт цвет в UI: red, orange, yellow, green, blue, purple, pink или gray. Помогает визуально различать агентов, когда их запущено несколько.
memory — самое важное поле. Оно даёт агенту постоянную память между вызовами:
user— глобально, сохраняется во всех проектахproject— на проектlocal— приватно в рамках проекта (в gitignore)
Это значит, можно построить агента, который учится. Security-ревьюер, который отслеживает прошлые находки. Code-ревьюер, который запоминает ваши паттерны между сессиями. Память хранится в том же формате frontmatter, что и система auto-memory.
---
name: codebase-guide
description: Answer questions about the codebase, learning more with each session
tools: [Read, Grep, Glob, Bash]
color: green
memory: project
---
You are a codebase guide with persistent memory. Check your memory first before exploring the code.
After answering a question, save useful context to memory:
- Architecture decisions (type: project)
- Code locations for common tasks (type: reference)
- Patterns and conventions (type: feedback)
Over time, you should answer faster because you remember where things are.
Через несколько сессий такой агент накапливает базу знаний о вашем коде и начинает отвечать из памяти ещё до того, как пойдёт грепать.
omitClaudeMd: true пропускает загрузку иерархии инструкций CLAUDE.md. Полезно для ревьюера со «свежим взглядом», который опирается на индустриальные стандарты, а не на конвенции вашего проекта:
---
name: fresh-eyes
description: Review code without project-specific biases
tools: [Read, Grep, Glob]
omitClaudeMd: true
effort: high
color: blue
---
Review this code purely from first principles. You have no project context. Focus on correctness, security, performance, and readability by industry standards.
criticalSystemReminder_EXPERIMENTAL — короткое сообщение, которое заново добавляется как системное напоминание на каждом шаге. Оно остаётся в контексте даже после сжатия истории:
---
name: prod-deployer
description: Manages production deployments with strict safety checks
tools: [Bash, Read, Grep]
color: red
criticalSystemReminder_EXPERIMENTAL: "Always run migrations with --dry-run first. Never skip the staging verification step."
---
Предупреждение: в самом имени поля в исходниках стоит EXPERIMENTAL. Инженеры Anthropic считают его нестабильным. Прямо сейчас оно работает, но в любом релизе может быть удалено или переименовано. Используйте для приятных, но необязательных напоминаний о безопасности и не стройте на нём критическую инфраструктуру.
requiredMcpServers перечисляет шаблоны имён MCP-серверов, которые должны быть настроены. Если серверов нет — агент не появится. Это не даёт агентам грузиться, когда их зависимости не настроены.
Классификатор auto-mode понимает обычный английский
Поле autoMode в settings.json настраивает то, что внутри Anthropic называют «YOLO Classifier». Оно управляет тем, что одобряется автоматически в auto mode:
{
"autoMode": {
"allow": [
"Bash(npm test)",
"Bash(npm run *)",
"Bash(git status)",
"Bash(git diff *)",
"Bash(git log *)",
"Read",
"Grep",
"Glob"
],
"soft_deny": [
"Bash(git push *)",
"Bash(rm *)",
"Write(.env*)"
],
"environment": [
"NODE_ENV=development",
"This is a local dev machine with no production database access",
"All Docker containers use isolated networks",
"The test suite is safe to run repeatedly, it uses a dedicated test database"
]
}
}
Шаблоны из allow одобряются автоматически. Шаблоны из soft_deny всегда требуют подтверждения. Самое интересное — массив environment: это вообще не шаблоны. Это обычные английские строки контекста, которые классификатор читает, чтобы понять ваше окружение. Можно написать «This project uses Docker, all commands run in containers», и классификатор учтёт это при решениях о безопасности для неоднозначных команд.
Это можно представить как брифинг для классификатора о вашем окружении. Чем конкретнее, тем лучше его решения. «No production access» говорит ему меньше параноить по поводу разрушающих операций. «Test database is isolated» говорит, что прогонять тесты всегда безопасно.
Флаги обучающего цикла, которые никто не описал
Два поля в settings.json активируют систему самообучения Claude Code:
{
"autoMemoryEnabled": true,
"autoDreamEnabled": true
}
autoMemoryEnabled заставляет Claude Code автоматически извлекать долговременные записи памяти из ваших сессий. После каждой беседы фоновый агент вытаскивает то, что стоит запомнить — ваши предпочтения, паттерны кодовой базы, принятые решения — и пишет их в ~/.claude/projects/<path>/memory/ в стандартном формате frontmatter для памяти.
autoDreamEnabled включает фоновую консолидацию памяти. Раз в 24 часа, если накопилось 5 и более сессий, фоновый агент просматривает прошлые транскрипты сессий и объединяет записи памяти. Он сливает дубликаты, разрешает противоречия, конвертирует относительные даты в абсолютные и удаляет устаревшие записи.
Вместе они образуют составной обучающий цикл: после сессий появляются записи памяти, фоновая консолидация приводит их в порядок, а результат помогает будущим сессиям. Включите оба, и через несколько недель вы заметите, что Claude Code запоминает ваши предпочтения, конвенции и привычные паттерны без явных указаний. Это настоящее обучение на опыте без какого-либо дообучения модели.
Magic Docs: точный формат
Исходники открывают регулярку: /^#\s*MAGIC\s+DOC:\s*(.+)$/im. Это должен быть заголовок H1, регистр не важен, а следующая строка может содержать инструкции курсивом (в _подчёркиваниях_ или *звёздочках*), которые ограничивают, на чём концентрируется агент обновления:
# MAGIC DOC: API Endpoint Reference
_Only document public REST endpoints. Include method, path, request body, response schema, and auth requirements._
## Endpoints
(content auto-maintained by Claude Code)
Без строки с инструкцией агент попробует обновлять всё подряд. С ней — вы говорите «отслеживай только публичные эндпоинты» или «фокусируйся на breaking changes», и он следует этим указаниям. Агент обновления работает в фоне и может редактировать только этот конкретный файл. Если удалить заголовок — отслеживание автоматически прекращается.
Полный синтаксис правил разрешений
Документация показывает базовые примеры вроде Bash(git *). Исходники раскрывают полный язык шаблонов:
Bash(npm *) # wildcard after "npm "
Bash(git commit *) # specific subcommand
Read(*.ts) # file extension
Read(src/**/*.ts) # recursive directory with extension
Write(src/**) # recursive, all files
mcp__slack # all tools on slack server
mcp__slack__* # explicit wildcard (same effect)
mcp__slack__post_message # specific tool
Bash(npm:*) # legacy colon prefix (word boundary)
* совпадает в пределах границ, как shell globbing. ** рекурсивно проходит по директориям. Разрешения для MCP-инструментов используют двойные подчёркивания: mcp__<server>__<tool>. Поле if в hooks использует ровно тот же синтаксис. Никаких регулярок — только globs.
{
"permissions": {
"allow": [
"Bash(npm *)", "Bash(git status)", "Bash(git diff *)",
"Read(src/**)", "Read(tests/**)", "Grep", "Glob",
"mcp__database__query"
],
"deny": [
"Bash(rm -rf *)", "Write(/etc/**)", "Write(.env*)",
"mcp__slack__delete_*"
],
"ask": [
"Bash(git push *)", "Write(*.json)", "Write(*.lock)",
"mcp__slack__post_message"
]
}
}
context: fork и почему выбор модели важен
Когда вы задаёте context: fork у skill, он запускается как фоновый форк-субагент. Исходники показывают, что форки разделяют prompt cache родителя через типизированный контракт под названием CacheSafeParams. Все форки производят побайтово идентичные префиксы API-запросов, чтобы максимизировать попадания в кэш.
Практическое следствие: если задать другую модель у форкнутого skill, кэш ломается. Родительская беседа на Opus, форк на Haiku — префиксы расходятся, промах кэша, вы платите полную цену. Либо не указывайте поле model, либо ставьте model: inherit у форкнутых skills, чтобы кэш продолжал работать.
Используйте context: fork для тяжёлой работы: сканов безопасности, анализа зависимостей, генерации документации, прогонов тестов. Форк работает в фоне и уведомляет вас, когда закончит, оставляя основную беседу отзывчивой.
---
name: full-audit
description: Comprehensive codebase audit running in the background
context: fork
allowed-tools: Bash, Read, Grep, Glob, WebSearch
effort: high
---
Run a comprehensive audit:
- Security scan (grep for dangerous patterns, check dependencies for CVEs)
- Code quality (duplicated logic, dead code, missing error handling)
- Test coverage (untested critical paths)
- Dependency health (outdated packages, unused deps, license issues)
Write a detailed report to /tmp/audit-report.md when complete.
Собираем всё вместе
Самообучающийся code-ревьюер с постоянной памятью и hooks с ограниченной областью действия:
.claude/agents/reviewer.md:
---
name: reviewer
description: Code reviewer that learns your codebase patterns over time
tools: [Read, Grep, Glob, Bash]
effort: high
color: yellow
memory: project
hooks:
PostToolUse:
- matcher: "Bash"
hooks:
- type: command
command: "~/.claude/hooks/log-review.sh"
async: true
---
Before reviewing, read your memory for past findings on this codebase.
Review git diff HEAD~1 for:
- Patterns you've flagged before (check memory)
- New issues worth flagging
- Resolved issues from past reviews
After review, save to memory:
- New patterns found (type: feedback)
- Recurring issues (type: project)
End with VERDICT: PASS, FAIL, or NEEDS_REVIEW.
Этот агент помнит, что нашёл в прошлый раз. Он знает, какие паттерны повторяются. После нескольких ревью он начинает ловить специфичные для проекта проблемы, которые обычный ревьюер бы пропустил.
Hook SessionStart со слежением за файлами плюс защитная сетка через asyncRewake:
settings.json:
{
"hooks": {
"SessionStart": [{
"hooks": [{
"type": "command",
"command": "~/.claude/hooks/session-context.sh",
"statusMessage": "Loading project context..."
}]
}],
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "~/.claude/hooks/auto-approve-readonly.sh"
}, {
"type": "command",
"command": "~/.claude/hooks/block-dangerous.sh",
"asyncRewake": true,
"statusMessage": "Safety check..."
}]
}]
}
}
~/.claude/hooks/block-dangerous.sh:
#!/bin/bash
CMD=$(jq -r '.tool_input.command' < /dev/stdin)
echo "$CMD" | grep -qE '(rm -rf /|sudo rm|chmod 777|> /dev/)' && exit 2 || exit 0
Команды только для чтения одобряются мгновенно. Опасные блокируются. Всё, что между ними, идёт по обычному потоку разрешений. Сканер безопасности работает async и не тормозит обычный сценарий.
Skill с переопределением модели, контролем effort и делегированием агенту:
---
name: architecture-review
description: Deep architecture review using max effort, delegated to fresh-eyes agent
agent: fresh-eyes
effort: max
---
Review the architecture of this project. Ignore existing conventions (the agent has omitClaudeMd: true).
Focus on: $ARGUMENTS
Evaluate structural decisions, dependency graph health, separation of concerns, and scalability characteristics.
Здесь сцеплены три недокументированные возможности: effort: max для глубокого размышления, делегирование конкретному агенту и сам этот агент с omitClaudeMd: true для непредвзятого анализа.
Эти недокументированные возможности показывают разрыв между сегодняшним Claude Code и тем, во что Anthropic его развивает. Система hooks с полями ответа на конкретные события — это программируемый слой middleware для использования инструментов ИИ, более гибкий, чем большинство CI/CD-пайплайнов. Постоянная память агентов создаёт ИИ-специалистов, которые накапливают настоящую экспертизу между сессиями. Фоновая консолидация памяти даёт обучение на опыте без дообучения модели. Классификатор auto-mode принимает описания вашего окружения на естественном языке, чтобы принимать решения о безопасности.
Это не скрытые настройки и не пасхалки. Это каркас для постоянных, обучающихся, автономных сред разработки на ИИ, и он уже работает в npm-пакете на вашей машине. Документация, скорее всего, рано или поздно догонит, но если хочется строить на переднем крае того, что Claude Code реально умеет — настоящая документация лежит в исходниках.