# Ats Resume Maker

> ATS resume maker for job applications: tailor a base resume to a JD with true, minimal edits, keep canonical Markdown structure, and ship a parseable PDF. Use when drafting or updating a resume for applications, matching a job description without inventing facts, fixing malformed AI resume drafts, running ats-resume validate/build/render, checking real PDF page count, or reviewing page previews. Do not use for DOCX export, LibreOffice conversion, or online ATS score chasing.

- Skill: `just-sampath/ats-resume-maker` (Agent Skill, multi-file: 7 files)
- Install (CLI): `npx skillmds@latest add just-sampath/ats-resume-maker`
- Raw SKILL.md: https://api.skillmd.com/api/skills/just-sampath/ats-resume-maker/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: just-sampath (https://skillmd.com/u/just-sampath)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/just-sampath/ats-resume-maker

---


# ATS Resume Maker

Produce truthful, ATS-parseable resumes as **canonical Markdown** and a gated
**PDF** delivery. **Input is Markdown only** — PDF extract is deferred (convert
offline). Content rules run on Markdown; page count and layout truth come from
the generated PDF and page images—not character estimates or vendor scores.
Factual adds in a change manifest require evidence; never invent metrics or skills.

```text
IRON LAWS
1. Never invent metrics, titles, employers, dates, credentials, or skills.
2. Never overwrite the user's source file; work only in run dirs / copies.
3. final/ is populated only when required gates pass (or visual is skipped).
4. Page count = actual PDF pages only. Never treat char/word count as page limit.
5. Do not claim visual pass without reviewing every previews/page-NN.png.
6. No DOCX. No runtime package installs during build. No silent renderer switch.
7. Spirit equals letter: "almost pass" is a fail until issues are fixed or waived.
```

## When to use

- Create or rewrite a resume in the controlled Markdown dialect
- Tailor an existing resume with an approved change manifest
- Validate Markdown, PDF, or a full multi-gate build
- Inspect page previews and complete visual review

## When not to use

- DOCX / Word-only deliverables
- Scraping or gaming online ATS scoring websites
- Designing multi-column creative portfolios as the ATS artifact
- PDF extraction from scanned/legacy PDFs (P0: not implemented—provide Markdown)

## Quick start

```bash
pip install -e ".[dev]"   # once per environment
ats-resume build path/to/resume.md -o outputs/
# With Gate B (source + evidenced changes required together):
ats-resume build path/to/updated.md -o outputs/ \
  --source path/to/base.md --changes path/to/change_manifest.yaml
# CI without agent visual review:
ats-resume build path/to/resume.md -o outputs/ --skip-visual-review
```

Config: auto-loads `resume.config.yaml` from cwd / parents / package repo when
`--config` is omitted; or pass `--config PATH`. Run layout:

```text
outputs/<slug>/<run-id>/
  source/   work/   final/   previews/   reports/
```

Primary command path is **`ats-resume build`**. Prefer the CLI over re-implementing checks.

## Gates (delivery blockers)

| Gate | Name | What | CLI |
|------|------|------|-----|
| A | markdown | Structure + content (section-aware) | `validate-markdown` |
| B | semantic_diff | Unexpected changes vs source + manifest | `diff` |
| C | pdf | Pages, size, extractable text, links | `validate-pdf` |
| D | visual | Agent/human review of every page image | via `build` + `visual_review.json` |

Preflight (Python, templates, WeasyPrint) and render failures also block delivery.
Advisory issues may remain after a pass; critical (and important in `strict`) fail.

## Agent checklist

```text
- [ ] Canonical Markdown (see references/canonical_markdown.md + resume_template.md)
- [ ] Facts only from user/source; additions evidenced in change_manifest when using Gate B
- [ ] ats-resume build (or stepwise validate → render → validate-pdf → render-images)
- [ ] Read reports/validation.json + reports/validation_report.md
- [ ] Fix issues by code (references/validation_issue_codes.md); re-run build
- [ ] Open every previews/page-NN.png; write reports/visual_review.json with matching pdf_sha256
- [ ] Confirm final/ has *_Resume.md and *_Resume.pdf only after overall pass
- [ ] Deliver final artifacts + report summary; do not claim pass if final/ empty
```

## Correction loop (agent-driven)

1. Run `ats-resume build …` (or isolated gate commands).
2. If exit ≠ 0: read `reports/validation.json` issues (`code`, `severity`, `gate`).
3. Fix Markdown (or template/config)—never invent facts to silence DIFF_*.
4. **Re-run** `build` after each fix. `workflow.max_attempts` (default 3) is
   advisory for agents only — the package does **not** loop or retry internally.
   Escalate if stuck after that budget.
5. When PDF + previews exist: complete visual review → re-run build with
   `--visual-report path/to/visual_review.json` (or place file under `reports/`).
6. Stop only when status is pass and `final/` is populated (or visual legitimately skipped).

Source is **always** preserved under `source/` (immutable base when `--source` is
set; otherwise a copy of the input).

## Commands and exit codes

| Command | Role |
|---------|------|
| `ats-resume build UPDATED.md -o DIR` | Full pipeline; `--source` required with `--changes`; optional `--visual-report`, `--skip-visual-review`, `--config`, `--candidate` |
| `ats-resume validate-markdown RESUME.md` | Gate A |
| `ats-resume diff SOURCE.md UPDATED.md -m MANIFEST.yaml` | Gate B (factual ops need evidence) |
| `ats-resume render RESUME.md -o out.pdf` | WeasyPrint render (`**bold**` → strong) |
| `ats-resume validate-pdf PDF --source RESUME.md` | Gate C (content inventory + links) |
| `ats-resume render-images PDF -o DIR` | PNG previews |
| `ats-resume report --run-dir RUN` | Summarize existing run |
| `ats-resume extract …` | Deferred — Markdown-only product; convert PDF offline (exit 2) |

| Code | Meaning |
|------|---------|
| 0 | Success / pass |
| 1 | Validation failure |
| 2 | Invalid args / extract not implemented |
| 3 | Dependency or renderer failure |
| 4 | Visual incomplete/failed (other gates ok) |
| 5 | Internal error |

## References

Load on demand (one level deep):

| File | Use |
|------|-----|
| `references/ats_guidelines.md` | Severity model, MD vs PDF rules, style heuristics |
| `references/canonical_markdown.md` | Controlled Markdown dialect (parser contract) |
| `references/resume_template.md` | Copy-paste template matching the dialect |
| `references/visual_validation.md` | Gate D checklist + `visual_review.json` schema |
| `references/validation_issue_codes.md` | All MD_*/DIFF_*/PDF_*/VISUAL_*/PREFLIGHT_* codes |
| `references/troubleshooting.md` | WeasyPrint/Windows, install, empty `final/` |

If you are **editing this skill itself**, also read `references/skill_authoring_standards.md`.

## Red flags

- Skipping visual review then claiming delivery success
- Using char-count “page estimate” as a hard error
- Reintroducing DOCX or `generate_docx.js` / LibreOffice paths
- Global word-repetition caps or treating em dashes as universal ATS blockers
- Inventing keywords/metrics to pass Gate B or impress a score site
- Installing packages mid-build or switching renderers without config change

## Rationalizations

| Excuse | Reality |
|--------|---------|
| “Char count says ~2 pages” | Only PDF page count gates (`PDF_PAGE_LIMIT`) |
| “Em dash is fine / always fatal” | Configurable style (`em_dash`); default often ignore—not a universal ATS parse fail |
| “Bold everything for ATS” | Selective bold is advisory presentation, not a keyword signal |
| “Close enough on visual” | Incomplete review → exit 4; no `final/` |
| “Need DOCX for ATS” | Text PDF is the delivery; DOCX is out of scope |
| “Add skills from the JD” | Only with evidence + manifest; never invent |
| “Title has I—pronoun fail” | Pronoun scan skips titles; Roman `I` in job titles is not first person |
| “Short certs look weak” | Short certification lines are valid; do not pad with filler |

## Delivery artifacts

On pass, under `outputs/<slug>/<run-id>/`:

| Path | Content |
|------|---------|
| `final/*_Resume.md` | Validated Markdown |
| `final/*_Resume.pdf` | Validated PDF |
| `previews/page-NN.png` | One image per PDF page |
| `reports/validation.json` | Gate results + issues |
| `reports/validation_report.md` | Human-readable summary |
| `reports/semantic_diff.json` | Gate B detail (when run) |
| `reports/visual_review.json` | Gate D (when required) |
| `source/source.md` | Preserved input |
| `work/` | Intermediate HTML/PDF/updated.md |

Do not treat the run as delivered if `final/` is empty.

## Non-goals

- DOCX generation or round-trip
- Proprietary online ATS scores as ground truth
- Automated computer-vision visual pass (agent/human checklist only)
- PDF→Markdown extraction (`extract` exits 2; convert PDF offline)
- Character-count page limits as hard errors
- Inventing content to satisfy keyword density

