Beyond ATS Spam: Inside an Open-Source Architecture That Automates Job Hunts with Deterministic LaTeX and Agent Verification

Beyond ATS Spam: Inside an Open-Source Architecture That Automates Job Hunts with Deterministic LaTeX and Agent Verification

By Reggi, 20 Jul 2026

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:

  1. Hallucinated Competencies: LLMs invent libraries, metrics, or years of experience when forced to match a strict job description.
  2. Broken Document Parsing: Generated PDFs look acceptable to human eyes but produce broken, unreadable text streams when parsed by ATS engines.
  3. 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 lualatex or xelatex and 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:

CommandOperational Scope
/setupIngests candidate source material, references, and exports to establish ground-truth profile files.
/scrapeRuns search skills across integrated portals, deduplicates postings, and outputs fit-ranked listings.
/rankEvaluates 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.
/interviewBuilds tailored preparation dossiers from the stored application state, company research, and STAR examples.
/outcomeUpdates job_search_tracker.csv with status changes (interview, offer, rejection) and archives artifacts.
/gmail-syncScans Gmail for assessment invites, rejections, and offer signals, presenting updates for confirmation.
/notion-syncPushes a read-only, one-way pipeline visualization directly to a connected Notion database.
/expandPulls external context from public GitHub profiles, portfolios, and course syllabi into your local profile.
/upskillAudits recurring gaps across tracked listings to produce a prioritized skill heatmap and learning schedule.
/html-reportCompiles job_search_tracker.csv and archived runs into a standalone local dashboard with visual analytics.
/add-templateConfigures and registers custom LaTeX CV and cover letter classes within the compilation pipeline.
/add-portalScaffolds a new search skill targeting regional job boards by analyzing URL structures and payloads.
/resetFlushes 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 /setup step 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.


Popular Reads