ML · Web2026
JobPilot
A self-hosted multi-agent job hunter that continuously discovers roles across Greenhouse, Lever and other boards, then uses Claude-powered Matcher and Tailor agents to score fit and draft tailored resumes and cover letters. It never auto-submits.
- After three-layer dedup
- 4.7K → 627
- Claude agents (Matcher, Tailor)
- 2
- Auto-submitted applications
- 0
The problem
The mechanical part of job hunting — finding the roles, deduplicating the same posting across four boards, rewriting the same resume for the fortieth time — consumes the hours that should go to preparing properly for the three roles that actually matter. It is grunt work, and grunt work is what machines are for. But full automation is the wrong answer: mass auto-applying is how you become spam.
The approach
Split it. Automate discovery and tailoring completely; automate submission not at all. A worker pipeline continuously discovers and deduplicates postings, then Claude-powered Matcher and Tailor agents score fit and draft the materials. Everything lands in a queue for a human to review, and the apply button stays human-operated.
Job hunting is a full-time job on top of your job. I wanted an always-on system that does the discovery and tailoring grunt work overnight, while keeping a human firmly in control of every actual submission.
Architecture
- 01
Discovery workers
BullMQ + Redis workers polling Greenhouse, Lever and other boards on a schedule.
- 02
Three-layer dedup
The same role posted across multiple boards collapses to one entry — 4.7K raw postings reduce to 627.
- 03
Matcher & Tailor agents
Claude agents score role fit, then draft a tailored resume and cover letter for the ones that clear the bar.
- 04
Human gate
Prepared applications surface via Discord alerts. The system never submits anything itself.
Stack
- API
- Fastify · Node.js · TypeScript
- Workers
- BullMQ · Redis
- Storage
- Prisma · SQLite
- Node.js
- TypeScript
- Fastify
- BullMQ
- Redis
- Prisma
- SQLite
- Claude
- Docker
Outcome
A live discovery pipeline reducing 4,700 raw postings to 627 genuine roles through three-layer deduplication, with tailored materials waiting for review. The design constraint that matters most is the one it refuses to cross: a human sends every application.