my-resume

A LaTeX resume you can git diff, tailored per job with Claude Code.

GitHub

The template

One class file owns the layout; a resume file holds only content. These are the real pages, built by CI from this commit: Duna's complete canonical resume, and the one-page variant tailored for a job.

Canonical resume, page 1
Canonical, page 1
Canonical resume, page 2
Canonical, page 2
Resume tailored for one job, page 1
Tailored for one job

What to notice, from the top of a page down:

  1. Section tabs

    Each section opens with a graphite tab and a rule to the margin. Sections always print in the same order (Summary, Experience, Projects, Education, Publications, Service, Honors & Awards), whatever the order in the source; leave one out to drop it.

    Close-up of page 1: the Experience tab
  2. A timeline spine

    Roles and projects hang off one line, a ring for each entry, and the line keeps going across a page break.

    Close-up of page 1: the spine beside two roles
  3. Date pills

    Dates are written once as 2023-04 or present; the class prints them as Apr 2023 – Present.

    Close-up of page 1: the date pill Apr 2023 – Present
  4. Facts cited by key

    A role's title, employer, place, and dates are defined once in common/facts/ and cited by key, so every variant prints them the same way.

    % common/facts/roles.tex
    \defrole{windowsill}{
      title = {Head of Windowsill Operations},
      org = {Sunbeam Estates},
      location = {Living Room},
      start = 2023-04, end = present,
    }
    % canonical/resume.tex
    \begin{role}{windowsill}
      \item Initiated and led
        ``Operation Red Dot'', …
    \end{role}
    Close-up of page 1: the role header Head of Windowsill Operations, Sunbeam Estates, Living Room
  5. A typo fails the build

    Cite windowsil instead of windowsill and the build stops with an error that names it. So do a missing field, a duplicate section, and a date like 2024-13.

    ./canonical/resume.tex:60: Package resume Error: Unknown role key 'windowsil'.
  6. No stranded titles

    Pages break between bullets, never between a role's title and its first bullet or between a heading and its first entry. A test moves the content through 51 page positions to check.

How it works

One complete resume, a tailored copy for each job, and git to remember what you sent.

  1. Facts, written once

    Roles, projects, degrees, publications, service, and honors are defined once in common/facts/ and cited by key. A wrong key, a missing field, or a bad date stops the build, so a title or a date can't drift between variants.

  2. /customize-resume tailors, with your approval

    Give Claude Code a job posting. It saves a summary as jd.md in a new application folder, maps what the job asks for to evidence already in your resume, and stops for your approval before it edits. An ask with no evidence is marked as such, never invented.

  3. /update-resume and tags keep history

    New experience goes into the facts and the canonical resume, and Claude asks for any date or title it doesn't have. Each application is a folder; tag it submitted/… when you send it, and checking out the tag and building it gives back what you sent (with the same TeX Live).

Get started

Use the repo as a template and clone your copy. Then, on macOS with Homebrew:

brew bundle          # BasicTeX, just, tex-fmt, prettier, poppler
just deps            # + the extra TeX Live packages (asks for sudo once)
just build           # canonical/resume.tex → canonical/resume.pdf
just check applications/2026-09-granary-senior-mouser   # build + check it fits in 2 pages
just test            # run the template tests

To make it yours, put your details in common/profile.tex and common/facts/ (or run /update-resume in Claude Code and let it ask for them), and rewrite canonical/resume.tex. For a job, run /customize-resume with the posting.