AI-powered autonomous job application pipeline — from discovery to submission, completely hands-free.
Discover → Enrich → Score → Tailor → Cover Letter → Apply
Six stages. Three commands. Zero manual work.
JobApply is a 6-stage autonomous job application pipeline that takes you from zero to submitted without ever opening a browser.
It scrapes 5+ major job boards and 78+ employer career portals, scores every listing against your resume using AI, rewrites your resume per position, generates custom cover letters, and autonomously submits applications — navigating complex multi-page forms, uploading documents, and answering screening questions.
All of this happens through three commands:
pip install jobapply
jobapply init # One-time setup
jobapply run # Discover → Enrich → Score → Tailor → Cover Letter
jobapply apply # Autonomous browser-driven application submission| Scrapes Indeed, LinkedIn, Glassdoor, ZipRecruiter, Google Jobs via JobSpy + 48 Workday employer portals + 30 direct career sites. All results deduplicated automatically. | Every job receives a 1–10 fit score based on your resume, skills, experience, and preferences. Only high-fit jobs proceed — saving you hours of manual filtering. |
| AI rewrites your resume for each position — reorders experience, emphasizes relevant skills, incorporates keywords. Never fabricates — your facts are preserved exactly. | Generates a unique, targeted cover letter per job referencing the specific company, role, and how your experience maps to their requirements. |
| Claude Code + Playwright launch a Chrome instance, navigate application forms, detect field types, fill personal info, upload PDFs, answer screening questions — and submit. | Real-time terminal dashboard shows progress across all workers — which jobs are being processed, succeeded, failed, or blocked by CAPTCHAs. |
| Stage | What Happens | Output |
|---|---|---|
| Queries 5 job boards + 48 Workday portals + 30 direct sites. Deduplicates by URL across all sources. | Raw jobs in database | |
| Extracts full job descriptions via 3-tier cascade: JSON-LD → CSS selectors → AI fallback for unknown layouts. | Enriched job records | |
| AI rates each job 1–10 against your profile. Only jobs above your threshold proceed. | Scored + filtered | |
| AI rewrites your resume per job — reorders, emphasizes, incorporates keywords. Facts preserved. | Tailored resume (TXT + PDF) | |
| Generates company + role specific cover letter referencing your actual experience. | Cover letter (TXT + PDF) | |
| Chrome fills forms, uploads PDFs, answers screening questions, and submits. Live dashboard. | ✅ Application submitted |
🔍 Stage 1: Discover — Deep Dive
Discovery runs across three parallel systems:
- JobSpy integration — Queries Indeed, LinkedIn, Glassdoor, ZipRecruiter, and Google Jobs programmatically using
python-jobspy - Workday scraper — Hits 48 preconfigured Workday employer portals (configurable in
employers.yaml), parses job listings from their API - Direct site scraper — Scrapes 30+ direct career sites with custom CSS selectors defined in
sites.yaml
All results are normalized, deduplicated by URL, and stored in a local SQLite database.
jobapply run discover # Run discovery only
jobapply run discover --workers 4 # Parallel discovery📄 Stage 2: Enrich — Deep Dive
Each job URL is visited and the full description is extracted using a 3-tier cascade:
- JSON-LD — Parses structured data embedded in the page's
<script type="application/ld+json">tags (fastest, most reliable) - CSS selectors — Falls back to known selectors for sites like LinkedIn, Indeed, etc. defined in
sites.yaml - AI extraction — For unknown layouts, sends the raw HTML to an LLM which extracts the job description intelligently
This tiered approach ensures >95% extraction success rate while minimizing API costs.
⭐ Stage 3: Score — Deep Dive
The LLM evaluates every enriched job against your complete profile:
| Score Range | Meaning | Action |
|---|---|---|
| 9–10 | Strong match across skills, experience, location, and preferences | ✅ Proceed |
| 7–8 | Good fit with minor gaps | ✅ Proceed |
| 5–6 | Moderate fit — relevant but not ideal | |
| 1–4 | Weak match — misaligned skills or requirements | ❌ Skipped |
Scoring considers years of experience, education level, target role, skills match, location, work authorization, and compensation expectations.
jobapply run score # Score all pending jobs
jobapply run --min-score 8 # Only keep jobs scoring 8+✏️ Stage 4: Tailor — Deep Dive
The tailoring engine creates a custom resume version per job using a two-phase process:
- Generation — The LLM receives your base resume and the job description, then produces a rewritten version optimized for the role. It can reorder experience, emphasize relevant projects, add keywords, and rephrase bullet points.
- Validation — A validator checks the tailored resume against strict rules: no fabricated companies, no inflated metrics, no hallucinated skills. If validation fails, it retries with stricter instructions.
What is preserved exactly (never modified):
- Company names and job titles
- Project names and descriptions
- Quantitative metrics
- Education details
- Years of experience
What is optimized per job:
- Bullet point emphasis and ordering
- Keyword inclusion from job description
- Skills section reordering
- Summary/profile rewording
Output is saved as both .txt (for editing) and .pdf (for submission).
💌 Stage 5: Cover Letter — Deep Dive
The cover letter generator produces a unique, professional cover letter for each job:
- References the specific company name and role title
- Maps your actual experience to their stated requirements
- Maintains a professional tone matching industry standards
- Keeps length appropriate (250–400 words)
Output is saved as both .txt and .pdf.
jobapply run cover # Generate cover letters for all tailored jobs🤖 Stage 6: Auto-Apply — Deep Dive
The auto-apply system uses Claude Code + Playwright to autonomously submit applications:
- Launches an isolated Chrome instance per worker
- Navigates to the job's application URL
- Detects the form type — Workday, Greenhouse, Lever, LinkedIn Easy Apply, or custom ATS
- Fills all fields — name, email, phone, address, work history, education, skills
- Uploads documents — tailored resume + cover letter PDFs
- Answers screening questions — Yes/No, multiple choice, and free-text questions answered by LLM
- Handles CAPTCHAs — Attempts solving via CapSolver API (optional)
- Clicks Submit — Or flags the job for manual review if something goes wrong
A live Rich dashboard shows progress for all workers simultaneously.
jobapply apply # Launch auto-apply (1 worker)
jobapply apply --workers 3 # 3 parallel workers
jobapply apply --dry-run # Fill forms without submitting
jobapply apply --headless # Run without visible browser
jobapply apply --continuous # Keep running, polling for new jobs| Step | Command | What Happens |
|---|---|---|
| 1 | pip install jobapply |
Installs the package and all dependencies |
| 2 | jobapply init |
Interactive wizard — resume, profile, API keys, preferences |
| 3 | jobapply run |
Discovers → enriches → scores → tailors → generates cover letters |
| 4 | jobapply apply |
Launches browser and submits applications autonomously |
# Alternatively, everything in one go:
jobapply run && jobapply apply🔵 Full Pipeline (Recommended)
| Requires | Python 3.11+, Node.js 18+, Gemini API key (free), Claude Code CLI, Chrome |
| Stages | All 6 — from discovery through auto-submission |
| Best for | Users who want fully autonomous job applications |
🟢 Discovery + Tailoring Only
| Requires | Python 3.11+, Gemini API key (free) |
| Stages | 1–5 (discover, enrich, score, tailor, cover letter) |
| Best for | Users who prefer reviewing AI-prepared materials before manual submission |
| Component | Purpose | How to Get |
|---|---|---|
| Core runtime | python.org | |
| Playwright MCP (auto-apply) | nodejs.org | |
| AI scoring, tailoring, cover letters | Free API key | |
| Browser automation | Auto-detected on most systems | |
| Form navigation + submission | claude.ai/code |
LLM Providers Supported: Gemini, OpenAI, DeepSeek, Anthropic, OpenRouter, Ollama, Groq
| Component | What It Does |
|---|---|
| CapSolver API key | Solves CAPTCHAs during auto-apply (hCaptcha, reCAPTCHA, Turnstile, FunCaptcha). Without it, CAPTCHA-blocked applications fail gracefully. |
| Feature | 🚀 JobApply | AIHawk | Manual |
|---|---|---|---|
| Job discovery | 5 boards + Workday + direct sites | LinkedIn only | One tab at a time |
| AI scoring | 1–10 fit score with rationale | Basic keyword filter | Gut feeling |
| Resume tailoring | Per-job AI rewrite | Template-based | Hours per application |
| Auto-apply | Full form navigation + submission | LinkedIn Easy Apply only | Click, type, repeat |
| Cover letters | AI generated per job | ❌ | Hours per letter |
| Site coverage | Indeed, LinkedIn, Glassdoor, ZipRecruiter, Google Jobs, 48 Workday, 30 direct | LinkedIn only | Whatever you open |
| License | AGPL-3.0 | MIT | N/A |
All configuration files are generated by jobapply init — zero manual editing required.
| File | Contents |
|---|---|
profile.json |
Personal data — full name, email, phone, address, work authorization, compensation expectations, experience, skills, resume facts, EEO |
searches.yaml |
Job search configuration — target titles, locations, job boards, tier settings |
.env |
API keys — LLM_PROVIDER, GEMINI_API_KEY, LLM_MODEL, optional CAPSOLVER_API_KEY |
config/employers.yaml |
48 preconfigured Workday employer portals with instance and tenant IDs |
config/sites.yaml |
30+ direct career sites with CSS selectors + blocked sites + SSO domains + ATS patterns |
config/searches.example.yaml |
Example search configuration to use as reference |
Click to expand — full command reference
⚡ SETUP & DIAGNOSTICS
jobapply init First-time interactive setup wizard
jobapply doctor Verify installation — checks Python, Node,
Chrome, API keys, and dependencies
▶️ PIPELINE COMMANDS
jobapply run [stages...] Run one or more pipeline stages
jobapply run --workers 4 Enable parallel discovery/enrichment
jobapply run --stream Run stages concurrently (streaming mode)
jobapply run --min-score 8 Override the minimum fit score threshold
jobapply run --dry-run Preview what would happen without executing
jobapply run --validation lenient Relax validation rules (recommended for Gemini free tier)
jobapply run --validation strict Strict validation with retries on any issues
🤖 AUTO-APPLY COMMANDS
jobapply apply Launch browser-based auto-apply
jobapply apply --workers 3 Run multiple browser workers in parallel
jobapply apply --dry-run Fill forms without clicking Submit
jobapply apply --continuous Run in a loop, polling for new jobs
jobapply apply --headless Run browser without visible UI
jobapply apply --url URL Apply to a specific job by URL
jobapply apply --mark-applied URL Manually mark a job as applied
jobapply apply --mark-failed URL Manually mark a job as failed
jobapply apply --reset-failed Reset all failed jobs for retry
jobapply apply --gen --url URL Generate a prompt file for manual debugging
📊 STATUS & MONITORING
jobapply status Show pipeline statistics and job counts
jobapply dashboard Open the HTML results dashboard in browser
job-apply/
├── src/
│ └── jobapply/ # Main package
│ ├── cli.py # Typer CLI — all command definitions
│ ├── pipeline.py # Stage orchestrator — sequential & streaming
│ ├── config.py # Path resolution, Chrome detection, feature gates
│ ├── database.py # SQLite layer with WAL mode & migrations
│ ├── llm.py # Unified LLM client — 6+ provider support
│ ├── view.py # HTML dashboard generator
│ ├── discovery/ # Stage 1 — job board & portal scrapers
│ ├── enrichment/ # Stage 2 — 3-tier description extraction
│ ├── scoring/ # Stages 3–5 — scoring, tailoring, cover letters, PDF
│ ├── apply/ # Stage 6 — browser automation & form filling
│ └── wizard/ # Interactive setup wizard
├── config/ # Shipped YAML registries (employers, sites)
├── applied-jobs/ # Output directory (created at runtime)
├── pyproject.toml # Package metadata & dependencies
└── resume.txt # Your base resume (plain text)
Contributions of all sizes are welcome — from adding a single Workday employer to building new features.
Ways to contribute:
- 🏢 Add Workday employers — Add entries to
config/employers.yaml - 🌐 Add career sites — Add CSS selectors to
config/sites.yaml - 🐛 Bug fixes — Check open issues
- ✨ Features — Open an issue first to discuss the approach
See CONTRIBUTING.md for full development setup, coding standards (Ruff, type hints, Google-style docstrings), and PR guidelines.
This project is licensed under the GNU Affero General Public License v3.0 — see the LICENSE file for details.
You are free to use, modify, and distribute this software. If you deploy a modified version as a service over a network, you must release the corresponding source code under the same license.
⭐ Star this repository to help others discover it!