An agent that scans LinkedIn, jobs.bg, and dev.bg for job listings matching your criteria, scores each one against your CV with Claude, drafts a tailored cover letter for the good matches, and helps you apply — with a human review step before anything is actually submitted.
- LinkedIn's Terms of Service prohibit scraping and automated activity, including auto-applying. LinkedIn actively detects and can suspend accounts for this. This tool is built to minimize that risk (real login session instead of scripted credentials, low request volume, no headless-only automation, no unattended final submit), but the risk is not zero. Use your own judgment about how much of this to automate on your own account.
- Nothing is submitted automatically by default.
scanonly reads public listings and drafts cover letters.applyonly acts on applications you explicitly approved inreview. Even then, the site adapters currently fill the application form and stop short of clicking the final submit button (see "Current state of the site adapters" below) until you've verified the flow yourself. - Ask yourself whether an AI-generated cover letter sent to real employers meets your own standard of honesty — review each one before it goes out.
npm install
cp .env.example .env # add your ANTHROPIC_API_KEY
cp config/criteria.example.yaml config/criteria.yaml # edit to your criteria
cp config/profile.example.yaml config/profile.yaml # edit with your infoThen:
- Put your CV file at
cv/cv.pdf(or whereverprofile.yaml'scvPathpoints). - Put a plain-text/markdown copy of your CV at
cv/cv.md(cvTextPath) — this is what's actually sent to the LLM as context, so keep it current.
This tool never scripts your password. For any site where you want it to apply on your behalf, log in once yourself in a real browser window it opens for you, and it reuses that session:
npm run login -- linkedin
npm run login -- jobsbg
npm run login -- devbgnpm run scan # search enabled sites, score fit, draft cover letters for good matches
npm run review # interactively approve / reject / edit each drafted application
npm run apply # submit everything you approved (nothing else)
npm run status # see counts by status, and anything that failedRun scan → review → apply in that order, as often as you like (e.g.
daily). Already-seen listings are skipped on subsequent scans.
This sandbox environment's network policy blocks outbound access to
linkedin.com, jobs.bg, and dev.bg, so the scrapers in src/sites/*.ts
were written from general knowledge of those sites, not a live DOM
inspection — treat them as a first draft, not verified code. When you run
this locally:
- If
scanfinds nothing on a site, runnpm run inspect -- <url>(e.g.npm run inspect -- https://dev.bg/company/jobs/) to dump the live page structure, and fix theSELECTORSobject at the top of the relevant file insrc/sites/. - Every
apply()implementation deliberately fills the application form and stops without clicking final submit, leaving the browser open (headless: false) so you can verify it looks right and submit it yourself the first few times. Once you've confirmed a site's flow works, add the final submit click in that file — the spot is marked with a comment. - LinkedIn's "Easy Apply" wizard varies step-to-step by job (screening
questions, etc.);
src/sites/linkedin.tsonly opens it and attaches your CV/cover letter where possible. Postings that use an external ATS (applyMethod: "external") are surfaced for manual application and are not automated at all.
criteria.maxApplicationsPerRuncaps how many applicationsapplywill submit in one run, regardless of how many are approved.criteria.minMatchScorekeeps low-fit jobs out of the review queue entirely (they're recorded asscored_lowso they aren't rescanned, but no cover letter is generated and you never see them).criteria.excludeCompanies/keywordsExcludeare checked before any LLM call, so obviously-unwanted listings never cost an API call or reach you.
config/ your criteria.yaml and profile.yaml (gitignored)
cv/ your CV files (gitignored)
data/ application queue/history + saved login sessions (gitignored)
src/config.ts loads and validates config/*.yaml
src/store.ts JSON-file-backed application tracker
src/llm/ Claude-based job-fit scoring and cover letter generation
src/sites/ one adapter per site (search / getDetail / apply)
src/commands/ scan / review / apply / status
scripts/login.ts interactive login, saves a reusable session
scripts/inspect.ts dumps a live page's structure to help fix selectors