Use when the user provides a job posting URL or description and wants a tailored resume, asks to analyze job fit, says build/tailor resume or apply for a role, or wants to import an existing resume file into resume.md
Interactive workflow: analyze a job description against the user's master resume (resume.md), identify strongest matches, fill gaps through conversation, and generate an ATS-optimized 2-page Word document.
resume.md in working directory (master resume — additive, never remove content)python-docx installed (pip3 install python-docx)pdfplumber installed (pip3 install pdfplumber)playwright installed (pip3 install playwright), Google Chrome installedNote: The helper scripts (generate_resume.py, import_resume.py, apply_to_role.py) are bundled with this plugin and available on PATH automatically.
If resume.md does not exist and the user provides a resume file (.docx, .pdf, .txt), run the import flow before the main workflow:
import_resume.py <resume_file>
resume.md in this format:
# Full Name
phone | email | linkedin
## Overview
Summary paragraph...
## Experience
### Job Title
**Company | Location**
*Dates*
Role description...
- Bullet 1
- Bullet 2
## Education
Degree — School
## Skills
- Skill 1
- Skill 2
resume.md to the user for review. Ask:
digraph {
rankdir=TB; node [shape=box];
fetch [label="1. Fetch & parse JD"];
analyze [label="2. Analyze resume vs JD"];
ask [label="3. Ask questions\n(1-2 rounds max)"];
update [label="4. Update resume.md"];
tailor [label="5. Tailor summary,\nbullets, & skills"];
review [label="6. Present selection\nsummary for approval"];
gen [label="7. Generate .docx"];
apply [label="8. Apply to role\n(optional)", style="dashed"];
fetch -> analyze -> ask -> update -> tailor -> review -> gen;
gen -> apply [style=dashed, label="if user\nwants to apply"];
ask -> ask [label="follow-up if needed"];
}
WebFetch on the URL first.WebFetch the URL directlyWebSearch for the exact job title + company + "job description requirements" to extract JD details from search result snippetsRead resume.md. For each JD requirement, classify resume coverage:
| Category | Meaning |
|---|---|
| Covered | Strong bullet with quantified results directly maps to requirement |
| Partial | Related experience exists but weak fit or missing metrics |
| Gap | No relevant experience in resume.md |
Select top 3-5 strongest matches. Prioritize:
Present your analysis first, then ask ALL questions in one round, grouped:
Gaps — "The JD requires X. Do you have experience with this?"
Clarifications — "Your bullet about X — should this rank higher for Y requirement?"
Deepening — "For [bullet], can you share [specific metric/dollar amount/percentage]?"
Additional skills — "Do you have experience with [JD-mentioned tools/technologies/certs] not in your resume?"
If the first round surfaces significant new info, do ONE follow-up. Never more than 2 rounds.
resume.mdresume.md is additive only — never remove existing contentSummary: Rewrite targeting THIS role. Mirror JD language. Hit top 3-4 keywords. 3-4 sentences max.
Bullet selection (within 10-15 year range):
Skills: Reorder with JD-matched skills first. Add user-confirmed skills. Remove irrelevant skills from tailored output only (keep in resume.md).
Before generating, show:
Compile JSON matching the schema in generate_resume.py, then:
generate_resume.py /tmp/resume_input.json resume_[company]_[role].docx
/tmp/resume_input.json afterAfter generating the resume, ask the user if they want to apply directly. If yes:
Setup (first time only):
pip3 install playwright
Automation loop — screenshot-driven:
apply_to_role.py launch "<job_url>"
/tmp/apply_screenshot.png) to understand the page state.apply_to_role.py screenshot
apply_to_role.py click-apply
apply_to_role.py upload resume_[company]_[role].docx
resume.md (name, email, phone, LinkedIn):
apply_to_role.py fill "<selector>" "<value>"
apply_to_role.py select "<selector>" "<option text>"
click "text=Next" and repeat.apply_to_role.py close
Other useful commands:
text — extract page text (faster than screenshot for reading form labels)scroll down / scroll up — see more of the pagepages / switch <index> — manage tabs if the site opens new onesurl — check current page URLKey rules:
When running repeated resume builds (especially via scheduled tasks), maintain a job application tracker spreadsheet (job_application_tracker.xlsx) as the single source of truth.
| Column | Description |
|---|---|
| Date Found | Date the role was surfaced |
| Company | Company name |
| Job Title | Full job title |
| Location | City, State or Remote |
| Salary (if listed) | Salary range or blank |
| Job Posting URL | Must be a clickable hyperlink (see below) |
| Status | New, In Progress, Applied, Didn't Apply, Rejected, Interviewing, Offer |
| Reason (if Didn't Apply) | Why the user skipped this role |
| Resume File | Filename of the generated .docx |
| Date Applied | User fills this in |
| Last Contacted | Date of last interaction |
| Notes | Brief match summary |
When writing URLs to the tracker with openpyxl, always set both the value and the hyperlink:
cell = ws.cell(row=row, column=6, value=url)
cell.hyperlink = url
cell.font = Font(name="Arial", size=10, color="0563C1", underline="single")
An alternate entry point for automated or scheduled runs that searches for multiple roles and lets the user pick which ones to build resumes for.
WebSearch across multiple job titles, locations, and boardsresume.md for themes)This mode can be configured as a scheduled task (e.g., 3x daily) using the schedule skill. The scheduled task prompt should include all search criteria, filtering rules, file paths, and the full build-resume workflow instructions so it runs autonomously.
| Mistake | Fix |
|---|---|
| Picking impressive bullets over relevant ones | Score against JD requirements, not general impressiveness |
| Too many Q&A rounds | Batch all questions, max 2 rounds |
| Generic summary | Rewrite per role with JD keywords |
| Forgetting to update resume.md | Always persist new info before generating |
| Ignoring preferred qualifications | Still critical for ATS keyword matching |
| Assuming WebFetch will work on job boards | Most job sites block it — use the fallback chain |
| Writing plain-text URLs in the tracker | Always set cell.hyperlink for clickable links |
| Skipping Q&A in batch/scheduled mode | ALWAYS ask the user enhancement questions, even in batch mode |