The Problem
Job‑seekers must manually scan multiple portals, copy‑paste job details, and repeatedly rewrite CVs and cover letters. The effort is repetitive, error‑prone, and hard to scale across languages or countries.
What This Does
ai-job-search bundles a set of Claude‑driven agents that automate the full application pipeline:
- Portal scrapers live under
.agents/skills/*-search/cli/. Each contains a TypeScript CLI (src/cli.ts) that fetches listings, normalises fields, and outputs JSON with a fit score. - Claude prompts in
.claude/commands/(e.g.,apply.md,interview.md) consume that JSON, evaluate the posting, and generate a LaTeX CV, cover letter, or interview prep script. - Utility scripts (
salary_lookup.py, LaTeX templates incover_letters/andcv/) provide salary benchmarking and document rendering.
The workflow is intentionally modular: swap a scraper folder for a local job board, keep the Claude prompts unchanged.
How It Is Wired
Entry point → scraper → Claude → output
- CLI start – The concrete entry is a TypeScript file such as
.agents/skills/jobbank-search/cli/src/cli.ts. It registers commands (search,detail) viacommander(seesrc/commands/*.ts).
- Network I/O –
search.tsbuilds an HTTP request (often RSS) and calls helper functions insrc/helpers.tsto fetch and retry (request-timeout.test.tsvalidates the logic). The response is parsed into a normalized object (detail.tsfor per‑posting enrichment).
- File system – Parsed results are written to
stdoutas JSON; the user typically redirects to a file (> results.json). No database is used.
- Claude hand‑off – The user runs a Claude command from
.claude/commands/(e.g.,apply.md). The Claude Code CLI reads the JSON file, injects it into the prompt defined in.claude/skills/job-application-assistant/04-job-evaluation.md, and returns LaTeX files (cover_letters/cover.cls,cv/main_example.tex).
- Post‑processing – Optional Python helper
salary_lookup.pycan be invoked to enrich the JSON with market salary data before the Claude step.
Responsibility map
| Folder / File | Primary Effect |
|---|---|
.agents/skills/*-search/cli/src/cli.ts | Parses CLI args, dispatches to search/detail. |
search.ts | HTTP request, pagination, retry/back‑off. |
detail.ts | Normalises a single posting, adds fit metadata. |
helpers.ts | Shared request logic, timeout handling. |
.claude/commands/*.md | Claude prompt templates; no code execution, but drives AI output. |
salary_lookup.py | Reads CSV/Excel salary tables, returns a numeric estimate. |
cover_letters/ & cv/ | LaTeX templates consumed by Claude output. |
The only hub is the CLI dispatcher; each scraper is isolated, so changes to one portal do not affect others. No circular imports are present.
How To Use It
# 1. Clone the repo
git clone https://github.com/moses-y/ai-job-search.git
cd ai-job-search
# 2. Install a scraper (example: Jobbank)
cd .agents/skills/jobbank-search/cli
npm ci # installs deps; note: no package‑lock present
# 3. Search a portal
npx ts-node src/cli.ts search --query "data scientist" --location "Copenhagen" > jobs.json
# 4. (optional) Enrich with salary data
python ../../salary_lookup.py jobs.json > jobs_enriched.json
# 5. Run Claude to generate application assets
# Assuming Claude Code CLI is installed and authenticated
claude apply --input ../../jobs_enriched.json --output ./out
Configuration:
- Claude credentials are stored in
.claude/settings.json(generated by the Claude CLI on first run). - Each scraper reads its portal URL from the sibling
url-reference.md. No other environment variables are required.
Real‑World Use
A user runs the Jobbank scraper nightly, pipes results into Claude with claude apply, and receives a ready‑to‑compile LaTeX CV and cover letter for each high‑fit posting. The same JSON can be fed to claude interview to get tailored interview questions and suggested answers.
Code Health & Issues
- Low – Missing lockfile –
*.agents/skills/*/cli/package.jsonlack apackage-lock.jsonorpnpm-lock.yaml, making builds non‑deterministic. - Low – Duplicate scraper scaffolding – Each portal repeats the same CLI skeleton (
cli.ts,commands/,helpers.ts). Consolidating common logic could reduce maintenance overhead. - Low – Test coverage – 71 test files exist, covering CLI flag validation, retry logic, and parsing. No integration tests for the Claude hand‑off are present.
- Low – CI – GitHub Actions (
.github/workflows/ci.yml) run the TypeScript test suite and Python lint checks; the pipeline succeeds on the upstream fork but does not build a distributable artifact.
No critical security findings are visible in the repository tree.
The Bottom Line
ai-job-search provides a practical, modular stack for automating job‑board scraping and AI‑driven application drafting. It works out‑of‑the‑box for Danish portals and can be retargeted elsewhere, but the lack of lockfiles and duplicated scraper code raise maintenance concerns. It is suited for engineers comfortable with TypeScript CLIs and Claude Code who want a customizable, self‑hosted job‑application assistant.