Applying to 70 technical jobs manually is an unmitigated systems failure. You are essentially acting as a human copy-paste engine, juggling messy markdown variants, fighting with flaky word processors, and hoping some opaque Applicant Tracking System (ATS) correctly parses your contact information. One geophysicist hit this exact bottleneck after a late-2025 layoff. Instead of brute-forcing manual submissions, he engineered an open-source framework called AI Job Search on top of Claude Code. The outcome: 69 targeted applications, 20 first-round interviews, and a signed AI Engineer contract by June 2026.
This project is not a thin OpenAI wrapper or a paid crypto-token play. It is a strictly local, deterministic workflow framework designed to transform Claude Code into an autonomous job-hunting pipeline without hallucinating a single credential.
+-----------------------------------------------------------------------+
| CLAUDE CODE CLI |
+-----------------------------------------------------------------------+
| |
v v
[ 1. Discovery & Profiling ] [ 2. Autonomous Scraping ]
- Ingest Docs / Diplomas / References - linkedin-search
- Interactive Profile Interview - freehire-search
- Output: 01-candidate-profile.md - Local Market Scrapers (Bun)
| |
+-----------------------+-----------------------+
|
v
[ 3. /apply Orchestration ]
|
+-------------------+-------------------+
| |
v v
( Agent 1: Drafter ) ( Agent 2: Reviewer )
- Pulls Grounded Facts - Fresh Context Window
- Generates Raw TeX - Researches Company
- Applies Relevance Scoring - Critiques & Catches Gaps
| |
+-------------------+-------------------+
|
v
[ 4. Deterministic Pipeline ]
|
+------------------------+------------------------+
| |
v v
( pdftotext ATS Sanity Check ) ( PDF Visual Verification )
- Verifies contact details - Compiles via LuaLaTeX/XeLaTeX
- Checks real keyword reading order - Fixes orphaned headers
- Flags unbacked gaps - Ensures clean 2-page fit
The Real Engineering Problem Behind Job Hunt Automation
Most attempts to automate job applications fail due to three critical flaws:
- Hallucinated Competencies: LLMs invent libraries, metrics, or years of experience when forced to match a strict job description.
- Broken Document Parsing: Generated PDFs look acceptable to human eyes but produce broken, unreadable text streams when parsed by ATS engines.
- Layout Regressions: Standard LaTeX outputs frequently break formatting rules, producing orphaned headers or spilling three lines onto an accidental third page.
AI Job Search solves these issues by treating CV generation as a compilation and verification pipeline rather than a simple text-generation task.
The Dual-Agent Drafter-Reviewer Architecture
The core runtime uses two distinct execution contexts to draft and finalize application materials.
[Candidate Profile Data] + [Target Job Description]
|
v
+----------------------------+
| Agent 1 (Drafter) |
| - Initial LaTeX Draft |
+----------------------------+
|
v
+----------------------------+
| Agent 2 (Reviewer) |
| - Fresh Context Window |
| - External Research |
| - Detects Generic Tone |
+----------------------------+
|
v
+----------------------------+
| Agent 1 (Revision Loop) |
| - Applies Critique |
| - Emits Final .tex Files |
+----------------------------+
Agent 1 receives your profile and the target job description to produce initial LaTeX drafts for the CV and cover letter. It is strictly constrained to your source profile. If you have never used a technology mentioned in the job description, the system refuses to fabricate it.
Once the draft is ready, Agent 2 steps in with a completely fresh context window. It researches the company, evaluates the alignment, and checks for weak framing or generic phrasing. Agent 1 then ingests this critique and revises the output. This multi-pass separation guarantees high signal while filtering out low-effort generation artifacts.
Relevance-Based Truncation Mechanics
When your experience exceeds the standard two-page limit, naive systems simply slice off your oldest roles. AI Job Search uses a multi-factor scoring model to determine which lines stay:
$$\text{Line Score} = f(\text{JD Relevance}) + f(\text{Document Uniqueness}) + f(\text{Cover Letter Dependency})$$
If an older bullet point from 2018 contains high semantic relevance to a niche requirement in the job description, it stays. A generic management bullet from 2023 with low topical overlap gets cut first.
ATS and Visual Verification
Once LaTeX files are written (moderncv for resumes and cover.cls for cover letters), the system runs two deterministic checks:
- Text-Layer ATS Sanity Check: The compiled PDF is fed through
pdftotext. The agent validates contact details, checks reading order, and evaluates keyword visibility against what the parser extracts. Unsupported keywords are logged as actual skill gaps rather than stuffed into invisible text layers. - Visual PDF Compilation Checks: The system compiles the layout using
lualatexorxelatexand programmatically inspects the visual output. It catches orphaned section headers and enforces strict structural boundaries, such as a two-page CV limit and a single-page cover letter with an intact signature block.
Setting Up the Local Runtime
The framework runs locally on your development environment. You need a functioning Claude Code CLI installation, Python 3.10+, Bun for the CLI scrapers, and a functional TeX distribution.
bash# Clone the repository gh repo fork MadsLorentzen/ai-job-search --clone cd ai-job-search # Install the search tool dependencies across the scrapers for tool in jobbank-search jobdanmark-search jobindex-search jobnet-search linkedin-search freehire-search; do (cd .agents/skills/$tool/cli && bun install) done # Initialize Claude Code and begin onboarding claude
Inside the Claude Code session, kick off the onboarding pipeline:
text/setup
The /setup command accepts raw PDF CVs, LinkedIn data exports, diplomas, or references. Alternatively, you can run an interactive interview session directly in the terminal to capture historical metrics and unlisted project details.
+---------------------------------------------------------------------------+
| LOCAL DIRECTORY TOPOLOGY |
+---------------------------------------------------------------------------+
ai-job-search/
├── CLAUDE.md # Global agent directives & runtime rules
├── 01-candidate-profile.md # Ground-truth profile & verified skills
├── 04-job-evaluation.md # Fit criteria & scoring parameters
├── job_search_tracker.csv # Local application pipeline state
└── .agents/skills/ # Extensible Bun-based search tooling
The Command Surface
The system ships with purpose-built commands to manage every stage of the hiring pipeline:
| Command | Operational Scope |
|---|---|
/setup | Ingests candidate source material, references, and exports to establish ground-truth profile files. |
/scrape | Runs search skills across integrated portals, deduplicates postings, and outputs fit-ranked listings. |
/rank | Evaluates fresh scraped jobs against 04-job-evaluation.md and generates a prioritized shortlist. |
/apply <url | jd> | Executes the full drafter-reviewer pipeline, builds LaTeX assets, verifies ATS text, and outputs PDFs. |
/interview | Builds tailored preparation dossiers from the stored application state, company research, and STAR examples. |
/outcome | Updates job_search_tracker.csv with status changes (interview, offer, rejection) and archives artifacts. |
/gmail-sync | Scans Gmail for assessment invites, rejections, and offer signals, presenting updates for confirmation. |
/notion-sync | Pushes a read-only, one-way pipeline visualization directly to a connected Notion database. |
/expand | Pulls external context from public GitHub profiles, portfolios, and course syllabi into your local profile. |
/upskill | Audits recurring gaps across tracked listings to produce a prioritized skill heatmap and learning schedule. |
/html-report | Compiles job_search_tracker.csv and archived runs into a standalone local dashboard with visual analytics. |
/add-template | Configures and registers custom LaTeX CV and cover letter classes within the compilation pipeline. |
/add-portal | Scaffolds a new search skill targeting regional job boards by analyzing URL structures and payloads. |
/reset | Flushes local application state, compiled documents, or profile data for a clean reset. |
Running the Core Application Loop
Once your profile is set up, find matching opportunities by running the scraper:
text/scrape
This triggers configured search providers, such as the built-in linkedin-search (which queries public endpoints without external runtime dependencies) and freehire-search (which interfaces with the freehire.dev API).
When you identify a strong role, pass the listing directly to the application engine:
text/apply https://example.com/jobs/staff-infrastructure-engineer
The system retrieves the description, scores your profile against the requirements, spins up the drafter-reviewer cycle, compiles the LaTeX source files, verifies the output, and updates job_search_tracker.csv.
When an interview is scheduled, initialize targeted prep:
text/interview
The /interview command compiles a focused prep pack directly from the application archive. It reads the job listing, reviews the generated CV and cover letter seen by the hiring team, researches the interviewers, maps potential questions directly to your STAR-format project history, and runs an interactive mock interview.
Maximizing Input Quality
The output quality of this architecture depends on the depth of the input data you provide.
LOW INPUT SIGNAL:
"Python Developer, 2021-2024. Maintained company backend systems and APIs."
|
v
Produces: Generic, low-converting application materials.
HIGH INPUT SIGNAL:
"Backend Engineer, 2021-2024. Built ML churn prediction pipeline in Python
using scikit-learn. Scaled pipeline throughput by 35% on internal workloads."
|
v
Produces: Grounded, highly targeted, ATS-verified LaTeX artifacts.
To extract the best results from the system:
- Provide Deep Project Context: Avoid simple bulleted lists of technologies. Detail architecture decisions, internal components owned, tools used, and measurable engineering outcomes.
- Anchor Skills to Implementations: Rather than listing "Machine Learning" as an isolated keyword, provide the exact context: "Built ML churn prediction pipeline in Python using scikit-learn." This gives the agent the semantic hooks it needs to defend your experience during both drafting and interview prep.
- Leverage Career Discovery: If you want to explore adjacent roles, the
/setupstep supports open discovery. By analyzing your entire career history, it can surface matching technical paths that fit your background beyond your default job title search. - Calibrate Salary Expectations: Use the local benchmarking workflows to map your target compensation against personal baseline data before entering negotiation rounds.
AI Job Search takes an unorganized, high-friction job hunt and turns it into a transparent, deterministic software pipeline. You can audit the code, build new scrapers for local job portals using /add-portal, or integrate custom TeX styling via /add-template. Check out the project repository on GitHub at https://github.com/MadsLorentzen/ai-job-search to clone the framework and run your job search directly from the terminal.
