resumeme
Your résumé deserves better than LinkedIn's PDF export. Skip the clunky
formatting and the copy-paste routine of maintaining a second résumé. resumeme ☕ turns your profile into a polished, illustrated PDF you'll actually want to send to a hiring manager offline.
Build and release your résumé like software: fork the project, set your username,
capture your profile, and keep main current with monthly refreshes. Tag the
version you want to share to get a signed release.
View the résumé (PDF) - Preview a fork's README - Fork this project
Why use this tool?
- Review your résumé in Git. Profile text, images, configuration, and templates live in your repository. Changes have diffs and history.
- Keep the engineering detail. Expanded descriptions, project links, company logos, and illustrations flow across plain US Letter pages in Garamond, with a two-column first page for your profile, contact information, and About section.
- Keep it current and release deliberately. Monthly CI refreshes LinkedIn and commits the PDF. Tag a revision to publish its signed PDF through the GitHub CLI.
- Share verifiable output. Cosign signatures, verification bundles, checksums, and a public-key fingerprint accompany each release.
- Own the presentation. Adjust paper size, colors, or text size in YAML, or
select an inline theme, including the autumn-colored
tigeroption. Custom LaTeX templates can change the layout without changing the collector.
Contents
- resumeme
Quick start
Fork into your own account as resume, with the description "My resume, generated
from LinkedIn and signed with GitHub Actions." Select Copy the main branch only.
1. Install
In your fork's local checkout, install the package. Local capture requires Python 3.13+, Poetry 2.5.1, and Firefox (default) or Chrome. GitHub Actions handles PDF compilation; Docker is needed only for a local PDF preview.
poetry install --only main
poetry run resumeme --help
macOS prerequisites
On macOS with Homebrew installed, bootstrap host tools from the Brewfile and install the project's pinned Poetry version:
brew bundle install
pipx install --python "$(brew --prefix python@3.13)/bin/python3.13" "poetry==2.5.1"
export PATH="${PIPX_BIN_DIR:-$HOME/.local/bin}:$PATH"
poetry env use "$(brew --prefix python@3.13)/bin/python3.13"
Run brew bundle check to verify host dependencies. Start Docker Desktop before
building a PDF locally. Homebrew supplies current host tools; CI keeps its existing
version pins, and Python dependencies and linters install from poetry.lock.
2. Capture your profile
For a new fork, copy resumeme.config.ref.yaml over resumeme.config.yaml, which contains the author's personal settings. The reference uses package defaults, with optional integrations disabled and no job, school, project, or date exclusions. Set your LinkedIn username:
linkedin:
username: your-linkedin-username
Capture your profile and check the saved snapshot:
poetry run resumeme capture
poetry run resumeme validate
Sign in to LinkedIn in the browser window and leave it open. Capture waits for you to finish signing in, then saves your profile and images locally. A username change alone does not fetch a profile in CI: Actions builds the snapshot you push.
To use Chrome, set capture.browser: chrome in the config; firefox is the default.
Install the selected browser first. See browser setup.
3. Publish
Before your first push, enable Actions in your fork, allow it to write repository contents, and configure the fork environment variables. Branch rules must allow the bot's PDF commit. This setup is required once per fork.
Review data/profile.json and data/assets/, including the contact fields that will
appear in the PDF, then publish:
git add resumeme.config.yaml data/profile.json data/assets/
git commit -m "Update resume profile"
git push origin main
After the pipeline succeeds, your fork contains resume.pdf on main.
Set readme.output: README.md to make its README a personal résumé page: your name,
a clickable first-page preview, and links to the full PDF, profiles, and releases.
This repository overrides the destination to FORK_EXAMPLE.md
so you can preview the result alongside these instructions. CI refreshes the
configured page and preview in the same commit as the PDF. Set readme.mode: project
to disable generation, or customize readme.introduction; see README publication.
Configure LinkedIn secrets for automatic monthly refreshes. When ready to share,
tag the updated commit to create a release with signatures, hashes, and the key
fingerprint; see monthly refresh and release.
The PDF link stays relative to your fork and follows output.pdf. Preview images
use absolute GitHub URLs so they also display on package indexes such as PyPI.
Use with an AI agent
Open your checkout in an agent with terminal access and give it this prompt:
Read
SKILL.mdin this checkout and generate my résumé for LinkedIn usernameYOUR-USERNAME. For first setup, start fromresumeme.config.ref.yamlif the fork still has the author's config. Preserve my existing configuration choices. Handle setup, capture or reuse of my matching saved profile, validation, PDF generation, and visual checks. Let me complete browser login and MFA when needed, then return the finished PDF and what you verified.
The portable agent skill also covers filters and themes, GitHub activity, Codex summaries and employer-specific PDFs, signing, monthly refreshes, personal READMEs, and Pages. Add the specific operation you want: for example, "publish to my fork's main branch" or "create a signed résumé release from the accepted PDF commit." Live LinkedIn About updates and skill additions are separate requests. See the CLI reference for commands and options.
How it works
The Python package captures your profile through local Firefox or Chrome and uses requests
to cache images and project previews. Your browser login stays in the ignored local
profile. The portable inputs are data/profile.json and data/assets/.
Jinja translates those inputs and your YAML configuration into tex/resume.tex.
The digest-pinned drpsychick/texlive-pdflatex image compiles the PDF. CI installs
from the Poetry lockfile. Ordinary pushes rebuild committed inputs; monthly runs
capture LinkedIn first. After validation, main-branch publication commits the PDF
and any refreshed inputs together. User-created tags add a release link and key
fingerprint to the committed PDF's footer, sign it, and publish a release.
Pull requests validate without publishing or signing in.
For applications, add LinkedIn company usernames and job links to
codex.companies. CI tailors additional summaries to those employers and commits
the PDFs under single-origin/, alongside your generic resume. See
single-origin resumes for configuration and
company/job context overrides.
See configuration, architecture, and capture limits for the details.
Update your résumé
Refresh your profile
After editing your LinkedIn profile, run poetry run resumeme capture again, review
the changed snapshot and assets, and commit and push them. For layout changes,
edit resumeme.config.yaml and push; the saved profile can be reused.
Logs default to ERROR. Set logging.level: DEBUG or use --log-level DEBUG
before the command for request and browser diagnostics. Logs use OpenTelemetry
JSON on stdout; see logging controls.
Refresh links and previews
To discover URLs in already captured text and refresh their destinations, page titles, and preview images without another LinkedIn login:
poetry run resumeme enrich
poetry run resumeme validate
poetry run resumeme build
Capture also performs this enrichment. HTTP(S) and www. URLs become clickable
within the PDF's prose. Original text and URLs stay in the snapshot alongside
observed redirect destinations and titles; rendering reuses those saved references.
capture.fetch_link_previews: false disables remote link inspection while keeping
local URL discovery. Contact links remain clickable without fetching their pages.
Preview the PDF locally
To preview the PDF locally with Docker running:
poetry run resumeme build
Customize your résumé
Edit resumeme.config.yaml to choose what appears in the PDF. For colors and typography, see inline themes.
Sections and projects
Use the section_order array for both visibility and order. Comment out an entry
to hide it; uncomment or move it to include or reorder it:
section_order:
- about
- experience
- projects
# - featured
- education
- skills
This changes the generated resume while retaining the captured data. See configuration for section keys and other options. The shipped config lists every known section, with Contact info, Featured, Recommendations, Interests, Causes, Organizations, and Languages commented out. Only uncommented entries appear in the PDF and its table of contents. Projects and enabled Featured posts use matching light-gray, two-column tiles.
Projects and project attachments from visible jobs and Featured posts appear in
one two-column Projects section. Matching resolved links merge into a single entry
with their role associations. Attachment descriptions move out of Experience and
appear below the project's image or logo; role narrative stays with the job.
Post text and inline links stay in Featured. Commenting out projects also hides
the relocated project cards.
project_filter selects projects by source URL using a Python regex and defaults
to GitHub URLs. Set it to null to remove the URL restriction.
Use projects.include to choose names and optionally distinguish their companies:
projects:
include:
- name: resumeme
- name: Deployment platform
affiliation: Example Company
exclude:
- name: resumeme
affiliation: Former Company
Matching ignores case and extra spaces. include: null keeps all names;
include: [] hides every project tile. exclude uses the same selectors and wins
when both lists match; exclude: [] excludes nothing. The URL filter still applies. See
project filtering for examples.
Job history
Filter individual jobs in the same file:
experience:
disable:
- title: Intern
company: Example Company
last_years: 5
as_of: null
Exclusions match the exact job title, company, or both, ignoring case and extra
whitespace. last_years: 5 includes any job overlapping the last five years,
including jobs that began earlier and ongoing roles. The boundary is inclusive;
the full description and original dates stay intact. Jobs with unreadable or
missing dates remain visible. Defaults keep all jobs (disable: [],
last_years: null). as_of: null uses today's UTC date; set a quoted date such as
as_of: '2026-10-07' to keep builds anchored to the same window. See
job filtering for grouped roles and date precision.
Education
Use education.disable to exclude entries by school, degree, major, or a
combination. All fields in a selector must match; any matching selector hides the
entry. The default is []. For example:
education:
disable:
- school: Example University
- degree: Associate's Degree
major: Mathematics
Comment out education in section_order to hide the entire section. See
education filtering for matching rules.
Profile header and contact information
The headline beneath the portrait is hidden by default; set
style.show_headline: true to restore it. The company and location remain visible.
Set github.username to your GitHub account for an icon and profile link directly
below LinkedIn, or null to omit it. Both links use their platform icons.
The cover/background photo is hidden by default in resumeme.config.yaml. Set
style.show_header_photo to true to display it again; the portrait stays visible.
Below the LinkedIn profile link, a compact contents list links to each visible
section in PDF order. Set style.show_table_of_contents: false to hide it;
it defaults to true and supports inline theme overrides.
Connection details are optional: set style.show_connection_count: true to show the captured count,
style.show_connection_link: true for a Connections link, or both to link the count.
Both default to false and can also be overridden in inline themes. Re-enable the
separate contact block by removing contact from disable.
The birthday stays hidden unless you also set style.display_birthday: true;
this setting defaults to false and supports inline theme overrides.
GitHub activity
Show clickable contribution circles beneath the GitHub link or in an appendix:
github:
username: your-github-account
contributions:
enabled: true
months: 1
placement: profile # or appendix
The graph uses GitHub's light-theme greens and each day's contribution link.
It follows the profile column's side and fills its width. No additional token or
secret is required. Set enabled: false to omit it; use months: 1 through 12
to choose the window. See saved calendars and offline builds.
Skills
The top 20 skills appear as a word cloud scored by references + 2 * endorsements.
Size reflects this score; color reflects endorsements relative to the most-endorsed
displayed skill. style.skill_colors defines the gradient from 0% to 100%.
Disabled sections contribute no references. Set style.skills_word_cloud: false
for the text list, or add skills to disable to hide it. Profiles with no optional
sections also work. See the profile schema and scoring rules.
Codex summaries
Optionally let Codex write About and a short description beneath your portrait.
Add the OPENAI_API_KEY Actions secret, set codex.enabled: true, and provide
target roles, tone, or extra background under codex.context in
resumeme.config.yaml. Main-branch CI generates the copy
once for both document checks and the PDF build. The captured profile stays intact.
See model choices and API key setup and local previews.
Publishing
GitHub Pages
Host the résumé at your Pages root or a custom domain. Enable pages.enabled in
resumeme.config.yaml and select GitHub Actions as the
publishing source in your fork's Settings > Pages. CI updates index.html and
its linked PDF after successful publication to main.
pages.path: / serves the root; use a path such as /cv/ for a subdirectory.
See Pages setup for custom domains, DNS, and local previews.
Fork environment variables
Configure these GitHub Actions repository secrets in your own fork for the features you use. GitHub supplies the publication token:
LINKEDIN_USERNAME- required for monthly refresh. Your LinkedIn login email or account identifier; this is separate fromlinkedin.username, the profile slug.LINKEDIN_PASSWORD- required for monthly refresh. The login password. These two secrets reach capture on refresh runs and the optional LinkedIn signing identity update after signed releases.OPENAI_API_KEY- required whencodex.enabledorcodex.skills.enabledistrue. Create a project key on the OpenAI API keys page and store it as an Actions repository secret. The Codex summary jobs receive it; pull-request checks do not. API usage is billed to that project. To stop API usage, setcodex.enabled,codex.skills.enabled, andcodex.skills.publishtofalse. See Codex setup and tag-only skill suggestions.COSIGN_PRIVATE_KEY- required for signed releases. Set this to the complete PEM contents of your own Cosign private key, including the header, footer, and newlines. The value is the key itself, not a filename.COSIGN_PASSWORD- required for an encrypted signing key. Set this to that key's password. Leave it unset for an unencrypted key; the signing script defaults to an empty password.GH_TOKEN/GITHUB_TOKEN- supplied automatically; no secret to create. Actions generates the repository token, and the deploy workflow passes it to the GitHub CLI asGH_TOKEN. It usescontents: writeto commitresume.pdfand publish releases. No personal access token is needed; repository and branch rules must permit those writes. Tag publication also uses the built-in token withpackages: writeto push the tool's container image to GHCR.PYPI_API_TOKEN- package maintainers only. Grant the repository access to this organization secret, or define it as a repository/pypienvironment secret. Version-tag releases expose it to Poetry asPOETRY_PYPI_TOKEN_PYPIand uploadresumemeto PyPI. Forks that only generate resumes do not need it. See package releases.
Configure signing secrets
With OpenSSL, Cosign 3.x, and an authenticated GitHub CLI installed, run
bash scripts/release/setup-signing.sh --repo YOUR-USERNAME/YOUR-FORK.
The script creates an encrypted signing key, retains a local backup, and sets
COSIGN_PRIVATE_KEY and COSIGN_PASSWORD on your fork. To reuse a saved key,
add --key-dir /path/to/backup. See signing setup and recovery
for prerequisites, key storage, and verification.
LinkedIn authentication
Set the public profile slug under linkedin.username in resumeme.config.yaml.
Local resumeme capture opens the configured browser and waits for you to finish signing in.
When both login environment variables are present, it submits them automatically;
interactive capture still waits for you to complete MFA. Scheduled runs use
capture --headless and fail without updating main if authentication requires
interaction. See automation setup and recovery.
Documentation
- CLI reference: complete command help, options, examples, and exit status.
- Configuration and operation: capture, job filters, rendering, and signed releases.
- Monthly refresh and release: LinkedIn secrets, scheduling, and shareable signed PDFs.
- Suggested LinkedIn skills: tag-only Codex proposals and optional additions that preserve existing skills and endorsements.
- GitHub Pages: automatic website updates, publication paths, and custom domains.
- Themes and templates: colors, typography, and custom layouts.
- Container image: Docker usage, local builds, and tag publication to GHCR.
- Development: setup, parallel tests, tooling, and document checks.
Metadata
Release files for resumeme 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| resumeme-0.1.2.tar.gz | 3.8 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| resumeme-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 7.6 MB
Release files / resumeme-0.1.2.tar.gz
| Download URL | resumeme-0.1.2.tar.gz |
|---|---|
| Size | 3.8 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4b983919b30a94c401621723c6420dc57fde339e488f9e9e0c5c9c9061d8202c
|
|
BLAKE2b-256 checksum How to use checksums |
555d87bc984494fb569a98b06763c27a5daab64ddc1fd9044e6676809789345a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.5.1 CPython/3.13.12 Linux/6.17.0-1022-azure
|
Release files / resumeme-0.1.2-py3-none-any.whl
| Download URL | resumeme-0.1.2-py3-none-any.whl |
|---|---|
| Size | 3.8 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
afc0bd77425b37d372a0f39cc24a86e1015b252ffe5ec3aa35a4d6d908b23324
|
|
BLAKE2b-256 checksum How to use checksums |
e65b8e3829e300ee304ecfba579b3b8d34c6c1870a31bb654566aa7ed2167606
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.5.1 CPython/3.13.12 Linux/6.17.0-1022-azure
|