Skip to main content

hhru-bot

CLI-бот для поиска работы на hh.ru: ищет вакансии, откликается письмом, поднимает резюме, следит за ответами и умеет редактировать само резюме. Работает через Playwright (браузер), а не через API — hh.ru закрыл его для соискателей в декабре 2025.

Чем мы отличаемся от аналогов

Идея сравнения и разбор референсов — issue #84. Легенда: ✅ есть, ❌ нет, ⚠️ частично или не проверяли (не значит «нет»).

Фича s3rgeym fikstt2 Steev193 tgeruzov konard hhru-bot
Поиск + отклик ✅ ✅ ✅ ✅ ✅ ✅
Поднятие резюме ✅ ⚠️ ⚠️ ⚠️ ⚠️ ✅
Троттлинг и дневные лимиты ✅ ⚠️ ⚠️ ⚠️ ⚠️ ✅
Редактирование и создание резюме ⚠️ клон целиком ❌ ❌ ❌ ❌ ✅
Анализ резюме конкурентов ❌ ❌ ❌ ❌ ❌ ✅
Обучаемые ответы на анкеты ❌ ❌ ❌ ❌ ⚠️ Q&A-файл, без обучения ✅
Честный статус «не знаю, дошло ли» ❌ ❌ ❌ ❌ ❌ ✅
Воронка и статистика по истории ⚠️ ❌ ❌ ❌ ❌ ✅
  • Редактирование и создание резюме — create-resume, edit-experience, edit-education, edit-skills, edit-languages, resume-position, publish-resume и другие: собрать резюме с нуля или довести до публикации.
  • Анализ резюме конкурентов (competitors) — с кем ты конкурируешь за вакансию: отчёт по ролям, зарплатам и навыкам других соискателей.
  • Обучаемые ответы на анкеты (questionnaire) — бот подбирает ответ по подтверждённым формулировкам, для новых вопросов подключает LLM; неуверенные случаи идут в очередь на твоё решение.
  • Честный статус «не знаю» (uncertain) — если связь с hh.ru оборвалась в момент клика, бот не врёт «готово»/«не готово», а говорит «не знаю».
  • Воронка и статистика (funnel, stats, responses, market) — сколько откликов ушло, сколько ответов, где «мёртвая зона».

Проекты и ссылки — «Похожие проекты» ниже. Полный список команд — «Справочник команд» ниже.

Как это работает

Запускается вручную из терминала. Каждая команда печатает, что делает, поддерживает --dry-run (план без единого клика по hh.ru) и ограничена дневными лимитами и случайными паузами — чтобы не выглядеть подозрительной автоматизацией для анти-фрод системы hh.ru. Опасные действия (отклик, публикация, удаление резюме) без --force или подтверждения не выполняются.

Для регулярного запуска (например, поднимать резюме каждые 4 часа) подключи внешний планировщик — cron/launchd или Docker (см. «Автопилот» ниже). Своего фонового демона у бота нет.

⚠️ Важное предупреждение

Селекторы hh.ru в src/hhru_bot/selectors.py не проверены вживую — код писался без доступа к hh.ru (DDoS-Guard блокировал автоматизированный браузер).

Перед первым использованием:

  1. Открой hh.ru, сверь через F12 → Elements актуальные data-qa атрибуты карточек вакансий, кнопки отклика, формы письма, кнопки поднятия резюме с тем, что в src/hhru_bot/selectors.py.
  2. Поправь несоответствия прямо в этом файле.
  3. Прогони search --dry-run, затем apply --dry-run, и только потом — боевой запуск с малым --limit.

Установка

pip3 install -r requirements.txt
python3 -m playwright install chromium
pip3 install -e .

Настройка

hhru account create default
./scripts/run.sh --account default login

Отредактируй созданный data/accounts/default/config.yaml:

  • resumes — твои резюме, у каждого свои фильтры поиска (text, area, salary_from, experience, schedule, exclude_employers, exclude_keywords) и опционально своё сопроводительное письмо.
  • exclude_keywords — стоп-слова для заголовков вакансий (без учёта регистра), отдельно для каждого резюме. Пример — в config/config.example.yaml.
  • throttle — паузы между действиями и дневные лимиты откликов/поднятий.
  • В письме доступны плейсхолдеры {vacancy_title} и {company_name}.

Структура каталогов

Всё изменяемое — конфиг, база, сессия hh.ru, логи — живёт в data/, целиком в .gitignore.

data/
  accounts/
    default/
      config.yaml           # конфиг аккаунта (создаётся account create)
      history.db            # история аккаунта
  config.yaml               # шаблон — config/config.example.yaml
  history.db                # SQLite: история откликов, вакансии, ответы
  storage_state/
    hh_session.json         # сессия hh.ru — секрет, никогда не коммитить
  logs/
    hhru_bot.log            # лог CLI (дублируется в консоль)
    probe_*.html / .png     # дампы probe
    scheduled.log           # вывод запусков по расписанию

config/
  config.example.yaml       # шаблон формата, лежит в репозитории

Пути — относительно текущей директории: запускай команды из корня проекта или указывай --config/--history явно. hh_session.json даёт доступ к hh.ru наравне с паролем — не коммить data/ и не включай в Docker-образ.

Первый запуск: вход в аккаунт

./scripts/run.sh login

Откроется окно браузера на странице входа hh.ru. Войди в аккаунт вручную (логин, пароль, СМС-код, капча — что бы ни попросил hh.ru), затем вернись в терминал и нажми Enter. Сессия сохранится в data/storage_state/hh_session.json — все последующие команды будут переиспользовать её без повторного входа.

Мультилогин: несколько аккаунтов hh.ru

Каждый аккаунт — своё имя и своя папка data/accounts/<name>/.

hhru account create marketing
./scripts/run.sh --account marketing login
# или, если куки hh.ru уже есть в профиле Chrome:
./scripts/run.sh --account marketing import-cookies --profile Default

Флаг --account <name> ставится до имени подкоманды:

./scripts/run.sh --account marketing apply --resume resume-name-1 --limit 5

Для плановых задач то же самое делает HHRU_ACCOUNT (понимает scripts/scheduled_run.sh); явный --account в приоритете:

HHRU_ACCOUNT=marketing scripts/scheduled_run.sh --headless apply --limit 5

Список аккаунтов и их состояние: ./scripts/run.sh account list.

У каждого аккаунта своя сессия, своя история откликов/поднятий и свои дневные лимиты — они не суммируются и не переносятся между аккаунтами. Разные аккаунты можно гонять параллельно; два одновременных прогона одного аккаунта запрещены (второй получит [FAIL]).

hh_session.json даёт доступ к hh.ru наравне с паролем; файлы сессии создаются с правами 0600, каталог аккаунта — 0700 (проверка — diagnostics doctor).

Чтобы убрать аккаунт — удали data/accounts/<name>/ вручную.

Команды

Все команды поддерживают --resume <id> (по умолчанию — все резюме из конфига) и --dry-run (показать план действий без реальных кликов).

# Проверить, что находит поиск, без откликов
./scripts/run.sh search --resume resume-name-1 --dry-run

# Откликнуться на подходящие вакансии (максимум 5 за запуск)
./scripts/run.sh apply --resume resume-name-1 --dry-run --limit 5

# То же самое по-настоящему, без dry-run
./scripts/run.sh apply --resume resume-name-1 --limit 5

# Поднять резюме в поиске (hh.ru разрешает не чаще раза в 4 часа)
./scripts/run.sh bump --resume resume-name-1

# Полный цикл (apply + bump) для всех резюме из конфига
./scripts/run.sh run

Профиль для внешних форм

Контактные данные аккаунта сохраняются автоматически после login. Для данных, которых нет на hh.ru (например, Telegram) — задай вручную, с тем же --account:

./scripts/run.sh --account default profile set "Telegram" "@username"
./scripts/run.sh --account default profile show
./scripts/run.sh --account default profile unset "Telegram"

Добавь --headless, если не нужно видеть окно браузера.

Автопилот: запуск по расписанию

Регулярность задаёт внешний планировщик. Каждый вариант ниже запускает обычную команду run (apply + bump) — те же лимиты и кулдаун, что и вручную. Перед автоматизацией проверь ./scripts/run.sh run --dry-run.

Локаль (cron / launchd)

Скопируй scripts/crontab.example, замени __REPO_ROOT__ и __PYTHON_BIN__ на абсолютные пути, добавь через crontab -e. Обёртка пишет в data/logs/scheduled.log сама.

responses --alert-new пишет ***** НОВОЕ ПРИГЛАШЕНИЕ ***** при новом приглашении; HHRU_ALERT_CMD опционально запускает свою команду при обнаружении. Пример — в scripts/crontab.example.

На macOS вместо cron — готовые шаблоны deploy/com.hhru.bot.apply.plist (ежедневный apply) и deploy/com.hhru.bot.bump.plist (bump каждые 4 часа). Замени __REPO_ROOT__/__PYTHON_BIN__, установи:

cp deploy/com.hhru.bot.apply.plist ~/Library/LaunchAgents/com.hhru.bot.apply.plist
launchctl load ~/Library/LaunchAgents/com.hhru.bot.apply.plist

Выгрузить: launchctl unload ~/Library/LaunchAgents/com.hhru.bot.apply.plist. Сгенерировать шаблон: ./scripts/run.sh schedule --format plist --action apply --apply-time 10:00 --apply-limit 5.

Docker

data/ монтируется с хоста и не попадает в образ. Подготовь конфиг на хосте, затем разовый прогон:

mkdir -p data
./scripts/run.sh account create default
docker compose run --rm --entrypoint hhru hhru --headless --account default run

Непрерывный режим — docker compose up -d: docker-compose.yml запускает run --headless каждые 4 часа без дрейфа расписания.

docker compose up -d
docker compose logs -f hhru

Остановить: docker compose down. Не монтируй storage_state в публичные каталоги и не добавляй data/ в образ или git.

Сценарий: пришло приглашение

  1. Планировщик распознаёт новое приглашение (код выхода 10):

    ./scripts/run.sh --headless responses --alert-new
    
  2. Посмотреть, что нового: ./scripts/run.sh responses.

  3. Что подтянуть по требованиям из собранных вакансий: ./scripts/run.sh learn --resume <id>.

  4. Время собеседования CLI не угадывает — responses --calendar-hint печатает готовую команду calendar event с плейсхолдерами:

    ./scripts/run.sh responses --calendar-hint
    ./scripts/run.sh calendar event --summary "ООО Ромашка - 12345" \
      --start 2026-09-01T14:00:00+03:00 --end 2026-09-01T15:00:00+03:00
    

Если работодатель молчит после отклика — напомнить о себе:

./scripts/run.sh reply-employers --follow-up --after-days 7 --dry-run
./scripts/run.sh reply-employers --follow-up --after-days 7 --force

VPS

ssh user@example.com 'cd /opt/hhru && docker compose up -d --build'
ssh user@example.com 'cd /opt/hhru && docker compose logs -f hhru'

Сессию создай локально (./scripts/run.sh --account default login) или в контейнере с временно отключённым --headless. Обновление: git pull && docker compose up -d --build.

Claude Code и Codex plugin

Репозиторий — маркетплейс плагина hhru-cc-plugin: подключает команды бота как инструменты и скиллы прямо из агентской сессии Claude Code или Codex.

Установка

claude plugin marketplace add axisrow/hhru
claude plugin install hhru-cc-plugin@hhru --scope user

Codex: установка и обновление

Одна команда покрывает первую установку, апгрейд и восстановление после ошибки — она идемпотентна, повторный запуск безопасен:

hhru update

Проверить состояние без изменений: hhru diagnostics doctor (или ./scripts/run.sh diagnostics doctor из checkout). При рассинхроне между CLI, marketplace и plugin cache печатает [DRIFT] и подсказывает hhru update.

Уже открытая задача Codex после обновления продолжает работать со старым skill — начни новую задачу, чтобы подхватить изменения.

Команда /hhru

/hhru whoami
/hhru search --resume <id> --dry-run --max-pages 3
/hhru competitors collect --text "AI" --auth-mode anonymous --detail-workers 10
/hhru apply --resume <id> --dry-run --limit 5
/hhru responses

Write-команды (apply/bump/run/...) сначала --dry-run, потом подтверждение перед боевым запуском.

Скиллы

  • hhru — главный: CLI-справочник, правила безопасности, проверка готовности.
  • hhru-apply — воркфлоу отклика (dry-run-first, safety-critical).
  • hhru-market — анализ рынка (read-only).
  • hhru-monitor — мониторинг/статус (read-only).

Подготовка к интервью

Бот автоматизирует цепочку «пришло приглашение → follow-up» (см. «Сценарий: пришло приглашение» выше). Само собеседование — нарратив, портфолио, поведенческие вопросы — готовишь сам:

  • подготовь проекты и портфолио под требования, которые показал learn;
  • подготовь нарратив («расскажите о себе») и ответы на поведенческие вопросы;
  • поставь реальное время интервью в calendar event вместо плейсхолдера.

Справочник команд

Этот блок генерируется автоматически из argparse (см. scripts/gen_cli_docs.py). Не редактируй его руками — правь код команд в src/hhru_bot/commands/ и перегенерируй. CI упадёт, если блок рассинхронизирован с кодом.

Глобальные флаги (до имени команды):

  • --config — Путь к config.yaml
  • --history — Путь к файлу истории (SQLite)
  • --account — Имя аккаунта (data/accounts//config.yaml + history.db)
  • --headless — Запустить браузер в headless-режиме
  • --verbose — Подробное логирование
  • --quiet — Не печатать поток прогресса

Команды:

about

Генерирует текст раздела «Обо мне» через настроенный LLM. Сначала всегда показывает dry-run-предложение; сохранение требует --force или подтверждения. С --text LLM не нужен: готовый текст (например, перевод) сохраняется как есть (#326).

  • --resume — Slug из конфига или реальный resume_id HH.ru (#319)
  • --text — Готовый текст раздела «Обо мне» без LLM (#326): ai_profile/секция ai не требуются, текст сохраняется как есть
  • --dry-run — Показать предложение без сохранения
  • --force — Подтвердить сохранение без prompt

account

Создание и управление локальными профилями аккаунтов hh.ru.

  • (без аргументов)

account create

Создать data/accounts// и скопировать туда шаблон конфига.

  • (без аргументов)

account delete

Показать, что будет удалено в data/accounts//, а с --force выполнить необратимое удаление.

  • --dry-run — Показать план и ничего не удалять (это поведение по умолчанию)
  • --force — Выполнить удаление (необратимо; уносит конфиг, историю и сессию)

account list

  • (без аргументов)

adaptive-report

  • --format — ASCII-таблица (по умолчанию: 'table')

adaptive-resume

Генерирует заголовок, «Обо мне», порядок навыков и отбор мест работы/проектов под один из четырёх кластеров вакансий (#752). Без --apply только показывает предложение (браузер не открывается). С --apply применяет title/about/skills на hh.ru; боевая запись требует --force или интерактивного подтверждения. work_experience/projects этой командой на hh.ru не пишутся (#769: вне скоупа первой версии).

  • --resume — Slug из конфига или реальный resume_id HH.ru (#319)
  • --cluster — Кластер вакансий, под который адаптируется резюме
  • --apply — Открыть браузер и применить title/about/skills на hh.ru (иначе только печать плана)
  • --dry-run — С --apply: открыть формы и показать план по каждому шагу, ничего не сохраняя. Без --apply — no-op (команда и так не пишет на hh.ru, флаг оставлен для единообразия и совместимости)
  • --force — С --apply: подтвердить запись без TTY prompt

apply

  • --resume — Slug из конфига или resume_id HH.ru (по умолчанию — все)
  • --dry-run — Показать, что будет сделано, без реальных действий
  • --max-pages MAX_PAGES — Явный максимум страниц поиска (по умолчанию — адаптивный)
  • --force — Разрешить реальную отправку отклика с LLM-ответами на вопросы
  • --learn-questionnaires — Спрашивать подтверждение сопоставления вопроса анкеты с шаблоном
  • --limit LIMIT — Целевое число успешных откликов за запуск (0 = без ограничения кроме дневного лимита)
  • --approved ID — Отправить ровно approved-запись review-очереди
  • --permit — Одноразовый permit из review approve

backup

  • --output OUTPUT — Путь к tar.gz

blacklist

  • (без аргументов)

blacklist add

  • --reason
  • --by (по умолчанию: 'cli')

blacklist list

  • (без аргументов)

blacklist remove

  • (без аргументов)

bump

  • --resume — Slug из конфига или resume_id HH.ru (по умолчанию — все)
  • --dry-run — Показать, что будет сделано, без реальных действий
  • --max-pages MAX_PAGES — Максимум страниц поиска (по умолчанию: 5)

calendar

Создание события только по явно подтверждённым --start/--end. Автоматического триггера из responses нет.

  • (без аргументов)

calendar auth

  • --credentials (по умолчанию: 'data/google_calendar/client_secret.json')
  • --token (по умолчанию: 'data/google_calendar/token.json')

calendar event

  • --credentials (по умолчанию: 'data/google_calendar/client_secret.json')
  • --token (по умолчанию: 'data/google_calendar/token.json')
  • --calendar-id (по умолчанию: 'primary')
  • --summary
  • --start — Начало, RFC3339, например 2026-08-20T10:00:00+07:00
  • --end — Конец, RFC3339
  • --timezone (по умолчанию: 'UTC')
  • --description
  • --location
  • --dry-run — Показать payload без OAuth и записи

call-api

  • -m, --method — HTTP-метод (разрешён только GET) (по умолчанию: 'GET')

census

  • --url — Полный URL страницы hh.ru
  • --json — Машиночитаемый JSON-вывод

clear-negotiations

Отозвать один отклик по уникальному topic или все отклики аккаунта. Фильтры --vacancy и --resume формируют только план; боевой отзыв требует --topic или --account-wide и --force/подтверждение.

  • --topic — Уникальный ID переписки для точечного отзыва
  • --vacancy — ID вакансии (только план, не боевой отзыв)
  • --resume — ID резюме (только план, не боевой отзыв)
  • --account-wide — Явно отозвать все найденные отклики аккаунта
  • --dry-run — Показать план без отзывов
  • --force — Подтвердить боевой отзыв
  • --max-pages MAX_PAGES — Максимум страниц переговоров (по умолчанию: 5)

clear-skipped

Удалить записи из журнала отсева (таблица skipped). Без --reason чистит все причины. Без --dry-run удаляет, с --dry-run — только показывает, сколько записей ушло бы.

  • --reason — Очистить только эту причину (по умолчанию — все причины)
  • --dry-run — Показать, сколько записей будет удалено, без реального удаления

common

Заполняет через UI поля common, включая условия работы. area, metro и citizenship пока не входят в команду.

  • --resume — Slug из конфига или resume_id HH.ru
  • --first-name — Имя
  • --last-name — Фамилия
  • --birthday — Дата в формате, который принимает форма hh.ru
  • --gender — Пол
  • --phone — Телефон
  • --area — Точный leaf города из live-каталога hh.ru
  • --metro — Точная станция метро
  • --citizenship — Точное гражданство из live-каталога; можно повторять
  • --work-ticket — «Наличие трудовой книжки» (true/false). Только в шейпе редактора профиля: на common-визарде черновика поле не рендерится (честный отказ), контрол work-ticket-selector визарда — это «Разрешение на работу» (#997)
  • --relocation — Готовность к переезду
  • --schedule — График работы; можно указать несколько раз
  • --employment — Тип занятости; можно указать несколько раз
  • --work-format — Формат работы; можно указать несколько раз
  • --business-trip, --business-trips — Готовность к командировкам
  • --show — Показать фактические значения полей common (включая предзаполненные hh.ru) и выйти
  • --dry-run — Показать план без сохранения
  • --force — Подтвердить запись без prompt

competitors

READ hh.ru: competitors collect --text QUERY [--search-in SCOPE] [--max-pages N]; локальный отчёт: competitors report [--text QUERY] [--search-in SCOPE] [--auth-mode MODE] [--top N].

  • (без аргументов)

competitors collect

  • --text — Ключевое слово поиска резюме
  • --max-pages MAX_PAGES — Необязательный safety-cap (по умолчанию — до конца видимой выдачи)
  • --resume — Продолжить последний прерванный запуск того же запроса с checkpoint
  • --execution-mode — Режим выполнения (по умолчанию foreground; background не поддерживается) (по умолчанию: 'foreground')
  • --progress-verbosity PROGRESS_VERBOSITY — Поток прогресса: 1 — показывать, 0 — только финал/ошибки (по умолчанию 1) (по умолчанию: 1)
  • --items-per-page ITEMS_PER_PAGE — Запрошенный размер страницы hh.ru (по умолчанию 100; для smoke можно 20) (по умолчанию: 100)
  • --search-in — Область поиска --text на hh.ru: position — только желаемая должность (заголовок резюме), самая узкая и чистая (по умолчанию); keywords — по ключевым навыкам; full_text — по всему резюме (должность, навыки, описание опыта, достижения), самая широкая: запрос вроде «AI» так вытягивает дизайнеров с Adobe Illustrator (по умолчанию: 'position')
  • --auth-mode — Сессия браузера: anonymous — чистый контекст без cookie (по умолчанию); authenticated — загрузить сохранённую сессию из конфига (по умолчанию: 'anonymous')
  • --detail-workers DETAIL_WORKERS — Параллельные процессы деталей: 1–1000 (по умолчанию 10; для authenticated требуется 1) (по умолчанию: 10)

competitors report

  • --text — Ограничить отчёт одним поисковым запросом
  • --search-in — Ограничить отчёт одной областью поиска: один и тот же --text в разных областях — это РАЗНЫЕ выборки (full_text по «AI» тянет дизайнеров с Adobe Illustrator). Без флага отчёт охватывает все области
  • --auth-mode — Ограничить отчёт одним режимом сессии: анонимная выдача hh.ru урезана относительно авторизованной. Без флага отчёт охватывает оба режима
  • --top TOP — Число строк в каждом топе (по умолчанию 20) (по умолчанию: 20)

config

Показать и локально изменить значения в config.yaml.

  • -p, --path — Показать полный путь к config.yaml
  • -e, --edit — Открыть config.yaml в $EDITOR
  • -k, --key — Получить значение по ключу
  • -s, --set — Установить значение ключа
  • -u, --unset — Удалить ключ

copy-resume

Создаёт копию резюме на hh.ru — то же, что «Дублировать» в меню резюме (в референсах — клонирование). WRITE-команда: боевой режим требует --force или интерактивного подтверждения; --dry-run ничего не отправляет.

  • --resume — Slug из конфига или реальный resume_id HH.ru (#319)
  • --dry-run — Показать, что будет сделано, без реальных действий
  • --force — Подтвердить боевой запуск без интерактивного вопроса
  • --write-config — Добавить новое резюме в config.yaml
  • --slug — Slug нового резюме (по умолчанию <исходный>-copy)
  • --title — Желаемая должность для созданной копии (после клонирования)

create-resume

Открывает визард hh.ru и создаёт новый черновик резюме. Один запуск создаёт одно резюме с одной основной профессией; для нескольких профессий нужны отдельные резюме и отдельные запуски. С --allow-unresolved-area, если area отсутствует в каталоге, черновик создаётся с ролью-плейсхолдером «Другое» — профессию затем заменяют вручную через «Дополнить». WRITE-команда: по умолчанию только dry-run; боевой запуск требует --force или интерактивного подтверждения.

  • --area — Профессия для выбора в визарде создания резюме. Если hh.ru показывает ровно одну подсказку автодополнения с однозначной ролью, она принимается автоматически; иначе выбирается дерево каталога — точным совпадением, а при его отсутствии единственным кандидатом фильтра (#920). Несколько подсказок автоматически не выбираются — перезапустите с точным именем одной из них
  • --title — Одна основная профессия резюме
  • --allow-unresolved-area, --allow-unresolved — Если area не найдена в каталоге — создать черновик с ролью-плейсхолдером «Другое» (id 40), профессия заменяется вручную (синоним: --allow-unresolved)
  • --dry-run — Показать план без создания
  • --force — Подтвердить боевое создание
  • --fill-common — #985: если readback после создания вернёт draft_started с nextIncompleteScreenId=common — подтвердить экран common в том же прогоне («Сохранить и продолжить»; hh.ru предзаполняет его из профиля аккаунта) и перевести резюме к ready_to_publish. Значения не выдумываются: незаполненное в профиле поле — честный отказ до клика с вердиктом draft_started

delete-education-entry

Удаляет ровно одну запись основного/дополнительного образования через UI hh.ru, адресуя её реальным id из /profile/edit/{kind}Education/{id}. --entry-id и --kind обязательны; по умолчанию выполняется только dry-run.

  • --entry-id — Числовой id записи из URL /profile/edit/{kind}Education/{id}
  • --kind — Основное (primary) или дополнительное (additional) образование
  • --dry-run — Показать план без удаления (по умолчанию; --force включает боевой режим) (по умолчанию: True)
  • --force — Подтвердить необратимое удаление

delete-photo

По умолчанию скрывает фото из ОДНОГО резюме (пункт «Скрыть фото из резюме»; фото остаётся в библиотеке, возвращается select-photo). --from-library необратимо удаляет фото из библиотеки аккаунта — оно исчезает из ВСЕХ резюме, где установлено. WRITE-hh-ru: dry-run включён по умолчанию (read-only инвентарь библиотеки и пунктов more-меню «Действия с фото»); боевой режим (необратимый при --from-library) включает только --force и требует --photo-id.

  • --resume — Slug из конфига или resume_id HH.ru
  • --photo-id — Числовой id фото из dry-run инвентаря (обязателен в боевом режиме)
  • --from-library — Удалить фото из библиотеки аккаунта (необратимо, бьёт по ВСЕМ резюме с этим фото), а не только скрыть из одного резюме
  • --dry-run — Показать план и пункты меню, ничего не меняя (по умолчанию; --force включает боевой режим) (по умолчанию: True)
  • --force — Подтвердить боевое удаление/скрытие

delete-resume

Удаляет ровно одно резюме через UI hh.ru. --resume обязателен; по умолчанию выполняется только dry-run.

  • --resume — Slug из конфига или реальный resume_id HH.ru (#319)
  • --dry-run — Показать план без удаления (по умолчанию; --force включает боевой режим) (по умолчанию: True)
  • --force — Подтвердить необратимое удаление

diagnostics

  • (без аргументов)

diagnostics doctor

Сравнивает версию, release/tag и commit SHA установленного CLI, marketplace snapshot и загруженного Codex plugin; проверяет права каталогов аккаунтов и файлов сессий.

  • --marketplace-path, --marketplace MARKETPLACE — Путь к marketplace snapshot (для диагностики нестандартной установки)
  • --plugin-cache PLUGIN_CACHE — Путь к Codex plugin cache (для диагностики нестандартной установки)

diagnostics export

  • --run-id
  • --output OUTPUT
  • --log LOG (по умолчанию: PosixPath('data/logs/hhru_bot.log'))
  • --dom-dir DOM_DIR (по умолчанию: PosixPath('data/logs'))

edit-education

Составляет LLM-план образования и заполняет поля через UI hh.ru. --dry-run не нажимает Save; боевой режим требует --force или TTY-подтверждение.

  • --resume — Slug из конфига или реальный resume_id HH.ru (#319)
  • --section — Какой блок редактировать (по умолчанию: оба) (по умолчанию: 'both')
  • --source — Контекст кандидата (переопределяет education.source)
  • --mode — Режим планирования
  • --institution — Учебное заведение (основное образование, без LLM)
  • --faculty — Факультет (основное образование, без LLM)
  • --specialty — Специальность (без LLM)
  • --year — Год окончания (без LLM)
  • --primary-entry — Готовая запись основного образования JSON без LLM (#326), можно несколько: '{"institution":..., "faculty":..., "specialty":..., "year":...}'
  • --additional-entry — Готовая запись доп. образования JSON без LLM (#326), можно несколько: '{"institution":..., "organization":..., "specialty":..., "year":...}'
  • --dry-run — Заполнить только локальную форму; Save не нажимать
  • --force — Разрешить боевое сохранение

edit-experience

Предлагает записи опыта через LLM и показывает их в dry-run. WRITE-hh-ru: боевой режим требует --force или подтверждения TTY. Опыт работы общий для всех резюме аккаунта (#782): --resume задаёт не 'куда писать', а какое резюме останется отмеченным в панели привязки hh.ru.

  • --resume — Slug из конфига или реальный resume_id HH.ru (#319). Опыт общий для профиля (#782) — резюме определяет привязку, не место записи.
  • --mode — Режим LLM-планирования, действует только вместе с --career: fill — до-заполнить существующие записи (по умолчанию), create — составить план с нуля. При --entry не действует: ручной путь сам читает живое состояние резюме; явный fill идентичен умолчанию, create будет отвергнут (#326). (по умолчанию: 'fill')
  • --career — Факты карьеры для LLM (обязательно без --entry)
  • --entry — Готовая запись опыта JSON без LLM (#326), можно несколько: '{"company":..., "position":..., "start_year":..., "start_month":..., "end_year":..., "end_month":..., "current":..., "duties":..., "achievements":[...], "company_url":...}'. start_month обязателен (число 1-12 строкой) — форма опыта hh.ru не сохраняется без месяца начала работы (#811). Записи только ДОБАВЛЯЮТСЯ к резюме (#957): существующие строки печатаются перед записью и не меняются, а дубликат (та же компания+должность+начало) отклоняется.
  • --existing EXISTING — JSON-массив существующих записей для LLM-планирования: в режиме fill заменяет живое чтение hh.ru, в create уходит в контекст промпта и служит fallback-планом
  • --dry-run — Показать план, не нажимая save
  • --force — Разрешить запись без TTY prompt

edit-languages

Без --language: LLM только предлагает языки (уровень CEFR не угадывается и не пишется на hh.ru). С --language NAME=CEFR: записывает явно подтверждённые языки. Раздел 'Языки' общий для всего профиля hh.ru: запись применяется ко всем резюме аккаунта, а не только к --resume.

  • --resume — Slug из конфига или resume_id HH.ru — используется только для выбора аккаунт-сессии; языки общие для всего профиля
  • --mode — (по умолчанию: 'append')
  • --language — Добавить язык вручную; CEFR: A1, A2, B1, B2, C1 или C2 (можно повторять)
  • --dry-run — Показать план без записи (только с --language; без него запись не идёт всегда)
  • --force — Подтвердить WRITE без prompt (только с --language)

edit-skills

Предлагает навыки с уровнями и, после явного подтверждения, добавляет их в inline-форму hh.ru. Без --dry-run боевой запуск требует --force или TTY-подтверждение.

  • --resume — Slug из конфига или реальный resume_id HH.ru (#319)
  • --mode — (по умолчанию: 'append')
  • --skill — Добавить навык вручную; LEVEL: basic, intermediate или advanced (можно повторять)
  • --dry-run — Показать план и отменить форму без сохранения
  • --force — Подтвердить WRITE без интерактивного вопроса

fill-form

  • --url — Явный URL внешней формы
  • --resume — ID резюме из конфига
  • --dry-run — Обязательный режим: без submit и навигации формы

funnel

  • --resume — Slug из конфига или resume_id HH.ru (по умолчанию — все)
  • --search-query — Группировать воронку по поисковому запросу вместо резюме
  • --format — Формат вывода: table (по умолчанию) или md (по умолчанию: 'table')
  • --period PERIOD — Срез за последние N дней (по умолчанию 30; 0 = за всё время) (по умолчанию: 30)
  • --dead — Показать «мёртвую зону»: отклики без ответа старше --dead-days
  • --dead-days DEAD_DAYS — Порог «мёртвой зоны» в днях (по умолчанию 14) (по умолчанию: 14)
  • --rejections — Показать агрегат отказов по работодателю, поиску и вилке зарплаты

import-cookies

  • --profile PROFILE — Путь к профилю Chrome или имя профиля (Default, Profile 1) — имя резолвится от стандартного корня профилей Chrome

learn

  • --resume — Slug резюме для исключения уже указанных навыков
  • --limit LIMIT — Сколько строк вывести (по умолчанию: 20)

list-resumes

  • --status — Дополнительно: можно ли поднять (кулдаун) и дата последнего поднятия
  • --local — Без похода на hh.ru: только записи config.yaml (overlay настроек)

log

  • -n, --lines LINES — Количество строк (по умолчанию 50) (по умолчанию: 50)
  • -f, --follow — Следить за логом (tail -f); прерывается по Ctrl-C
  • --prune — Чистка дампов probe/apply (.html/.png) в data/logs; по умолчанию только план (dry-run), удаление — по --yes или TTY-подтверждению
  • --older-than DAYS — Удалять дампы старше N дней (по умолчанию 14) (по умолчанию: 14)
  • --yes — С --prune: подтвердить удаление без TTY prompt

login

  • (без аргументов)

login-code

  • --login — Email или телефон
  • --code-file CODE_FILE — Файл с одноразовым кодом; без него код читается из stdin

mark

  • --resume — Slug из конфига или resume_id HH.ru (обязательно)
  • --vacancy — ID вакансии (число из URL https://hh.ru/vacancy/)
  • --status — Статус для пометки (по умолчанию offer) (по умолчанию: 'offer')

market

  • --estimates — Достроить медиану эвристическими оценками ЗП для вакансий без указанной (помечаются ~). По умолчанию только реальные ЗП

probe

  • --resume — Slug из конфига или resume_id HH.ru (по умолчанию — все)
  • --dry-run — Показать, что будет сделано, без реальных действий
  • --max-pages MAX_PAGES — Максимум страниц поиска (по умолчанию: 5)
  • --vacancy-id — ID целевой вакансии (число из URL https://hh.ru/vacancy/)
  • --vacancy-url — URL целевой вакансии (альтернатива --vacancy-id)
  • --start-page START_PAGE — Начальная страница поиска (нумерация с 0)
  • --healthcheck — Read-only проверка ключевых селекторов hh.ru (OK/NOT_FOUND) без отклика (#88)
  • --json — Добавить machine-readable JSON-результат healthcheck
  • --negotiations — Read-only дамп списка переговоров или чата без отправки (#107)
  • --topic — ID topic из SSR-дампа negotiations для открытия чата (только чтение)
  • --questionnaires-only — Read-only на hh.ru bulk-проверка анкет; подтверждённые вопросы пишутся в локальную SQLite, без заполнения, AI и submit
  • --limit-questionnaires LIMIT_QUESTIONNAIRES — Остановить bulk-проверку после N подтверждённых анкет (0 — без лимита)

professional-roles

Без --refresh читает только data/cache/professional_roles.json. --refresh открывает live-каталог поиска вакансий (фильтры /search/vacancy), но не выбирает профессии и не нажимает «Сохранить».

  • --query — Короткое название профессии для локального поиска (можно повторять)
  • --limit LIMIT — Максимум кандидатов в выводе (по умолчанию: 20)
  • --refresh — Явно перечитать полный live-каталог поиска вакансий и атомарно обновить локальный кэш

profile

Установить, показать или удалить ручные ответы профиля.

  • (без аргументов)

profile set

  • (без аргументов)

profile show

  • (без аргументов)

profile unset

  • (без аргументов)

publish-resume

Публикует черновик резюме кликом по кнопке hh.ru. WRITE-hh-ru: боевой режим требует --force; --dry-run ничего не нажимает.

  • --resume — Slug из конфига или реальный resume_id HH.ru (#319)
  • --dry-run — Проверить состояние без клика
  • --force — Разрешить боевой UI-клик

query

Исполнить SELECT к history.db и вывести ASCII-таблицу или CSV. Только read-only (SELECT/WITH) — история меняется только через бот.

  • --csv — Вывести CSV вместо ASCII-таблицы
  • -o — Записать результат в файл вместо stdout

questionnaire

Показать очередь, аудит и шаблоны, задать ответ или обучить шаблон.

  • (без аргументов)

questionnaire audit

Что бот ответил в анкетах: ответ, уверенность, шаблон.

  • --resume — Slug резюме или resume_id (по умолчанию — все)
  • --last LIMIT — Сколько последних ответов показать (по умолчанию: 50)
  • --template — Только ответы этого шаблона
  • --low-confidence — Только вопросы, на которые бот не стал отвечать

questionnaire learn

Интерактивный разбор накопившихся вопросов анкет.

  • --resume — Slug резюме или resume_id
  • --limit LIMIT — Сколько вопросов разобрать (по умолчанию: 20)

questionnaire pending

Вопросы, на которые бот не стал отвечать сам.

  • --resume — Slug резюме или resume_id (по умолчанию — все)
  • --limit LIMIT — Сколько строк вывести (по умолчанию: 50)

questionnaire set

static — готовое значение; contextual — инструкция для LLM.

  • --mode — static (значение) или contextual (инструкция)
  • --answer — Готовый ответ (для --mode static)
  • --instruction — Инструкция для LLM (для --mode contextual)
  • --example — Формулировка вопроса, относящаяся к этому шаблону (можно повторять)
  • --cluster — Тематический кластер вопроса
  • --resume — Задать только для этого резюме

questionnaire templates

Шаблоны уровня аккаунта и переопределения резюме.

  • --resume — Slug резюме или resume_id

questionnaire unset

Удаляет шаблон только из своего скоупа.

  • --resume — Снять только переопределение этого резюме

refresh-token

  • --force — Пересохранить подтверждённую сессию в storage_state

reject

  • --resume — ID резюме
  • --vacancy — ID вакансии
  • --reason — Причина ручного отклонения
  • --generated-letter — Сгенерированное письмо до ручной правки
  • --edited-letter — Письмо после ручной правки

rename-resume

Изменяет название одного резюме в списке hh.ru. WRITE-hh-ru: боевой режим требует --force или интерактивного подтверждения; --dry-run ничего не сохраняет. До подтверждения селектора поля названия в живом DOM боевой режим недоступен (fail-closed).

  • --resume — Slug из конфига или resume_id HH.ru
  • --name — Новое название резюме
  • --dry-run — Показать план без записи
  • --force — Подтвердить боевую запись

reply-employers

Account-wide ответы в чатах: план из локальной истории, финальная проверка живого чата и запись аудита.

  • --dry-run — Показать план без отправки
  • --limit LIMIT — Максимум чатов за запуск (0 = все)
  • --max-pages MAX_PAGES — Максимум страниц negotiations для SSR mapping (по умолчанию 5) (по умолчанию: 5)
  • --template TEMPLATE — Текст ответа (по умолчанию cover_letter_default)
  • --suggest — Сгенерировать и сохранить draft по входящему сообщению (без отправки)
  • --follow-up — Режим напоминания (#710): вместо ответа на входящее — напомнить о себе там, где последнее слово уже за нами и работодатель молчит --after-days N
  • --after-days AFTER_DAYS — Порог молчания работодателя в днях для --follow-up (обязателен вместе с ним)
  • --force — Подтвердить боевой запуск

report-vacancy

Открывает вакансию, кликает 'Ещё' -> 'Пожаловаться на вакансию', выбирает причину и заполняет комментарий. Останавливается ПЕРЕД финальной отправкой (issue #745): этот шаг не подтверждён живым DOM и намеренно не реализован. Всегда завершается [FAIL] — жалоба не отправляется этой командой ни при каких условиях.

  • --vacancy-id — ID вакансии (число из URL https://hh.ru/vacancy/)
  • --reason — Причина жалобы (подтверждённый перечень hh.ru)
  • --comment — Комментарий к жалобе (обязателен для всех причин на hh.ru)
  • --dry-run — Показать план без открытия формы (по умолчанию; --force доходит до формы) (по умолчанию: True)
  • --force — Дойти до заполненной формы жалобы (без отправки — см. описание команды)

responses

  • --resume — ID резюме из конфига (по умолчанию — все)
  • --max-pages MAX_PAGES — Максимум страниц списка откликов (по умолчанию 5) (по умолчанию: 5)
  • --since-hours SINCE_HOURS — Показать ответы, сменившие статус за последние N часов (по умолчанию 24). 0 — выполнить живой обход hh.ru и показать синхронизацию/историю. (по умолчанию: 24.0)
  • --detect-external-tests — Прочитать последние сообщения работодателей и записать внешние тесты (#180)
  • --remindable — Показать переписки, для которых hh.ru явно разрешает напоминание
  • --sync-applied — Импортировать однозначные ручные/внешние отклики в dedup ledger
  • --alert-new — Сообщить о новых приглашениях и вернуть специальный exit-код
  • --calendar-hint — Для каждого нового приглашения напечатать готовую команду hhru calendar event с плейсхолдерами времени (#711)

restore

  • --apply — Выполнить восстановление (без флага — только показать состав)

resume-pool

Копирует базовое резюме --source по разу на каждый недостающий кластер вакансий (resume_clusters.py) и помечает каждую копию своим кластером в config.yaml. WRITE-команда: боевой режим требует --force или интерактивного подтверждения; --dry-run показывает полный план без обращения к hh.ru.

  • --source — Slug из конфига или реальный resume_id HH.ru базового резюме (#319)
  • --dry-run — Показать план создания пула без реальных действий
  • --force — Подтвердить боевой запуск без интерактивного вопроса
  • --write-config — Добавить каждую успешно созданную копию в config.yaml с её кластером
  • --limit LIMIT — Предел числа создаваемых за прогон копий (по умолчанию — все недостающие кластеры; троттлинга у copy-resume нет вовсе, поэтому предел обязателен для контролируемого batch-запуска)

resume-position

  • --resume — Slug из конфига или реальный resume_id HH.ru (#319)
  • --title — Готовая желаемая должность без LLM (#326)
  • --specialization — Точная профессия из live-каталога поиска вакансий hh.ru; для черновика одна, для опубликованного резюме можно несколько
  • --salary SALARY — Зарплата (целое число, без LLM)
  • --currency — Валюта зарплаты
  • --employment — Тип занятости (пока только одно значение — #526)
  • --work-format — Формат работы (пока только одно значение — #526)
  • --commute — Время в пути
  • --business-trips — Готовность к командировкам
  • --mode — Режим LLM-планирования (по умолчанию fill); не сочетается с ручными полями
  • --dry-run — Показать план без изменения hh.ru
  • --force — Подтвердить запись без prompt
  • --allow-auto-publish — Разрешить закрытие professional_role, после которого hh.ru может автоматически опубликовать резюме
  • --fallback-other — Если специализация не найдена в дереве резюме — выбрать роль-плейсхолдер «Другое» (id 40) вместо отказа (#950)

resume-sections

Заполняет аттестации и рекомендации по подтвержденным UI-маршрутам; умеет создать первую строку в пустом блоке. Сертификаты, портфолио и ссылки пока пропускаются, удаления не выполняются.

  • --resume — Slug из конфига или реальный resume_id HH.ru (#319)
  • --attestation — Готовая аттестация JSON без LLM (#326), можно несколько: '{"name":..., "organization":..., "specialty":..., "year":...}'
  • --recommendation — Готовая рекомендация JSON без LLM (#326), можно несколько: '{"text":..., "company":..., "name":..., "position":...}'. text не поддерживается текущей формой HH.ru и приведёт к [FAIL] для этой строки, если непустой (#367).
  • --dry-run — Показать план без изменений на hh.ru
  • --force — Подтвердить WRITE без prompt

resume-views

  • --resume — ID резюме (по умолчанию — все резюме)
  • --limit LIMIT — Максимум snapshots на резюме (по умолчанию 100) (по умолчанию: 100)
  • --max-pages MAX_PAGES — Максимум страниц истории (по умолчанию 5) (по умолчанию: 5)

resume-visibility

Изменяет режим видимости резюме и/или список работодателей whitelist/blacklist ('Кто видит'/'Кто не видит'). WRITE-hh.ru опасного уровня: боевой режим требует --force или подтверждения; --dry-run ничего не сохраняет. --resume all применяет одно и то же действие ко всем резюме аккаунта (основной сценарий: стоп-лист обычно общий для всех резюме).

  • --resume — Slug из конфига, resume_id HH.ru или 'all' — все резюме аккаунта
  • --mode — Новый режим видимости; без флага — режим не меняется, редактируется только список
  • --add-employer — Добавить работодателя в активный whitelist/blacklist (можно повторять)
  • --remove-employer — Убрать работодателя из активного whitelist/blacklist (можно повторять)
  • --dry-run — Показать план без записи
  • --force — Подтвердить боевую запись

review

  • (без аргументов)

review approve

  • --ttl TTL (по умолчанию: 900)

review edit

  • (без аргументов)

review list

  • --status

review requeue

  • (без аргументов)

review skip

  • (без аргументов)

robot-queue

  • --limit LIMIT — (по умолчанию: 50)

run

  • --resume — Slug из конфига или resume_id HH.ru (по умолчанию — все)
  • --dry-run — Показать, что будет сделано, без реальных действий
  • --max-pages MAX_PAGES — Явный максимум страниц поиска (по умолчанию — адаптивный)
  • --force — Разрешить реальную отправку отклика с LLM-ответами на вопросы
  • --learn-questionnaires — Спрашивать подтверждение сопоставления вопроса анкеты с шаблоном
  • --limit LIMIT — Целевое число успешных откликов за запуск (0 = без ограничения кроме дневного лимита)

schedule

  • --format — Формат вывода: plist (launchd, по умолчанию) или crontab (по умолчанию: 'plist')
  • --action — Какое действие планировать: bump/run (периодически) или apply (раз в день) (по умолчанию: 'bump')
  • --bump-interval-hours BUMP_INTERVAL_HOURS — Интервал запуска bump/run в часах (по умолчанию 4, равен кулдауну) (по умолчанию: 4)
  • --apply-time — Время ежедневного apply в формате HH:MM (по умолчанию 10:00) (по умолчанию: '10:00')
  • --apply-limit APPLY_LIMIT — Лимит откликов за один apply-прогон (по умолчанию 5) (по умолчанию: 5)

search

  • --resume — Slug из конфига или resume_id HH.ru (по умолчанию — все)
  • --dry-run — Показать, что будет сделано, без реальных действий
  • --max-pages MAX_PAGES — Максимум страниц поиска (по умолчанию: 5)
  • --text — Разовый текст поиска; можно использовать без --resume

select-photo

Открывает вьюер фото на странице резюме кнопкой-карандашом, показывает библиотеку фото аккаунта и назначает выбранное фото этому резюме (в том числе замену существующего). WRITE-hh-ru: по умолчанию dry-run (read-only инвентарь библиотеки); боевой запуск требует --photo-id и --force или интерактивного подтверждения.

  • --resume — Slug из конфига или resume_id HH.ru
  • --photo-id — Числовой id фото из dry-run инвентаря (обязателен в боевом режиме)
  • --dry-run — Показать библиотеку фото, ничего не назначая
  • --force — Подтвердить боевое назначение

settings

Показать все настройки, получить значение или установить ключ.

  • (без аргументов)

skipped

Показать записи skipped с данными вакансий из локальной истории.

  • --reason — Показать только эту причину (по умолчанию — все причины)

stats

  • --resume — Slug из конфига или resume_id HH.ru (по умолчанию — все)
  • --period — Период агрегации (по умолчанию all) (по умолчанию: 'all')
  • --format — Формат вывода: table (по умолчанию), csv, md (по умолчанию: 'table')
  • --list — Вместо сводки вывести список последних действий
  • --limit LIMIT — Лимит строк в режиме --list (по умолчанию 50) (по умолчанию: 50)

uncertain

  • (без аргументов)

uncertain inspect

  • (без аргументов)

uncertain list

  • --limit LIMIT (по умолчанию: 50)

uncertain reconcile

  • (без аргументов)

update

Обновляет hhru и установленный Codex plugin из одного commit, проверяет provenance обоих компонентов и явно завершается ошибкой при частичном сбое. Уже открытая задача Codex продолжит использовать старый skill — после обновления начните новую задачу.

  • --codex — Путь к Codex CLI (для диагностики и тестов; по умолчанию: codex) (по умолчанию: 'codex')

upload-photo

Передаёт файл фото в скрытый file-input блока аватара на странице резюме. WRITE-hh-ru: по умолчанию только dry-run (read-only осмотр блока фото); боевой запуск требует --force или интерактивного подтверждения. Замена существующего фото не поддерживается.

  • --resume — Slug из конфига или resume_id HH.ru
  • --photo PHOTO — Путь к файлу jpg/jpeg/png
  • --dry-run — Осмотреть блок фото, ничего не загружая
  • --force — Подтвердить боевую загрузку

whoami

  • --resume — Slug из конфига или resume_id HH.ru (по умолчанию — все)
  • --online — Проверить сессию на hh.ru (открывает браузер)

wizard-next

Кликает «Сохранить и продолжить» на незавершённом экране визарда черновика. WRITE-hh-ru: боевой режим требует --force; --allow-auto-publish нужен только на последнем незакрытом экране — hh.ru публикует резюме сам (#900, #1012); --dry-run ничего не нажимает.

  • --resume — Slug из конфига или реальный resume_id HH.ru (#319)
  • --screen — Явный экран; по умолчанию — текущий nextIncompleteScreenId
  • --dry-run — Проверить экран без клика
  • --force — Разрешить боевой UI-клик
  • --allow-auto-publish — Разрешить сабмит последнего незакрытого экрана: hh.ru опубликует резюме сам (#900, #1012). На промежуточных экранах не требуется

Как это устроено

  • config.py — загрузка data/config.yaml.
  • history.py — локальная SQLite-история (data/history.db).
  • throttle.py — случайные паузы и дневные лимиты.
  • browser.py/auth.py — запуск Playwright и вход в аккаунт.
  • search.py — поиск вакансий и фильтрация.
  • apply.py — отклик с сопроводительным письмом.
  • bump.py — поднятие резюме.
  • selectors.py — все CSS/data-qa селекторы hh.ru в одном месте.

Всё — в src/hhru_bot/.

Логи

data/logs/hhru_bot.log и консоль, --verbose для подробностей. Ротация при 10 MiB (hhru_bot.log.1, .2...), архивы копятся без автоочистки.

Похожие проекты (для идей)

Источник идей, не код для копирования — смотреть, а не переиспользовать.

15 декабря 2025 hh.ru закрыл соискательский API — отклик и работа с резюме для сторонних приложений отключены, остался поиск вакансий и GET /me. Все живые проекты 2026 года, как и наш, работают через браузер (Playwright), а не через API.

Браузерные боты (наш стек — Playwright/Selenium)

  • Steev193/hh-ru-apply — Node + Playwright, MIT. Вынесенные селекторы + codegen для их обновления.

  • tgeruzov/hh-auto-responder — Tampermonkey userscript. Роутинг трёх исходов отклика.

  • YAMAKAYAMACO/hh-autoresponder — Python + Playwright + SQLite, ближе всего к нашей архитектуре.

  • fikstt2/hh-ai-agent — Python + Playwright. Персистентная сессия: вход руками один раз, потом headless.

  • semernyakov/hh-auto-apply — Python + Playwright, MIT. Парсер cooldown поднятия резюме из текста hh.ru.

  • beatwad/XX_Auto_Jobs_Applier — Python + Playwright, MIT. Config-driven (YAML), капча через Telegram.

  • s3rgeym/hh-applicant-tool — Python, API + Playwright, 500+ звёзд. Эталон по шаблонам писем, схеме SQLite и троттлингу. README запрещает коммерческое использование — только как референс, код не брать.

  • konard/hh-job-application-automation — Bun, Playwright и Puppeteer, Unlicense. Q&A-файл с нечётким матчем (Левенштейн + keyword overlap) для тест-вопросов формы.

Поднятие резюме

  • Vlad9572324/hh.ru-clicker — bump через API /applicant/resumes/touch (проверять актуальность после дек. 2025).
  • rycln/hhraiser — Go. Джиттер расписания против антифрода.

Адаптация и хранение резюме

Отдельный трек (issue #671) от ботов-автооткликов выше: у нас резюме — внешний артефакт на hh.ru, эти проекты работают с резюме как с локальными данными (JSON/PDF/веб-форма). Разобран по коду один прошедший фильтр по лицензии и активности кандидат из восьми рассмотренных — остальные отсеяны, причины ниже.

  • srbhr/Resume-Matcher — Python (FastAPI) + TypeScript, Apache-2.0, ревизия 116f9cc3b00e1ac91734a6c2679bf41ea64a0edc (2026-08-11). Единственный кандидат про адаптацию резюме под конкретную вакансию — задачу, которую наш проект пока не решает. Заимствуемая идея не код, а два механизма:

    • apps/backend/app/services/improver.py двигает содержимое резюме под вакансию через diff-патчи по regex-whitelist путей (_ALLOWED_PATH_PATTERNS — только summary, description-поля и списки навыков/языков/сертификатов) и явный blocklist полей (_BLOCKED_FIELD_NAMES — company, institution, title, years и т.п. трогать нельзя); LLM физически не может переписать факты вроде места работы или диплома, только формулировки.
    • apps/backend/app/services/refiner.py::validate_master_alignment — постфактум-проверка, что ни один навык, сертификат или работодатель в адаптированной версии не появился «из воздуха»: сверяет их с исходным («мастер») резюме и репортит fabricated_skill/fabricated_cert/ fabricated_company как critical-нарушения.

    У нас похожий принцип уже есть с другой стороны — не пост-проверкой LLM-вывода, а входным гейтом до генерации (STRICT_CLUSTERS + templates.is_compliance_text в пакете questionnaires/, см. «Ключевые архитектурные решения» в CLAUDE.md). Whitelist путей на запись и alignment-проверка Resume-Matcher — предметный пример того же принципа «уверенная ошибка здесь необратима», применённый к тексту резюме, а не к ответам на анкеты; полезно как референс, если будет отдельная задача на адаптацию резюме под вакансию.

Отсеяны без разбора по коду (см. issue #671 для метрик):

  • Reactive-Resume, OpenResume — веб-конструкторы резюме с нуля. У нас резюме уже существует на hh.ru и правится по DOM; локальный конструктор — не наша задача. Дополнительно у OpenResume лицензия AGPL-3.0 (портирование кода закрыто) и последний push — октябрь 2024.
  • RenderCV, sb2nov/resume, McDowell CV — генерация предсказуемого PDF/LaTeX резюме как локального файла. Наш артефакт живёт в интерфейсе hh.ru, а не в файле, который мы рендерим сами — вне скоупа.
  • JSON Resume CLI (jsonresume/resume-cli) — репозиторий архивирован; сама структура данных как формат остаётся жизнеспособной идеей, но брать нечего — код не развивается.
  • YAMLResume — та же задача структурированного хранения резюме, что уже закрыта внутри проекта своими средствами (CandidateFacts в конфиге, issue #751), без заимствования у reference-проекта.

Изучены точечно (отдельные селекторы, не полный аудит)

Разобраны по конкретным находкам (docs/research/reference-selector-diff-audit.md), не по всему функционалу — сравнивать их с остальными в таблице фич нечестно.

Обход DDoS-Guard / антидетект браузера

Гарантий обхода DDoS-Guard в headless нет; капчу приходится проходить руками — это уже частично делает login.

Metadata

Release files for hhru-bot 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hhru-bot 0.1.1
File Size Uploaded
hhru_bot-0.1.1.tar.gz 1.7 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for hhru-bot 0.1.1
File Interpreter ABI Platform
hhru_bot-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 2.7 MB

Release files / hhru_bot-0.1.1.tar.gz

Download URL hhru_bot-0.1.1.tar.gz
Size 1.7 MB
Tags Source
SHA-256 checksum
How to use checksums
4e47fc9ac86e35da72c28cac9678d7f7782848f4a40aebf35008fbf4bfe6594c
BLAKE2b-256 checksum
How to use checksums
493255fb2891b27b0533e083c49b6f76a9794234a36f40c08f985d9bb820b83d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Release files / hhru_bot-0.1.1-py3-none-any.whl

Download URL hhru_bot-0.1.1-py3-none-any.whl
Size 951.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e71771ee7a47c94f801fad8c4f3193349d74e47997c2bf648b472cdc5c497c51
BLAKE2b-256 checksum
How to use checksums
2a39134c383b09cdd79a06810112deea0f3ce29b8c291a5194143a15cbbefca2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page