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 in cover_letters/ and cv/) 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

  1. CLI start – The concrete entry is a TypeScript file such as .agents/skills/jobbank-search/cli/src/cli.ts. It registers commands (search, detail) via commander (see src/commands/*.ts).
  1. Network I/Osearch.ts builds an HTTP request (often RSS) and calls helper functions in src/helpers.ts to fetch and retry (request-timeout.test.ts validates the logic). The response is parsed into a normalized object (detail.ts for per‑posting enrichment).
  1. File system – Parsed results are written to stdout as JSON; the user typically redirects to a file (> results.json). No database is used.
  1. 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).
  1. Post‑processing – Optional Python helper salary_lookup.py can be invoked to enrich the JSON with market salary data before the Claude step.

Responsibility map

Folder / FilePrimary Effect
.agents/skills/*-search/cli/src/cli.tsParses CLI args, dispatches to search/detail.
search.tsHTTP request, pagination, retry/back‑off.
detail.tsNormalises a single posting, adds fit metadata.
helpers.tsShared request logic, timeout handling.
.claude/commands/*.mdClaude prompt templates; no code execution, but drives AI output.
salary_lookup.pyReads 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.json lack a package-lock.json or pnpm-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.