agentleFS
AkbarDevopAkbarDevop/ai-job-agent/skills/job-cv/SKILL.md

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
  1. Very specific:

    If none of the above is reachable: tell the user to run /job-setup first and stop.

    line 32
  2. Distinctive:

    If only a company is given and no URL, search for the listing first, then confirm the exact posting with the user before continuing.

    line 51
  3. Distinctive:

    If you cannot find the JD body after two reasonable fetches, ask the user to paste it.

    line 59
  4. Distinctive:

    Read the resolved base CV markdown.

    line 63
  5. Distinctive:

    Do not invent quantities, accomplishments, employers, or dates.

    line 77
  6. Distinctive:

    Do not "round up" timelines.

    line 78
  7. Very specific:

    Default format is letter (US).

    line 128
  8. Distinctive:

    One page when realistic: Don't pad. Don't shrink the font below 10.5pt to fit.

    line 167
  9. Very specific:

    One PDF per posting per day: If output/cv-<slug>-<today>.pdf exists, append -v2, -v3, etc.

    line 172

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

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:

  1. 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.md so future runs reuse it. Confirm with the user before writing.

    If none of the above is reachable: tell the user to run /job-setup first and stop.

  2. Chromium is reachable for Playwright. If npm test or a previous run errored with Executable doesn't exist, tell the user:
    npx playwright install chromium

    then retry. Stop until set up.

  3. 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 WebFetch to pull the page. If the result is a JS-only shell with no JD text, fall back to WebSearch for 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:

  1. Reorders sections and bullets so the JD's must-haves surface in the top half of the first page.
  2. 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).
  3. 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.)
  4. Trims to one page when realistic. Two pages is fine if Step 3 has 5+ years of experience or many publications. Never zero-pad.
  5. 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.

  1. Render:

    echo "$PAYLOAD" | node "$AI_JOB_AGENT_ROOT/scripts/generate-tailored-cv.mjs"

    Parse the JSON output. Expect ok: true, outputPath, bytes, pages. If ok: false with code: 3 and the error mentions "Executable doesn't exist", tell the user to run npx playwright install chromium and 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:

FieldValue
Company<Company>
Role<Role>
Tailored MDoutput/cv-<company-slug>-<YYYY-MM-DD>.md
PDFoutput/cv-<company-slug>-<YYYY-MM-DD>.pdf
Pages<pages>
Size<bytes / 1024> KB
Formatletter / 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 css unless 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.md with the tailored version. Tailored output always goes to output/.
  • One PDF per posting per day. If output/cv-<slug>-<today>.pdf exists, append -v2, -v3, etc. — don't silently overwrite.

Related skills

  • /job-setup — onboarding; writes the base cv.md if 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.

Download now (ZIP)

  • Other versions1 project uses a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 1

    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.

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.