End-to-end job application automation piloted by Claude Code.
claude-apply is a toolkit for running your entire job search as a pipeline — scan ATS career pages, score offers with a small LLM call, and apply to them in a real browser, all orchestrated by Claude Code. The heavy lifting happens in deterministic JavaScript modules; Claude is only in charge of the loose, hard-to-script bits (reading the DOM, generating cover letters, deciding when to stop and ask).
- Scans Lever / Greenhouse / Ashby / Workable / Workday career pages via their public APIs (zero LLM cost).
- Filters offers by keyword (
required_any,excluded_anyinconfig/portals.yml). - Scores individual offers with a stripped-down
claude -pcall (~$0.03/offer) using your CV. - Applies to offers in a real Chrome window via Chrome DevTools Protocol (CDP):
- classifies form fields using label + name patterns,
- fills text/email/select inputs (with React-safe setters),
- uploads your CV via Playwright CDP (bypasses all page-level file restrictions),
- optionally generates a cover letter,
- submits, detects the confirmation page, updates your tracker.
- Tracks applications in
data/applications.mdanddata/apply-log.jsonl. - Dashboards everything to a self-contained
dashboard.html.
- No headless scraping of logged-in accounts. If an offer requires a login, claude-apply stops and asks you to sign in manually in the open Chrome tab.
- No captcha solving. Same — it stops and asks.
- No lying on forms. Cover letters and free-text answers are grounded strictly in your CV (
config/cv.md). - No stealth / anti-bot evasion. It runs in your own Chrome profile, as you.
- No scraping of non-API career pages. Only ATSes with a usable public API are auto-scanned (Lever, Greenhouse, Ashby, Workable, Workday). Custom career pages require a manual fallback or a new fetcher (see
docs/extending.md).
git clone https://github.com/LeoLaborie/claude-apply.git
cd claude-apply
bash scripts/setup.shThen, from Claude Code, run /apply-onboard with the path to your CV PDF — it extracts your CV, builds config/cv.md + config/candidate-profile.yml, discovers ~30 target companies, and runs scripts/setup.sh non-interactively.
Or, manually:
- Edit
config/candidate-profile.ymlwith your identity, availability, preferences. - Edit
config/cv.mdwith your CV (markdown). - Edit
config/portals.ymlwith the companies to scan. - Reload your shell (
source ~/.zshrcor~/.bashrc). - Launch Chrome with CDP:
chrome-apply. - Install the claude-in-chrome extension in that Chrome window.
- From Claude Code:
/scan, then/score <url>, then/apply <url>.
┌──────────────┐
│ portals.yml │
└──────┬───────┘
│
▼
┌─────────────────────────┐ ┌───────────────────┐
│ src/scan (5 ATSes) │◄──────►│ scan-history.tsv │
└──────────┬──────────────┘ └───────────────────┘
▼
data/pipeline.md
│
▼
┌─────────────────────────┐ ┌───────────────────┐
│ src/score (claude -p) │───────►│ evaluations.jsonl │
└──────────┬──────────────┘ └───────────────────┘
▼
(human / agent triage)
│
▼
┌─────────────────────────┐ ┌───────────────────┐
│ src/apply (Chrome CDP) │◄──────►│ applications.md │
│ + /apply command │ │ apply-log.jsonl │
└──────────┬──────────────┘ └───────────────────┘
▼
dashboard.html
| Command | Purpose |
|---|---|
node src/scan/index.mjs |
Scan ATSes listed in portals.yml; append new offers to data/pipeline.md. |
node src/score/index.mjs <url> |
LLM-evaluate an offer; append to data/evaluations.jsonl. |
node src/scan/explain.mjs |
Trace which prefilter rule accepts or rejects a given title (npm run explain -- "<title>"). |
node src/apply/upload-file.mjs |
CDP file upload helper (called by /apply). |
node src/dashboard/build.mjs |
Regenerate dashboard.html from data/ and reports/. |
bash scripts/setup.sh |
Interactive first-time setup (Chrome CDP profile + templates + rc). |
bash scripts/check-no-pii.sh |
Grep the tree for personal data patterns (CI gate). |
npm test |
Run the node test suite. |
/apply-onboard [cv.pdf] |
First-time setup — extract CV, build configs, discover companies, run scripts/setup.sh non-interactively. |
/add-company <name or URL> |
Discover and append a new company to config/portals.yml (no hand-editing YAML). |
/scan |
Claude Code slash command wrapping node src/scan/index.mjs. |
/score <url> |
Claude Code slash command wrapping node src/score/index.mjs. |
/explain "<title>" |
Trace which prefilter rule accepts or rejects a given title against your current config. |
/tune-filter |
Interactive calibration of title_filter against cached scan-history.tsv. No network calls. |
/apply <url> |
Claude Code orchestrator: open → classify → fill → upload → submit. |
/dashboard |
Rebuild dashboard.html from data/ and reports/. |
All user data lives under config/ and data/ — both are .gitignored. Templates live in templates/ and are copied by scripts/setup.sh on first run.
config/candidate-profile.yml— identity, availability, CV paths, preferences.config/cv.md— plain markdown CV used byscoreand cover-letter generation.config/portals.yml— companies to scan + title filter.data/applications.md— tracker (Markdown table).data/pipeline.md— inbox of new offers from/scan.data/scan-history.tsv— dedup source of truth.data/evaluations.jsonl— output of/score.data/apply-log.jsonl— output of/apply.
Read CLAUDE.md first. It lays out the invariants (no PII in commits, no guessed values, stop on ambiguity), entry points, conventions, and where to find things.
See also docs/for-agents.md for typical workflows, patterns to follow, and anti-patterns to avoid.
| ATS | Scanner | Form fill | File upload | Notes |
|---|---|---|---|---|
| Lever | ✅ auto | ✅ | ✅ CDP | Dedup by URL; blocks re-submission for ~3 months. |
| Greenhouse | ✅ auto | ✅ | ✅ CDP | Splits first/last name; many optional subforms. |
| Ashby | ✅ auto | ✅ | ✅ CDP | _systemfield_* naming; custom questions are free text. |
| Workable | ✅ auto | ✅ | ✅ CDP | Public widget API; body is empty (no job description). |
| Workday | ✅ auto | — | — | Scanner supports paginated public API; /apply support not yet implemented. |
| WTTJ | ✅ | ✅ CDP | Aggregator — jumps to the real ATS in most cases. | |
| Teamtailor, SmartRecruiters | ❌ | ✅ CDP | Custom React form; standard fields classify correctly; add-ons may need help. | |
| Custom career pages | ❌ | — | — | Manual fallback; PRs welcome (see docs/extending.md). |
See CONTRIBUTING.md. Short version: npm test, bash scripts/check-no-pii.sh, Conventional Commits, one logical change per PR.
MIT.
claude-apply was bootstrapped from the private workspace driving the author's own internship search, and its scan / score / dashboard layers are inspired by and initially derived from santifer/career-ops (MIT). The apply module, the CDP upload helper, the Claude Code commands, and the AI-agent documentation are original to this project.