ats-resume

Checks whether a machine can read your résumé at all, then whether it matches the posting you are about to apply to.

ats-resume

Checks that an applicant tracking system can read a résumé at all, then matches it against a posting. Built on the JSON Resume schema.

CInpm versioninstall sizetestsruntime depsLicense: MITNode >=18JSON ResumeClaude Code
1,366 downloads 516/week v1.1.1 published 25 Sept 2026 MIT licence Node >=18 JavaScript
$ npm i -D @alokraj68/ats-resume
resumecvatsjson-resumejob-searchhiring

Built on the JSON Resume schema, so you bring a resume.json you may already have rather than learning another format. Zero dependencies.

This is not a writing checker. plainspoken asks whether prose reads as machine-written; this asks whether a machine can parse the file. The two are deliberately separate tools.

It also compares two versions of the same résumé and reports which facts the rewrite dropped. Reordering bullets is where a figure quietly disappears, because both versions read as perfectly good English and no linter compares them: "carrying over $50M in annual revenue, held at over 99.95% uptime" and "held at high availability" are each fine on their own.

The half that matters most reads the extracted text rather than the source, because that is what an applicant tracking system actually receives. Standalone separator elements in a contact block look perfect in the DOM and on screen, and can be dropped from a PDF text layer entirely, leaving one unsplittable string where a parser expected four fields. Only reading the extraction finds it.

What it catches

Using it

Lint the source

npx @alokraj68/ats-resume lint resume.json

Lint what an ATS receives

pdftotext -layout Sam-Rivera-Resume.pdf out.txt
npx @alokraj68/ats-resume lint out.txt

Match against a posting

npx @alokraj68/ats-resume tailor resume.json posting.txt

Check a rewrite dropped nothing

npx @alokraj68/ats-resume diff before.txt after.txt

Questions

Do I have to write my résumé in JSON?

For the source checks, yes - it uses the JSON Resume schema, which is an existing open format rather than a new one. The extracted-text checks take a plain .txt dumped from your PDF, whatever produced it.

What match rate should I be aiming for?

Seventy per cent or more against a posting generally clears. Sixty to sixty-nine is marginal. Under sixty and a human is unlikely to see it. The more useful output is the gap list, because that is your interview preparation.

Does it rewrite my résumé?

No. It reports what a parser cannot read and which terms from the posting are missing. What to do about a missing term is a judgement call: add it where the work actually happened, mention it once if it is weak, or leave it out and treat it as a gap.

How do I know a rewrite did not quietly drop something?

Run diff against the version you trust: npx @alokraj68/ats-resume diff before.txt after.txt. A missing figure is an error, a missing client name is a warning, and a bullet that only moved is reported as nothing at all.

Also published