Stitchjob is a plaintext-first toolchain for assembling custom-fit resumes from modular parts. Rather than rewriting or cloning past resumes, Stitchjob encourages thoughtful tailoring by letting you trim, stitch, and combine prewritten bullet points into job-specific documents.
Built for writers, developers, and anyone tired of one-size-fits-all job applications.
The LaTeX resume class was heavily inspired by Patrick Benito's resume template.
- Python 3.8+
- frontmatter 3.08+
- Mako 1.3.10+
- LaTeX installation with
pdflatex - Make (optional, for automated builds)
-
Create a master resume using simple XML (see
resume/example.xmlandresume/template.xml) that captures your work experience in well-worded bullet points describing every significant aspect of what you did. -
When it comes time to apply for a job, remove irrelevant content, leaving only the details that speak directly to what the job posting asks for, saving the result as, for example,
resume/resume.xml. -
Write a cover letter in Markdown-with-YAML-header-like
letter/letter.md(seeletter/example.md). -
If you save the XML resume as
resume/resume.xmland the letter asletter/letter.md, you can also just runmake(ormake all) to generateresume/resume.tex,resume/resume.pdf,letter/letter.tex, andletter/latter.pdf.For arbitrarily named resume file
resume/myresume.xml, use make targets ofresume/myresume.texandresume/myresume.pdf, depending on what format you want. Similarly, for arbitrarily named letter fileletter/myletter.md, you would use make targets ofletter/myletter.texandletter/myletter.pdf.For more control, execute
stitch(orpython stitchjob/stitch.py) directly, for which see below. -
Review the resulting PDFs, make necessary adjustments, and recompile (step #4) as needed. Since both the Python script and the generated LaTeX files are lightweight, the compilation should be very quick.
Stitchjob resumes are authored in a lightweight XML format that balances
structure with flexibility. The XML file must begin with a <resume> root
element and typically includes the following:
<contact>: Your name, email, phone, location, and optional links (e.g., GitHub, LinkedIn).<section>: Major sections of the resume (e.g., Summary, Key Competencies, Experience, Education). Use theheadingattribute to specify a title; optionally, add atypefor semantic grouping.<skills>: Inside a section, lists individual<skill>elements.<experience>: Work or project entries, with attributesbeginandend. Child elements include<title>,<organization>,<location>, optional<blurb>, and a list of<item>bullet points or freeform text<description>.<degree>: For education, including<date>,<type>,<field>,<school>, and<location>.
The format is intentionally minimal and easy to edit. See
resume/example.xml for a complete, working example. Or
just jump in by copying resume/template.xml and filling
in your details.
Note: The content of the XML elements should be plain text that can be passed
directly to LaTeX. Commonly used characters that have special meaning in LaTeX
(i.e. & % $ # _ ^ ~) will be escaped, though. Backslashes (\) and squiggly
brackets ({}) are passed unescaped, allowing for simple LaTeX markup (e.g.
\\ for newline, \emph{} for emphasis, \textbf{} for bold, etc.).
Additionally, basic math symbols inside math mode are also handled properly, so
that $\leftarrow$ will be rendered as ←, for example.
Stitchjob letters are written in a text file that uses the familiar Markdown with YAML header format. However, to keep the dependencies low (i.e. not require the excellent but heavy pandoc), the file is not actually parsed as Markdown. Instead, it should be plain text with (optionally) simple LaTeX formatting (see the note above). Currently recognized YAML header keys are as follows:
recipient: The name or title of the letter's recipient.company: The recipient's organization.address: The organization's address.location: The city, state, and (if desired) ZIP code of the organization's location.salutation: The first line of the letter with all necessary punctuation. If not supplied, butrecipientis, defaults to "Dearrecipient,". If the recipient is not specified, defaults to "Dear Hiring Manager,".closing: The closing line of the letter with all necessary punctuation. If not specified, defaults to "Sincerely,".signature: The signature to appear below the closing line. If more than one line is needed, separate the lines with TeX line breaks (double forward slashes\\; seeletter/example.md).signature_image: Path to the image of your signature. It will be rendered to fit within two lines of text (2emin TeX).
If the Python project is installed with pip install -e ., it will make the
stitch command available on the command line:
stitch resume resume/example.xml --pdf
stitch letter letter/example.md --signature --pdfOtherwise, you can invoke the script directly:
python stitchjob/stitch.py resume resume/example.xml --pdfresume: Converts a trimmed XML resume into a LaTeX.texfile, and optionally compiles it to PDF.letter: Converts a Markdown-with-YAML-header letter file into LaTeX, pulling in contact details from a companion resume file.
--pdf: Compile the generated LaTeX file to PDF usingpdflatex.--verbose: Show detailed debug output.-o,--output: Manually specify output.texfilename (letters only).--signature: Include a graphic signature image in the cover letter.--signature-image: Path to the image used as signature (default:letter/signature.png).--resume: Path to XML resume to use for pulling contact info into the letter (default:resume/resume.xml).
stitchjob/
├── CHANGELOG.md # Log of major changes
├── LICENSE # Text of the MIT License
├── Makefile # Build script for PDF generation
├── pyproject.toml # Python project specification
├── README.md # This file
├── letter/ # Letter .MD, .TEX, and .PDF files
│ ├── example.md # Example letter
│ ├── example.tex # Generated from example.md (auto-generated)
│ ├── example.pdf # Compiled from example.tex (auto-generated)
│ └── example_signature.png # Example signature image
├── resume/ # Resume .XML, .TEX, and .PDF files
│ ├── example.xml # Full-featured example resume
│ ├── example.tex # Generated from example.xml
│ ├── example.pdf # Compiled from example.tex
│ ├── schemas.xml # XML schemas configuration file
│ ├── template.xml # Minimal template for starting a new resume
│ └── schema # XML schemas
│ ├── resume.dtd # DTD schema for the resume XML
│ └── resume.rnc # Relax NG Compact version of DTD schema
├── stitchjob/ # Python package
│ ├── __init__.py # Package marker
│ ├── letter.mako # LaTeX + Mako template for letters
│ ├── shared.py # Functions and exceptions used by all modules
│ ├── stitch.py # Unified CLI
│ ├── stitch_resume.py # Code to convert XML to LaTeX/PDF
│ ├── stitch_letter.py # Code to convert MD to LaTeX/PDF
│ └── stitched.cls # LaTeX resume class for Stitchjob resumes
└── tests/ # Test suite
├── test_shared.py
├── test_stitch_letter.py
└── test_stitch_resume.py