# Best Practices in the ai-job-search Repository: Architecture, Security, and Verification

> Discover best practices in the ai-job-search repo Learn about its secure architecture sandboxed tool-chain and automated verification for reliable AI job applications

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

---

**The ai-job-search repository implements a security-first, documentation-driven architecture featuring thin-pointer single source of truth, sandboxed tool-chain isolation, and automated verification checklists to ensure safe, reproducible AI-assisted job applications.**

The ai-job-search project by MadsLorentzen demonstrates how to build production-ready AI tooling with strict governance boundaries and privacy-preserving defaults. This repository combines disciplined architectural patterns with concrete operational safeguards to create a trustworthy framework for automating job applications. Understanding these best practices provides a blueprint for building secure, maintainable AI-assisted workflows that protect sensitive candidate data.

## Thin-Pointer Single Source of Truth

The repository establishes **CLAUDE.md** and the `.claude/` directory as the canonical data store for all candidate information, workflow rules, and skill definitions.

### Preventing Configuration Drift

Rather than duplicating candidate data across multiple files, the architecture enforces a single source of truth pattern. Other runtimes—including `.agents/` directories and CI pipelines—reference these central files through thin pointers. This design prevents duplication, eliminates configuration drift, and makes updates atomic across the entire system.

```bash

# The /setup command writes only to tracked files in CLAUDE.md

claude
/setup    # Runs onboarding wizard, updates canonical profile

```

## Structured Workflow Architecture

The project implements a clear three-stage pipeline (`/setup → /scrape → /apply`) expressed as isolated, single-purpose commands documented in `.claude/commands/`.

### Command Isolation and Reproducibility

Each workflow stage lives as a documented, standalone script that guarantees reproducibility. The **/scrape** command aggregates results from multiple job portals, deduplicates postings, and scores them against structured criteria, while **/apply** handles document generation and verification.

```bash

# Execute the structured workflow

/scrape   # Aggregates and scores job postings

/rank     # Batch-scores postings against evaluation criteria

/apply https://example.com/job/1234567  # Generates application package

```

### Sandboxed Tool-Chain Isolation

Job portal scrapers are implemented as small, **Bun-based CLIs** located under `.agents/skills/`. Each portal operates in isolation with its [`package.json`](https://github.com/MadsLorentzen/ai-job-search/blob/main/package.json) strictly validated against security allowlists to prevent arbitrary code execution during installation.

```bash

# Install portal CLIs with security validation

for tool in jobbank-search jobdanmark-search jobindex-search jobnet-search; do
  (cd .agents/skills/$tool/cli && bun install)  # No install scripts allowed

done

```

## Security Guards and Permission Whitelisting

The [`tools/security_guards.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/security_guards.py) module enforces strict runtime boundaries, validating that configuration files stay within predefined security constraints rather than attempting to block malicious behavior silently.

### Allowlist Enforcement

The script checks [`.claude/settings.json`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/settings.json), `.gitignore`, and portal CLI [`package.json`](https://github.com/MadsLorentzen/ai-job-search/blob/main/package.json) files against explicit `ALLOWED_PERMISSIONS`. According to the source code in [`tools/security_guards.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/security_guards.py) (lines 12-27), the validator blocks wildcard permission widening and npm lifecycle scripts (preinstall, postinstall), forcing any permission changes to be visible in pull request diffs.

```python

# Conceptual representation of the security check

# From tools/security_guards.py lines 38-53

ALLOWED_PERMISSIONS = [
    "mcp__jobbankSearch",
    "mcp__jobindexSearch",
    # New permissions must be explicitly added here

]

```

### Mandatory .gitignore Rules

Personal data files such as [`salary_data.json`](https://github.com/MadsLorentzen/ai-job-search/blob/main/salary_data.json), `cv/main_*.pdf`, and `documents/**` are hard-coded as required ignore patterns in [`tools/security_guards.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/security_guards.py) (lines 59-71). The system validates that these patterns remain active and blocks any negation attempts unless explicitly whitelisted, preventing accidental leakage of sensitive candidate information when developers push commits.

## Verification and Quality Assurance

Every generated application package undergoes mandatory verification before leaving the repository, ensuring error-free, truthful, and ATS-compatible documents.

### The Verification Checklist

The **CLAUDE.md** file contains a comprehensive verification checklist covering factual accuracy, targeting precision, consistency, quality metrics, PDF compilation, and ATS-readability. The [`tools/verify_pdf.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/verify_pdf.py) script extracts and validates text from generated PDFs to ensure compatibility with Applicant Tracking Systems.

```bash

# The /apply command automatically executes:

# 1. CV generation against CLAUDE.md profile

# 2. Cover letter generation with forward-looking framing

# 3. Verification checklist execution (CLAUDE.md)

# 4. PDF compilation via lualatex/xelatex

# 5. ATS text extraction via tools/verify_pdf.py

```

### Career-Guidance Best Practices

The framework encodes structured evaluation criteria in `.claude/skills/job-application-assistant/`, ensuring consistent, data-driven decision making for every job posting. This includes salary benchmarking capabilities and skill-gap analysis against the canonical candidate profile stored in [`CLAUDE.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/CLAUDE.md).

## Documentation-First Philosophy

Every command, skill, and configuration file maintains an accompanying Markdown specification describing inputs, outputs, and usage examples, enabling both human readers and AI agents to understand behavior without reading source code.

### Extensibility via Templates and Portals

The repository supports safe growth through `/add-template` and `/add-portal` commands documented in `.claude/commands/`. These extension points allow users to register custom LaTeX/Typst templates and new portal-search skills while validating new assets against the same security guards and verification rules that protect the core system.

## Privacy-Respecting Design

The architecture follows GDPR-style privacy expectations by ensuring all personal data lives only in tracked local files, never transmitting to external services unless explicitly authorized.

### Explicit Data Boundaries

As documented in [`.claude/commands/onboarding_privacy.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/commands/onboarding_privacy.md), the framework writes data only to controlled, local destinations. Personal information never leaves the repository for external services (such as Gmail sync) without explicit user authorization, protecting the user's identity throughout the job search process.

## Testing and Continuous Integration

A comprehensive test suite in `tests/` covers PDF verification, upstream triage, salary lookup, skill-gap analysis, and command correctness. The CI pipeline, indicated by the badge in [`README.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/README.md), executes [`tools/security_guards.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/security_guards.py) on every push to validate permission integrity and `.gitignore` compliance.

```bash

# CI automatically runs security validation

python tools/security_guards.py  # Validates ALLOWED_PERMISSIONS and .gitignore rules

```

## Summary

- **Thin-pointer architecture** centralizes all configuration in [`CLAUDE.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/CLAUDE.md), preventing drift across the workflow pipeline and ensuring atomic updates.
- **Security guards** in [`tools/security_guards.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/security_guards.py) enforce strict permission allowlists and mandatory `.gitignore` rules for personal data protection, making dangerous changes visible in PR diffs.
- **Tool-chain isolation** sandboxes portal scrapers as Bun-based CLIs under `.agents/skills/` with forbidden lifecycle script detection to prevent arbitrary code execution.
- **Verification checklist** in [`CLAUDE.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/CLAUDE.md) ensures all generated documents pass ATS compatibility and factual accuracy checks through [`tools/verify_pdf.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/verify_pdf.py) before submission.
- **Documentation-first approach** enables safe extensibility through `/add-template` and `/add-portal` commands without compromising security or verification guarantees.

## Frequently Asked Questions

### What makes the ai-job-search repository's security model different from typical AI automation tools?

Unlike tools that rely on ambient authority, ai-job-search implements explicit permission whitelisting through [`tools/security_guards.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/security_guards.py). The system validates [`.claude/settings.json`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/settings.json) and [`package.json`](https://github.com/MadsLorentzen/ai-job-search/blob/main/package.json) files against the `ALLOWED_PERMISSIONS` list (lines 38-53), requiring any new permissions to be explicitly added and reviewed in pull requests. This makes security changes auditable and visible rather than silent.

### How does the repository prevent accidental exposure of personal data?

The repository hard-codes required `.gitignore` patterns in [`tools/security_guards.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/security_guards.py) (lines 59-71), including [`salary_data.json`](https://github.com/MadsLorentzen/ai-job-search/blob/main/salary_data.json) and `cv/main_*.pdf`. The CI pipeline validates these patterns on every push, failing builds if any personal data file would be committed. Additionally, the thin-pointer design ensures personal data never duplicates into untracked runtime directories.

### Can I extend the framework with custom job portals or document templates?

Yes, through the `/add-portal` and `/add-template` commands documented in `.claude/commands/`. These extension points register new Bun-based CLIs or LaTeX/Typst templates while subjecting them to the same security guards—permission allowlists and verification checklists—that protect the core system. This ensures extensibility without compromising the repository's safety guarantees.

### What verification steps run before an application is submitted?

The `/apply` command executes a multi-stage pipeline defined in [`CLAUDE.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/CLAUDE.md): factual accuracy checking against the canonical profile, targeting alignment with job requirements, consistency validation between CV and cover letter, PDF compilation via `lualatex` or `xelatex`, and ATS-readability verification through [`tools/verify_pdf.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/verify_pdf.py). The system blocks submission until all checklist items pass.