AI Job Search Framework Architecture: A Deep Dive into the Thin-Pointer Design

The AI Job Search framework uses a thin-pointer architecture built around four layers—a canonical candidate profile, markdown-driven workflow specifications, modular portal-specific skills, and reusable core utilities.

This open-source automation system, maintained at MadsLorentzen/ai-job-search, eliminates configuration drift by making a single source of truth the driver for all agents, commands, and data. Every component reads from centralized specifications rather than maintaining independent state.

Four Core Architectural Layers

1. Candidate Profile (Canonical Data) — CLAUDE.md and Skill Files

The foundation of the framework is 集中式数据存储. All agent runtimes load candidate information from one location.

  • CLAUDE.md — Master file containing personal details, education, preferences, and CV information
  • .claude/skills/job-application-assistant/ — Directory of skill-specific supplements (e.g., 01-*.md files)

This design prevents duplication. When a candidate updates their profile in CLAUDE.md, every downstream agent automatically uses the refreshed data.

2. Workflow Specification (Orchestration) — .claude/commands/

High-level processes are defined as pure markdown specifications rather than hardcoded logic.

Command File Purpose
.claude/commands/setup.md Environment initialization
.claude/commands/rank.md Job ranking workflow
.claude/commands/apply.md Application submission
.claude/commands/scrape.md Data collection
.claude/commands/upskill.md Interview preparation

A generic runner interprets these markdown files and stitches together the required tools. Non-programmers can edit workflows without touching source code.

3. Portal-Specific Skills (Plug-ins) — .agents/skills/

Each job portal operates as a self-contained skill module:


.agents/skills/
├── linkedin-search/
│   ├── SKILL.md          # Markdown description

│   └── cli/              # TypeScript implementation

├── jobnet-search/
├── freehire-search/
└── [new-portal]/         # Auto-discovered on commit

The LinkedIn skill demonstrates the pattern:

  • .agents/skills/linkedin-search/SKILL.md — Defines required CLI flags (--query, --location), output format (JSON), and rate-limit handling
  • .agents/skills/linkedin-search/cli/ — Houses the TypeScript entry point and package configuration

The core runner automatically discovers new skill folders. Adding a portal requires zero changes to the orchestration layer.

4. Core Utilities and Test Suite — tools/ and tests/

Reusable components accessible across all commands:

Tool Function
tools/verify_pdf.py LaTeX source validation for cover letters
tools/salary_lookup.py Region-adjusted compensation data
tools/rank.py Ranking algorithm implementation

The tests/ directory contains 30+ unit and integration test files. Example: tests/test_rank_command.py validates the ranking workflow end-to-end.

Key Architectural Principles

  • Single Source of Truth — All specifications live in .claude/; all candidate data in CLAUDE.md. This eliminates drift between agent instances.
  • Modular Skill Plugins — Portal logic is encapsulated, making replacement trivial.
  • Command-Driven Workflow — Markdown specifications allow declarative process definition.
  • Extensive Test Coverage — Every skill, tool, and command has automated validation.
  • Tool-Centric Utilities — DRY patterns encourage reuse across commands.

Code Examples

Adding a New Portal Skill

Create the folder structure:

mkdir -p .agents/skills/myportal-search/cli

Add SKILL.md:


# MyPortal Search Skill

This skill scrapes job listings from MyPortal.

- Required flags: `--query`, `--location`
- Output: JSON array of listings
- Rate limit: 1 request/second

The runner detects the new skill on next execution.

Running the Rank Command

python -m ai_job_search rank \
  --profile CLAUDE.md \
  --input ./job_scraper/results.json \
  --output ./ranked_jobs.json

The rank command loads the candidate profile from CLAUDE.md, applies the algorithm in tools/rank.py, and outputs the ordered list.

Verifying a PDF Resume

from tools.verify_pdf import verify_pdf

result = verify_pdf("cover_letters/cover_example.tex")
print(result)

# → {"valid": true, "issues": []}

The verify_pdf function parses LaTeX source, checks for required sections, and returns a JSON-compatible report.

Looking Up Salary Data

from salary_lookup import lookup_salary

salary = lookup_salary(company="Acme Corp", title="Software Engineer")
print(f"Estimated salary: ${salary:,.0f}")

salary_lookup.py queries cached CSV data and applies regional multipliers.

Critical Source Files

Path Role
CLAUDE.md Central candidate profile
.claude/commands/setup.md Setup command specification
.claude/commands/rank.md Ranking workflow definition
.agents/skills/linkedin-search/SKILL.md LinkedIn skill description
tools/verify_pdf.py PDF verification utility
salary_lookup.py Salary lookup helper
tests/test_rank_command.py Rank command unit tests
SETUP.md Detailed installation guide

Summary

  • The thin-pointer architecture centralizes all state in CLAUDE.md and .claude/ specifications
  • Markdown-driven commands enable non-programmer workflow customization
  • Self-contained skill modules allow portal addition without core changes
  • Shared utilities in tools/ enforce DRY principles
  • Comprehensive test coverage in tests/ ensures reliability as the framework scales

Frequently Asked Questions

How does the framework handle new job portals?

Drop a new folder under .agents/skills/ with a SKILL.md description and CLI implementation. The generic runner auto-discovers the skill on next execution—no orchestration code changes required.

Where is candidate data stored?

All candidate information lives in CLAUDE.md at the repository root, supplemented by skill files in .claude/skills/job-application-assistant/. This single source of truth prevents synchronization errors across agents.

Can non-developers modify workflows?

Yes. Workflow steps are defined in markdown files under .claude/commands/. Users can edit rank.md, apply.md, or other command specifications without writing code—the runner interprets the markdown directly.

What testing coverage exists?

The tests/ directory contains over 30 files covering unit and integration scenarios. Every command, skill, and core utility has corresponding test files like tests/test_rank_command.py.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →