Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

autoapply

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.

Before you use this, read this

  • 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. scan only reads public listings and drafts cover letters. apply only acts on applications you explicitly approved in review. 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.

Setup

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 info

Then:

  • Put your CV file at cv/cv.pdf (or wherever profile.yaml's cvPath points).
  • 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.

Logging in

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 -- devbg

Usage

npm 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 failed

Run scanreviewapply in that order, as often as you like (e.g. daily). Already-seen listings are skipped on subsequent scans.

Current state of the site adapters

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:

  1. If scan finds nothing on a site, run npm run inspect -- <url> (e.g. npm run inspect -- https://dev.bg/company/jobs/) to dump the live page structure, and fix the SELECTORS object at the top of the relevant file in src/sites/.
  2. 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.
  3. LinkedIn's "Easy Apply" wizard varies step-to-step by job (screening questions, etc.); src/sites/linkedin.ts only 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.

Safety limits

  • criteria.maxApplicationsPerRun caps how many applications apply will submit in one run, regardless of how many are approved.
  • criteria.minMatchScore keeps low-fit jobs out of the review queue entirely (they're recorded as scored_low so they aren't rescanned, but no cover letter is generated and you never see them).
  • criteria.excludeCompanies / keywordsExclude are checked before any LLM call, so obviously-unwanted listings never cost an API call or reach you.

Project layout

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

About

An agent that applies to job listings on my behalf

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages