How to Generate Cover Letters with Keyword Mirroring and Four-Angle Prompts in Career-Ops
Career-Ops generates tailored cover letters by mirroring job-description keywords and requiring four strategic angle prompts before drafting, producing ATS-compatible PDFs via generate-cover-letter.mjs.
The open-source Career-Ops toolkit automates candidate-facing documents through structured Markdown workflows. When you generate cover letters with keyword mirroring and four-angle prompts, the system enforces a rigorous interaction model defined in modes/cover.md before emitting a single line of prose.
Input Files and Prerequisites
Before invoking the cover-letter mode, populate three core data files. [config/profile.yml](https://github.com/santifer/career-ops/blob/main/config/profile.yml) stores contact fields such as candidate.name, email, and notice-period defaults. [cv.md](https://github.com/santifer/career-ops/blob/main/cv.md) supplies the achievement bullets and professional summary used for scoring and evidence. Optional richer proof points live in [article-digest.md](https://github.com/santifer/career-ops/blob/main/article-digest.md), which overrides CV data when topics overlap.
Launch the Cover-Letter Mode
Start the workflow from your terminal using the Career-Ops CLI. You can pass an existing report slug or paste a job description interactively.
# Invoke with an existing report slug
career-ops cover {slug}
# Or launch interactively and paste the JD
career-ops cover
Job Description Validation and Parsing
The mode first checks that a complete job description is present, including role title, company, and responsibilities. It then extracts location, top competencies, domain, start-date cues, language requirements, and tone. Concurrently, the system runs three web-search queries covering product strategy, challenges, and news, synthesizing the results into a two-to-three-sentence briefing.
Keyword Extraction and Mirroring
Career-Ops extracts the top 8–10 exact phrases from the JD and classifies them into ATS-critical and human-trust groups. This keyword mirroring step is shown to you for confirmation before drafting begins. Any JD keywords that cannot be incorporated are reported in the post-generation notes.
The Four-Angle Prompt System
Before any text is drafted, modes/cover.md enforces four mandatory answers. The system will not proceed until all four are received:
- A. Why this role or company? — Capture a strategic or personal motivation.
- B. What problem will you solve? — Ground this in the company research briefing.
- C. How will you approach it? — Outline a credible first-day or first-month plan.
- D. Which tone? — Choose formal, direct, conversational, or JD-mirrored voice.
Gap Detection and Achievement Selection
The workflow detects mismatches across domain, notice period, language, and title, prompting you to acknowledge or explain each gap. Simultaneously, it scores every bullet in cv.md against the JD’s required competencies and selects the 4–5 highest-scoring achievements, preserving exact wording and metrics. A fact-validation step then verifies that all metric claims and employer or tool mentions are backed by cv.md or article-digest.md.
Drafting, Template Resolution, and PDF Generation
The draft follows a fixed structure: header, salutation, opening, profile intro, achievements, problem section, closing, and optional language closing. The chat-based draft is presented for your approval before any PDF generation begins. After you approve, the system resolves the HTML template via the shared resolver, which loads [templates/cover-letter-template.html](https://github.com/santifer/career-ops/blob/main/templates/cover-letter-template.html) for PDF rendering:
node cv-templates.mjs resolve cover ...
Next, Career-Ops assembles a JSON payload and calls generate-cover-letter.mjs to render an A4 PDF. The payload includes candidate metadata, role details, greeting, opening paragraph, curated achievements, and the problem statement.
{
"candidate": {
"name": "Alice Example",
"email": "alice@example.com",
"phone": "555-123-4567",
"location": "San Francisco, CA",
"linkedin": "alice-linkedin",
"github": "alice-github",
"credentials": ["MSc Computer Science", "AWS Certified Solutions Architect"]
},
"letter": {
"role_title": "Senior Machine Learning Engineer",
"company": "Acme AI",
"city": "Seattle",
"date": "2026-08-19",
"greeting": "Dear Jane Smith,",
"opening": "I’m excited to apply because Acme’s push into autonomous-driving aligns with my work on large-scale perception pipelines.",
"profile_intro": "With 6 years building end-to-end ML systems, I lead cross-functional teams delivering production-grade models.",
"achievements": [
{"lead":"Reduced inference latency", "impact":"from 120 ms to 38 ms, saving $250K annually"},
{"lead":"Scaled data pipelines", "impact":"to process 5 PB/day, enabling new product features"},
{"lead":"Mentored junior engineers", "impact":"to increase code-review throughput by 30 %"}
],
"problems_section": "I can help Acme tackle sensor-fusion latency by applying my experience with on-device optimisation.",
"closing": "I’m available to start in 4 weeks and would love to discuss how I can accelerate your roadmap.",
"language_closing": null
},
"output_path": "output/acme-ai-senior-ml-engineer-cover.pdf"
}
Generate the final artifact by passing the payload to the script:
node generate-cover-letter.mjs --payload /tmp/cover-payload-acme-ai.json
After generation, Career-Ops reports any JD keywords that could not be incorporated, documents gap-acknowledgment decisions, and confirms word-count compliance.
Shared Writing Guardrails
All cover-letter outputs inherit rules from [modes/_writing.md](https://github.com/santifer/career-ops/blob/main/modes/_writing.md), which enforces ATS-compatible style, active voice, buzzword bans, and length limits. Personalization overrides from [modes/_profile.md](https://github.com/santifer/career-ops/blob/main/modes/_profile.md) are applied after the generic rules, ensuring the final voice reflects your archetype and narrative preferences.
Summary
- The cover-letter workflow is orchestrated by
modes/cover.mdinside thesantifer/career-opsrepository. - Keyword mirroring splits the top 8–10 JD phrases into ATS-critical and human-trust groups for confirmed insertion.
- Four-angle prompts (Why, What, How, Tone) are mandatory gatekeepers that block drafting until answered.
- Achievements are scored against the JD and selected from
cv.md, while facts are validated againstcv.mdandarticle-digest.md. - Final PDF generation runs through
generate-cover-letter.mjsusing a JSON payload and an HTML template resolved bycv-templates.mjs.
Frequently Asked Questions
What files does Career-Ops read before generating a cover letter?
The system reads config/profile.yml for candidate identity fields, cv.md for achievement bullets, and optionally article-digest.md for supplemental proof points. It also consumes the job description you provide interactively or through a slug.
Can I generate a cover letter without answering the four-angle prompts?
No. As implemented in modes/cover.md, the workflow explicitly blocks drafting until you supply all four answers: why the role, what problem you will solve, how you will approach it, and which tone to use.
How does Career-Ops ensure the cover letter is ATS-friendly?
The system extracts 8–10 exact phrases from the JD and categorizes them into ATS-critical keywords. Shared guardrails in modes/_writing.md further enforce ATS-compatible formatting, active voice, and banned buzzwords.
What happens if my CV does not support a claim in the draft?
A fact-validation step runs before PDF generation to verify that every metric claim and employer or tool mention is backed by data in cv.md or article-digest.md. Unverifiable claims are flagged rather than printed.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →