Раньше это был PHP/Laravel-скрипт, а теперь Python-сервис, который я переписал с помощью Codex
domaintools.site начинался у меня как простой PHP/Laravel-проект: быстро поднять прототип, собрать в одном месте доменные утилиты, сделать понятный интерфейс и проверить, вообще будет ли этим кто-то пользоваться.
Потом я всерьёз пошёл учить Python, а в ChatGPT появился Codex (тот самый агентный режим, когда правки приходят в виде pull request’ов). И я решил сделать нормальный инженерный эксперимент: взять живой проект и перенести его на Python так, чтобы это не было “переписал всё одной простынёй”, а было похоже на взрослую разработку с ревью и диффами.
Сайт: domaintools.site. Репозиторий: github.com/A-Krivoshen/domaintools.
Что это за сервис сейчас
По факту domaintools.site это набор утилит “на каждый день”, когда работаешь с доменами, DNS и IP. Не энтерпрайз-комбайн и не “проверка домена на одной кнопке”, а нормальный набор инструментов, который помогает быстро получить ответ и не лезть в десять разных сервисов.
Что умеет
Я держу фокус на практичных вещах. То, что реально используется:
- Проверка доменного имени и быстрый поиск вариантов по зонам.
- WHOIS по домену.
- DNS-записи (A, AAAA, MX, NS, TXT и т.д.) с нормальным выводом.
- Поиск IP по домену и домена по IP.
- Сервисные проверки вроде “site checker” (проверка доступности/ответов, без фанатизма).
Смысл простой: я хочу, чтобы открываешь страницу, вводишь домен, получаешь результат быстро и понятно. Без “вот вам JSON, дальше разберётесь”.
Почему я ушёл от PHP/Laravel версии
Старый вариант был нормальным прототипом. Он отработал свою задачу: показал, что идея живая, и что инструменты нужны. Но дальше мне хотелось развивать проект на Python, потому что я учусь, и потому что по архитектуре это удобно: сетевые проверки, параллельность, аккуратная обработка ошибок, конфиги через окружение, простая сборка и деплой.
Плюс честно: когда ты активно учишь новый стек, лучше один раз переписать реальную вещь, чем десять раз написать “учебный блог”. На реальном проекте сразу видно, где ты ошибся, и почему “красивый код” внезапно начинает падать в проде.
Где здесь Codex и почему это не просто “чатик подсказал”
Я использовал Codex так, как мне нравится больше всего: не “нагенерь мне проект”, а “сделай маленький кусок работы, оформи это PR, а я посмотрю дифф”. В итоге история изменений в репозитории выглядит аккуратно: серия небольших pull request’ов, которые можно ревьюить и мерджить без риска снести половину проекта.
Это важный момент. Когда изменения приходят через PR, у тебя остаётся контроль: что поменялось, где поменялось, почему, и как откатиться, если что-то не зашло. Я не люблю “магическую” разработку. Я люблю диффы.
Если хочется посмотреть именно историю агентных правок, вот репозиторий и список PR: github.com/A-Krivoshen/domaintools/pulls.
Что я улучшал при переносе на Python
Я не делал “идеальную архитектуру на века”. Я делал сервис, которым удобно пользоваться и который не разваливается от реальных входных данных. Поэтому улучшения были вполне приземлённые.
Параллельность там, где всё упирается в сеть
Проверка доменных зон и DNS это в основном ожидание. Если делать всё последовательно, сайт начинает казаться “тормозным”, хотя CPU у сервера может вообще не напрягаться. Поэтому логика проверок уехала в параллельный режим с ограничениями по количеству зон и воркеров.
Настройки удобно держать через env, чтобы не лезть в код при каждом изменении лимитов:
# пример export DOMAIN_CHECK_MAX_TLDS=20 export DOMAIN_CHECK_WORKERS=8
Нормальный вывод данных, а не “простыня JSON”
Большая часть доменных утилит страдает одной болезнью: они честно показывают ответ, но этот ответ невозможно читать. Поэтому вывод DNS/WHOIS и похожих вещей я приводил к “табличному” виду: ключ и значение, аккуратная верстка, без ощущения, что ты открыл дамп из консоли.
Язык и интерфейс
Проект стал более “прикладным”: где-то подчистил шаблоны, где-то добавил двуязычность ru/en, где-то упростил логику страниц. Я не пытался сделать дизайн как у SaaS-платформы. Задача проще: чтобы инструмент выглядел нормально и не раздражал.
Сразу скажу честно. Codex это не “сделай всё за меня”. Это скорее “сделай кусок работы, оформи как PR, а я посмотрю глазами”. Если держать этот подход, агент становится ускорителем. Если отпустить руль, получится набор разрозненных правок, которые сложно поддерживать.
Главное правило: одна задача — один PR
У меня простая дисциплина. Один PR решает одну проблему. Не “рефакторинг всего проекта”, а “ускорить доменную проверку и добавить лимиты”, “нормально отрисовать JSON таблицей”, “поправить обработку ошибок в одном модуле”.
Почему так лучше:
- дифф читается за 2–5 минут;
- если PR не зашёл, его легко откатить;
- легко понять, что именно улучшилось;
- не появляется эффект “всё поменялось, но почему и где”;
Как я пишу задачу Codex: структура запроса, которая не подводит
Я не пишу “сделай красиво” или “улучши производительность”. Я пишу задачу в формате: контекст, цель, ограничения, критерии готовности. Прямо как для нормального разработчика.
Шаблон задачи
Контекст: - Проект: domaintools.site (Python/Flask) - Файл/модуль: app/site_checker.py (пример) - Сейчас: запросы выполняются последовательно, иногда таймауты. Цель: - Сделать параллельную проверку с лимитом на количество задач. Ограничения: - Не трогать внешний API/роуты. - Не добавлять тяжёлые зависимости. - Ошибки должны быть читаемыми, без traceback в ответе. Критерии готовности: - Есть PR с диффом. - В логах видно понятные ошибки. - Параметры лимитов берутся из env и имеют safe default.
С таким запросом Codex обычно не расползается, потому что ему сразу ясно “где копать” и “что нельзя трогать”.
Какие задачи Codex делает лучше всего
На практике у меня Codex идеально заходит на такие типы работ:
- локальный рефакторинг одного модуля: разложить функции, убрать дубли, привести код к нормальному виду;
- улучшение обработки ошибок: понятные сообщения, аккуратные fallback, без “тихих падений”;
- переписывание рендера в шаблонах: привести вывод JSON/DNS/таблиц к одному стилю;
- настройки через env: добавить параметры, дефолты, проверку значений;
- микро-оптимизации на структуре данных: list → set, кэширование, устранение лишних проходов;
А вот на задачи “перепиши всё приложение целиком” я Codex не пускаю. Не потому что “не умеет”, а потому что это сложно ревьюить и очень легко потерять контроль.
Как я заранее ограничиваю “креатив”
У меня есть несколько принципов, которые я проговариваю прямо в задаче. Они приземлённые, но сильно экономят время.
- Не менять публичные роуты и формат ответа, если это не оговорено отдельно.
- Не добавлять зависимости без причины. Если очень надо, объясни зачем.
- Не делать “архитектуру ради архитектуры”. Решаем конкретную проблему.
- Не трогать стили/верстку на всех страницах, если задача про один блок.
И ещё одно: если задача про скорость, я прошу предложить 2–3 варианта решения и выбрать самый простой, который даст нормальный эффект. Я люблю простое. Простое легче поддерживать.
Мой чек-лист перед мерджем PR от Codex
Это самая важная часть. Секрет успеха не в том, что Codex “идеально пишет”. Секрет в том, что ты не мерджишь вслепую.
- Смотрю дифф глазами. Особенно места с обработкой ошибок и с network-частью.
- Проверяю, не уехали ли env-переменные/настройки в странные значения.
- Прогоняю минимум проверок локально (или на тестовом стенде): старт приложения, один-два запроса к ключевым страницам.
- Если в PR добавлен параллелизм, смотрю лимиты и safe default.
- Если PR трогает шаблоны, проверяю страницу в браузере и в мобиле.
Минимальный набор команд зависит от проекта, но обычно достаточно:
# примерный минимум python -m compileall . python app.py # или твой entrypoint curl -I http://127.0.0.1:5000/ curl -s http://127.0.0.1:5000/dns?domain=example.com | head
Мне не нужно покрыть тестами вселенную. Мне нужно убедиться, что PR не ломает базовые маршруты и не добавляет сюрпризов.
Промпты, которые я реально использую на domaintools.site
Вот несколько готовых формулировок. Их можно копировать и адаптировать.
1) Рефакторинг модуля “Возьми модуль X. Разбей на мелкие функции, убери дубли, добавь понятные ошибки. Не меняй роуты и формат ответа. Сделай PR.” 2) Скорость и параллелизм “Ускорь проверки в функции Y. Добавь параллельность, но с лимитами и safe default. Параметры вынеси в env. Сделай PR и короткое объяснение.” 3) UI вывод данных “Сделай единый вывод JSON в виде таблицы key/value для страниц A, B, C. Без изменения логики получения данных. Только отображение. Сделай PR.” 4) Обработка ошибок “Сейчас при ошибке Z уходит traceback/500. Сделай аккуратный ответ пользователю и запись в лог. Не меняй happy-path. Сделай PR.”
Где Codex может ошибиться, и это нормально
Есть два типовых сценария, которые я вижу чаще всего:
- агент может “слишком поверить” в переменные окружения и не защититься от кривых значений;
- агент может чуть переборщить с рефакторингом и тронуть соседние части, хотя задача была локальной.
Это не трагедия. Это просто причина держать дисциплину: один PR — одна задача, и ревью глазами.
Итог
Codex для меня стал не “генератором кода”, а инструментом, который помогает быстрее двигать проект, сохраняя контроль. Формат “агент делает PR, я ревьюю и мерджу” хорошо ложится на реальную разработку. Особенно когда ты учишь новый стек и хочешь развивать проект без хаоса.
Репозиторий domaintools.site: github.com/A-Krivoshen/domaintools
Как пользоваться domaintools.site
Там всё довольно прямолинейно: выбираешь инструмент, вводишь домен или IP, получаешь результат. Если короткий маршрут, то обычно он такой:
-
- Нужно понять, жив ли домен и что по зонам — начинаешь с поиска/проверки домена.
-
- Нужно понять регистратора/сроки — идёшь в WHOIS.
-
- Не сходится почта/веб — идёшь в DNS и смотришь записи.
-
- Разбираешься с IP — используешь прямой/обратный поиск.
Ссылка на демо: domaintools.site.
Итог
Старый PHP/Laravel вариант был полезным стартом, но сейчас его уже нет смысла “продавать” как продукт. Вся основная жизнь проекта переехала в Python-версию, и перенос я делал как тест нового подхода: Codex как напарник, который готовит маленькие PR, а я принимаю решения и держу качество через ревью.