Assess job fit and generate tailored cover letter and resume for a job application based on job description, existing resume, and portfolio projects. Includes fit scoring, style presets, and gap analysis.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Assess job fit and generate tailored cover letter and resume for a job application based on job description, existing resume, and portfolio projects. Includes fit scoring, style presets, and gap analysis.
Evaluate job fit, then generate a tailored cover letter (1 page max) and resume (1-2 pages, prefer 1) optimized for both ATS parsing and human scanning, with visual styling appropriate for the target industry.
Input
Job Description: $ARGUMENTS
Determine input type:
If $ARGUMENTS is empty or blank, use AskUserQuestion to ask the user to provide a job description (paste text or provide a file path).
If $ARGUMENTS looks like a URL (starts with http:// or https://), use WebFetch to retrieve the job description from the page.
If $ARGUMENTS looks like a file path (ends in .txt, .md, .docx, or contains /), read the file. For .docx files, use Python's zipfile to extract text (see the technique in import_resume.py's extract_text_from_docx() function).
Otherwise, treat $ARGUMENTS as the job description text directly.
Workflow
Phase 0: Configuration and Dependency Check
Step 0.1: Check and Auto-Install Dependencies
Run this check (use python or py -3 instead of python3 on Windows):
If dependencies are missing, offer to install them automatically:
Use AskUserQuestion:
I need to install python-docx and pyyaml to generate Word documents.
Options:
- "Install now" - I'll run the install command for you
- "Show me the command" - I'll show you what to run manually
- "Skip" - Continue without installing (will fail at document generation)
If user chooses "Install now", run the appropriate command:
On Linux:
pip3 install python-docx pyyaml --user
On macOS (try standard install first, fall back to break-system-packages):
Look for config file in the same directory as this SKILL.md file (typically ~/.claude/skills/job-apply/config.yaml).
If config exists, load it and check that qualifications.experience is not empty. If qualifications are empty, inform the user and offer to run the resume import flow (from Step 0.3's "Ask about existing resume" section) before continuing to Phase 1.
If config does NOT exist, run the guided first-time setup (Step 0.3).
Step 0.3: Guided First-Time Setup (New Users Only)
Welcome the user:
"Welcome to the Job Application skill! Let's set up your profile. This takes about 2 minutes and you only need to do it once."
Gather contact information using AskUserQuestion:
Question 1 - Name:
What is your full name (as it should appear on your resume)?
(Free text input)
Question 2 - Contact Method:
How should employers contact you?
Options:
- "Phone and Email" - Provide both
- "Email only" - Just email address
- "Email + LinkedIn" - Email and LinkedIn profile
Question 3 - Based on previous answer, gather:
Phone number (if selected)
Email address
LinkedIn URL (if selected)
Question 4 - Style preference:
What industry are you targeting? (This affects content tone and structure. Visual styling currently uses Modern Professional for all presets.)
Options:
- "Tech/Corporate" - Modern Professional style (recommended for most roles)
- "Finance/Law/Healthcare" - Classic conservative style
- "Design/Marketing/Startups" - Creative style with more personality
Create config.yaml with the gathered information:
Use Write tool to create ~/.claude/skills/job-apply/config.yaml with:
Do you have an existing resume to import?
Options:
- "Yes, import from file" - I'll help you import your work history
- "No, I'll add details later" - Start with basic profile, add experience manually
- "Yes, let me paste it" - Paste your resume text and I'll parse it
If importing from file:
Ask for the file path
Read the file using the Read tool (for .txt/.md) or extract_text_from_docx() from import_resume.py (for .docx)
Parse the extracted text to identify contact info, summary, skills, experience, certifications, and education
Populate the qualifications section of config.yaml with the structured data
Confirm what was imported
Confirm setup complete:
"Profile created! Your documents will be saved to ~/Documents/Job Application Docs/generated/. You can edit your full work history anytime by running python3 ~/.claude/skills/job-apply/import_resume.py or editing config.yaml directly."
Phase 1: Gather Source Materials
Load candidate info from config.yaml
Name, phone, email, LinkedIn, calendar link
Load qualifications from config.yaml (preferred):
qualifications.summary: Professional summary
qualifications.skills: Skills by category
qualifications.experience: Work history with achievements
qualifications.certifications: Professional certifications
qualifications.education: Degrees and schools
If qualifications not in config, find and parse existing resume:
Search configured locations (or defaults):
~/Documents/Job Application Docs/resume/
~/Documents/resume/
Current project directory
Look for .docx or .md files with "resume" in the name
For .docx files, use Python's zipfile to extract text (cross-platform, no external dependencies)
Note: PDF files are not currently supported for automatic parsing
Load portfolio projects from config.yaml:
Each project includes: name, url, description, technologies, achievements, keywords
Match project technologies and keywords against job requirements
Use achievement metrics as evidence for qualifications
If portfolio projects not in config, scan ~/Projects/ for evidence:
Search for README.md files, package.json, and source code
Look for qualification assessments in ~/Documents/Job Application Docs/
Identify technologies, frameworks, and quantifiable achievements
ATS Keyword Fidelity Rule (applies to Phases 2, 4, 5)
ATS systems and human recruiters do early-stage keyword matching that can miss paraphrased terms. When the JD uses a specific phrase for a concept, the JD's exact wording should win in every output document.
Concrete rules:
When writing cover letter and resume content, prefer the JD's literal phrasing over the candidate's usual wording.
Extract verbatim phrases from the JD for required skills, tools, methodologies, and credentials - these are the canonical list of terms to preserve.
Never invent metrics or facts the candidate's config.yaml doesn't contain.
This rule applies even when the candidate's config.yaml bullets use a different word for the same concept (e.g., resume says "PRDs" but JD says "product requirement documents" - use "product requirement documents" in the tailored output).
Note: Document visual styling currently uses Modern Professional for all presets. Style selection affects content strategy (tone, structure, keyword emphasis) but not the generated document's colors, fonts, or layout.
Check config.yaml for default_style preference first.
Auto-detect industry from job description, or ask user to confirm:
Which style best fits this role? (Affects content tone; visual styling uses Modern Professional for all.)
- Classic (conservative industries: finance, law, healthcare)
- Modern Professional (corporate, tech, consulting)
- Creative (design, marketing, startups)
Phase 4: Match and Prioritize
Map candidate experience to job requirements:
Lead with strongest matches to must-haves
Identify transferable skills for partial matches
Prepare gap mitigation language for cover letter
Select strongest evidence for each key requirement:
Quantified achievements (percentages, dollar amounts, team sizes)
Recent and relevant project examples
Certifications that directly apply
Always reword the chosen evidence to use the JD's exact phrasing for any qualifier the JD names (see ATS Keyword Fidelity Rule)
Match portfolio projects to requirements:
For each relevant portfolio project from config.yaml:
Match technologies to job's technical requirements
Match keywords to job description language
Select most impressive achievement metrics
Prioritize projects with strongest alignment to must-have requirements
Include portfolio URLs in resume where appropriate
Identify keywords from job description for ATS optimization
Extract verbatim JD phrases for required skills, tools, methodologies, and credentials. Every such term should appear at least once verbatim in either the cover letter or the resume.
Reference portfolio projects that demonstrate rapid skill acquisition
Use the JD's exact phrasing for any qualifier the JD names
Phase 5: Generate Documents
Create both files in configured output directory (default: ~/Documents/Job Application Docs/generated/).
Primary output format: Microsoft Word (.docx) - preferred by recruiters and ATS systems.
Word Document Generation
Use the Python script at generate_word_docs.py (in the same directory as this SKILL.md) to create styled Word documents. Dependencies were verified in Step 0.1.
Dependencies (python-docx, pyyaml) should already be installed from Phase 0. If not, re-run the Phase 0 dependency check.
How to execute: Write a temporary Python script and run it via Bash. The script must add the skill directory to sys.path before importing:
# Write this to a temp file, then run with: python3 /tmp/gen_docs.pyimport sys, os
sys.path.insert(0, os.path.expanduser("~/.claude/skills/job-apply"))
from generate_word_docs import generate_application_documents
generate_application_documents(
candidate={
"name": "Full Name",
"phone": "Phone",
"email": "Email",
"linkedin": "LinkedIn URL",
"calendar": "Calendar link (optional)",
"title": "Target Role Title"
},
job={
"title": "Job Title",
"company": "Company Name",
"location": "Location"
},
cover_letter={
"opening": "Opening paragraph text...",
"sections": [
{
"title": "Section Title",
"paragraphs": [
{"label": "Bold Label", "text": "Content...", "highlights": ["phrase to bold"]},
["Bullet item 1", "Bullet item 2"]
]
}
],
"closing": "Best regards,",
"signature_title": "Title | Specialty"
},
resume={
"summary": "Summary paragraph...",
"skills": [{"category": "Category", "items": "Skill1, Skill2, Skill3"}],
"experience": [
{
"title": "Job Title",
"company": "Employer Name", # REQUIRED - employer ONLY"location": "City, ST", # optional"dates": "Mon YYYY - Mon YYYY", # dates ONLY"bullets": [
{"text": "Achievement with metric", "highlights": ["metric"]}
]
}
],
## โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ# โ ATS CRITICAL: experience field format โ# โ โ# โ โ RIGHT - company and dates are SEPARATE fields: โ# โ "company": "Ameriprise Financial", โ# โ "dates": "Jun 2021 - Oct 2022" โ# โ โ# โ โ WRONG - company baked into dates with pipe: โ# โ "company": "", โ# โ "dates": "Ameriprise Financial | Jun 2021 - Octโฆ" โ# โ โ# โ โ WRONG - company baked into dates with dash: โ# โ "dates": "Ameriprise Financial - Jun 2021 - Octโฆ" โ# โ โ# โ WHY: ATS "Fill from Resume" needs employer on its own โ# โ bold line. Combined formats break Workday, Taleo, etc. โ# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ#"certifications": [{"name": "Cert Name", "year": "2023", "issuer": "Org"}],
"education": [{"degree": "Degree, Major", "school": "University"}]
},
output_dir=os.path.expanduser("~/Documents/Job Application Docs/generated/")
)
The script also provides log_application(company, role, fit_score, output_dir) and open_output_folder(output_dir) - use these in Phase 6 instead of manual Bash commands.
Use standard section headers: Summary, Skills, Experience, Education, Certifications
Include exact keywords from job description - every required skill, tool, methodology, and credential named in the JD should appear at least once verbatim in the resume (Skills section is the natural place for terms that don't fit organically in bullets)
Reword existing config.yaml bullets to use the JD's exact phrasing where it names a qualifier (e.g., if config says "PRDs" and JD says "product requirements documents", use the JD's phrasing in the tailored output)
Use consistent date formatting (Mon YYYY - Mon YYYY)
Keep creative elements in header only; main content follows standard format
Use bullet points with action verbs
ATS-Unsafe Characters (Workday + similar):
Workday and several other ATS systems strip or mangle < and > characters during text extraction. A hierarchy like Capability > Epic > Story > Task can come out as Capability Epic Story Task with the markers gone, or worse, the section silently dropped.
Never write < or > in any user-visible bullet text, summary, skills line, or cover letter content. This applies whether you are writing fresh content for an application or reading from config.yaml (the canonical config has already been cleaned).
For hierarchies, use โ (Unicode rightward arrow, U+2192) instead of >. Example: Capability โ Epic โ Story โ Task.
For numeric comparisons, write over N instead of >N and under N instead of <N. Example: write "over 80% test coverage" not ">80% test coverage".
AI-Tell Characters (em-dash U+2014 and en-dash U+2013):
The em-dash (Unicode codepoint U+2014, looks like a long horizontal bar between spaces) has become a widely-recognized indicator of AI-generated writing. Recruiters and hiring managers increasingly flag em-dash-heavy prose as likely AI-edited, which carries stigma in 2026 and beyond. The same applies to the en-dash (U+2013) when used in numeric ranges: humans typing on a keyboard produce a plain hyphen instead.
Never write a U+2014 em-dash or U+2013 en-dash in any user-visible content (cover letter prose, resume summary, bullets, skills lines). This applies to fresh content you draft AND to content quoted or reshaped from config.yaml.
For a strong break in a sentence, prefer a colon, semicolon, period, or comma. Example:
GOOD: "Portfolio Factory: built and shipped an AI-powered career assessment platform..."
BAD: "Portfolio Factory โ built and shipped an AI-powered career assessment platform..." (uses U+2014)
For a parenthetical aside, use commas or parentheses. Example:
GOOD: "At Ameriprise, a regulated financial-services firm, I owned..."
BAD: "At Ameriprise โ a regulated financial-services firm โ I owned..." (uses U+2014)
For numeric ranges, use a plain ASCII hyphen. Example:
The literal U+2014 / U+2013 characters in this rule's examples are written as โ / โ escapes on purpose, so a mechanical clean-up pass over SKILL.md cannot delete the BAD examples and silently destroy the rule.
Defense-in-depth sanitizer:generate_word_docs.py contains a sanitizer (_sanitize_data_for_ats) that runs at the top of generate_application_documents() and replaces stray <, >, U+2014, and U+2013 characters automatically. Do not rely on it as a substitute for writing clean source content. Write it correctly the first time so the resume reads naturally to humans, and the sanitizer is only a backstop for source-data drift.
Human Scanning Optimization:
Apply visual hierarchy through typography (bold, sizing)
Use accent color strategically (headers, dividers, name)
Quantified achievements prominently displayed
Most relevant experience emphasized first within each role
Single line spacing for compact documents; adequate margins (0.7-1 inch)
Portfolio Project Integration:
Include relevant portfolio projects in experience or separate "Projects" section
For each included project:
Project name with URL (if live)
Brief description aligned to job requirements
Key achievement metric
Technologies used (matching job requirements)
Phase 6: Output
Step 6.1: Save Documents
The generate_application_documents() function handles file naming automatically:
{Full_Name}_Cover_Letter_{Role}_{Company}.docx
{Full_Name}_Resume_{Role}_{Company}.docx
Step 6.2: Log Application and Open Folder
Use the helper functions from the generation script (call in the same temp Python script):
from generate_word_docs import log_application, open_output_folder
log_application(company, role, fit_score, output_dir)
open_output_folder(output_dir)
Step 6.3: Provide Summary
Display comprehensive summary:
## Application Complete
### Documents Generated
- Cover Letter: {filename}.docx
- Resume: {filename}.docx
- Location: {output_dir} (folder opened)
### Fit Assessment
- Overall Score: {X}%
- Recommendation: {Strong/Good/Stretch Fit}
### Key Matches Highlighted
- {Top 3-5 strongest qualification matches}
### Gaps Addressed in Cover Letter
- {Gap}: {How it was addressed}
### ATS Keywords Preserved Verbatim
- {Comma-separated list of JD-verbatim required skills, tools, and credentials used in the documents}
### Next Steps
1. Review the documents in the opened folder
2. Upload to the job portal
3. Prepare for interview questions about: {gap areas}
### Interview Prep Tips
- Be ready to discuss: {Gap areas they may probe}
- Emphasize: {Your strongest differentiators}
- Portfolio demos: {Projects to show if asked}
Step 6.4: Ask About Next Action
Use AskUserQuestion:
What would you like to do next?
Options:
- "Apply to another job" - Provide the next job description and restart from Phase 1
- "Edit these documents" - Tell me what to change and I'll regenerate
- "Done for now" - Exit
For profile management (switching between configurations), see profiles.py in the skill directory.