Upload a resume and a job description, get an explainable ATS score, an honest rewrite with a per-line change log, and a coach that will never invent a number for you. The most important thing is, it works with your subscriptions. Here is the full walkthrough.
Every resume tool I tried had the same problem. I would paste in a job description, hit tailor, and get back a resume that was genuinely better written and quietly not true. A title nudged upward. A skill I had never used, sitting in a bullet as if it had always been there a number, always a good round one, that nobody had ever measured.
The tools were not broken. They were doing what I asked: make my resume to match the job. Truth was not part of the objective.
So I built Scrivio's resume studio around the opposite premise: the rewrite is only worth having if every fact in it is yours. This is a walkthrough of what actually happens when you run a resume through it, in the order you would experience it.
Step 1: Upload the resume and the job description
You can paste your resume as text, upload a PDF or DOCX, or import an existing resume.json. For the job description, you can paste it, give a URL, or pick a job target you already saved in the job interview studio.
The first thing that happens is not a model call. Your resume is extracted once into JSON Resume, an open standard with defined fields for work, education, skills, and projects. That extraction pass has exactly one job: faithful text-to-structure mapping, with no improvement and no invention.
This matters more than it sounds. Once the resume is a structure rather than a blob, every step can address a specific field. The change log can say work[0].highlights[2]. The interface can draw a mark on the exact line that changed. The honesty rules can compare fields instead of scanning the prose. And because JSON Resume is a public standard rather than my format, the file round-trips into other tools in that ecosystem, so the structure is a door out rather than a lock-in.
Step 2: The ATS report comes back before the AI does
Here is the part I am most pleased with. The scoring is pure Python, so it returns in the same response as the upload, in under a second, while the model work continues in the background. You are reading a real report immediately.
The score is a weighted checklist, and every row tells you what it looked at and why it passed or failed:
- Contact info up top, because ATS field parsers read email and phone from the first several lines and will miss them in a header graphic
- Standard section headers, at least three recognised ones, because that is how an ATS segments your document
- Quantified achievements, at least a third of your bullets carrying a real number
- Consistent date format, because mixing "Jan 2024" and "01/2024" confuses date parsing
- Single-column, parse-safe layout, detected from column and table artefacts in the extracted text
- No stuffing or filler, because repeating one keyword eight times reads as a fraud signal to modern systems
- Verb-first language, flagging "responsible for", "tasked with", "leveraged", and the rest of the duty-speak family
With a job description attached, a deterministic keyword-coverage percentage joins in, and the final number becomes 70% checks and 30% coverage.
There is no model anywhere in that score, which is the point. You can argue with it. It gives the same answer on Tuesday that it gave on Monday. And when it says you failed a check, it tells you what it counted: "6/19 bullets are quantified (32%)" rather than a mysterious 61 out of 100.
Step 3: Tailor it
Now the model gets involved and works on the structure rather than on text with some restrictive rules.
It may rephrase bullets and reorder them so that the most job-relevant work leads, condense material irrelevant to this role, rewrite your summary to mirror the role's actual title, and reorder your skills so matching ones come first.
It may not invent employers, titles, employment dates, degrees, institutions, certificates, metrics, or skills, but the Job history is never deleted, only reordered and condensed.
Adding a keyword from the job description is allowed in exactly one situation: when your resume already shows a real basis for it. If the posting says Kubernetes and you have a bullet describing deploying containerised services on k8s, it can name Kubernetes there. If there is no honest basis, it does not add the keyword. It tells you instead, in a warning that begins "Cannot honestly claim."
Then, after the model is done, deterministic code checks its work. Employers must appear on your original, or the entry is removed. Titles and employment dates must match byte for byte, or they are reverted. Institutions and certificates must be ones you actually have. Every correction is surfaced to you as a plain-English warning, never fixed silently:
Reverted job title at Acme to "Software Engineer II"; titles cannot be changed.
The prompt is the request. This is the contract. Only one of them is something I can write a test for.
Step 4: Read the change log, not just the result
You get back a rewrite plus a per-field record of every edit: what changed, where, and why it serves this specific job. In the classic interface, these are a list. In the React interface at /desk, which renders your resume as paper with findings drawn on it, they are marks on the lines themselves, linked two ways to a review rail.
The colors carry meaning. Red-pen underlines are ATS problems. Amber chips are honesty issues, things that need your decision. Teal bars are improvements that were made.
The change log is not decoration. A rewrite you cannot audit is a rewrite you have to trust blindly, and blind trust is exactly what got fabricated bullets onto resumes in the first place.
Step 5: Fill in your own numbers
When a bullet would clearly be stronger with a figure your resume does not contain, the tailor does not estimate one. It writes the literal token [METRIC], capped at four per resume so the result does not read as unfinished, and logs each one.
You get "Cut deploy time by [METRIC]%" and a note telling you where the real number lives, your CI history in that case. Then you fill them in inline, right where they will print.
The same rule protects every later edit. A numeral in edited text has to already exist somewhere in your resume or in something you typed yourself. Anything else reverts, with a warning naming the invented figure. Which also means that if you tell the tool "deploy time went from 20 minutes to 3," those numbers become legal everywhere, because they came from you.
Step 6: Ask the coach
There is a chat panel beside your resume that can see both your resume and the job description, and it is deliberately read-only. It cannot change anything.
Ask it what metric belongs in a weak bullet and it will quote the bullet, explain in one sentence what a recruiter thinks when they read it, name the kind of metric that would land and the specific place to find it (CloudWatch, pipeline history, billing console, org chart), and show you a template with a slot where your figure goes. It covers at most three bullets per answer so the advice stays deep rather than broad.
What it will never do is give you a number. It does not know your figures, and an invented one is a lie you get asked about in an interview.
When you want its advice applied, there is a "Make this edit" button. Type an instruction, or leave the box empty and it applies what the coach recommended in the conversation. Every edit goes through the same honesty guard, and the previous version lands on an undo stack.
Step 7: Export
Download either version, original or tailored, as PDF (what application portals want), DOCX, Markdown, or JSON Resume. All four are renderers over the same structure, so they cannot drift from each other.
One more thing it checks
My favourite rule is one no human reviewer would think to run. Java 17 became generally available in September 2021. If your resume claims Java 17 on a role that ended in 2020, that is not a style problem; it is impossible, and an interviewer who knows the ecosystem will catch it in one question.
The tool flags it, quotes your bullet, names the GA date, and offers the honest fix: drop the version, or scope the claim to when the upgrade actually happened. It does not correct the claim itself. Your history is yours, and only you know what really happened.
It runs on the subscription you already pay for
The whole studio can route its model calls through a local AI CLI instead of a metered API. If you have Claude Pro, Claude Code is enough:
npm install -g @anthropic-ai/claude-code && claude login
Pick "Local CLI" in Settings, and the marginal cost is zero. Codex, Gemini, Qwen, and Ollama are configured the same way: one setting, no code changes. Ollama provides fully local models with no account associated with them.
Being straight about the trade-off: CLI calls spawn a process each time, so they are slower than the API and bound by your plan's own limits. For resume work, which is a handful of calls, you will not notice.
Try it
git clone https://github.com/srinivas-reddy-gouru/scrivio.git
cd scrivio
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python -m uvicorn api.server:app --port 8899
Open http://localhost:8899, go to the resume studio, and paste a resume and a job posting.
It is MIT licensed and runs entirely on your machine. Your resume never leaves it except in the model calls you configure, and with a local CLI, it does not leave at all.
The thing I would want you to take away, whether or not you use it: a resume tool that will not tell you is not on your side. If it happily promotes your title, it will happily do that on the version you send to a company that checks.

Top comments (0)