Я залез в исходники Claude Code. Фичи, которых нет в документации. ai.. ai. ai-агенты.. ai. ai-агенты. Claude.. ai. ai-агенты. Claude. claude code.. ai. ai-агенты. Claude. claude code. Claude Code skills.. ai. ai-агенты. Claude. claude code. Claude Code skills. claude opus.. ai. ai-агенты. Claude. claude code. Claude Code skills. claude opus. machine learning.. ai. ai-агенты. Claude. claude code. Claude Code skills. claude opus. machine learning. machinelearning.
Я залез в исходники Claude Code. Фичи, которых нет в документации - 1
Комментарий от эксперта Александра Шустанова

Очень интересный разбор внутреннего устройства Claude Code. Но очень важно понимать, что завязываться на недокументированную функциональность в рабочих пайплайнах может быть небезопасным. Сегодня фича работает, а завтра уже нет. Конечно, с клодом от такого не застрахован никто, ведь продукт, по заявлению Anthropic, разрабатывается самим Claude Code.

Поля hooks, переписывающие команды на лету, постоянная память агентов, правила авто-режима на обычном английском, самоулучшающиеся циклы «снов» — и каждый пример готов к копированию.

Система разрешений авто-режима Claude Code внутри называется «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)

  • Скиллы: ~/.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 в реальном времени. Исходный код раскрывает, что именно принимает каждый тип события.

Hooks PreToolUse могут возвращать:

  • updatedInput — переписать входные данные инструмента до его выполнения. Можно менять команды на лету.

  • permissionDecision — принудительно выставить «allow» или «deny» без запроса пользователю.

  • permissionDecisionReason — пояснить решение (показывается в UI).

  • additionalContext — вставить текст в контекст разговора.

Hooks SessionStart могут возвращать:

  • watchPaths — настроить автоматическое отслеживание файлов, которое триггерит события FileChanged.

  • initialUserMessage — добавить содержимое в начало первого сообщения пользователя в сессии.

  • additionalContext — вставить контекст, который держится всю сессию.

Hooks PostToolUse могут возвращать:

  • updatedMCPToolOutput — изменить то, что Claude видит из ответа MCP-инструмента.

  • additionalContext — вставить контекст после выполнения инструмента.

Hooks 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 на предмет изменений и знает, на какой вы ветке и сколько у вас незакоммиченных файлов, ещё до того, как вы что-либо напечатаете.

А вот тот, что автоматически одобряет 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 нет ни в какой документации.

Три поля hooks, о которых документация забыла упомянуть

Задокументированные поля hooks — это 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..."
      }]
    }]
  }
}

Достаточно просто, чтобы написать inline. Проверяет, существует ли .env, копирует шаблон, если нет, и больше никогда не запускается.

async: true запускает hook в фоне, не блокируя Claude. Запустил и забыл:

{
  "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 — самое хитрое. Он работает в фоне как 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  # Блокируем: найдены секреты
fi
exit 0    # Чисто: продолжаем

Это сканирует каждый файл, который пишет Claude, на захардкоженные секреты. Если находит — блокирует и сообщает Claude. Если нет — вы даже не заметите, что он запускался.

Поля frontmatter скиллов, которых нет в документации

Документация описывает name, description, allowed-tools, argument-hint, when_to_use и context. Реальный парсер frontmatter в исходном коде принимает ещё шесть.

model позволяет переопределить, какая модель выполняет скилл. Используйте 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, привязанные к периоду, пока скилл активен. Они регистрируются, когда скилл срабатывает, и снимаются с регистрации, когда он завершается:

---
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

Пока этот скилл работает, каждый TypeScript-файл, который пишет Claude, синхронно проверяется типами и линтится в фоне. Когда скилл завершается, эти hooks исчезают. Скоупинг чистый.

agent делегирует скилл кастомному агенту:

---
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. Используйте это для деструктивных скиллов, которые не должны срабатывать случайно.

shell: bash указывает, какой shell использовать для выполнения.

Поля агентов, которых вы не найдёте ни в какой документации

Кастомные агенты в .claude/agents/ поддерживают поля frontmatter, не упомянутые в документации.

color задаёт цвет в UI: red, orange, yellow, green, blue, purple, pink или gray. Помогает визуально различать агентов, когда их запущено несколько.

memory — самое важное. Оно даёт агенту постоянную память между вызовами:

  • user — глобальная, держится во всех проектах

  • project — персистентность на уровне проекта

  • local — приватная на уровне проекта (в gitignore)

Это значит, что можно построить агента, который учится. Ревьюера безопасности, который отслеживает прошлые находки. Код-ревьюера, который запоминает ваши паттерны между сессиями. Память использует тот же формат frontmatter, что и система авто-памяти.

---
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.

Через несколько сессий этот агент строит базу знаний о вашей кодовой базе и начинает отвечать из памяти ещё до того, как лезть в grep.

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 — короткое сообщение, которое переинъецируется на каждом ходу как системное напоминание. Даже после сжатия контекста (compaction) оно остаётся в контексте:

---
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-серверов, которые должны быть настроены. Если серверы недоступны, агент не появится. Не даёт агентам загружаться, когда их зависимости не настроены.

Классификатор авто-режима принимает обычный английский

Поле autoMode в settings.json настраивает то, что Anthropic внутри называет «YOLO Classifier». Оно управляет тем, что автоматически одобряется в авто-режиме:

{
  "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*MAGICs+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)

Без строки с инструкциями агент пытается обновлять всё. С ней вы говорите ему «отслеживай только публичные эндпоинты» или «фокусируйся на ломающих изменениях», и он это уважает. Агент обновления работает в фоне и ограничен правкой только этого конкретного файла. Удаление заголовка автоматически прекращает отслеживание.

Полный синтаксис правил разрешений

Документация показывает базовые примеры вроде Bash(git *). Исходный код раскрывает полный язык шаблонов:

Bash(npm )              # wildcard после "npm "
Bash(git commit )       # конкретная подкоманда
Read(*.ts)               # расширение файла
Read(src/**/*.ts)        # рекурсивно по директории с расширением
Write(src/**)            # рекурсивно, все файлы
mcp__slack               # все инструменты на сервере slack
mcp__slack__*            # явный wildcard (тот же эффект)
mcp__slack__post_message # конкретный инструмент
Bash(npm:*)              # legacy-префикс с двоеточием (граница слова)

* совпадает в пределах границ, как 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 на скилл, он запускается как фоновый форк-субагент. Исходный код раскрывает, что форки разделяют кэш промптов родителя через типизированный контракт под названием CacheSafeParams. Все форки производят байт-в-байт идентичные префиксы API-запросов, чтобы максимизировать попадания в кэш.

Практическое следствие: если вы поставите другую модель на форк-скилл, вы сломаете кэш. Родительский разговор на Opus, форк на Haiku — префиксы расходятся, промах кэша, вы платите полную цену. Либо опускайте поле model, либо используйте model: inherit на форк-скиллах, чтобы кэш продолжал работать.

Используйте 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.

Собираем всё вместе

Самоулучшающийся код-ревьюер с постоянной памятью и привязанными 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

Read-only команды одобряются мгновенно. Опасные команды блокируются. Всё, что между, проходит через обычный поток разрешений. Сканер безопасности работает асинхронно, поэтому ничего не тормозит на «счастливом пути».

Скилл с переопределением модели, управлением 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) для использования AI-инструментов, более гибкий, чем большинство CI/CD-пайплайнов.

Постоянная память агентов создаёт AI-специалистов, которые накапливают настоящую экспертизу между сессиями. Система консолидации «снов» — это обучение на опыте без переобучения модели. Классификатор авто-режима принимает описания вашего окружения на естественном языке, чтобы принимать решения о безопасности.

Это не скрытые настройки и не пасхалки. Это каркас для постоянных, обучающихся, автономных сред AI-разработки, и они уже работают в npm-пакете на вашей машине. Документация, вероятно, со временем догонит, но если вы хотите строить на самом острие того, что Claude Code реально умеет, настоящая документация живёт в исходном коде.

Я залез в исходники Claude Code. Фичи, которых нет в документации - 2

Присоединяйтесь к русскоязычному сообществу разработчиков на Spring Boot в телеграм — Spring АйО, чтобы быть в курсе последних новостей из мира разработки на Spring Boot и всего, что с ним связано.

Автор: spring_aio

Источник