# How AI Job Search Drafts CVs and Cover Letters: A Technical Guide to Automated LaTeX Document Generation

> Learn how AI Job Search drafts CVs and cover letters with automated LaTeX document generation. Explore the technical process for creating professional application documents effortlessly.

- Repository: [Mads Lorentzen/ai-job-search](https://github.com/MadsLorentzen/ai-job-search)
- Tags: technical-guide
- Published: 2026-08-25

---

**AI Job Search drafts CVs and cover letters by combining candidate profile data with LaTeX templates through a two-stage process: the `/setup` command populates placeholders in template files, and the `/apply` command compiles the documents into PDFs using LuaLaTeX or XeLaTeX.**

AI Job Search is an open-source automation toolkit that streamlines job applications by generating professional CVs and cover letters from structured data. The system uses a **template-driven LaTeX workflow** where candidate information is stored in centralized profile files and injected into customizable document templates. This approach ensures consistent formatting while allowing complete control over the visual presentation through standard LaTeX classes.

## The Three-Stage Document Generation Pipeline

The drafting process follows a deterministic pipeline that separates data management from document rendering.

### Stage 1: Candidate Profile Definition

All personal data resides in [`.claude/skills/job-application-assistant/01-candidate-profile.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/skills/job-application-assistant/01-candidate-profile.md), the canonical candidate profile file. This Markdown file stores structured fields including `first_name`, `last_name`, `email`, `summary`, work experience, and education history. The `/setup` command reads this profile during initialization and prompts the user to complete any missing required fields before proceeding to template population.

### Stage 2: Template Preparation and Placeholder Injection

The system maintains stock LaTeX templates containing sentinel placeholders that await replacement with profile data. In `cv/main_example.tex`, the ModernCV class template includes explicit placeholders such as `\name{[First]}{[Last]}` and `\email{[your.email@example.com]}`. Similarly, `cover_letters/cover_example.tex` uses the `cover.cls` class with identical placeholder patterns. The integrity of these placeholders is verified by [`tests/test_placeholder_integrity.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tests/test_placeholder_integrity.py), which confirms that sentinel strings exist in the templates and are properly replaced during the setup phase.

### Stage 3: Automated Drafting via /setup and /apply Commands

The actual document generation occurs through two distinct command phases. First, **`/setup`** (documented in [`.claude/commands/setup.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/commands/setup.md)) performs an interview-style data capture session, injecting the candidate profile values into the LaTeX files to replace the bracketed placeholders. Second, **`/apply`** (implemented in [`.claude/commands/apply.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/commands/apply.md)) resolves the active template configuration, determines the appropriate compiler—`lualatex` for CVs and `xelatex` for cover letters—and executes the compilation pipeline to produce final PDF documents.

## How /setup Populates Document Templates

The `/setup` command functions as the data injection layer between the candidate profile and the LaTeX source files. When executed, the system parses [`01-candidate-profile.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/01-candidate-profile.md) and performs string substitution on the template files, replacing markers like `[First]` and `[Last]` with the actual candidate name fields. This process ensures that the LaTeX source files remain valid and compilable throughout the replacement process, maintaining the structural integrity required by the ModernCV and cover letter document classes.

## How /apply Compiles and Generates PDFs

Once templates are populated, `/apply` handles the rendering pipeline. The command first consults [`.claude/skills/job-application-assistant/05-cv-templates.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/skills/job-application-assistant/05-cv-templates.md) to determine the active template and its associated compile settings. For the stock configuration, CVs compile with `lualatex` while cover letters use `xelatex`. The command outputs finalized PDFs to `documents/cv/` and `documents/cover_letters/` respectively. Additionally, `/apply` extracts plain text from the generated PDFs to create ATS-compatible versions and records the file paths in the application tracking spreadsheet under the `cv_file` and `cover_letter_file` columns.

## Customizing Templates with /add-template

Users can override the stock templates by registering custom LaTeX files via the `/add-template` command (defined in [`.claude/commands/add-template.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/commands/add-template.md)). When invoked, the command prompts for the template name, source file extension, and compile command string. Upon registration, the system updates the `ACTIVE-TEMPLATE` block in [`05-cv-templates.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/05-cv-templates.md), ensuring that subsequent `/apply` executions use the custom compiler settings and file paths rather than the defaults.

## Practical Workflow Examples

### Running the Complete Draft Workflow

Execute the two primary commands to generate application documents:

```bash

# Populate candidate profile and inject data into templates

ai-job-search /setup

# Compile LaTeX sources into PDF files

ai-job-search /apply

```

These commands replace placeholders in `cv/main_example.tex` and `cover_letters/cover_example.tex`, compile them using the appropriate LaTeX engines, and deposit the final PDFs into `documents/cv/` and `documents/cover_letters/`.

### Adding a Custom LaTeX Template

Register a new template to change the visual presentation:

```bash

# Register custom template with specific compiler settings

ai-job-search /add-template --name my-modern-cv --src .tex --compile "lualatex -interaction=nonstopmode {file}"

```

This updates the active template manifest in [`05-cv-templates.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/05-cv-templates.md), directing future `/apply` operations to use your custom styling while maintaining the automated placeholder substitution.

### Inspecting Generated Files

Verify PDF generation programmatically:

```python
from pathlib import Path

cv_pdf = Path("documents/cv") / "my_cv.pdf"
cover_pdf = Path("documents/cover_letters") / "my_cover_letter.pdf"

print(cv_pdf.read_bytes()[:10])   # prints PDF header bytes

print(cover_pdf.read_bytes()[:10])

```

## Summary

- **AI Job Search** uses a **LaTeX-based templating system** to generate CVs and cover letters from structured candidate profiles stored in [`.claude/skills/job-application-assistant/01-candidate-profile.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/skills/job-application-assistant/01-candidate-profile.md).
- The **`/setup`** command injects profile data into templates by replacing placeholders like `\name{[First]}{[Last]}` in `cv/main_example.tex` and `cover_letters/cover_example.tex`.
- The **`/apply`** command compiles documents using `lualatex` for CVs and `xelatex` for cover letters, outputting PDFs to `documents/cv/` and `documents/cover_letters/`.
- **Custom templates** can be registered via `/add-template` and tracked in [`05-cv-templates.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/05-cv-templates.md), allowing full control over document styling while maintaining the automated data injection workflow.
- Placeholder integrity is verified by [`tests/test_placeholder_integrity.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tests/test_placeholder_integrity.py), ensuring reliable template substitution.

## Frequently Asked Questions

### What file formats does AI Job Search use for CVs and cover letters?

AI Job Search generates **PDF documents** compiled from **LaTeX source files** (`.tex`). The system uses the ModernCV class for CVs and a custom `cover.cls` for cover letters. Source templates contain plaintext placeholders that are substituted with candidate data before compilation.

### How does the system handle missing candidate information?

During the **`/setup` phase**, the system performs an interview-style data capture session that checks [`01-candidate-profile.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/01-candidate-profile.md) for completeness. If required fields such as `email` or `first_name` are missing, the command prompts the user to supply the data before proceeding with template population, ensuring no empty placeholders reach the final LaTeX compilation.

### Can I use my own LaTeX templates instead of the stock ones?

Yes. The **`/add-template`** command allows you to register custom `.tex` files. You specify the template name, file extension, and compile command (such as `lualatex` or `xelatex` with flags). The system stores this configuration in [`05-cv-templates.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/05-cv-templates.md) and applies it during subsequent `/apply` operations, while still performing the same placeholder substitution logic.

### Where are the generated PDF files stored?

By default, compiled CVs are saved to `documents/cv/` and cover letters to `documents/cover_letters/`. The `/apply` command automatically records these file paths in the application tracking spreadsheet under the `cv_file` and `cover_letter_file` columns, linking each generated document to its specific job application entry.