npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@bagasek/firehh

v0.4.0

Published

Bun-powered HeadHunter CLI for vacancy search, resume checks, OAuth tokens, and applications.

Readme

firehh

firehh is a Bun/TypeScript CLI for hh.ru (HeadHunter): OAuth login, resume listing, vacancy search/view, application status, and applying with a cover letter. It is designed for humans and AI agents: scoped commands, deterministic stdout/stderr, compact JSON envelopes, actionable errors, and complete --help at every level.

Install / build

bun install -g @bagasek/firehh
firehh --help

From this repository:

bun install
bun src/firehh.ts --help
bun test
bun run check

60-second quickstart

# 1) Login once. Opens Chrome/Chromium and stores a token.
firehh auth login
# stdout: {"ok":true,"data":{"token_file":"/Users/me/.config/firehh/token.json","expires_at":"2026-07-05T12:00:00.000Z","credential_source":"android","auth_flow":"browser"}}

# 2) Pick a resume id.
firehh resumes list
# stdout: {"ok":true,"data":{"found":1,"items":[{"id":"resume-abc","title":"Frontend Developer","status":"published","area":"Москва","updated_at":"2026-06-30T10:00:00+0300","total_experience_months":72}]}}

# 3) Search vacancies.
firehh vacancies search --text "frontend react" --remote --must "React|TypeScript|Next" --reject "Vue|Angular|React Native" --per-page 5
# stdout: {"ok":true,"data":{"found":120,"matched_items":3,"page":0,"pages":24,"per_page":5,"items":[{"id":"133561763","name":"Frontend React Developer","employer":{"id":"1","name":"Example"},"url":"https://hh.ru/vacancy/133561763",...}]}}

# 4) Inspect one vacancy before applying.
firehh vacancies view 133561763
# stdout: {"ok":true,"data":{"id":"133561763","name":"Frontend React Developer","active":true,"already_applied":false,"description_text":"...","apply_url":"https://hh.ru/applicant/vacancy_response?vacancyId=133561763",...}}

# 5) Dry-run an application payload, then send it.
firehh applications apply 133561763 --resume resume-abc --message-file cover-letter.txt --dry-run
firehh applications apply 133561763 --resume resume-abc --message-file cover-letter.txt
# stdout: {"ok":true,"data":{"applied":true,"negotiation_id":"987654","location":"https://api.hh.ru/negotiations/987654"}}

Command reference

Run firehh --help, firehh <scope> --help, or firehh <scope> <command> --help. A bare scope such as firehh vacancies prints that scope's help and exits 0.

auth

firehh auth login [--timeout <seconds>] [--browser <path>]
firehh auth status
  • auth login opens Chrome/Chromium, captures the hhandroid://oauthresponse redirect via DevTools, exchanges the code, and saves the token. Output data: token_file, expires_at, credential_source, auth_flow.
  • auth status prints token metadata only: token_file, token_source, token_source_file, access_token, refresh_token, expires_at.

resumes

firehh resumes list
firehh resumes for-vacancy <vacancy-id>
  • resumes list output data: found, items:[{id,title,status,area,updated_at,total_experience_months}].
  • resumes for-vacancy checks that the vacancy is remote and from an accredited IT employer, then returns vacancy, already_applied, found, items.

vacancies

firehh vacancies view <vacancy-id>
firehh vacancies search [--text <query>] [--area <id>] [--remote] [--hybrid] [--employment <id>] [--experience <id>] [--salary-from <n>] [--salary-to <n>] [--only-accredited] [--published-after <date>] [--must <regex>] [--reject <regex>] [--format json|tsv|md|jsonl] [--page <n>] [--per-page <n>]
firehh vacancies suitable <resume-id> [--page <n>] [--per-page <n>]
  • vacancies view output data includes normalized active, archived, salary.gross, contacts, apply_url, already_applied, description_text, and formalization.{labor_contract,gph,project_work,individual_entrepreneur}.
  • vacancies search uses hh.ru API filters plus local filters for salary bounds, accreditation, --must, and --reject. Defaults: --format json, --page 0, --per-page 20. JSON output data: found, matched_items, page, pages, per_page, items. --format tsv|md|jsonl writes raw rows to stdout without the {ok} envelope.
  • vacancies suitable searches hh.ru suitable vacancies by resume id. Output data: resume_id, query, found, page, pages, per_page, items.

applications

firehh applications apply <vacancy-id> --resume <resume-id> (--message <text> | --message-file <path>) [--dry-run]
firehh applications status <vacancy-id>
firehh applications list [--since <date>] [--page <n>] [--per-page <n>]
  • applications apply sends the requested vacancy, resume, and cover letter to hh.ru without local eligibility checks. --dry-run output data: dry_run, vacancy_id, resume_id, cover_letter_chars, cover_letter; real apply output data: applied, negotiation_id, location.
  • applications status output data: vacancy_id, already_applied, items.
  • applications list output data: since, page, per_page, scanned_pages, items:[{id,created_at,updated_at,state,employer_state,has_updates,viewed_by_opponent,vacancy,resume}]. Defaults: --page 0, --per-page 50.

Output contract and errors

  • Success JSON stdout: {"ok":true,"data":...}.
  • Error JSON stderr: {"ok":false,"error":{"code":"...","message":"..."}}.
  • Interactive prompts, browser progress, diagnostics, and update notices go to stderr.
  • Help/version are text on stdout.
  • Exception: firehh vacancies search --format tsv|md|jsonl writes raw machine-friendly rows to stdout.

Exit codes:

  • 0: success, help, or version.
  • 1: input/usage error (INPUT_ERROR) such as unknown command, unknown flag, missing required arg, invalid date/number/regex.
  • 2: auth, browser, hh.ru API, or runtime failure (AUTH_ERROR, HH_ERROR, hh_<status>, captcha, direct_response).

Important error codes:

  • INPUT_ERROR: fix invocation; rerun the command with --help.
  • AUTH_ERROR / missing token message: run firehh auth login.
  • captcha: stderr includes captcha_url; open it, solve it, then retry the same command.
  • direct_response: hh.ru requires manual apply; open returned url.
  • hh_<status>: hh.ru API returned HTTP status; message is compacted from the API response.

Authentication

The CLI includes hh.ru Android OAuth credentials, so login works without a project .env:

firehh auth login

Token lookup precedence:

  1. HH_ACCESS_TOKEN or HH_TOKEN environment variable. The value may be a raw access token or a JSON token object.
  2. Token file at ~/.config/firehh/token.json, or HH_TOKEN_FILE when set.

Stored tokens are refreshed automatically when expires_at is near and refresh_token exists. If refresh is impossible, run firehh auth login again.

Optional environment overrides:

HH_CLIENT_ID=
HH_CLIENT_SECRET=
HH_REDIRECT_URI=hhandroid://oauthresponse
HH_TOKEN_FILE=
HH_ACCESS_TOKEN=

Using with AI agents

firehh is agent-friendly beyond “it returns JSON”:

  • --help is self-contained: commands, flags, defaults, output shape, exit codes, and examples.
  • Every command is scoped (auth, resumes, vacancies, applications), so discovery is predictable.
  • Unknown commands/flags include nearest alternatives and a concrete help command.
  • Stdout is reserved for data; stderr is reserved for prompts/errors/diagnostics.
  • Exit code 1 means the agent should fix its invocation; exit code 2 means auth/hh.ru/browser state needs attention.

Examples:

firehh vacancies search --text "frontend react" --remote \
  | jq -r '.data.items[] | [.id, .name, .employer.name, .url] | @tsv'

if ! out=$(firehh resumes list 2>err.json); then
  jq -r '.error.message' err.json >&2
fi

Platform notes

  • Runtime: Bun.
  • Browser OAuth: Chrome/Chromium with DevTools; tested primarily on macOS.
  • DOCX cover letters: converted with macOS textutil. On non-macOS, convert DOCX to .txt yourself or pass --message.