Repo: ๐ github.com/bayuh85/applyfit (MIT, Python 3.10+, 32 tests)
The problem
Job hunting as a developer usually looks like this: twenty browser tabs of postings, one "master CV" you keep rewriting by hand, and a chat window where you paste your entire work history again for every single cover letter. Two weeks later you can't remember which version you sent to whom, or why you even applied to that on-site contract that pays under your floor.
The expensive part isn't writing. It's deciding which postings are worth writing for, and keeping a record of what you sent.
What applyfit does
applyfit keeps the profile, the posting, the fit score, and the drafts as plain files on your machine. One folder per application. A model is called only when you ask for one.
The loop:
- add a posting from a file or a URL.
- score it from 0 to 100: must-haves met and missing, nice-to-haves, red flags, deal-breakers.
- tailor a CV that reorders your existing bullets and names the gaps.
- letter a short cover letter.
- prep an interview sheet: likely questions, STAR prompts tied to real bullets, and questions to ask them.
-
board a status table (
saved,applied,interview,offer,rejected).
The score needs no API key and no network. It's a deterministic keyword-overlap baseline: requirement bullets are checked against your skills (and their aliases) and the words in your profile, then mixed with salary, remote, and deal-breaker rules. If one of your deal-breakers shows up in the posting, the score is capped at 25.
A real run: two postings, one worth your evening
The repo ships a sample profile (Rowan, a backend engineer with 8 years of Python, Kubernetes, Postgres, AWS) and two sample postings. Here's what happens when you score both.
applyfit init --profile examples/profile.yaml
applyfit add examples/postings/northline-platform.md
applyfit add examples/postings/bramble-mobile.md
applyfit score northline-platform
applyfit score bramble-mobile
Northline Systems, Platform Engineer:
northline-platform 90/100 offline
Platform Engineer โ Northline Systems
must-haves 5/5 met
nice-to-haves 1/2 met
keyword overlap 0.73
preferences 1.00
missing nice-to-haves
- Istio or another service mesh
90/100 offline. 5 of 5 must-haves appear in the profile. Keyword overlap is 0.73.
Bramble & Co, Mobile Product Lead:
bramble-mobile 6/100 offline
Mobile Product Lead โ Bramble & Co
must-haves 0/4 met
keyword overlap 0.00
preferences 0.60
deal-breakers
- preference deal-breaker present: unpaid trial
- preference deal-breaker present: security clearance
- preference deal-breaker present: 24/7 on-call
- posting is on-site and your profile requires remote work
- posted salary tops out at 95000 USD, under your floor of 150000 USD
red flags
- preference red flag present: relocation required
- posted employment 'Contract' is outside the kinds you listed
90 vs 6. That took zero tokens and about a second. You now know where your evening goes: Northline. The only gap to address is the service mesh, and you know that before writing a single line.
applyfit board
id status score company title
------------------ ------ ----- ----------------- -------------------
bramble-mobile saved 6 Bramble & Co Mobile Product Lead
northline-platform saved 90 Northline Systems Platform Engineer
Drafting the tailored CV
Now spend tokens, only on the posting that earned them:
applyfit tailor northline-platform
The prompt tells the model to never invent experience and to flag gaps instead. It reorders your real bullets and skills so the ones matching the posting come first. Even with --offline (no key) you get a draft that only copies and reorders facts already in your profile:
# Rowan Hale
**Backend engineer focused on reliable data-plane services**
## Skills
Closest to this posting:
- Python (expert, 8 years)
- Kubernetes (strong, 4 years) also k8s
- PostgreSQL (strong, 6 years) also postgres
- AWS (strong, 5 years) also amazon web services
- Distributed systems (strong, 6 years)
- Terraform (familiar, 2 years)
Then finish the application and mark it:
applyfit letter northline-platform
applyfit prep northline-platform
applyfit status northline-platform applied
Everything lands in one folder you can diff:
.applyfit/applications/northline-platform/
posting.md record.json score.md score.json cv.md letter.md prep.md
Each model call prints a cost line on stderr (tokens in, tokens out, estimated dollars), and record.json stores the token counts of every call. The API key is never written to disk.
Install
git clone https://github.com/bayuh85/applyfit
cd applyfit
python -m venv .venv && source .venv/bin/activate
pip install -e .
To use a model, copy the env file and set a key:
cp .env.example .env
# edit ATMOROUTER_API_KEY
applyfit score northline-platform --llm # model second opinion, offline baseline printed beside it
applyfit config prints the resolved base URL, API style, model, and a masked key.
Use it from Claude Code or Cursor (MCP)
applyfit mcp speaks MCP over stdio. Tools: add_job, score_job, tailor_cv, draft_letter, prep_interview, list_applications, set_status, show_profile.
{
"mcpServers": {
"applyfit": {
"command": "applyfit",
"args": ["mcp"],
"env": {
"APPLYFIT_HOME": "/absolute/path/to/.applyfit",
"ATMOROUTER_API_KEY": "ar-your-key-here",
"APPLYFIT_MODEL": "atmo/deepseek-v4.1-flash"
}
}
}
}
Point APPLYFIT_HOME at the same workspace you use from the terminal, and your agent and your shell share one board. "Score the three postings I saved today and draft a CV for the best one" becomes a single request.
Why it runs on AtmoRouter
A job search is a pile of short calls: one score, one CV, one letter, one prep sheet, then the same four again for the next posting. That's exactly the pattern where a monthly seat makes no sense and pay-per-token does.
applyfit's default provider is AtmoRouter, a cheap AI API gateway and OpenRouter alternative: 109 models behind one OpenAI/Anthropic-compatible key, pay per token, on average 83.7% below official prices. The base is https://atmorouter.dev/v1; set APPLYFIT_API_STYLE=anthropic and the same client calls the Messages API at https://atmorouter.dev/v1/messages. The default model is atmo/deepseek-v4.1-flash, which is more than enough for reordering bullets and writing a three-paragraph letter.
Base URL, key, and model are all overridable, so any OpenAI-compatible endpoint works too.
Privacy
Profile, postings, scores, and drafts stay in the workspace directory. Offline score, tailor, letter, and prep never open a network connection. LLM commands send only the profile fact sheet and the posting text to whatever host APPLYFIT_BASE_URL names. No account, no telemetry.
If it saves you one evening of rewriting a CV for a job you'd never take, a โญ on the repo helps. Issues and PRs welcome.
Top comments (1)
๊ณต๊ณ ์๋ฌธยท์ค์ฝ์ดยท์ง์์ ์ด์์ ์ง์๋ณ ํด๋์ ๋ฌถ๋ ์ค๊ณ๊ฐ ์ธ์์ ์ ๋๋ค. ํค์๋ ์ ์์ ์ค์ ์ญ๋ ํ๋จ์ ๋ค๋ฅผ ์ ์์ผ๋, ์ ์ ์์ ๋งค์นญ๋ ์๋ฌธ ๊ตฌ์ ๊ณผ ํ์ธ์ด ํ์ํ ์กฐ๊ฑด์ ํจ๊ป ๋ณด์ฌ์ฃผ๋ฉด ์ฌ์ฉ์๊ฐ ๋ฎ์ ์ ์์ ์ด์ ๋ ๊ฒํ ํ๊ธฐ ์ข๊ฒ ์ต๋๋ค.