ai-job-apply
by ajstars1
README.md
<div align="center">
**English** · [简体中文](https://github.com/ajstars1/ai-job-apply/blob/main/docs/readme/README_zh-CN.md) · [日本語](https://github.com/ajstars1/ai-job-apply/blob/main/docs/readme/README_ja.md) · [한국어](https://github.com/ajstars1/ai-job-apply/blob/main/docs/readme/README_ko.md) · [Español](https://github.com/ajstars1/ai-job-apply/blob/main/docs/readme/README_es.md) · [Português (Brasil)](https://github.com/ajstars1/ai-job-apply/blob/main/docs/readme/README_pt-BR.md) · [हिन्दी](https://github.com/ajstars1/ai-job-apply/blob/main/docs/readme/README_hi.md)
<img src="https://raw.githubusercontent.com/ajstars1/ai-job-apply/main/docs/images/vera.gif" alt="Vera, the ai-job-apply robot, scans a resume and stamps it verified" width="200" />
# ai-job-apply
### The AI that applies to jobs for you while you sleep.
**Finds jobs you fit. Tailors your resume for each one. Fills and submits the forms in your own browser. Follows up. You wake up to a report.**
[](https://www.npmjs.com/package/ai-job-apply)
[](#use-it-from-your-agent)
[](https://github.com/ajstars1/ai-job-apply/tree/main/skills)
[](https://github.com/ajstars1/ai-job-apply/actions/workflows/ci.yml)
[](https://github.com/ajstars1/ai-job-apply/blob/main/LICENSE)
[](https://github.com/ajstars1/ai-job-apply#fast-and-light-on-your-ai-credits)
[Try it](#try-it-on-your-resume-in-10-seconds) · [Why](#why-another-job-tool) · [How it works](#how-it-works) · [Speed and cost](#fast-and-light-on-your-ai-credits) · [Use it from your agent](#use-it-from-your-agent) · [CLI](#cli) · [FAQ](#faq)
<code>npx ai-job-apply ats my-resume.pdf --job <posting-url></code>
<br />
<img src="https://raw.githubusercontent.com/ajstars1/ai-job-apply/main/docs/images/demo.svg" alt="ai-job-apply reading a resume like an ATS, refusing inflated claims, and ranking jobs by fit" width="860" />
</div>
> [!IMPORTANT]
> **Tailored, never made up.** Every application is rewritten for its posting, and every line still comes from your real experience: a checker blocks numbers, titles and scope words ("solo", "led") your record doesn't contain. Nothing falls apart in the interview or the background check.
## Try it on your resume in 10 seconds
No account, no API key, nothing to configure:
```bash
npx ai-job-apply ats my-resume.pdf --job https://jobs.ashbyhq.com/company/job-id
```
You see your resume the way an applicant tracking system reads it, and which of the posting's keywords you're missing. `--job` also takes a Greenhouse or Lever link, or a `.txt` file with the posting.
<sub>Meet Vera (from *veritas*, truth). She checks every line of your resume against your record before anything is sent.</sub>
## Why another job tool?
Applying has become the job. It takes dozens of applications to land one interview, and every one wants a tailored resume and its own form. That's your evenings and weekends, gone.
ai-job-apply does that work for you, overnight. Unlike bots that spray one generic resume everywhere, **every application is tailored to its posting, and every line is still true.**
| | Auto-apply bots | AI resume writers | **ai-job-apply** |
|---|---|---|---|
| Picks jobs you fit | ✗ volume | ✗ | ✓ ranked by real keyword fit, deal-breakers flagged |
| Tailors per job | template | ✓ | ✓ most relevant facts first |
| Can invent a skill or number | often | often | **never: a checker blocks it** |
| ATS check of the actual PDF | ✗ | sometimes | ✓ text layer, contact details, keyword coverage |
| Applies for you | ✓ | ✗ | ✓ in your own browser, you approve |
| Tracks replies and follow-ups | ✗ | ✗ | ✓ from your inbox, rule-based |
| Your data | their servers | their servers | your machine |
## How it works
```
your record ─► discover ─► fit ─► tailor ─► check ─► render + ATS ─► apply ─► track
(fact ledger) ATS boards BM25 agent claims Typst PDF browser inbox + follow-ups
```
1. **Your record is a fact ledger.** A YAML profile where every bullet is a fact with an `id` and a `source` ("repo acme/dispatch", "Q1 ops report", "confirmed by me").
2. **Discover.** Reads the public job APIs of the company boards you watch (Ashby, Greenhouse, Lever), filters by title, remote and location, posting age and pay floor, then ranks what's left by how much of each posting your record covers. "Must be based in the US", "3 days in office", "clearance required" get flagged, not silently applied to.
3. **Tailor.** Your agent gets a resume already ordered for the posting (BM25 relevance per bullet) and rewords it. Every bullet still cites the facts it rests on.
4. **Check.** A claim checker compares numbers, units, scope words ("solo", "led", "architected") and links against the cited facts. "Built a 30-tool agent" when your fact says 14 tools doesn't render. Ever.
5. **Render and read it back.** Typst typesets the PDF, then the PDF's text layer is read the way an ATS reads it: name, email, phone, section headings, reading order, and keyword coverage split three ways: covered, **add these (your record supports them)**, and **real gaps (never claimed)**.
6. **Apply** through [pilot-browser](https://github.com/ajstars1/pilot-browser) in your own browser, with your approval mode. "Applied" is recorded only when the site confirms it.
7. **Track.** Replies are read from your inbox through your agent's mail tool and classified (interview, assessment, rejection, offer) by rules, then proposed for your approval. Follow-ups come due after 7 quiet days, two nudges at most.
## Fast, and light on your AI credits
The mechanical work runs as plain code, so your agent spends tokens only on writing.
| Step | Cost |
|---|---|
| Rank 6,221 postings from 76 company boards | 20 s, **0 LLM tokens** |
| ATS check of a PDF against a posting | 0.6 s, **0 LLM tokens** |
| Order resume bullets for a posting (BM25) | milliseconds, **0 LLM tokens** |
| Classify application emails | rules, **0 LLM tokens** |
| Read a posting | `detail: "brief"` returns only the requirement bullets |
| Postings | fetched once, cached for 30 minutes across tools |
Keyword matching indexes each text once into n-gram counts, so every lookup after that is a hash-map hit, and relevance is BM25, the scoring function behind most search engines.
## Use it from your agent
**Claude Code**
```bash
npx ai-job-apply init # creates ~/.ai-job-apply/profile.yaml: add your facts + sources
claude mcp add ai-job-apply -- npx -y ai-job-apply
claude mcp add pilot-browser -- npx -y @pilot-browser/mcp # optional: apply through your own browser
```
Then ask: *"Find remote AI engineer jobs I fit, tailor my resume for the top three and apply."*
**Cursor, Windsurf, Claude Desktop** and any MCP client with a JSON config:
```json
{ "mcpServers": { "ai-job-apply": { "command": "npx", "args": ["-y", "ai-job-apply"] } } }
```
For Claude Code there are two skills in [`skills/`](https://github.com/ajstars1/ai-job-apply/tree/main/skills): **job-apply** (the whole loop: replies, follow-ups, discovery, applying, with a fresh-context review pass for high-fit jobs) and **interview-coach** (gap analysis, a story bank that cites your facts, mock interviews).
| Tool | What it does |
|---|---|
| `profile_get` | Your facts with ids and sources, skills, preferences, standard answers |
| `jobs_discover` | Postings on your watched boards that fit, ranked by keyword fit, with gaps and deal-breakers |
| `job_fetch` | A posting (full or brief), its form questions, the employer's AI policy, and your fit |
| `resume_base` | A resume from your facts, ordered for a posting and trimmed to a bullet budget |
| `resume_check` | The claim checker |
| `resume_render` | Check, typeset, and ATS-read the PDF; refuses unsupported claims |
| `text_check` | Check a cover letter or form answer against your facts |
| `application_record` / `applications_list` | The tracker: `applied`, `needs_you`, `skipped`, `interview`, `offer`… |
| `followups_due` | Applications to nudge, oldest first |
| `inbox_query` / `inbox_match` | A mail search for replies, then rule-based status proposals |
## CLI
```bash
ai-job-apply ats resume.pdf [--job <url|file.txt>] # ATS read + keyword coverage, no profile needed
ai-job-apply init # start your fact ledger
ai-job-apply check resume.pdf # find claims your record doesn't support
ai-job-apply render [out.pdf] # a resume from every fact
ai-job-apply boards add ashby:acme https://jobs.lever.co/beta
ai-job-apply boards import-hn --months 2 # boards from HN "Who is hiring?"
ai-job-apply boards import-freehire "ai engineer" --remote # boards behind freehire.me results
ai-job-apply discover [--queue] [--preferred] [--limit N]
ai-job-apply followups [--days 7]
ai-job-apply report # today: applied, needs you, skipped, follow-ups
```
## Your profile
```yaml
basics:
name: Alex Rivera
email: alex@example.com
links: [{ label: GitHub, url: "https://github.com/alex-rivera" }]
work:
- id: acme
company: Acme Logistics
position: Senior Software Engineer
start: "2023-02"
facts:
- id: acme-dispatch-agent
text: Built a dispatch agent with 14 tools; it handled 2,300 shipments in its first quarter.
source: "repo acme/dispatch, src/agent/tools.ts; Q1 2025 ops report"
skills:
- { name: AI, keywords: [tool calling, RAG, evals, MCP] }
preferences:
remoteOnly: true
search: { titles: [engineer], exclude: [manager, intern], prefer: [AI, agent], regions: [EMEA] }
answers:
notice-period: { text: "Four weeks", source: "employment contract" }
```
The full example is in [`examples/alex-rivera/profile.yaml`](https://github.com/ajstars1/ai-job-apply/blob/main/examples/alex-rivera/profile.yaml). Standard form answers (notice period, work authorization, compensation…) live in `answers`, each with a source. A required question your profile can't answer is never guessed: the job is marked `needs_you` with the question.
## FAQ
**Is this a mass auto-apply bot?** No. It applies only to jobs that pass your filters, ranks them by fit, and you choose the approval mode. It skips postings whose employer forbids AI-assisted applications.
**LinkedIn or Indeed?** Not automated: their terms forbid it. Discovery uses the public APIs of company job boards (Ashby, Greenhouse, Lever), Hacker News "Who is hiring?" and freehire.me.
**Will it make my resume sound better than I am?** It can only reword facts you wrote down, and it refuses numbers, titles and scope words they don't contain. Missing keywords you genuinely have are suggested; ones you don't are listed as gaps.
**What does it cost?** Nothing. Open source, no API keys, no server. Your agent's own usage is the only cost, and the tools keep it small.
**Where is my data?** On your machine: your profile, resumes, tracker and inbox state are plain files in `~/.ai-job-apply/`.
## Libraries
```ts
import { checkText, keywordCoverage, loadProfile } from 'ai-job-apply';
const loaded = await loadProfile('profile.yaml');
if (!loaded.ok) throw new Error(loaded.errors.join('\n'));
const { profile } = loaded;
checkText(profile, 'Architected the platform solo; 3,000+ commits.');
// → number: "3,000+ commits" isn't supported · scope: "solo" claims more credit than your profile supports
keywordCoverage(postingText, resumeText, profile);
// → { covered: [...], addable: [...], gaps: [...], score, fit }
```
The checker and matcher are also published on their own as `ai-job-apply-core`, and rendering with the ATS check as `ai-job-apply-render`.
## Roadmap
- [x] Fact ledger and claim checker
- [x] Typst rendering, ATS read-back and keyword coverage
- [x] MCP server and CLI, live applies on Ashby and Greenhouse via pilot-browser
- [x] Discovery across company boards, HN and freehire.me, ranked by fit
- [x] Follow-ups and inbox status sync
- [ ] Workday, SmartRecruiters and Workable adapters
- [ ] Cover letter rendering
- [ ] Outreach drafts to hiring managers
**Won't do:** automate LinkedIn or Indeed, invent or "enhance" experience, or ignore postings that ask for no AI-generated applications.
## Contributing
```bash
git clone https://github.com/ajstars1/ai-job-apply && cd ai-job-apply
npm install && npm run build && npm test
```
Issues and pull requests are welcome, especially new ATS adapters and lexicon terms for your field. If ai-job-apply helped you land interviews, a ⭐ helps other job seekers find it.
## License
[Apache-2.0](https://github.com/ajstars1/ai-job-apply/blob/main/LICENSE)
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues