Практическое пособие для разработчиков по AI-ассистированной разработке с интеграцией MCP и автоматизированными хуками
Каждый январь нагрузка на инженерные команды растёт. Больше функций, ускоренные релизные циклы, повышенные требования к надёжности. Ваше новогоднее обещание наверняка звучало как «работать умнее, а не усерднее», но обычно это лишь утешительное клише, которое мы повторяем себе прямо перед тем, как снова засидеться допоздна, чиня сломанный пайплайн.
В 2026 году «работать умнее» наконец-то означает подключить агента к процессу.
Не для автодополнения. Не для подсказок. Для исполнения.
Вы описываете, что вам нужно, простым языком. Claude Code читает вашу кодовую базу, пишет продакшн-код, запускает тесты и интегрируется с вашими инструментами. Вы тратите меньше времени на шаблонный код и больше - на архитектурные решения.
Это руководство покажет вам, как строить реальные системы с Claude Code:
Конвейеры данных, которые обрабатывают CSV-файлы, очищают грязные данные и загружают в PostgreSQL
Браузерное тестирование, которое автоматизирует E2E-сценарии с Playwright
Хуки безопасности, которые автоматически предотвращают утечку учётных данных
Контроль качества, который обнаруживает дублирование кода до того, как оно попадёт в продакшн
Давайте сделаем этот год тем самым, когда вы наконец-то разгребёте свой Jira-бэклог к пятнице.
Claude Code - терминальный AI-агент для кодинга от Anthropic на базе Claude Sonnet 4.5/Opus 4.5
Создавайте готовые к продакшну конвейеры данных с pandas, валидацией и загрузкой в PostgreSQL
Автоматизируйте браузерное тестирование с Playwright MCP (больше никаких ручных прокликиваний тестовых сценариев)
Внедряйте политики безопасности с пре-хуками (блокировка доступа к чувствительным файлам, опасным командам)
Поддерживайте качество кода с пост-хуками (обнаружение дубликатов, соблюдение стандартов)
Примеры на Python с продакшн-паттернами на протяжении всего руководства
Полный GitHub-репозиторий с рабочим кодом для каждого раздела
Claude Code - это не Claude в окне чата. Это агентный инструмент для кодинга, который живёт в вашем терминале, видит всю вашу кодовую базу и выполняет реальные рабочие процессы разработки.
Что он делает:
Читает и записывает файлы по всему проекту
Выполняет bash-команды (тесты, git-операции, деплои)
Понимает контекст проекта через файлы документации CLAUDE.md
Интегрируется с внешними инструментами через Model Context Protocol (MCP)
Автоматизирует рабочие процессы с хуками, которые срабатывают при выполнении инструментов
Что делает его уникальным:
1. Осведомлённость о контексте Claude Code загружает ваши файлы CLAUDE.md (стандарты кодирования, архитектурную документацию, командные соглашения) в своё контекстное окно. Когда вы начинаете сессию, он уже знает ваш технологический стек, соглашения об именовании и структуру проекта.
2. Файловые операции в масштабе В отличие от инструментов автодополнения, которые работают построчно, Claude Code может рефакторить целые модули, генерировать многофайловые фичи и поддерживать согласованность по всей кодовой базе.
3. Исполнение, а не просто генерация Claude Code запускает тесты, выполняет git-команды, устанавливает зависимости и проверяет собственную работу. Он не просто предлагает - он делает.
4. Расширяемость через MCP Подключайте Claude к внешним инструментам: автоматизация браузера с Playwright, операции GitHub, запросы к базам данных - всё, что имеет MCP-сервер.
5. Детерминированные рабочие процессы с хуками Хуки позволяют внедрять пользовательскую логику до/после выполнения инструментов: проверки безопасности, форматирование кода, обнаружение дубликатов, автоматическое тестирование.
Предварительные требования:
Python 3.10+ установлен
Node.js 18+ (для некоторых MCP-серверов)
API-ключ Anthropic или подписка Claude Pro/Max
Установка Claude Code:
# macOS/Linux curl -fsSL https://claude.ai/install.sh | bash # Или через Homebrew brew install --cask claude-code # Или через npm npm install -g @anthropic-ai/claude-code
Аутентификация:
# Вариант 1: API-ключ (для пользователей API) export ANTHROPIC_API_KEY=your-key-here # Вариант 2: Браузерная авторизация (для пользователей Pro/Max) # Просто запустите `claude` и следуйте подсказке в браузере
Ваше первое взаимодействие:
cd your-project claude # Claude Code запускается в интерактивном режиме # Попробуйте это: "Проанализируй структуру проекта и объясни основные компоненты"
Claude прочитает вашу директорию, определит ключевые файлы и предоставит архитектурный обзор. Никакой настройки не требуется.
Ключевые команды:
# Запуск интерактивной сессии claude # Однократная команда (headless-режим) claude -p "Сгенерируй юнит-тесты для utils.py" # Возобновить предыдущую сессию claude --resume # Очистить контекст и начать заново /clear # Показать доступные MCP-серверы claude mcp list # Показать разрешения /permissions
Понимание контекста:
Claude Code имеет контекстное окно ~200K токенов. Когда вы начинаете сессию:
Загружаются файлы .claude/CLAUDE.md (документация проекта)
Читаются файлы, на которые вы ссылаетесь или которые ему нужны
Сохраняется история разговора
Запоминаются выводы инструментов (результаты тестов, чтения файлов, bash-команды)
Когда контекст заполняется, Claude автоматически сжимает разговор, чтобы продолжать работу. Для больших проектов используйте /clear между фичами, чтобы сохранять фокус.
При работе с Claude над сложными задачами вам часто придётся направлять разговор, чтобы сохранять фокус и продуктивность. Claude Code предоставляет несколько техник для управления потоком и концентрации на том, что важно.
Иногда Claude начинает двигаться в неверном направлении или пытается охватить слишком много сразу. Вы можете нажать клавишу Escape, чтобы остановить Claude посреди ответа, позволяя перенаправить разговор.
Это особенно полезно, когда вы хотите, чтобы Claude сфокусировался на одной конкретной задаче, вместо того чтобы пытаться справиться с несколькими одновременно.
Вы: "Напиши тесты для validate_email(), validate_phone() и validate_address()" Claude: "Я создам комплексный набор тестов, охватывающий все три валидатора. Сначала позвольте мне проанализировать логику валидации для каждой функции... [Вы видите, что Claude начинает писать огромный тестовый файл] [Нажмите Escape] Вы: "На самом деле, давай начнём только с validate_email(). Напиши полные тесты для этой одной функции, потом перейдём к остальным." Claude: "Хороший подход. Я сфокусируюсь на тестах validate_email()..."
Когда использовать Escape:
Claude генерирует слишком много кода за раз
Ответ идёт в неверном направлении
Вы хотите добавить дополнительный контекст посреди ответа
Claude собирается выполнить команду, которую вы хотите изменить
Одно из самых мощных применений техники прерывания - исправление повторяющихся ошибок. Когда Claude совершает одну и ту же ошибку многократно в разных разговорах, вы можете:
Нажать Escape, чтобы остановить текущий ответ
Использовать шорткат # для добавления воспоминания о правильном подходе
Продолжить разговор с исправленной информацией
Пример рабочего процесса:
Claude: "Я добавлю API-эндпоинт в routes.py..." [Нажмите Escape — вы знаете, что ваш проект использует routers.py, а не routes.py] Вы: "#" [Открывается редактор памяти] Добавьте: "Этот проект использует routers.py для API-эндпоинтов, а не routes.py" Вы: "Продолжай, но помни, что мы используем routers.py для API-эндпоинтов" Claude: "Верно, я добавлю эндпоинт в routers.py..."
Это предотвращает повторение той же ошибки Claude в будущих разговорах по вашему проекту. Память сохраняется между сессиями, поэтому Claude будет помнить соглашения вашего проекта.
Типичные паттерны памяти:
Соглашения об именовании файлов: "Используй формат test_*.py для тестовых файлов"
Архитектурные решения: "Запросы к базе данных идут в repositories/, а не напрямую в routers/"
Предпочтения по стилю кода: "Используй двойные кавычки для строк, одинарные только для ключей словарей"
Технологические выборы: "Используй SQLAlchemy 2.0 async API, а не legacy ORM-паттерны"
Во время длинных разговоров у вас может накопиться контекст, который становится нерелевантным или отвлекающим. Например, если Claude столкнулся с ошибкой и потратил время на её отладку, эта переписка может быть бесполезна для следующей задачи.
Вы можете перемотать разговор, нажав Escape дважды. Это покажет вам все сообщения, которые вы отправляли, позволяя вернуться к более ранней точке и продолжить оттуда.
Пример сценария:
[Длинный разговор о построении ETL-пайплайна] Вы: "Добавь обработку ошибок для некорректных строк CSV" Claude: [Генерирует код с багом] Вы: "Это не работает, вот ошибка..." Claude: [Пробует исправление 1] Вы: "Всё ещё падает..." Claude: [Пробует исправление 2] Вы: "Заработало! Теперь давай добавим логирование" [Нажмите Escape дважды] [Выберите сообщение "Добавь обработку ошибок для некорректных строк CSV"] [Продолжите оттуда с рабочим решением, удалив отладочную переписку] Вы: "Теперь давай добавим логирование в пайплайн" Claude: [Продолжает с чистым контекстом]
Эта техника помогает вам:
Сохранять ценный контекст (например, понимание Claude'ом вашей кодовой базы)
Удалять отвлекающую или нерелевантную историю разговора
Держать Claude сфокусированным на текущей задаче
Убирать неудачные попытки и ложные старты
Когда перематывать:
После отладки сложной проблемы (сохранить решение, убрать неудачные попытки)
Когда побочное обсуждение стало слишком длинным
Перед началом новой связанной задачи (сохранить знание проекта, убрать специфичные для задачи детали)
Когда Claude неправильно понял требования и вы хотите перезапустить с чистой точки
Claude предоставляет несколько команд для эффективного управления контекстом разговора. Понимание того, когда использовать каждую, критично для поддержания продуктивных разговоров.
Команда /compact суммирует всю историю вашего разговора, сохраняя ключевую информацию, которую узнал Claude. Это идеально, когда:
Claude получил ценные знания о вашем проекте
Вы хотите продолжить со связанными задачами
Разговор стал длинным, но содержит важный контекст
Когда использовать /compact:
✅ ХОРОШО: После реализации фичи и желания добавить связанный функционал Вы: "Отлично, ETL-пайплайн работает. Теперь давай добавим валидацию данных." [Перед этим используйте /compact, чтобы сохранить знание пайплайна, уменьшить использование токенов] ✅ ХОРОШО: При приближении к лимитам контекстного окна, но с нужным знанием проекта Claude: [Ответ кажется медленнее, менее детальным] Вы: /compact [Продолжите с обновлённым контекстом] ❌ ПЛОХО: Переключение на совершенно несвязанную задачу Вы: "Теперь давай поработаем над фронтенд-аутентификацией" [Используйте /clear вместо этого — контекст ETL не релевантен]
Что /compact сохраняет:
Понимание структуры и архитектуры проекта
Паттерны кода и соглашения, которые узнал Claude
Взаимосвязи между компонентами
Ключевые решения и их обоснование
Что /compact удаляет:
Многословные объяснения и обучающий контент
Неудачные попытки и сессии отладки
Избыточные подтверждения и acknowledgements
Команда /clear полностью удаляет историю разговора, давая вам чистый старт. Это наиболее полезно, когда:
Вы переключаетесь на совершенно другую, несвязанную задачу
Текущий контекст разговора может запутать Claude для новой задачи
Вы хотите начать заново без какого-либо предыдущего контекста
Когда использовать /clear:
✅ ХОРОШО: Полное переключение доменов [Завершено: работа над Backend API] Вы: /clear Вы: "Теперь я хочу создать ноутбук анализа данных для данных продаж" [Контекст бэкенда будет нерелевантен/запутывающ] ✅ ХОРОШО: Начало новой фичи в другой части кодовой базы [Завершено: модуль обработки платежей] Вы: /clear Вы: "Давай построим систему email-уведомлений" [Другие зависимости, паттерны, заботы] ❌ ПЛОХО: Добавление связанного функционала [Завершено: регистрация пользователя] Вы: /clear Вы: "Теперь добавь функционал входа" [Вы потеряете ценный контекст о модели User, паттернах валидации и т.д.]
Языковые модели - мощный инструмент, но только когда понимаешь их сильные и слабые стороны. Тогда рутина уходит, а фокус остаётся на главном.
Делегируйте часть рутинных задач вместе с BotHub!
Для доступа к сервису не требуется VPN, и можно использовать российскую карту.
Теперь мы строим. Четыре готовых к продакшну проекта, которые демонстрируют возможности Claude Code по всему спектру разработки.
Проблема: У вас есть грязные CSV-данные из нескольких источников. Нужно очистить их, агрегировать метрики и загрузить в PostgreSQL для дашборда. Ручное написание pandas-кода утомительно и подвержено ошибкам.
Решение Claude Code: Опишите трансформацию простым языком. Claude генерирует полный ETL-пайплайн с обработкой ошибок, логированием и валидацией.


Шаг 1: Определите требования
В вашей сессии Claude Code:
""" Создай ETL-пайплайн для данных продаж: ВХОД: data/raw/sales_2024.csv - Колонки: date, product_id, customer_id, quantity, price, region ТРАНСФОРМАЦИИ: 1. Очистка: Удалить нули, стандартизировать формат даты (YYYY-MM-DD) 2. Валидация: Quantity > 0, price > 0 3. Обогащение: Добавить колонку месяца, вычислить revenue (quantity * price) 4. Агрегация: Сумма revenue по продукту и месяцу ВЫХОД: PostgreSQL таблица `sales_summary` - Схема: product_id, month, total_revenue, total_quantity ТРЕБОВАНИЯ: - Обработка ошибок для некорректных строк - Логирование в data/logs/etl.log - Поддержка инкрементальной загрузки (проверка существующих данных) - Типовые подсказки и docstrings """
Шаг 2: Claude генерирует пайплайн
Claude создаёт полный, готовый к продакшну пайплайн:



Шаг 3: Генерация валидации данных
Попросите Claude добавить комплексную валидацию:
"Добавь проверки качества данных: обнаружение дубликатов, выбросов в price/quantity, валидацию диапазонов дат и создай отчёт о качестве"
Claude входит в режим планирования, затем задаёт вопросы:
ФОТО (серия из 3 скриншотов планирования)
Проверки качества полностью интегрированы и готовы мониторить качество данных, при этом позволяя загружать все валидные данные!
Шаг 4: Генерация визуализации
"Сгенерируй Plotly-дашборд, показывающий: 1. Тренды выручки во времени 2. Топ-10 продуктов по выручке 3. Разбивку по регионам Сохрани как HTML-файл
Claude генерирует дашборд.
Я попросил Claude запустить, и он исправил проблемы с зависимостями как взрослый мальчик.
Вот он, сгенерированный дашборд.
Ключевые выводы:
Claude генерирует полные, готовые к продакшну пайплайны из описаний на английском языке
По умолчанию включает обработку ошибок, логирование и валидацию
Легко расширяется визуализацией, планировщиком (Airflow) или мониторингом
Используйте для: обработки CSV, загрузки данных API, миграций баз данных, генерации отчётов
Вы построили полные проекты с Claude Code. Теперь мы расширяем его возможности за пределы встроенных инструментов, используя Model Context Protocol (MCP).
Проблема, которую решает MCP:
До MCP подключение AI-инструментов к внешним сервисам было кошмаром:
Каждый инструмент (Claude, ChatGPT, Copilot) требовал кастомных интеграций
Каждый сервис (GitHub, базы данных, браузеры) имел разные API
Результат: проблема N×M интеграций — N инструментов × M сервисов = хаос
Решение MCP:
Один протокол, универсальные соединения:
MCP-серверы: Предоставляют возможности (Playwright = автоматизация браузера, GitHub = операции с репозиторием)
MCP-клиенты: AI-инструменты вроде Claude Code подключаются к любому MCP-серверу
MCP-протокол: Стандартизированная коммуникация JSON-RPC 2.0
Архитектура:
Доступная экосистема MCP:
Сообщество построило 1000+ MCP-серверов. Ключевые:
Playwright (Microsoft) — автоматизация браузера, тестирование
Puppeteer — альтернативная автоматизация браузера
GitHub — операции с репозиториями, PR, issues
PostgreSQL/MySQL — прямые операции с базой данных
Google Drive — управление документами
Slack/Discord — командная коммуникация
Filesystem — продвинутые файловые операции
Brave Search — интеграция веб-поиска
Sequential Thinking — сложные задачи рассуждения
Установка MCP-сервера:
# Установка Playwright MCP claude mcp add playwright -s local npx '@playwright/mcp@latest' # Установка GitHub MCP claude mcp add github -s local npx '@modelcontextprotocol/server-github' # Проверка установки claude mcp list
Конфигурация MCP:
Claude Code хранит конфигурацию MCP в .claude/settings.json:
{ "mcpServers": { "playwright": { "command": "npx", "args": ["@playwright/mcp@latest"] }, "github": { "command": "npx", "args": ["@modelcontextprotocol/server-github"], "env": { "GITHUB_TOKEN": "your-github-token" } }, "postgres": { "command": "npx", "args": ["@modelcontextprotocol/server-postgres"], "env": { "DATABASE_URL": "postgresql://user:pass@localhost/dbname" } } } }
Области видимости:
MCP-серверы могут устанавливаться на разных уровнях:
# Уровень пользователя (все проекты) claude mcp add playwright -s user npx '@playwright/mcp@latest' # Уровень проекта (только текущий проект) claude mcp add playwright -s local npx '@playwright/mcp@latest'
Теперь посмотрим три MCP-сервера в действии.
Сценарий использования: Автоматизация E2E-тестирования фронтенда приложения управления задачами из Проекта 2.
Почему Playwright MCP vs ручной Playwright:
Claude генерирует тесты, используя браузер, а не просто пишет код
Захватывает дерево доступности для LLM-дружественного понимания (скриншоты не нужны)
Валидация и отладка в реальном времени
Естественный язык → исполняемые тесты
Шаг 1: Установка Playwright MCP
claude mcp add playwright -s local npx '@playwright/mcp@latest'
Шаг 2: Интерактивное создание тестов
В Claude Code:
""" Используй Playwright MCP для создания E2E-теста создания задачи: СЦЕНАРИЙ: 1. Перейди на http://localhost:8501 (Streamlit-приложение) 2. Войди с [email protected] / testpass123 3. Создай новую задачу "Написать документацию" 4. Проверь, что задача появилась в списке задач 5. Отметь задачу как выполненную 6. Проверь, что задача показывается как выполненная Сгенерируй pytest-тестовый файл из этого потока. Включи assertions и правильные ожидания. """
Claude использует Playwright MCP для:
Открытия браузера (вы его видите!)
Навигации и взаимодействия с приложением
Захвата дерева доступности на каждом шаге
Генерации тестового кода на основе того, что он наблюдал
Сгенерированный тест:
# tests/e2e/test_task_flow.py (выдержка — полный в GitHub) import pytest from playwright.sync_api import Page, expect @pytest.fixture def authenticated_page(page: Page): """Навигация и вход""" page.goto("http://localhost:8501") # Заполнение формы входа page.get_by_label("Email").fill("[email protected]") page.get_by_label("Password").fill("testpass123") page.get_by_role("button", name="Login").click() # Ожидание дашборда expect(page.get_by_role("heading", name="My Tasks")).to_be_visible() return page def test_create_and_complete_task(authenticated_page: Page): """Тест полного рабочего процесса создания и завершения задачи""" page = authenticated_page # Создание задачи page.get_by_placeholder("Task title").fill("Write documentation") page.get_by_placeholder("Description").fill("Complete API docs") page.get_by_role("button", name="Add Task").click() # Проверка появления задачи task_card = page.locator('text="Write documentation"').locator('..') expect(task_card).to_be_visible() expect(task_card.get_by_text("Complete API docs")).to_be_visible() # Отметка как выполненной task_card.get_by_role("checkbox", name="Complete").check() # Проверка состояния выполнения expect(task_card).to_have_class(re.compile(r"completed")) # Проверка в фильтре выполненных page.get_by_label("Show completed").check() expect(page.locator('text="Write documentation"')).to_be_visible() def test_task_filtering(authenticated_page: Page): """Тест фильтрации задач по статусу и тегам""" # Полная реализация в GitHub pass def test_error_handling(authenticated_page: Page): """Тест корректной обработки ошибок приложением""" # Попытка создать задачу с пустым заголовком # Проверка появления сообщения об ошибке # Полная реализация в GitHub pass
Шаг 3: Визуальное регрессионное тестирование
"Используй Playwright MCP для создания визуальных регрессионных тестов: - Захвати скриншоты основных страниц - Сравни с базовыми изображениями - Обнаружь изменения UI - Сгенерируй отчёт сравнения"
# tests/e2e/test_visual_regression.py (выдержка) def test_task_list_screenshot(authenticated_page: Page): """Захват и сравнение скриншота списка задач""" page = authenticated_page # Переход к конкретному состоянию page.goto("http://localhost:8501") page.wait_for_load_state("networkidle") # Создание скриншота page.screenshot(path="screenshots/task-list-current.png") # Сравнение с базовым (используя pixelmatch или аналог) # Полная логика сравнения в GitHub
Запуск Playwright-тестов:
# Запуск всех E2E-тестов pytest tests/e2e/ # Запуск с видимым браузером (headed-режим) pytest tests/e2e/ --headed # Запуск в конкретном браузере pytest tests/e2e/ --browser chromium pytest tests/e2e/ --browser firefox # Генерация Playwright-отчёта pytest tests/e2e/ --html=report.html
Ключевые выводы:
Playwright MCP позволяет интерактивное создание тестов с Claude
Браузер виден во время разработки для отладки
Подход с деревом доступности надёжнее, чем инструменты на основе скриншотов
Бесшовно сочетается с pytest из Проекта 3
Легко расширить: мульти-браузерное тестирование, мобильные вьюпорты, перехват сети
Вы построили проекты и интегрировали внешние инструменты. Теперь мы добавляем финальный слой: хуки — детерминированная автоматизация, которая запускается на событиях выполнения инструментов.
Что такое хуки?
Хуки — это скрипты, которые запускаются автоматически в определённых точках рабочего процесса Claude Code:
До того как Claude использует инструмент (пре-хуки)
После того как Claude завершает действие инструмента (пост-хуки)
Когда пользователь отправляет промпт
Когда Claude прекращает отвечать
Когда сессия начинается или заканчивается
Почему хуки важны:
Без хуков вы говорите Claude: «Помни проверять чувствительные файлы перед чтением.» С хуками вы принуждаете: «Блокировать любую попытку чтения .env файлов, автоматически, каждый раз.»
Хуки превращают предложения в автоматизированные, воспроизводимые политики.
Сценарий использования: Предотвратить чтение Claude'ом чувствительных файлов и выполнение опасных команд.
Шаг 1: Создание конфигурации хука
// .claude/settings.json { "hooks": { "PreToolUse": [ { "name": "Security Validator", "matcher": "Read|Bash", "hooks": [ { "type": "command", "command": "python .claude/hooks/pre_tool_security.py" } ] } ] } }
Шаг 2: Реализация хука безопасности
# .claude/hooks/pre_tool_security.py """Пре-хук безопасности: Блокировка доступа к чувствительным файлам и опасным командам""" import sys import json import re def validate_file_access(tool_input: dict) -> bool: """Проверка, должен ли быть заблокирован доступ к файлу""" file_path = tool_input.get('file_path', '') # Заблокированные паттерны sensitive_patterns = [ r'\.env$', r'\.env\.', r'credentials', r'secrets', r'\.pem$', r'\.key$', r'id_rsa', r'\.ssh/', r'config\.json$', # Если содержит секреты r'\.aws/credentials', ] for pattern in sensitive_patterns: if re.search(pattern, file_path, re.IGNORECASE): return False # Заблокировать доступ return True # Разрешить доступ def validate_bash_command(tool_input: dict) -> bool: """Проверка, должна ли быть заблокирована bash-команда""" command = tool_input.get('command', '') # Опасные паттерны dangerous_patterns = [ r'rm\s+-rf\s+/', # rm -rf / r'sudo\s+rm', # sudo rm r'chmod\s+777', # Слишком разрешительные права r'>\s*/etc/', # Запись в системные директории r'curl.*\|\s*bash', # Pipe в bash (рискованно) r'eval\s+', # Eval с недоверенным вводом r'dd\s+if=.*of=/dev/', # Дисковые операции ] for pattern in dangerous_patterns: if re.search(pattern, command, re.IGNORECASE): return False # Заблокировать команду return True # Разрешить команду def main(): """Главное выполнение хука""" try: # Чтение ввода инструмента из stdin input_data = json.loads(sys.stdin.read()) tool_name = input_data.get('tool_name', '') tool_input = input_data.get('tool_input', {}) # Валидация на основе типа инструмента if tool_name == 'Read': if not validate_file_access(tool_input): # Блокировка выполнения print( f"ЗАБЛОКИРОВАНО: Доступ к чувствительному файлу запрещён: {tool_input.get('file_path')}", file=sys.stderr ) sys.exit(2) # Код выхода 2 блокирует выполнение инструмента elif tool_name == 'Bash': if not validate_bash_command(tool_input): # Блокировка выполнения print( f"ЗАБЛОКИРОВАНО: Опасная команда заблокирована: {tool_input.get('command')}", file=sys.stderr ) sys.exit(2) # Если мы достигли этой точки, разрешить выполнение sys.exit(0) except Exception as e: # При ошибке — безопасный отказ (блокировка) print(f"Ошибка хука безопасности: {e}", file=sys.stderr) sys.exit(2) if __name__ == '__main__': main()
Как это работает:
Claude пытается прочитать файл .env
Пре-хук перехватывает вызов инструмента Read
Хук проверяет путь файла по заблокированным паттернам
Совпадает с паттерном .env$ → Код выхода 2
Claude получает ошибку: «ЗАБЛОКИРОВАНО: Доступ к чувствительному файлу запрещён: .env»
Операция чтения никогда не выполняется
Claude знает, что не нужно пробовать снова
Тестирование хука:
# В сессии Claude Code: "Прочитай файл .env и покажи мне учётные данные базы данных" # Ответ Claude: # "Я попытался прочитать .env, но хук безопасности заблокировал это. # Этот файл содержит чувствительные учётные данные и не может быть доступен. # Можете ли вы предоставить нужную информацию другим способом?"
Сценарий использования: После того как Claude записывает или редактирует файлы, проверить, существует ли уже похожий код в кодовой базе, чтобы предотвратить дублирование.
Шаг 1: Конфигурация хука
// .claude/settings.json (добавить в секцию hooks) { "hooks": { "PostToolUse": [ { "name": "Duplicate Code Detector", "matcher": "Write|Edit", "hooks": [ { "type": "command", "command": "python .claude/hooks/post_tool_duplicates.py" } ] } ] } }
Шаг 2: Реализация обнаружения дубликатов
# .claude/hooks/post_tool_duplicates.py """Пост-хук: Обнаружение дублирования кода после модификации файлов""" import sys import json import os from pathlib import Path from difflib import SequenceMatcher from typing import List, Dict def normalize_code(code: str) -> str: """Нормализация кода для сравнения (удаление комментариев, пробелов)""" lines = [] for line in code.splitlines(): # Удаление Python-комментариев line = line.split('#')[0].strip() # Удаление пустых строк if line: lines.append(line) return '\n'.join(lines) def similarity_ratio(code1: str, code2: str) -> float: """Вычисление коэффициента схожести между двумя фрагментами кода""" norm1 = normalize_code(code1) norm2 = normalize_code(code2) return SequenceMatcher(None, norm1, norm2).ratio() def find_similar_code( file_path: str, content: str, threshold: float = 0.7 ) -> List[Dict[str, any]]: """Поиск похожего кода в других файлах""" similar_files = [] project_root = Path.cwd() # Поиск Python-файлов в проекте for py_file in project_root.rglob('*.py'): # Пропуск самого модифицированного файла if str(py_file) == file_path: continue # Пропуск тестовых файлов (они часто имеют похожую структуру) if 'test' in str(py_file): continue try: with open(py_file, 'r', encoding='utf-8') as f: existing_content = f.read() # Вычисление схожести ratio = similarity_ratio(content, existing_content) if ratio >= threshold: similar_files.append({ 'path': str(py_file.relative_to(project_root)), 'similarity': ratio }) except Exception: # Пропуск файлов, которые не удаётся прочитать continue return sorted(similar_files, key=lambda x: x['similarity'], reverse=True) def extract_functions(content: str) -> List[str]: """Извлечение определений функций для гранулярного сравнения""" # Простое извлечение функций (можно использовать AST для большей точности) functions = [] current_func = [] in_function = False for line in content.splitlines(): if line.strip().startswith('def '): in_function = True current_func = [line] elif in_function: if line and not line[0].isspace(): # Функция закончилась functions.append('\n'.join(current_func)) current_func = [] in_function = False else: current_func.append(line) if current_func: functions.append('\n'.join(current_func)) return functions def main(): """Главное выполнение хука""" try: # Чтение вывода инструмента из stdin input_data = json.loads(sys.stdin.read()) tool_name = input_data.get('tool_name', '') tool_input = input_data.get('tool_input', {}) # Обработка только операций Write/Edit if tool_name not in ['Write', 'Edit']: sys.exit(0) file_path = tool_input.get('file_path', '') content = tool_input.get('content', '') or tool_input.get('new_str', '') # Пропуск если нет контента if not content or len(content) < 100: # Пропуск очень маленьких файлов sys.exit(0) # Поиск похожих файлов similar_files = find_similar_code(file_path, content, threshold=0.7) if similar_files: # Предупредить Claude о потенциальном дублировании message = f"\n⚠️ ОБНАРУЖЕНО ДУБЛИРОВАНИЕ в {file_path}:\n\n" for similar in similar_files[:3]: # Показать топ-3 message += f" - {similar['path']} ({similar['similarity']:.0%} схожести)\n" message += "\nРассмотрите рефакторинг для повторного использования существующего кода или создания общей утилиты.\n" # Вывод в stderr (Claude это видит) print(message, file=sys.stderr) # Всегда разрешать операцию (мы только предупреждаем) sys.exit(0) except Exception as e: # Логировать ошибку, но не блокировать операцию print(f"Ошибка обнаружения дубликатов: {e}", file=sys.stderr) sys.exit(0) if __name__ == '__main__': main()
Как это работает:
Claude записывает новый файл backend/utils/validators.py
Пост-хук запускается после завершения Write
Хук сканирует кодовую базу на похожий код
Находит, что backend/auth/validators.py на 85% похож
Выводит предупреждение Claude через stderr
Claude видит: «⚠️ ОБНАРУЖЕНО ДУБЛИРОВАНИЕ… Рассмотрите рефакторинг для повторного использования существующего кода»
Claude может предложить объединить в общий модуль
Пример в действии:
# В Claude Code: "Создай новый файл backend/utils/email_validator.py с логикой валидации email" # Claude записывает файл, затем запускается хук: # Вывод хука (Claude это видит): """ ⚠️ ОБНАРУЖЕНО ДУБЛИРОВАНИЕ в backend/utils/email_validator.py: - backend/auth/validators.py (89% схожести) - backend/api/validation.py (72% схожести) Рассмотрите рефакторинг для повторного использования существующего кода или создания общей утилиты. """ # Claude отвечает: # "Я создал валидатор email, но хук дублирования нашёл очень # похожий код в backend/auth/validators.py (89% схожести). # Должен ли я провести рефакторинг обоих файлов для использования общего модуля валидации?"
Помните то обещание в начале - разгрести ваш Jira-бэклог к пятнице? Теперь у вас есть фундамент, чтобы сделать это реальностью.
Вы прошли путь от базовой настройки до продакшн-готовых паттернов в трёх критических областях:
1. Инженерия данных:
Полный ETL-пайплайн, обрабатывающий CSV-данные с pandas и PostgreSQL
Встроенная обработка ошибок, логирование и валидация качества данных
Интерактивные дашборды с Plotly для отчётности стейкхолдерам
Естественный язык → продакшн-код за минуты, не часы
2. Автоматизация качества:
Браузерное E2E-тестирование с Playwright MCP (больше никаких ручных прокликиваний тестов)
Визуальное регрессионное тестирование, автоматически фиксирующее изменения UI
Подход с деревом доступности для надёжных, детерминированных тестов
Интеграция с pytest для комплексного покрытия тестами
3. Безопасность и контроль качества:
Пре-хуки, блокирующие доступ к чувствительным файлам (.env, credentials, SSH-ключи)
Обнаружение опасных команд, предотвращающее rm -rf /, эскалацию привилегий, модификации системы
Пост-хуки, обнаруживающие дублирование кода по всей кодовой базе (порог 70%+ схожести)
Автоматизированное принуждение - не полагаясь на то, что Claude «запомнит» правила
Вот как теперь выглядит разработка конвейера данных:
9:00 — Бизнесу нужны данные продаж, агрегированные по региону и месяцу 9:05 - cd analytics-project && claude
9:10 — «Создай ETL-пайплайн: читай sales_2024.csv, очисти нули, агрегируй по продукту/месяцу, загрузи в PostgreSQL»
9:30 — Claude генерирует extract.py, transform.py, load.py с полной обработкой ошибок
9:45 — «Добавь проверки качества данных: обнаружение дубликатов, валидацию диапазонов дат, обнаружение выбросов»
10:00 — Ваш хук безопасности предотвратил чтение учётных данных базы из config.json
10:15 — «Сгенерируй Plotly-дашборд, показывающий тренды и топ-продукты»
10:45 — Пайплайн протестирован, дашборд отрендерен, готово к обзору стейкхолдерами
То, что занимало полный день, теперь занимает меньше 2 часов. А после обеда? Архитектурное планирование. Моделирование данных. Стратегическая работа.
1. Начните с одного сценария использования
Конвейеры данных - отличная отправная точка (чёткие входы/выходы, легко валидировать)
Добавьте браузерное тестирование, когда у вас есть UI для тестирования
Наложите хуки безопасности до того, как забудете их реализовать
2. Создайте свою библиотеку хуков
Начните с хука безопасности из Части 4 (предотвращает утечку учётных данных)
Добавьте обнаружение дубликатов для поддержания принципов DRY
Расширьте проект-специфичными правилами (стандарты кодирования, соглашения об именовании, обязательные тесты)
3. Установите командные соглашения
Создайте .claude/CLAUDE.md с вашими стандартами кодирования, технологическим стеком и паттернами
Закоммитьте .claude/settings.json, чтобы все использовали одни и те же MCP-серверы
Делитесь эффективными промптами через кастомные слэш-команды
4. Доверяй, но проверяй
Просматривайте код, сгенерированный Claude, перед деплоем в продакшн
Используйте хуки как автоматизированные ограничители, а не замену код-ревью
Запускайте свой набор тестов - Claude генерирует тесты, вы валидируете покрытие
5. Масштабируйтесь обдуманно
Освойте конвейеры данных, затем добавляйте паттерны веб-разработки
Добавляйте по одному MCP-серверу за раз (сначала Playwright, потом GitHub, потом базы данных)
Наращивайте сложность постепенно - хуки принуждают больше по мере созревания ваших паттернов
Больше MCP-интеграций:
GitHub MCP: Автоматизация создания PR, сортировки issues, код-ревью, управления релизами
PostgreSQL MCP: Прямые операции с базой данных, анализ схемы, оптимизация запросов
Filesystem MCP: Продвинутые файловые операции, пакетная обработка, управление директориями
Кастомные серверы: Создавайте MCP-интеграции для ваших внутренних инструментов, используя Python/TypeScript SDK
Продвинутые рабочие процессы:
Субагенты: Специализированные экземпляры Claude (data-quality-checker, test-generator, documentation-writer)
Навыки: Переиспользуемые пакеты знаний для доменно-специфичной работы (финансовое моделирование, ML-пайплайны, compliance-отчётность)
Многошаговая автоматизация: Цепочка MCP-серверов (получить данные из API → трансформировать → загрузить → протестировать → задеплоить)
Full-Stack разработка:
Расширьте паттерны конвейеров данных на FastAPI-бэкенды
Добавьте React/Streamlit-фронтенды для визуализации данных
Реализуйте CI/CD с GitHub Actions (тест → сборка → деплой)
Используйте те же паттерны хуков для разработки веб-приложений
Claude Code не заменяет вас как разработчика. Он меняет то, что означает «работа разработчика».
Механические части - чтение CSV, написание pandas-трансформаций, генерация pytest-фикстур, настройка Playwright-селекторов — это исполнение. Claude занимается исполнением.
Вы занимаетесь интересными частями:
«Нам агрегировать по неделе или по месяцу?»
«Какие пороги качества данных важны для этого сценария?»
«Какие метрики действительно интересуют стейкхолдеров?»
«Как нам обрабатывать запоздавшие данные в этом пайплайне?»
Это вопросы, которые требуют вашей экспертизы. А шаблонный код? Это то, для чего теперь нужны пятничные дни, когда бэклог уже разгребён.
Спасибо за прочтение!
Источник


