job-cv
Skill61 starsChanged 6 months agoMITView on GitHub
Tailor the candidate's base CV for one specific job posting and render an ATS-friendly PDF. Reads `cv.md` (or extracts a CV from `config/candidate-profile.md`), pulls the job description from a URL or pasted text, has Claude rewrite — never invent — bullets to match the JD's keywords/priorities, gets explicit user approval on the tailored markdown, then calls `scripts/generate-tailored-cv.mjs` to print a PDF. Proactively invoke this skill (do NOT answer conversationally) when the user says "tailor my resume for this job", "tailor my CV for X", "make a CV for [posting]", "generate a resume for this role", "ATS-optimize my resume for this posting", "build a tailored PDF for this JD", pastes a job URL and asks for a resume, or invokes /job-cv. Never fabricate experience — only reorder/rephrase what's already in the base CV.
We split this skill into the rules it gives an agent
9 rules. About 0 are common, 6 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 32
If none of the above is reachable: tell the user to run /job-setup first and stop.
- Distinctive: line 51
If only a company is given and no URL, search for the listing first, then confirm the exact posting with the user before continuing.
- Distinctive: line 59
If you cannot find the JD body after two reasonable fetches, ask the user to paste it.
- Distinctive: line 63
Read the resolved base CV markdown.
- Distinctive: line 77
Do not invent quantities, accomplishments, employers, or dates.
- Distinctive: line 78
Do not "round up" timelines.
- Very specific: line 128
Default format is letter (US).
- Distinctive: line 167
One page when realistic: Don't pad. Don't shrink the font below 10.5pt to fit.
- Very specific: line 172
One PDF per posting per day: If output/cv-<slug>-<today>.pdf exists, append -v2, -v3, etc.
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Job CV
A skill (not an API call) for producing a tailored, ATS-friendly PDF resume for one specific posting. Claude does the rewriting. A small Node script renders the approved markdown to PDF via headless Chromium (Playwright). No LaTeX, no pandoc, no extra deps.
This pairs with /job-outreach (the cold-email skill): a tailored CV in hand makes the outreach concrete. It also feeds /job-apply — most ATS forms accept a custom resume upload.
Repo location
$AI_JOB_AGENT_ROOT → ~/.claude/skills/ai-job-agent/ → REPO_PATH marker file → ~/ai-job-agent/.
Prerequisites
Before drafting anything:
A base CV exists. Look in this order:
$AI_JOB_AGENT_ROOT/cv.md(preferred)$AI_JOB_AGENT_ROOT/config/cv.md- Extract a CV-shaped markdown from
$AI_JOB_AGENT_ROOT/config/candidate-profile.md(sections: identity, education, experience, projects, skills) and write it to$AI_JOB_AGENT_ROOT/cv.mdso future runs reuse it. Confirm with the user before writing.
If none of the above is reachable: tell the user to run
/job-setupfirst and stop.- Chromium is reachable for Playwright. If
npm testor a previous run errored withExecutable doesn't exist, tell the user:npx playwright install chromiumthen retry. Stop until set up.
output/exists at$AI_JOB_AGENT_ROOT/output/. If not, create it (mkdir -p).
Workflow
Step 1 — Understand the target
Parse $ARGUMENTS. It might be:
- A direct job URL (LinkedIn, Greenhouse, Lever, Ashby, Jobvite, careers page)
- Pasted JD text in the user's message
- A company name + role ("backend intern at Stripe" — fetch the listing yourself)
If only a company is given and no URL, search for the listing first, then confirm the exact posting with the user before continuing.
Step 2 — Read the JD
- URL → use
WebFetchto pull the page. If the result is a JS-only shell with no JD text, fall back toWebSearchfor the same role at the same company and try the second hit. - Pasted text → use as-is.
- Extract: company, role title, location / work-auth notes, 3-7 must-have skills (the ones most repeated or in the title), 3-5 nice-to-haves, tone (research-y? startup-y? enterprise?).
If you cannot find the JD body after two reasonable fetches, ask the user to paste it. Don't guess.
Step 3 — Read the base CV
Read the resolved base CV markdown. Note every concrete bullet, project, and skill. This is the bounding box — Step 4 may reorder, condense, or rephrase any of these, but cannot invent new ones.
Step 4 — Tailor (the actual job of this skill)
Produce a new markdown CV that:
- Reorders sections and bullets so the JD's must-haves surface in the top half of the first page.
- Rephrases existing bullets to use the JD's vocabulary (e.g., the CV says "computer vision pipeline"; the JD says "perception stack" — rewrite to match, but only if the underlying work is the same thing).
- Drops sections / bullets that don't connect to the role. (E.g., a Quran subtitle editor side project is not landing on a substation engineering CV.)
- Trims to one page when realistic. Two pages is fine if Step 3 has 5+ years of experience or many publications. Never zero-pad.
- Preserves everything truthful: dates, titles, GPAs, links, work-auth phrasing.
Hard constraint — never fabricate:
- If the JD requires a skill the candidate does not have on the base CV, flag it to the user inline (e.g., "JD requires Rust; not on your CV. Should I (a) leave it off, (b) add a one-line 'Familiar with Rust syntax via X' if true, or (c) skip this posting?").
- Do not invent quantities, accomplishments, employers, or dates.
- Do not "round up" timelines. "3 months" stays "3 months."
Step 5 — Present the tailored CV for approval
Render exactly this structure in chat:
**Tailored CV draft** · for: <Role> at <Company> · base: cv.md (<line-count> lines) → tailored: <new-line-count> lines
```markdown
# <Name>
…full tailored markdown…Changes vs base:
- Reordered:
<section A>before<section B>(matches JD priority on<skill>) - Rephrased: "
<old bullet>" → "<new bullet>" (uses JD term <…>) - Dropped: <section / bullet> (not relevant to
<role>) - Flagged gaps:
<skill from JD not on CV>— what should we do?
Approve, edit, or cancel? (approve / edit / cancel)
### Step 6 — Handle the response
- **approve** → go to Step 7.
- **edit** → ask "what should I change?" and regenerate Step 4 + 5. Loop until `approve` or `cancel`.
- **cancel** → do nothing, don't write any file. Tell the user "nothing rendered, nothing logged."
### Step 7 — Render the PDF
1. Save the approved markdown to:
$AI_JOB_AGENT_ROOT/output/cv-<company-slug>-<YYYY-MM-DD>.md
Slugify the company name: lowercase, alphanumerics + dashes only.
2. Build the JSON payload for the renderer:
```json
{
"cv": "<approved markdown>",
"outputPath": "<repo>/output/cv-<company-slug>-<YYYY-MM-DD>.pdf",
"title": "Resume — <Candidate Name> — <Role> @ <Company>",
"format": "letter"
}Default format is letter (US). Use a4 if the role is EU-based.
Render:
echo "$PAYLOAD" | node "$AI_JOB_AGENT_ROOT/scripts/generate-tailored-cv.mjs"Parse the JSON output. Expect
ok: true,outputPath,bytes,pages. Ifok: falsewithcode: 3and the error mentions "Executable doesn't exist", tell the user to runnpx playwright install chromiumand stop.
Step 8 — Log
Append a notes-column entry on the matching row of $AI_JOB_AGENT_ROOT/application-tracker.csv. If no row exists yet for this <company> + <role>, just store the path — /job-apply will create the tracker row when the user actually applies.
Notes-column format (semicolon-separated, append, don't replace):
tailored-cv: output/cv-<company-slug>-<YYYY-MM-DD>.pdf (<pages>p, <bytes>B)Step 9 — Confirm and suggest next
Print:
| Field | Value |
| Company | <Company> |
| Role | <Role> |
| Tailored MD | output/cv-<company-slug>-<YYYY-MM-DD>.md |
output/cv-<company-slug>-<YYYY-MM-DD>.pdf | |
| Pages | <pages> |
| Size | <bytes / 1024> KB |
| Format | letter / a4 |
Then nudge: "Want me to (a) draft a cold email to a hiring manager at this company via /job-outreach, (b) submit the application via /job-apply, or (c) tailor for the next posting?" — don't auto-do, wait.
Rules
- Never invent experience. Reorder, rephrase, drop. Never add. Flag JD-skill gaps explicitly.
- One page when realistic. Don't pad. Don't shrink the font below 10.5pt to fit. If it's two pages, that's fine.
- One column, serif body, no icons, no multicol. ATS parsers choke on fancy layouts. The default CSS in the renderer is already ATS-tested — don't override
cssunless the user asks. - Truth-preserving rewrites only. "Computer vision pipeline" → "perception stack" is fine if the work is the same. "Built a CV pipeline" → "Led a perception team" is not.
- Never auto-send the PDF anywhere. This skill produces a file. The user decides what to do with it.
- Never overwrite the base
cv.mdwith the tailored version. Tailored output always goes tooutput/. - One PDF per posting per day. If
output/cv-<slug>-<today>.pdfexists, append-v2,-v3, etc. — don't silently overwrite.
Related skills
/job-setup— onboarding; writes the basecv.mdif absent./job-apply— submits the application via the right ATS filler. Pass it the tailored PDF path when the form has a resume-upload field./job-outreach— companion cold-email skill; works great with a freshly-tailored CV in hand./tailor-resume(community skill) — alternative tailoring flow that does not render PDF; use this skill if you want both rewrite + PDF in one shot.
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- rockbenben/ai-job-search-cn★ 41same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository14 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- job-applySkill
- job-coachSkill
- job-dashboardSkill
- job-evaluateSkill
- job-followupSkill
- job-interviewSkill
- job-outreachSkill
- job-patternsSkill
- job-recapSkill
- job-setupSkill
- job-statusSkill
- job-trackSkill
- job-triageSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

