# How the AI Job Search Framework Manages Configuration Drift Across Different AI Coding Assistants

> Discover how the AI Job Search framework prevents configuration drift by using a Thin-Pointer Design for centralized AI coding assistant management. Learn more!

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

---

**The AI Job Search framework eliminates configuration drift by implementing a Thin-Pointer Design that forces every AI coding assistant to read from centralized canonical files rather than maintaining local copies of configuration rules.**

The MadsLorentzen/ai-job-search repository solves the fragmentation problem inherent in multi-assistant workflows. Rather than allowing each AI assistant—whether Claude Code, Google Antigravity, Codex, Cursor, or Gemini CLI—to maintain its own interpretation of job application rules, the framework establishes a single source of truth that all runtimes must reference. This architectural decision ensures that updates to candidate profiles, workflow steps, or portal integrations propagate instantly to every assistant without manual synchronization.

## The Thin-Pointer Architecture

The framework’s core innovation is the **Thin-Pointer Design**, a pattern that prevents configuration drift by forbidding any assistant from duplicating or caching workflow definitions locally.

Instead of embedding logic within individual assistants, the system stores all canonical specifications in markdown and TypeScript files under version control. Each AI assistant functions as a thin pointer that reads these files at runtime, executing the commands and skills defined in the central repository. Because no assistant maintains its own copy of the rules, divergence becomes technically impossible—every runtime consumes the exact same instructions simultaneously.

## Single Source of Truth in Canonical Files

The framework centralizes all configuration within three specific directory structures that serve as the authoritative source for every assistant.

### Candidate Profile and Skills

All biographical data, skills, and preferences live in [`CLAUDE.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/CLAUDE.md) and detailed markdown files under `.claude/skills/job-application-assistant/`【/cache/repos/github.com/MadsLorentzen/ai-job-search/master/AGENTS.md#L13-L17】. 

When an assistant needs to evaluate a job posting against the candidate’s background, it reads from these canonical files. The personal profile is not hardcoded into any assistant’s context window; it is loaded dynamically from the repository, ensuring that updates to education or skills immediately reflect across all AI tools.

### Workflow Commands

The step-by-step automation commands—`/setup`, `/scrape`, `/apply`, and `/interview`—are defined as markdown specifications stored in `.claude/commands/` and `.claude/skills/`【/cache/repos/github.com/MadsLorentzen/ai-job-search/master/AGENTS.md#L15-L18】.

These files describe the exact sequence of operations an assistant must perform. Since the commands are repository assets rather than assistant configurations, switching from Claude Code to Cursor requires zero migration effort; both assistants read the same `/scrape` definition from [`.claude/commands/scrape.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/commands/scrape.md).

### Portal-Specific Skills

External job portals integrate through CLI tools housed in `.agents/skills/`. Each portal skill must conform to a standard [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) contract【/cache/repos/github.com/MadsLorentzen/ai-job-search/master/AGENTS.md#L18-L19】.

The `/scrape` workflow automatically discovers any subdirectory containing a valid [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) file, meaning new portals integrate seamlessly without modifying the core framework logic. This **contract-based discovery** ensures that portal implementations remain consistent regardless of which AI assistant executes the scrape.

## Version Guardrails and CI Enforcement

To prevent accidental drift during updates, the repository includes automated enforcement tools that verify the integrity of the single source of truth.

The [`tools/check_framework_version.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/check_framework_version.py) script runs in CI to ensure that any modification to canonical files increments the `framework_version` marker【/cache/repos/github.com/MadsLorentzen/ai-job-search/blob/master/tools/check_framework_version.py】. This version guard guarantees that all assistants recognize when the central configuration has evolved, triggering a refresh of their pointers.

Additionally, [`tools/lint_skills.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/lint_skills.py) validates the structure of skill definitions and command specifications, catching malformed markdown or missing contract fields before they can propagate to assistants. These guardrails ensure that every runtime stays synchronized with the repository state.

## Extending Without Duplicating

The thin-pointer architecture allows the framework to scale without creating configuration fragmentation.

Adding a new job portal requires running the `/add-portal` command, which scaffolds a new skill directory under `.agents/skills/`:

```bash
claude
/add-portal

# Example answers:

#   Portal name: example-jobs

#   Search URL pattern: https://example.com/jobs?q={query}

#   Output format: json

```

This generates:

```

.agents/skills/example-jobs/
│   SKILL.md          # contract file

│   cli/
│       src/commands/search.ts   # search implementation

│       src/commands/detail.ts   # job-detail implementation

│   package.json

```

Because `/scrape` discovers skills dynamically based on the presence of [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md), the new portal is immediately available to all assistants without editing assistant-specific configuration files.

Similarly, the `/add-template` command registers new LaTeX or Typst CV templates under `templates/` without touching any other part of the system, ensuring that template changes remain centralized.

## Summary

- **Thin-Pointer Design** forces every AI assistant to read canonical files directly, eliminating local copies that could drift.
- **Canonical directories** (`.claude/commands/`, `.claude/skills/`, `.agents/skills/`) serve as the single source of truth for workflows, profiles, and portal integrations.
- **Contract-based discovery** via [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) files allows dynamic extension without configuration duplication.
- **CI guardrails** ([`check_framework_version.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/check_framework_version.py), [`lint_skills.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/lint_skills.py)) enforce version consistency and structural validity across all assistants.
- **Zero-migration switching** between Claude Code, Cursor, Codex, and other assistants because all read from the same repository files.

## Frequently Asked Questions

### What prevents an AI assistant from caching an old version of the configuration?

The framework relies on the [`check_framework_version.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/check_framework_version.py) CI tool to enforce version bumps whenever canonical files change【/cache/repos/github.com/MadsLorentzen/ai-job-search/blob/master/tools/check_framework_version.py】. Assistants read the `framework_version` marker from [`AGENTS.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/AGENTS.md) and can verify they are operating against the latest committed state. Since the canonical files are repository assets, any assistant launched within the workspace sees the current file system state immediately.

### How does the framework handle different capabilities across AI assistants?

All assistants consume the same markdown specifications in `.claude/commands/` and `.claude/skills/`, but they interpret these specifications according to their own runtime capabilities. The framework defines the *what* (the workflow steps) in the canonical files, while each assistant handles the *how* (the execution mechanics). This separation ensures that fundamental logic never diverges even when implementation details vary between Claude Code and Cursor.

### Can I use this framework with AI assistants not explicitly listed in the documentation?

Yes. Any AI assistant that can read files from the repository workspace can execute the workflows defined in `.claude/commands/` and `.agents/skills/`. The Thin-Pointer Design requires only that the assistant parse markdown files and execute CLI commands found in the repository. As long as the assistant respects the [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) contracts in `.agents/skills/`, it will remain synchronized with the central configuration.

### What happens if I modify a portal skill locally?

Local modifications to files under `.agents/skills/` or `.claude/commands/` are immediately visible to all assistants running in that workspace. However, the [`lint_skills.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/lint_skills.py) tool validates these changes against the contract schema, and [`check_framework_version.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/check_framework_version.py) ensures the `framework_version` is updated to reflect the modification【/cache/repos/github.com/MadsLorentzen/ai-job-search/blob/master/tools/check_framework_version.py】. This prevents silent drift by forcing explicit version acknowledgment whenever the single source of truth changes.