# CV Match Upload your CV, paste a job description, get a tailored resume and cover letter: https://ward-superelated-maynard.ngrok-free.dev/ Tailoring is done by a local LLM served by [LM Studio](https://lmstudio.ai) (same setup as the Tickerfairy app) -- no cloud LLM calls. Access is gated by an API key sent as the `X-API-Key` header, same pattern as Tickerfairy -- see [Setup](#setup). ## Setup ```bash cd CV_match python3 -m venv .venv .venv/bin/pip install -r requirements.txt ``` ## API key Access is gated by an API key sent as the `X-API-Key` header. Valid keys live in the `CVMATCH_API_KEYS` env var (comma-separated), loaded from `.env` in this directory (see `.env.example`). The web UI asks for the key once and keeps it in the browser's localStorage. To add or rotate keys, edit `.env` and restart the app (`systemctl --user restart cvmatch.service`). ## Local LLM (LM Studio) -- required ```bash ~/.lmstudio/bin/lms get qwen/qwen3.5-9b # download (once) ~/.lmstudio/bin/lms load qwen/qwen3.5-9b # keep the model resident ``` The app starts/stops the LM Studio server itself on first request, same as Tickerfairy -- both apps share the same local model. ## How it works 1. Upload a `.pdf` or `.docx` CV -- text is extracted with `pdfplumber` / `python-docx`. 2. Paste a job description, or a URL (best-effort fetch via `trafilatura`; many job boards block non-browser requests or require login/JS, so pasting the text is the reliable fallback). 3. The LLM rewrites the CV content and drafts a cover letter as one JSON payload (`app/tailor.py`), instructed never to invent employers, titles, dates, or achievements -- only to reword/reorder/re-emphasize what's already in the source CV. 4. The JSON is rendered into two `.docx` files with a shared professional style (`app/docstyle.py`, `app/docgen.py`, `app/coverletter.py`) and offered for download, with a preview shown first in the browser. ## Notes - Runs as two systemd user services for persistence: `cvmatch.service` and `ngrok-cvmatch.service` (the public tunnel, config in `cvmatch.yml`). - `.doc` (legacy Word) and scanned/image-only PDFs are not supported -- re-save as `.docx` or a text-based PDF first.