# How to Integrate ai-job-search with Other Tools: Extending the Modular Framework

> Discover how to integrate ai-job-search with other tools. Extend its modular framework by adding skills, registering templates, or calling Python utilities for seamless workflow automation.

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

---

**You can integrate ai-job-search with external systems by adding job-portal skills in `.agents/skills/`, registering custom document templates in `templates/`, or calling Python utilities like [`salary_lookup.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/salary_lookup.py) directly from your own scripts.**

The ai-job-search repository is architected as a modular, thin-pointer framework where the single source of truth lives in the hidden `.claude` directory. Because each layer—from skill plugins to document generators—is decoupled, you can extend the system to support custom job boards, corporate HR APIs, CI pipelines, and personal dashboards without touching the core logic.

## Understanding the Plugin Architecture

The framework separates concerns into distinct layers, each exposing a specific extension point:

- **Skill plugins** – CLI tools stored under `.agents/skills/*-search/cli` that query job portals and output JSON. Each skill follows a strict contract requiring search and detail commands, JSON output, and an `enabled:` flag.
- **Template plugins** – LaTeX or Typst files stored in `templates/` that generate CVs and cover letters, registered via the `/add-template` command.
- **Data-exchange helpers** – Stand-alone Python scripts in `tools/` and the root directory (such as [`salary_lookup.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/salary_lookup.py)) that handle ancillary tasks like salary lookups and PDF verification.
- **Synchronization adapters** – Notion and Gmail connectors implemented as `/notion-sync` and `/gmail-sync` commands.

Because these layers are decoupled, you can introduce new capabilities by dropping files into the appropriate directory and running the corresponding slash command.

## Method 1: Add a New Job-Portal Skill

To integrate a new job board, create a folder under `.agents/skills/` that matches the existing CLI contract. The `/scrape` command auto-discovers these directories at runtime, so your new portal immediately enters the normal search flow.

The contract requires:
- A [`package.json`](https://github.com/MadsLorentzen/ai-job-search/blob/main/package.json) defining the CLI entry points
- Source code implementing `search` and `detail` subcommands
- JSON output formatted to match the schema defined in [`.agents/skills/jobindex-search/SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.agents/skills/jobindex-search/SKILL.md)
- An `enabled:` flag in configuration to toggle availability

```bash

# Clone the repo and scaffold a new skill directory

cd ai-job-search
mkdir -p .agents/skills/myboard-search/cli

# Populate the directory following the contract in 

# .agents/skills/linkedin-search/SKILL.md

# Register and test the skill interactively

claude /add-portal

```

## Method 2: Register a Custom Document Template

You can introduce custom CV or cover-letter formats by placing LaTeX, Typst, or other command-line-compilable files into `templates/`. After registration with `/add-template`, all subsequent `/apply` commands will use your new template automatically.

```bash

# Create your template directory

mkdir -p templates/custom_cv
cp my_template.tex templates/custom_cv/

# Run the interactive registration wizard

claude /add-template

# Select "custom_cv" when prompted and verify the test compile passes

```

## Method 3: Hook Into the Python Toolchain

For programmatic integrations, call the stand-alone Python utilities directly from your scripts or CI pipelines. These helpers perform ancillary tasks and return structured data you can feed back into the Claude workflow.

For example, [`salary_lookup.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/salary_lookup.py) benchmarks compensation data:

```python
import subprocess
import json
import pathlib

# Point to your target salary CSV

csv_path = pathlib.Path("data/desired_salaries.csv")

# Execute the lookup tool

result = subprocess.run(
    ["python3", "salary_lookup.py", "--input", str(csv_path)],
    capture_output=True,
    text=True,
)

# Parse JSON output for further processing

salary_data = json.loads(result.stdout)
print("Salary benchmarks:", salary_data)

```

Other useful utilities include [`tools/verify_pdf.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/verify_pdf.py) for PDF validation and [`tools/check_upstream_updates.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/check_upstream_updates.py) for keeping forks synchronized in CI environments.

## Method 4: Synchronize with External Dashboards

The framework provides first-class adapters for Notion and Gmail, allowing you to push application outcomes or pull status signals without manual data entry.

**Notion synchronization** updates a database with rows from `job_search_tracker.csv`:

```bash

# Run after recording outcomes with /outcome

claude /notion-sync

# One-time OAuth setup persists credentials for future runs

```

**Gmail integration** pulls status updates from your inbox:

```bash

# Scan Gmail for application status emails

claude /gmail-sync

# Review detected events before they are written to the tracker

```

## Summary

- **Add job portals** by creating CLI tools in `.agents/skills/` that follow the JSON output contract, then run `/add-portal`.
- **Register templates** by dropping LaTeX/Typst files into `templates/` and executing `/add-template`.
- **Leverage Python helpers** like [`salary_lookup.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/salary_lookup.py) and [`tools/verify_pdf.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/verify_pdf.py) from external scripts or automation pipelines.
- **Sync with dashboards** using `/notion-sync` and `/gmail-sync` to connect with external productivity tools.

## Frequently Asked Questions

### How do I add support for a niche job board that isn't included by default?

Create a new directory under `.agents/skills/` (for example, `.agents/skills/nicheboard-search/cli`) and implement the standard CLI contract: expose `search` and `detail` commands that output JSON, include an `enabled:` configuration flag, and follow the structure documented in [`.agents/skills/linkedin-search/SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.agents/skills/linkedin-search/SKILL.md). Run `claude /add-portal` to register the skill, and the `/scrape` command will auto-discover it.

### Can I use my existing LaTeX CV template with ai-job-search?

Yes. Copy your `.tex` files into a new subdirectory under `templates/` (such as `templates/my_cv/`), then run `claude /add-template`. The interactive wizard will prompt you to select the new folder and verify that it compiles correctly. Once registered, you can generate applications using your custom template via the `/apply` command.

### Is it possible to automate salary research as part of a CI pipeline?

Absolutely. The [`salary_lookup.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/salary_lookup.py) script is designed to run stand-alone without the Claude CLI. You can invoke it from GitHub Actions, GitLab CI, or local cron jobs by passing a CSV input file with the `--input` flag. The script returns JSON to stdout, which you can parse and feed into subsequent automation steps or commit back to your repository.

### What files should I avoid modifying when extending the framework?

You should not modify any files in the `.claude/commands/` directory or the core workflow logic. Instead, place your custom code in the designated extension points: `.agents/skills/` for portal integrations, `templates/` for document generators, and `tools/` (or external scripts) for utility functions. This preserves your ability to pull upstream updates from the main repository without merge conflicts.