LLM-powered resume analysis, extraction, and scoring
Project description
Hyre
Hire on evidence, not vibes.
Reads a resume, extracts what matters, and shows you the full picture.
Our goal: take what HackerRank's Hiring Agent started and build on top of it. Better CLI, better output, cleaner code. Everything stays open source.
Install it with pip install -e . and the hyre command is available anywhere in your terminal. Or use the one-liner above.
Hyre turns a resume PDF into Markdown, runs it through LLM pipelines for layout analysis, data extraction, and scoring, then shows the results in a rich terminal UI.
Commands
hyre analyze <resume.pdf> # Analyze resume layout
hyre extract <resume.pdf> # Extract structured data (JSON Resume)
hyre evaluate <resume.pdf> # Score resume across 4 categories
analyze (layout analysis)
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Layout Analysis ┃
┃ Layout: Two Column ┃
┃ Method: Column boundary detection ┃
┃ Confidence: high ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
Section Order
├─ Header
├─ Summary
├─ Experience
├─ Education
├─ Skills
└─ Projects
Subsections with Columns
┌──────────────┬─────────┬────────────────┬──────────┐
│ Subsection │ Columns │ Items │ Evidence │
├──────────────┼─────────┼────────────────┼──────────┤
│ Skills │ 2 │ Python, Go,... │ Sidebar │
└──────────────┴─────────┴────────────────┴──────────┘
extract (structured data)
╭────────────────────────────────╮
│ Jane Doe │
│ fauzan@example.com │
│ github.com/fauzan │
╰────────────────────────────────╯
Work Experience (3)
├─ Senior Engineer @ Acme Corp 2021-03 – present
│ └─ Led team of 5, built microservice infra
├─ Software Engineer @ Beta Inc 2018-06 – 2021-02
│ └─ Built REST APIs, reduced latency 40%
└─ Junior Dev @ Gamma LLC 2016-01 – 2018-05
└─ Maintained legacy app
Skills (4 categories)
┌──────────────┬──────────────────────────┐
│ Category │ Skills │
├──────────────┼──────────────────────────┤
│ Languages │ Python, TypeScript, Go │
│ Frameworks │ React, FastAPI, Next.js │
│ Tools │ Docker, Kubernetes │
│ Databases │ Postgres, Redis │
└──────────────┴──────────────────────────┘
Education (1)
┌──────────────┬────────┬───────┬──────────────┬───────┐
│ Institution │ Degree │ Field │ Dates │ Score │
├──────────────┼────────┼───────┼──────────────┼───────┤
│ MIT │ BSc │ CS │ 2012 – 2016 │ 3.8 │
└──────────────┴────────┴───────┴──────────────┴───────┘
evaluate (scoring)
╭──────────────────────────────────────╮
│ Resume Evaluation: Fauzan │
╰──────────────────────────────────────╯
Category Scores
┌──────────────────┬─────────┬──────────────────────┬──────────────────┐
│ Category │ Score │ Bar │ Evidence │
├──────────────────┼─────────┼──────────────────────┼──────────────────┤
│ Open Source │ 18/35 │ █████░░░░░░ 51% │ 2 minor PRs │
│ Self Projects │ 24/30 │ ████████░░ 80% │ Strong portfolio │
│ Production │ 15/25 │ █████░░░░░░ 60% │ 3 yrs exp │
│ Technical Skills │ 8/10 │ ██████████ 80% │ Broad stack │
├──────────────────┼─────────┼──────────────────────┼──────────────────┤
│ Total │ 65/100 │ │ │
│ Bonus: +5 Deductions: -2 │ │ Final: 68/120 │
└──────────────────┴─────────┴──────────────────────┴──────────────────┘
╭─── Bonus Points (+5) ──────────────────────────────╮
│ Notable volunteer work, blog, GSoC participation │
╰────────────────────────────────────────────────────╯
╭─── Deductions (-2) ────────────────────────────────╮
│ Missing GitHub links for 1 project │
╰────────────────────────────────────────────────────╯
╭─── Key Strengths ──────────────────────────────────╮
│ • Strong full-stack engineering experience │
│ • Complex personal projects with real-world impact │
│ • Broad technical skills across the stack │
╰────────────────────────────────────────────────────╯
╭─── Areas for Improvement ──────────────────────────╮
│ • Limited open source contributions │
│ • Consider enhancing technical communication │
╰────────────────────────────────────────────────────╯
How it works
PDF → Markdown → LLM → Structured Data → Rich TUI
│ │ │
│ pymupdf4llm │ Jinja │ Typer + Rich
│ │ templates │
1. PDF → Text
PDFParser uses pymupdf4llm to convert PDF pages to clean Markdown. Headings, links, and tables all survive the round trip.
2. Text → Structured Data
The core.Hyre orchestrator sends the Markdown to an LLM with Jinja2 system prompts from core/prompts/. Each command (analyze, extract, evaluate) uses a different prompt template.
3. Rich TUI Output
Results render with rich: tables, trees, panels, color-coded score bars, and progress spinners while the LLM works.
Quick start
One-liner (Linux / macOS)
curl -sSL https://raw.githubusercontent.com/grandimam/hyre/main/install.sh | bash
Or if you prefer wget:
wget -qO- https://raw.githubusercontent.com/grandimam/hyre/main/install.sh | bash
This installs to ~/.hyre, creates a venv, and symlinks the hyre command to ~/.local/bin/hyre.
Prerequisites
- Python 3.12+
- An OpenRouter API key
Setup
git clone <your-repo-url> && cd hyre
python -m venv .venv && source .venv/bin/activate
pip install -e .
Configure
cp .env.example .env # then edit .env with your OpenRouter API key
Run on the sample resume
hyre analyze examples/java-engineer.pdf
hyre extract examples/java-engineer.pdf
hyre evaluate examples/java-engineer.pdf
Configuration
| Variable | Default | What it does |
|---|---|---|
OPENROUTER_API_KEY |
required | OpenRouter API key |
MODEL_NAME |
openrouter/openai/gpt-3.5-turbo |
LLM model to use |
PROMPT_DIR |
prompts |
Directory with .jinja templates |
Project layout
.
├── main.py # CLI entry point (Typer)
├── cli/
│ ├── analyze.py # Layout analysis command
│ ├── extract.py # Structured extraction command
│ └── evaluate.py # Scoring command
├── core/
│ ├── __init__.py # Hyre orchestrator
│ ├── config.py # Pydantic settings
│ ├── constants.py # Role/content constants
│ ├── parsers.py # PDFParser (pymupdf4llm)
│ ├── prompt.py # JinjaPromptProvider
│ ├── schemas.py # Pydantic schemas (GitHub)
│ ├── types.py # Type aliases
│ └── providers/
│ ├── base.py # Provider protocols
│ ├── chat.py # OpenRouterProvider
├── core/prompts/
│ ├── layout.jinja # Layout analysis prompt
│ ├── extract.jinja # Structured extraction prompt
│ └── evaluate.jinja # Resume scoring prompt
├── pyproject.toml
├── uv.lock
└── requirements.txt
What we fixed from Hiring Agent
We started from HackerRank's Hiring Agent and rebuilt most of it. Here is what we think it got wrong:
Too many entry points. Hiring Agent had score.py, pdf.py, github.py all doing overlapping things. You had to dig through the code to figure out which script to run. Hyre has three commands: analyze, extract, evaluate. One entry point (main.py), consistent flags.
No feedback while it runs. You ran score.py and stared at a blank terminal for 30 seconds. Hyre shows a spinner with status messages so you know it is actually working.
Raw JSON dumps. The output was unformatted JSON blobs. Hyre renders tables, trees, panels, and color-coded bars so you can actually read the results.
Single-use architecture. The old code mixed PDF parsing, LLM calls, GitHub fetching, and scoring into one tangled flow. Hyre splits these into a core module with clean interfaces. You can swap parsers, model providers, or prompt loaders without rewriting everything.
Prompt templates scattered. Templates were spread across files with no clear naming convention. Hyre keeps them in prompts/ with one file per command. The JinjaPromptProvider loads them automatically.
Template variables were not being passed. The {{ text_content }} variables in the prompts rendered as empty strings because nobody called template.render() with the resume text. The resume was sent in the user message but the system prompt had a blank where the resume should have been. Hyre passes the parsed text into the template so the LLM sees the full context.
GitHub overreach. Hiring Agent spends a lot of effort fetching GitHub profiles and classifying repos. That is useful but it should not be the main pipeline. Hyre keeps GitHub as a separate provider you can call if you want, not something baked into every resume scan.
We are not done. There is more to fix. But every change stays open source.
License
MIT © HackerRank
Acknowledgments
Hyre is built on Hiring Agent by HackerRank. Their open-source work made this possible. We are committed to keeping it going.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hyre-0.1.0.tar.gz.
File metadata
- Download URL: hyre-0.1.0.tar.gz
- Upload date:
- Size: 23.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6c1a3cda7cdecc56359a296782c99e316c7dd4d9d27fdd033d5703576a554083
|
|
| MD5 |
5eab234e1994c078637d0d498091908a
|
|
| BLAKE2b-256 |
7bc7c629094707b0a15deb1bddc9dc080c2d592b144e640c9377f698943fb08f
|
File details
Details for the file hyre-0.1.0-py3-none-any.whl.
File metadata
- Download URL: hyre-0.1.0-py3-none-any.whl
- Upload date:
- Size: 23.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
91afdbb13c67111ed87a155772627d8191b37c7ad6db2dd1f8a9e048626b568f
|
|
| MD5 |
6099a92e930b4fac48b24db860b1ef48
|
|
| BLAKE2b-256 |
c02bee1de02bb6c1c37941e1ddb2b20ac57dc840c04674397897a1067112bd87
|