A Python tool that generates a professional CV/resume in PDF format using LaTeX and the Awesome-CV template.
- Loads CV data from YAML files
- Takes a link to a job ad to fit your resume and coverletter to the position you seek
- No (all too) personal information is sent to the interwebs
- Uses Claude for content enhancement
- Generates professional PDFs using Jinja2 and LaTeX
- Based on the Awesome-CV template
- Python 3.13+
- uv (not required but strongly encouraged)
- LaTeX installation with XeLaTeX
- Fonts: Lora and Fira
- Some AI key comes in handy
- Clone this repository
- Set up your API key:
export ANTHROPIC_API_KEY='your-api-key'
-
Update your CV data in the YAML files under
data/:carstories.yaml: CAR stories (challenge, action, result) with skills and a job identifiereducation.yaml: Educational backgroundjobs.yaml: Work experience with job identifierskills.yaml: Skills and competenciesheaders.yaml: Various things like phone number, mail address...languages.yaml: The languages you speakstatements.yaml: Statements about last job positions, with job identifiers
-
Generate your resume:
uv run main.py
PyCv sends some parts of your data to an online LLM. This is restricted to:
- The link for the job ad
- CAR stories in
data/carstories.yaml - Jobs data in
data/jobs.yaml - Job Statements in
data/statements.yaml - Skills in
data/skills.yaml
When creating these data files, you might want to make sure you do not include any personal data, names of actual companies or other things you do not want to share with the internet.
Not sent are information in data/headers.yaml such as your phone number or your email address.
Yes, because that's what fits my needs. Feel free to change the template in template/ or the prompts in pycv/*-prompt.txt to your own taste.
PyCv uses instructor in ai.py. If you want to address a different model (the code defaults to Claude), you will have to adapt client = ... and the parametrization of the model in the constructor and in ask().
All AI prompts are save in pycv/*-prompt.txt. Feel free to adapt those to your needs. The current version is in German; you might want to change that.
All things layout are done in the jinja2 templates in the templates folder. If you want to test different layout options, you can run main.py with the project name test; this will exchange the AI parts with some default strings to test if the LaTeX part works as expected.
Entries in data/headers are transformed into header tags defined in awesome-cv.cls. The value for the key phone will be used as \phone{value} in the latex output. To add different/more/less header information, add the appropriate entries in data/headers.yaml.
(job links with identifier in jobs.yaml)
- job: 1
challenge: "Something happened"
action: "I did this"
result: "This was the outcome"
skills:
- Skill 1
- Skill 2
- job: 2
...- edu: 1
title: "Degree Title"
organization: "Institution Name"
location: "Location"
date:
- "Start"
- "End"
desc: "Optional description"
- edu: 2
...- job: 1
position: "Job Title"
organization: "Company Name"
location: "Location"
date:
- "Start"
- "End"
- job: 2
...- language: Some Language
level: Mostly fine
- language: Other Language
...- category: Some Topic I Know About
- "Skill 1"
- "Skill 2"
- category:
...(job links with identifier in jobs.yaml)
- job: 2
statement: >
Mr me was hired as a Super Contractor to fix the wrinkles in the fabric of spacetime in our lavatories. He...
- job: 1
...- photo: data/myface.jpg
name:
- MyFirstname
- Lastname
position: Something Great
address: Where I live
mobile: 123 45 67 890
email: me@home.somewhere
linkedin: findme-here-aswell- job: 1
statement: Mr Me was always...This project uses the Awesome-CV template which is licensed under CC BY-SA 4.0.