Resume Builder skill for Codex

ATS-proof resumes from one honest source file. Codex keeps a resume as structured YAML and renders matching DOCX and PDF files with a single-column, ATS-safe layout. It rewrites bullets as verb, scope and measurable result, tailors to a job description using only facts the user supplied, flags missing metrics instead of inventing them, and checks both files by extracting their text the way an applicant tracking system would.

  • Documents & Office
  • $resume-builder
  • 191 lines
  • 2 files
  • ~1,950 tokens
  • MIT
  • Updated

Install

curl -fsSL codexskills.dev/install.sh \  | sh -s -- resume-builder

Installs to ~/.agents/skills/resume-builder/ for every project on this machine.

104-line POSIX script. No sudo, no telemetry. Read install.sh

Use it in Codex

Start a prompt with $resume-builder, or pick it from /skills. You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.

What Codex reads before loading it

Builds resumes and CVs as DOCX and text-based PDF from one structured source (JSON Resume style YAML or JSON), with single-column ATS-safe layout, standard section headings, achievement bullets, and a parse check that extracts the text the way applicant tracking systems do. Use when the user asks to create, rewrite, reformat or tailor a resume or CV, convert a designed resume into an ATS-friendly one, or generate resume files from data.

Use it when

  • Creating or rewriting a resume or CV
  • A designed resume needs an ATS-friendly version
  • Tailoring a resume to a specific job posting
  • Generating resume files from structured data

Use something else when

How to check the result

Extract text from the PDF with pdftotext and from the DOCX with python-docx, and confirm contact details come first, sections are in order and every role keeps its title, company and dates together.

The mistake it prevents

Putting contact details in the page header or a sidebar, where many applicant tracking systems never read them.

~/.agents/skills/resume-builder/SKILL.md

--- name: resume-builder description: Builds resumes and CVs as DOCX and text-based PDF from one structured source (JSON Resume style YAML or JSON), with single-column ATS-safe layout,… license: MIT ---

Done well means: an ATS extracts every section in the right order with correct dates and contact details, a recruiter scanning for six seconds sees role, scope and results, every claim is true and supplied by the user, and DOCX and PDF come from the same source.

Hard rules

  • Never invent employers, titles, dates, degrees, skills or numbers. When a bullet needs a metric the user has not given, write [metric?] and ask. Tailoring means choosing and phrasing true material, not adding new claims.
  • Resumes are personal data. Keep files local; do not paste contents into online tools or commit them to public repositories.
  • Follow regional norms the user confirms: US/UK/Canada usually omit photo, birth date and marital status; some European markets expect a photo or more personal details.

Workflow

- [ ] 1. Collect source material: old resume, LinkedIn export, target job description
- [ ] 2. Normalise into resume.yaml (schema below); confirm facts with the user
- [ ] 3. Write or rewrite bullets (achievement formula); mark gaps with [metric?]
- [ ] 4. Tailor: map job-description keywords to true experience; order by relevance
- [ ] 5. Render DOCX (python-docx) and PDF (Typst or HTML + WeasyPrint)
- [ ] 6. Run the ATS parse check on both files
- [ ] 7. Deliver files + a short list of open questions

Source of truth

# resume.yaml - loosely follows the JSON Resume schema
basics:
  name: Ada Lovelace
  label: Senior Backend Engineer
  email: [email protected]
  phone: "+44 20 7946 0000"
  location: London, UK
  links: [linkedin.com/in/adalovelace, github.com/ada]
summary: >-
  Backend engineer with 9 years in payments; led the ledger rewrite that cut
  reconciliation time from days to minutes.
work:
  - company: Analytical Engines Ltd
    position: Senior Backend Engineer
    location: London
    start: 2021-03
    end: present
    highlights:
      - Led a 5-person team rebuilding the payments ledger in Go; reconciliation time fell from 2 days to 15 minutes.
      - Cut p99 API latency from 900 ms to 180 ms by replacing N+1 queries and adding read replicas.
education:
  - institution: University of London
    area: Mathematics
    studyType: BSc
    end: 2015
skills:
  - {name: Languages, keywords: [Go, Python, SQL]}
  - {name: Infrastructure, keywords: [PostgreSQL, Kafka, AWS, Terraform]}

Writing bullets

Formula: verb + what you did + scope + measurable result.

WeakStrong
Responsible for the billing serviceOwned the billing service (40k invoices/month); cut failed charges 35% by adding retry with idempotency keys
Worked on performanceReduced p99 checkout latency from 1.2 s to 300 ms by caching price rules
Helped onboard new hiresWrote the onboarding guide and pairing plan; new engineers shipped first PR in 3 days instead of 2 weeks
  • 3-6 bullets for recent roles, 1-2 for older ones; drop roles older than ~15 years to a one-line “Earlier experience” entry.
  • Length: one page under ~10 years of experience, two pages beyond. Never three.
  • Tailoring: list the job description’s hard requirements, find the true evidence for each, move it up, and use the employer’s wording where it is accurate (ATS keyword match is literal: “PostgreSQL” vs “Postgres”, “CI/CD” vs “continuous delivery”).

ATS-safe layout

DoAvoid
Single column, top-to-bottom reading orderTwo-column layouts, sidebars
Real text, standard fonts (Calibri, Arial, Garamond, Source Sans)Text in images, icons for phone/email
Headings named Experience, Education, Skills, Projects, CertificationsCreative headings (“My Journey”)
Contact details in the body at the topContact details only in the page header/footer
Dates as Mar 2021 - Present or 2021-03 - present, one style throughoutYears only on some roles; “Spring ‘21”
.docx when the portal asks for Word; text-based PDF otherwiseScanned PDF, tables for layout, text boxes

Render DOCX with python-docx

from datetime import datetime
import yaml
from docx import Document
from docx.enum.text import WD_TAB_ALIGNMENT
from docx.shared import Cm, Pt

def fmt(d):
    if d in (None, "present"):
        return "Present"
    return datetime.strptime(str(d), "%Y-%m").strftime("%b %Y") if "-" in str(d) else str(d)

cv = yaml.safe_load(open("resume.yaml", encoding="utf-8"))
doc = Document()
sec = doc.sections[0]
sec.left_margin = sec.right_margin = Cm(2)
sec.top_margin = sec.bottom_margin = Cm(1.6)
normal = doc.styles["Normal"]
normal.font.name, normal.font.size = "Calibri", Pt(10.5)
normal.paragraph_format.space_after = Pt(2)
right_tab = sec.page_width - sec.left_margin - sec.right_margin

b = cv["basics"]
doc.add_heading(b["name"], level=0)
doc.add_paragraph(" | ".join([b["label"], b["location"], b["email"], b["phone"], *b["links"]]))
doc.add_heading("Summary", level=1)
doc.add_paragraph(cv["summary"])

doc.add_heading("Experience", level=1)
for job in cv["work"]:
    p = doc.add_paragraph()
    p.paragraph_format.tab_stops.add_tab_stop(right_tab, WD_TAB_ALIGNMENT.RIGHT)
    p.paragraph_format.space_before = Pt(6)
    p.add_run(f"{job['position']}, {job['company']}").bold = True
    p.add_run(f"\t{fmt(job['start'])} - {fmt(job['end'])}")
    for h in job["highlights"]:
        doc.add_paragraph(h, style="List Bullet")

doc.add_heading("Education", level=1)
for ed in cv["education"]:
    doc.add_paragraph(f"{ed['studyType']} {ed['area']}, {ed['institution']}, {ed['end']}")

doc.add_heading("Skills", level=1)
for s in cv["skills"]:
    p = doc.add_paragraph()
    p.add_run(f"{s['name']}: ").bold = True
    p.add_run(", ".join(s["keywords"]))

doc.core_properties.title = f"{b['name']} - Resume"
doc.core_properties.author = b["name"]
doc.save("Ada_Lovelace_Resume.docx")

Contact details sit in the body, the right-aligned dates use a tab stop (not a table), and headings use real Heading styles. Restyle Title and Heading 1 in the document’s styles (size, colour, a bottom border) rather than formatting runs one by one.

Render PDF

Generate the PDF from the same resume.yaml: a Typst template (yaml("resume.yaml") loads it directly; see $typst-documents) or Jinja2 HTML + WeasyPrint (see $pdf-generation). Converting the DOCX with LibreOffice also works (soffice --headless --convert-to pdf Ada_Lovelace_Resume.docx) and keeps both files identical. Embed fonts, keep one column, and set the PDF title metadata to the person’s name.

File names: Firstname_Lastname_Resume.pdf, not resume_final_v3.pdf.

ATS parse check

Extract text the way an ATS does and read it top to bottom:

pdftotext -layout Ada_Lovelace_Resume.pdf - | head -60
python3 -c "import docx,sys; print('\n'.join(p.text for p in docx.Document(sys.argv[1]).paragraphs))" Ada_Lovelace_Resume.docx

Pass criteria:

  • Name, email and phone appear in the first lines of extracted text.
  • Section headings appear as their own lines in the expected order.
  • Each role’s title, company and dates are on adjacent lines, not split across columns.
  • No (cid: codes, missing characters or merged words (font or ligature problems).
  • Every hard requirement from the job description appears verbatim at least once, backed by a true bullet.
  • pdffonts shows embedded fonts; page count is 1 or 2.

Delivery note

**Files:** Ada_Lovelace_Resume.docx, Ada_Lovelace_Resume.pdf (1 page, from resume.yaml)
**Tailored for:** Staff Engineer, Payments - matched 9/10 listed requirements
**ATS check:** text order correct in both files; contact details in body; fonts embedded
**Needs your input:** [metric?] on the 2019 migration bullet; confirm the Kafka certification date

What the zip contains

SKILL.md plus the interface file below. Nothing runs on install.

agents/openai.yamlgenerated from this page

Gives the Codex app a display name, a one-line description and a starter prompt for this skill.

interface:
  display_name: "Resume Builder"
  short_description: "ATS-proof resumes from one honest source file"
  default_prompt: "$resume-builder Turn my two-column Canva resume into an ATS-friendly Word and PDF version"

About this skill

Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.

esc
New

Introducing Codex Skills Pro

79 professional skills that take Codex through complete engagements, each with its own scripts, references and a report that verifies the result.

All-AccessOne-time payment, no subscription
$49
Get All-AccessOr browse individual skills from $2.99 →

Secure checkout by Creem