jev-job-search
Health Uyari
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 6 GitHub stars
Code Basarisiz
- spawnSync — Synchronous process spawning in bin/jev.js
Permissions Gecti
- Permissions — No dangerous permissions requested
Bu listing icin henuz AI raporu yok.
Find software internships and new-grad jobs, fill the application forms, check every answer on the page, and send the ones you approve. JEV decides, code acts, Claude writes. Runs on your machine with Claude Code.
jev-job-search
The job search that fills the forms for you.
An open-source job application tool built on Claude Code. Clone it, fill in your profile, and let it find software internships and new-grad roles, fill the application forms in a Chrome window you can watch, read every answer back from the page, and send the ones you approve. A resume and a cover letter written for each job are one flag away.
This is an independent open-source project. It is not affiliated with, endorsed by or maintained by Anthropic, OpenRouter, or any job board. There is no token, coin or paid tier; the only ways to support it are using it and contributing on GitHub.
Does it actually work?
It is how I run my own search. I sent 100 applications in less than 10 minutes across Ashby, Lever, Workable, Rippling, BambooHR, Jobvite and JazzHR forms, for about a dollar in JEV, while fixing what it got wrong on each new kind of form. Every answer on every one of those forms was read back from the page before it was sent, and every form it could not finish truthfully is in applications/manual.csv with the reason. The numbers it reports about itself are in How well it works. I will add what came of the applications once I know.
What this is
A command-line tool and nine Claude Code skills that run it with you in the loop. Two models share the thinking: JEV makes every decision that has a fixed set of answers (which of your details goes in this box, which option, how good a fit this job is) for a fraction of a cent, and Claude, on your own subscription, writes the sentences. The code does the rest: finds the jobs, drives Chrome, checks every answer on the page, and keeps your records.
/setup /discover /apply
| | |
v v v
Your resume Read public job Fill each form in Chrome
and a short lists and company JEV picks every option
interview boards Claude writes the sentences
| | |
v v v
Profile files Ranked queue with Read every answer back
ready fit scores Send only what is ready
| |
v v
Pick what to send applications/applied.csv
-> /apply manual.csv for what is yours
The tool never lies on a form, never signs in anywhere, never passes a human check for you, and never sends a form it could not verify. What it cannot finish truthfully, it lists for you with the reason.
Prerequisites
- A Mac with Google Chrome. The tool opens its own Chrome window with its own profile; your everyday browser is not touched.
- Node.js 22 or newer.
- Claude Code, signed in. Claude Code has no free tier: you need a Claude Pro or Max subscription, or a Claude API key in
.env(then the commands work and the skills do not; see Claude Code or the Claude API). - An OpenRouter account with a few dollars of credit. That pays for JEV, the only separate bill: about 1 to 1.5 cents for every 10 applications, and 7 to 9 cents per search. Five dollars covers about 60 searches and 3,000 applications. See What it costs.
Quick start
1. Clone and install
git clone https://github.com/qbeka/jev-job-search
cd jev-job-search
npm install
[!IMPORTANT]
Everything about you stays in git-ignored files (data/,documents/,applications/,.env), so your own clone can be pushed anywhere without leaking anything. Fork only to contribute.
2. Set up your profile
claude
# Then inside Claude Code:
/setup
/setup checks what is installed, reads your resume PDF and anything else you drop into documents/ (old resumes, a LinkedIn export, past applications), asks only what those do not say (where you may work, what you are looking for, how you want recurring questions answered), opens .env for you to paste your OpenRouter key, builds your profile, finds jobs, rehearses three forms for you to read, and stops for your "go". About 20 minutes, most of it your answers. /setup is safe to run again.
3. Find jobs
/discover
Reads the public lists and the company boards, drops the jobs you could not or would not apply to (no work authorization, wrong level, closed), rates the rest with JEV against your profile, and writes a ranked queue. Run it every day or two; a posting that has not changed is not rated again.
4. Apply
/apply
Fills the best queued forms, one Chrome tab each, answers what JEV left open with Claude, reads every value back from the page, and sends each form the moment it is ready once you say so. Every result is printed as it happens. Your records appear in applications/.
5. Apply to one posting you found yourself
/apply https://jobs.ashbyhq.com/company/job-id
A Greenhouse, Lever or Ashby link is read from the board, rated, and filled like any other. For another board, /discover picks it up when it appears on the public lists.
Other commands
/setup, /discover and /apply are the workflow. Six more skills and a handful of terminal commands extend it once your profile is in place:
/tailor <job id> [--cover]writes a one-page resume for the job from your profile and the posting, and with--covera one-page cover letter, and shows you the PDFs. Every number and every name of a tool, a place or a company in the draft is checked against your profile in code; the keywords the posting wants and your profile cannot support are listed, never stuffed in./apply --tailor --coverwrites and attaches them as it applies. See A resume and a cover letter written for the job./reportopens a dashboard on your own machine: applications sent, today, waiting for you, left for you; sent per day and per board; every job with its status, which you can change by hand, and a notes box per row.npx jev report --static applications/report.htmlwrites a snapshot page to keep. Nothing leaves your machine./expandreads the public places your profile already links to (your GitHub repositories, your portfolio site) and proposes projects, skills and facts that are missing from the profile, each with its source. Nothing is added without your yes./add-sourceadds a job board or a public list as a source: it inspects the site, writes the source in the shape of the shipped ones, tests it on a captured sample and runs one live query before registering it./profilechanges your profile, your standing answers (how recurring questions are answered), your drafts and your voice guide with you. When a form answer looked wrong, this is where you fix it, once.log,statusandcostshow your applications (log --manuallists what the tool left for you), the totals and skip reasons, and what you have spent.npx jev log --openopens your applications in your spreadsheet program.doctorchecks everything a run needs and names the next step./setupruns it for you.knowledge --sharecopies what your runs learned about job sites into the repo, so a pull request can hand it to everyone. It holds site names and kinds of controls, nothing about you.
Every terminal command is npx jev <command> from the project folder; npx jev --help lists them all, including the apply loop one step at a time (fill, resolve, submit, check, inspect, set).
File structure
jev-job-search/
├── CLAUDE.md # Rules for Claude Code when it works on the code
├── .claude/skills/
│ ├── setup/ # /setup: from a clone to the first rehearsal
│ ├── discover/ # /discover: build the ranked queue
│ ├── apply/ # /apply: fill, check, send
│ ├── tailor/ # /tailor: a resume and a cover letter per job
│ ├── report/ # /report: the dashboard
│ ├── expand/ # /expand: enrich the profile from your public links
│ ├── add-source/ # /add-source: a new job board or list
│ └── profile/ # /profile: change what the tool knows about you
├── applications/ # Your records (git-ignored)
│ ├── applied.csv # what was sent, newest first
│ ├── manual.csv # what the tool left for you, with the reason and the link
│ ├── takehome.csv # take-home assignments to do
│ └── all.csv # every job considered
├── documents/ # Your files (git-ignored)
│ ├── resume.pdf # the resume you send
│ ├── transcript.pdf # for forms that ask for one
│ └── tailored/ # <Company>_<Role>_<id>/ resume.pdf, cover.pdf, resume.md
├── data/ # Your profile and the tool's working files (git-ignored, examples tracked)
│ ├── profile.json # who you are; standing answers to recurring questions
│ ├── bank.json # your starting drafts for common open questions
│ ├── voice.local.md # how you write
│ └── queue.json, cache/, runs/
├── knowledge/sites.json # What runs have learned about job sites, shared through the repo
├── src/
│ ├── cli.ts # every command
│ ├── config.ts # every setting, in one place
│ ├── run/ # the apply loop
│ ├── browser/ # Chrome over the DevTools protocol, no browser library
│ ├── forms/ # reading and filling pages; three scripts that run in the page
│ ├── answers/ # the writer (Claude), the answer memory, drafts, voice
│ ├── documents/ # tailored resumes and cover letters
│ ├── jobs/, sources/ # finding and rating
│ ├── knowledge/, log/, jev/ # site notes; the CSV records; the JEV client
├── tests/ # offline, on captured fixtures with no personal data
├── docs/ # SETUP, USAGE, ARCHITECTURE, JEV, SOURCES, SAFETY
└── .github/workflows/ # CI: typecheck, tests, audit, CodeQL, a guard against personal data
How /apply works
Each job goes through the same loop on its own, and its result is printed the moment it is known:
- Open the form in its own Chrome tab and read every control on the page: labels, options, which are required, which file box wants which file.
- Map the page with one JEV call: which of your details goes in each box, which option is true for you, which boxes stay empty. A form that has not changed keeps its mapping.
- Fill with real input events, one control at a time on boards that save as you type. Dropdowns are opened and clicked; calendars are turned to the month and the day is clicked; the resume goes in the resume box and nowhere else.
- Write what is left. Open questions, and the few fields JEV was unsure of, go to Claude with your facts, your drafts and your voice guide. Answers are remembered, so a form you rehearsed is not written twice.
- Read back every value from the page. A box that shows something other than what it was given fails the fill and holds the form; an optional box the site refused is reported as left blank.
- Walk to the next page when the form has one, and repeat.
- Send, only when every wanted value is on the page and no required box is empty, and only when you asked. The page after the click must be a confirmation before the application counts.
- Record the application in
applications/applied.csv, with one sentence on what the company does and one on why you fit. What the tool could not finish is inmanual.csvwith the reason.
What makes this workflow different
- Decisions and sentences are split. JEV, a model built for typed judgements, makes every fixed-answer choice and returns probabilities, not text, in about half a second for a fraction of a cent. Claude writes only the sentences. A form with no open question never calls Claude at all.
- Nothing is trusted until it is read back. Every value is read from the page after it is written. A wrong dropdown pick, a date a masked box mangled, or a value a site quietly dropped is caught before Submit, not after.
- It never lies, signs or sneaks. Work authorization, dates and education come from your profile and are never bent to fit a posting. A signature, an NDA, a human check or a sign-in is yours; the tool stops and tells you.
- It learns per site. How each board's controls take values, which sites want a sign-in, which email codes, is recorded after every form and read before the next, and shared through the repo.
- Every record is a plain CSV with fixed column names, at the top of the project, so you and your scripts can read it.
The longer version, with what it handles and what it leaves to you, is in docs/USAGE.md.
A resume and a cover letter written for the job
Off by default: your applications carry the resume file in your profile.
Turn it on and the tool writes a one-page resume for each job from your
profile and the posting, and attaches that one instead.
npx jev tailor <job id> --cover --open
npx jev apply --count 10 --submit --tailor --cover
tailorwrites the documents for a job and shows you the PDFs.apply --tailorwrites one per job as it goes.apply --coveralso writes a
cover letter wherever a form has a box for one, and uploads it or pastes
it. SetcoverLetterto"when_asked"in your profile to make that the
default.- The resume is built from your own bullets, reordered and cut for the
posting, with the posting's keywords used where your profile has the same
thing. The cover letter names one specific thing from the posting and ties
two or three of your facts to it. - Nothing is invented. Every number and every name of a tool, a place or
a company in the draft is checked against your profile in code. A draft
that claims something your profile does not say is sent back once with
the claims named, and refused if it still does. The keywords the posting
wants and your profile cannot support are listed for you, not stuffed in. - The PDFs are rendered by the tool's own Chrome, so there is nothing to
install. They live indocuments/tailored/<Company>_<Role>_<job id>/with the resume as
Markdown next to it, git-ignored.
The method follows the drafter and verifier workflow of
MadsLorentzen/ai-job-search
(MIT), redone here in code against the profile instead of as a prompt.
Customization
Everything about you is in data files, not in the code. /profile changes any of them with you.
Which files to edit manually
| File | What to change |
|---|---|
data/profile.json |
Your details, education, experience, projects, skills, work authorization, and answers: how recurring questions are answered (relocation, text messages, notice period, pay, agreements). JEV and Claude both follow this list |
data/bank.json |
Your starting draft for each common open question ("Why this company?", "Tell us about a project") |
data/voice.local.md |
How you write, so the answers read as yours |
documents/resume.pdf |
The resume the tool sends when you do not tailor one |
src/config.ts |
Every setting in one place: the job lists, the scoring and where ranks highest, how many forms run at once, how fast the tool works on each site, which Claude model writes, the resume and cover letter page limits |
Where the jobs come from, and adding a board
Jobs come from public lists on GitHub (the SimplifyJobs internship and new-grad lists among them) and from the company boards those lists point at, read through the boards' own APIs for Greenhouse, Lever and Ashby. Workday, iCIMS, Taleo, Oracle and the other boards that want an account are filtered out; a site found behind a sign-in during a run is remembered and skipped. docs/SOURCES.md describes each source and how to add one, and data/imports/ takes a CSV of your own.
Which jobs it keeps
The filters and the scoring are in src/config.ts: early-career titles only, the countries you may work in, how much a Vancouver, Canadian, remote or US posting is worth to you, and how old a posting may be (/discover --max-age 30). A posting that prefers another graduation date is ranked lower, not dropped: whether to apply is your decision.
Custom resume and cover letter templates
The stock resume and cover letter are plain HTML with system fonts, printed to PDF by Chrome. To use your own design, make a folder with a resume.html and, if you want letters, a cover.html, written with these placeholders:
| Placeholder | What it prints |
|---|---|
{{name}}, {{headline}}, {{contact}}, {{summary}}, {{skills}} |
Your name, the role in the posting's words, your contact line, the summary written for the job, the skills joined with dots ({{#skillList}}{{.}}{{/skillList}} for one at a time) |
{{#experience}} ... {{/experience}} |
One block per job, with {{title}}, {{company}}, {{location}}, {{when}} and {{#bullets}}{{.}}{{/bullets}} inside |
{{#projects}} ... {{/projects}} |
The same, with {{name}}, {{role}}, {{link}}, {{when}}, {{#bullets}} |
{{#education}} ... {{/education}} |
{{degree}}, {{field}}, {{minor}}, {{school}}, {{when}} |
Cover letter: {{date}}, {{company}}, {{role}}, {{greeting}}, {{#paragraphs}}{{.}}{{/paragraphs}}, {{closing}} |
Then register it. The tool checks every placeholder, prints a test pair from the example profile, and refuses a template that does not render or runs long:
npx jev templates --add ~/my-template --name mine
npx jev templates --use mine
npx jev templates lists what is registered and which one /tailor uses. The stock pair is in src/documents/templates/default/, the easiest starting point to copy.
What the tool will not do
- It will not lie. Your right to work, your education and your dates
come from your profile. The tool does not change them to suit a job. - It will not invent facts. Written answers use only what your profile
says. - It will not send a form it has not checked. Every answer must be
confirmed on the page first. - It will not send anything unless you ask. Sending needs
--submitor
thesubmitcommand. - It will not sign for you. If a form asks you to type your name to
agree to a contract, the tool leaves it for you. - It will not choose a date for you. If a form asks you to pick an
interview or test slot, the tool leaves it for you. - It will not sign in anywhere, and it will not create accounts. A job
behind a sign-in goes on your by-hand list. - It will not pass a "prove you are human" test for you. That covers
picture puzzles and the codes a board emails you. - It will not read your email.
- It will not write a cover letter or give references. It skips jobs
that require them. - It will not give your GPA unless the form cannot be sent without it,
or you chose to always give it.
docs/SAFETY.md has the full list and shows where each rule
lives in the code.
Starting over
Delete data/profile.json, data/bank.json and data/voice.local.md and run /setup again. npx jev memory --clear forgets the remembered answers; applications/ and documents/ are yours to keep or remove.
What it costs
Two services do the thinking.
- JEV answers the questions that have a fixed set of answers, such as
"which of my details goes in this box?" and "how good a fit is this
job?" You pay for it through your OpenRouter key. This is the only
separate bill. - Claude writes the answers that need sentences, such as "Why do you
want to work here?" It runs on the Sonnet 5.5 model at low effort,
through Claude Code on your own Claude subscription, so there is no
separate bill for it. If you would rather use a Claude API key, you can,
and then those calls are billed to that key. See
Claude Code or the Claude API.
What JEV costs
Measured on three real batches on 2 October 2026, every call recorded:
| Batch | Forms filled | Applications sent | JEV cost | Per 10 forms |
|---|---|---|---|---|
| 1 | 15 | 10 | $0.022 | $0.015 |
| 2 | 27 | 16 | $0.037 | $0.014 |
| 3 | 36 | 18 | $0.037 | $0.010 |
So 1 to 1.5 cents for every 10 forms. Most of that is one call per
form that decides what goes in each field; reading the page after Submit
and matching remembered answers add a tenth of a cent.
A search is separate: rating 350 to 460 new postings costs $0.06 to
$0.09, and a second search on the same day costs close to nothing, because
a posting that has not changed keeps its rating.
Five dollars of OpenRouter credit pays for about 60 searches and 3,000
applications.
For the record, everything we spent while building and testing the tool
from 1 to 2 October came to $1.43: 4 searches ($0.35), 118 applications
sent, and 67 forms that were rehearsed over and over while fixing bugs
($0.67 of it). Normal use does not do that.
What changes these numbers:
- Forms with more fields cost more to map. A long form is one JEV call
of a few thousand tokens; a short one is a fraction of a cent. A form
with several pages is one call per page. - A rehearsal costs the same as a real fill, except the "read the page
after Submit" step, which only a real application reaches. Sending a
form you rehearsed does not map it again. - Claude calls count toward your subscription's usage allowance. On
an API key,costshows what they cost instead.
To see what you have spent, run npx jev cost. Every run that
fills forms also prints its own cost at the end.
How the tool keeps the cost down
- It remembers answers. Every answer Claude writes is kept on your
computer. When you rehearse a form and then send it, the tool reuses the
answers you read in the rehearsal and does not ask Claude again. We ran
the same 10 forms a second time: Claude was asked about 1 form instead of - It reuses an answer on another company's form only when that is safe.
Claude marks an answer as reusable only if it would be true for any
company. JEV then checks that the new question asks for the same thing.
Most open questions name the company, so expect this to save a little,
not a lot: in our test, 1 answer in 8 was reusable. - It forgets when you change your profile. A remembered answer is used
only while your profile, your drafts and your voice guide are unchanged.
A corrected fact is never overruled by an old answer. - It does not ask JEV the same thing twice. A posting that has not
changed keeps its rating from the last search, and a form that has not
changed keeps its field mapping. A second search on the same day costs
close to nothing. - It sends Claude only what Claude needs. Your profile is sent once per
run and reused from a cache for the following forms. - JEV does everything it can. On a typical form JEV settles all but one
or two fields, for about a tenth of a cent.
To see or clear what the tool remembers, run npx jev memory.
Claude Code or the Claude API
The tool reaches Claude in one of two ways. Both run the same model and
the same prompts, and everything else works the same.
| Claude Code (the default) | The Claude API | |
|---|---|---|
| What you need | Claude Code installed and signed in | A Claude API key in .env as ANTHROPIC_API_KEY |
| What it costs | Your Claude subscription's allowance. No separate bill. | Billed to your key at API prices. cost shows the amount. |
The skills /setup, /apply, /discover, /profile |
Work | Need Claude Code too. Without it, run the commands yourself. |
With a key in .env, the tool uses the API. To keep using Claude Code
while a key is present, add WRITER_BACKEND=claude-code to .env. Runnpx jev doctor --online to prove either one works.
Tips for better results
Profile depth matters
The writer may use only what your profile says. A bullet with a number in it ("cut page load by 44%") gives Claude something to tie to a posting; a vague one gives it nothing. Run /profile after each internship, project or course and add the facts. The tailored resume and the cover letter are only as specific as the profile is.
Standing answers save you from repeating yourself
Every recurring question you answer by hand once (pay, relocation, start date, agreements, skill ratings) belongs in answers in your profile. The next form gets it right without you.
Rehearse after a change
/apply --dry fills and checks forms without recording or sending anything. Read the values it reports after you change your profile or the code.
Stay near your computer the first few runs
Boards sometimes email a code or show a "not a robot" check after Submit. The tool never types a code or passes a check for you: it closes that form, lists the job in applications/manual.csv with the reason, and moves on to the next one, so a run never waits on you. Apply to those few by hand, or try them again later; boards stop asking after a while.
Contributing
Bug reports, fixes for a form that filled wrongly, new job sources and site notes are welcome. Read CONTRIBUTING.md first: how the code is organized, how the docs are written, and what to run before a pull request. knowledge --share is the easiest contribution: what your runs learned about job sites, with nothing about you in it.
Acknowledgements
- MadsLorentzen/ai-job-search (MIT) for the drafter and reviewer method behind the tailored resume and cover letter, and for showing what a clear job-search repo looks like.
- SimplifyJobs for the public internship and new-grad lists the tool reads.
- typesafe/jev-1.13 for a model that answers a typed question with a probability.
License
MIT. See LICENSE.
Yorumlar (0)
Yorum birakmak icin giris yap.
Yorum birakSonuc bulunamadi