# Key Functions and Modules in the ai-job-search Codebase: A Complete Architecture Guide

> Explore the ai-job-search codebase architecture. Understand key modules like Claude-Code commands, portal search skills, and data tracking for end-to-end job application management.

- Repository: [Mads Lorentzen/ai-job-search](https://github.com/MadsLorentzen/ai-job-search)
- Tags: architecture
- Published: 2026-09-02

---

**The ai-job-search repository organizes its automation workflow into six primary modules—Claude-Code commands, portal search skills, LaTeX templates, utility tools, salary benchmarking, and data tracking—that coordinate end-to-end job application management through markdown-driven configuration and CLI interfaces.**

The ai-job-search project by MadsLorentzen provides a comprehensive framework for automating job searches using AI agents. Understanding the key functions and modules within the ai-job-search codebase is essential for developers who want to extend portal integrations or customize document generation workflows. Each module is designed as a pure-function orchestration layer, allowing users to add new job portals or evaluation criteria without modifying core logic.

## Core Claude-Code Commands

The conversational command interface resides in `.claude/commands/` and implements the primary user-facing workflows. These markdown-defined commands coordinate the entire application lifecycle.

### Profile and Application Commands

The `/setup` command, defined in [`.claude/commands/setup.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/commands/setup.md), handles profile onboarding by reading [`CLAUDE.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/CLAUDE.md) and documents in the `documents/` folder to establish the candidate's single source of truth. The `/apply` command in [`.claude/commands/apply.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/commands/apply.md) drives the drafter-reviewer loop that generates LaTeX documents, compiles PDFs, and verifies output quality.

### Discovery and Tracking Commands

Job discovery is handled by `/scrape` ([`.claude/commands/scrape.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/commands/scrape.md)), which enumerates all installed portal skills under `.agents/skills/` and executes their CLI search commands. The `/rank` command evaluates postings against rubrics defined in [`.claude/skills/job-application-assistant/04-job-evaluation.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/skills/job-application-assistant/04-job-evaluation.md), while `/outcome` archives applications and updates tracking spreadsheets.

## Job-Portal Search Skills

Each job portal is implemented as a self-contained skill module under `.agents/skills/`, exposing standardized CLI interfaces that return JSON or table output.

### Portal-Specific Implementations

The repository includes dedicated search modules for major Danish and international platforms:

- **Jobbank**: `.agents/skills/jobbank-search/cli/` provides the CLI interface for Denmark's official job portal
- **LinkedIn**: [`.agents/skills/linkedin-search/SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.agents/skills/linkedin-search/SKILL.md) defines the skill configuration and search parameters
- **Additional portals**: `jobdanmark`, `jobindex`, `jobnet`, and `freehire` follow the same structural pattern

These skills are automatically discovered by the `/scrape` command, enabling modular expansion—adding support for a new portal requires only creating a new subdirectory under `.agents/skills/` with a [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) definition and executable CLI.

## Document Generation System

The framework generates application materials using LaTeX templates compiled to PDF, ensuring professional formatting and ATS compatibility.

### CV and Cover Letter Templates

The primary CV template resides in `cv/main_example.tex` and utilizes the **moderncv** document class for standardized academic and professional layouts. Cover letters employ a custom LaTeX class defined in `cover_letters/cover.cls`, allowing consistent branding across application materials.

When `/apply` executes, it populates these templates with candidate data from [`CLAUDE.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/CLAUDE.md) and job-specific details from scraped postings, then orchestrates compilation and verification.

## Utility and Validation Tools

The `tools/` directory contains Python scripts supporting CI pipelines, security checks, and document verification.

### PDF Verification and Framework Guards

The [`tools/verify_pdf.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/verify_pdf.py) script validates compiled PDFs by extracting text layers and verifying page counts, ensuring outputs remain ATS-readable. Continuous integration relies on [`tools/check_framework_version.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/check_framework_version.py) to enforce version bumps when skill files change, while [`tools/upstream_triage.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/upstream_triage.py) classifies upstream commits for review automation.

These utilities are invoked both interactively by Claude-Code commands and automatically by CI workflows.

## Salary Benchmarking Module

Market rate analysis is handled by [`salary_lookup.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/salary_lookup.py), a lightweight utility that processes JSON salary tables (or Excel files converted via [`tools/convert_salary_excel.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/convert_salary_excel.py)) to provide compensation estimates.

```python
from salary_lookup import SalaryLookup

# Load a JSON salary table that you placed in `salary_data.json`

lookup = SalaryLookup("salary_data.json")
median = lookup.median_for("Data Scientist", location="Copenhagen")
print(f"Median salary for Data Scientist in Copenhagen: {median} DKK")

```

The `SalaryLookup` class supports location-specific queries and median calculations, enabling data-driven negotiation preparation before submitting applications.

## Data Persistence and Tracking

Application state is maintained through CSV ledgers and structured document archives.

### Tracking and Archive Infrastructure

The `job_search_tracker.csv` file serves as the persistent ledger for all applications, updated automatically by `/outcome` commands with status changes and submission dates. The `documents/` directory stores user-provided assets including LinkedIn exports, diplomas, reference letters, and archived application PDFs, creating a comprehensive audit trail.

## Integration Workflow

Understanding how these modules interact clarifies the extension points for developers:

1. **Profile creation**: `/setup` ingests [`CLAUDE.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/CLAUDE.md) and `documents/` to build the candidate context
2. **Job discovery**: `/scrape` iterates through `.agents/skills/*/cli/` directories, executing portal-specific searches and merging results into `job_scraper/`
3. **Quality assurance**: `/rank` scores postings against evaluation criteria while `/apply` generates documents verified by [`tools/verify_pdf.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/verify_pdf.py)
4. **Outcome management**: `/outcome` updates `job_search_tracker.csv` and archives materials to `documents/`

This architecture ensures that extending functionality—whether adding a new portal skill or customizing evaluation rubrics—requires only adding files to designated directories without modifying core orchestration logic.

## Summary

- **Core commands** in `.claude/commands/` provide the primary interface for setup, scraping, ranking, and application via markdown-defined workflows
- **Portal skills** under `.agents/skills/` implement modular job search CLIs that auto-register with the scraping system
- **LaTeX templates** in `cv/` and `cover_letters/` generate ATS-compatible PDFs through the `/apply` command
- **Utility scripts** in `tools/` handle PDF verification, version checking, and upstream commit triage
- **Salary lookup** via [`salary_lookup.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/salary_lookup.py) enables market rate analysis from JSON or Excel data sources
- **State management** uses `job_search_tracker.csv` and the `documents/` folder for persistent application tracking

## Frequently Asked Questions

### How do I add support for a new job portal to the ai-job-search codebase?

Create a new directory under `.agents/skills/` containing a [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) definition file and a CLI executable (typically in a `cli/` subdirectory) that returns job postings in JSON or table format. The `/scrape` command automatically discovers and executes any skill following this convention without requiring changes to core command logic.

### What ensures the PDFs generated by the ai-job-search system are ATS-compatible?

The [`tools/verify_pdf.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/verify_pdf.py) script validates compiled documents by extracting text layers and verifying page counts, ensuring the PDFs contain readable text rather than image-based content. Additionally, the default `cv/main_example.tex` template uses the moderncv class, which produces standard academic formatting recognized by applicant tracking systems.

### Where does the ai-job-search codebase store application history and candidate profiles?

Candidate profiles reside in [`CLAUDE.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/CLAUDE.md) and supporting documents within the `documents/` directory, while application history is tracked in `job_search_tracker.csv`. The `/outcome` command updates this CSV with submission dates, statuses, and links to archived PDFs stored in `documents/`.

### How does the salary benchmark feature work in the ai-job-search repository?

The [`salary_lookup.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/salary_lookup.py) module reads JSON-formatted salary data (converted from Excel using [`tools/convert_salary_excel.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/convert_salary_excel.py) if necessary) and provides market rate estimates through the `SalaryLookup` class. Developers can query median salaries by job title and location to inform compensation expectations before applying.