resume-matcher
Use Resume Matcher with no API key, with you doing the AI work. Sets up the app, creates a master resume, tailors it to job descriptions (pasted in chat or saved in jobs/), writes cover letters and outreach messages, and exports PDFs. Use when the user asks about resumes, CVs, job descriptions, tailoring, cover letters, or setting up or running Resume Matcher.
含まれるファイル(1)
- SKILL.md13.3 KB
SKILL.md(原文)
インストールする前に、エージェントに与えられる指示の中身を確認できます。
Resume Matcher, driven by you
You are the AI. The resume-matcher command stores, validates, scores and renders what you write, in the same database as the web app, so everything you save appears at http://localhost:3000. The user makes small edits there.
Work in this order: set up (once), master resume (once), tailor (per job), hand off to the UI. Skip a step that is already done. Talk to the user in their language.
The command
From the repository root:
uv run --directory apps/backend resume-matcher <tool> [arguments]
resume-matcher --helplists the tools;resume-matcher <tool> --helpshows one tool's arguments as a JSON schema.- Arguments are either one JSON object (
'{"resume_id": "…"}',@args.json, or-for stdin) or fields:key=value(string),key=@file(string from a file),key:=json(any JSON value),key:=@file.json(JSON from a file). - Use absolute paths.
--directoryruns the command fromapps/backend, so a relative path resolves from there. - The result is JSON on stdout. Exit code 1: the tool failed and stderr says why. Exit code 2: the command line was wrong.
- Write argument files (large JSON such as a whole resume) to
jobs/.work/in this repository (mkdir -p jobs/.workfirst). It is gitignored and inside every agent's sandbox. - To shorten it, define a shell function, not a variable (zsh does not split a command stored in a variable):
rmx() { uv run --directory "$PWD/apps/backend" resume-matcher "$@"; }
Docker install: run the same tools inside the container, from its backend folder so they use the app's data:
docker exec -i -w /app/backend resume-matcher python -m app.mcp_server.cli <tool> [arguments]
File arguments are then read inside the container, so pass a whole JSON object on stdin instead: … add_job - < /abs/path/jobs/.work/add_job.json. To import a resume file, copy it in first (docker cp ~/resume.pdf resume-matcher:/tmp/resume.pdf) and pass file_path=/tmp/resume.pdf.
1. Set up (once)
Check whether the app is already running:
curl -s http://localhost:3000/api/v1/health
{"status":"healthy"} means it is up: go to Agent mode below. Otherwise ask the user which install they want (if their request already says, that is the answer), and recommend local when uv and Node are installed:
-
Local needs Python 3.13+, uv and Node.js 24+ (
uv --version,node --version). Install once, then start the backend, wait for it, and start the frontend. Both are long-running: start them in the background so they keep running after you finish (never in the foreground, which blocks you).# From the repository root mkdir -p jobs/.work (cd apps/backend && { [ -f .env ] || cp .env.example .env; } && uv sync && uv run playwright install chromium) (cd apps/frontend && npm install) (cd apps/backend && nohup uv run app > ../../jobs/.work/backend.log 2>&1 &) # API on :8000 for i in $(seq 60); do curl -sf http://127.0.0.1:8000/api/v1/health > /dev/null && break; sleep 2; done (cd apps/frontend && nohup npm run dev > ../../jobs/.work/frontend.log 2>&1 &) # web app on :3000 for i in $(seq 60); do curl -sf http://localhost:3000/api/v1/health > /dev/null && break; sleep 2; doneIf a health check still fails after two minutes, read the log in
jobs/.work/. On Windows use PowerShell:Copy-Item .env.example .envinstead ofcp, and start each server withStart-Process(or ask the user to run each in its own PowerShell window). Until agent mode is on, the backend log shows an LLM health-check error from the placeholder key in.env; it is harmless. -
Docker needs Docker Desktop or Docker Engine. From the repository root, run
docker compose up -d --build. Building from this checkout includes the command-line tool, which older published images lack. The app is on http://localhost:3000.
Wait until the health check answers before going on. More detail and troubleshooting: SETUP.md.
Agent mode
curl -s http://localhost:3000/api/v1/status
If agent_mode is false, ask the user before switching it on (a request that already asks for agent mode, or for no API key, counts as yes). It makes the app stop calling an AI model and show prompts for you instead. Saved API keys are kept, and the user can switch back in Settings at any time.
curl -s -X PUT http://localhost:3000/api/v1/config/llm-api-key \
-H 'Content-Type: application/json' -d '{"provider":"agent"}'
On Windows: Invoke-RestMethod -Method Put -Uri http://localhost:3000/api/v1/config/llm-api-key -ContentType 'application/json' -Body '{"provider":"agent"}'. The user can also pick Coding agent under Settings > LLM configuration.
2. Master resume (once)
Run get_status. If master_resumes is 0, ask the user for their resume file (PDF, DOCX, Markdown or text). If they have none, interview them: contact details, each role with dates and achievements, education, skills.
-
extract_document_text file_path=/abs/path/resume.pdfturns the file into Markdown. -
Build
resume_datafrom the Markdown faithfully: copy names, employers, titles, dates and bullets as written; do not improve or invent anything yet.get_resume_schemahas the full structure; most resumes need only this much (leave outsectionMetaandcustomSectionson a new master, and the app fills them in):{"personalInfo": {"name": "Ada Lovelace", "title": "Engineer", "email": "ada@example.com", "phone": "+1 555 0100", "location": "London", "linkedin": "", "github": "", "website": ""}, "summary": "One or two sentences from the resume.", "workExperience": [{"id": 1, "title": "Engineer", "company": "Analytical Engines", "location": "London", "years": "Jan 2020 - Present", "description": ["Bullet one", "Bullet two"]}], "education": [{"id": 1, "institution": "University", "degree": "B.Sc. Mathematics", "years": "2014 - 2018"}], "personalProjects": [], "additional": {"technicalSkills": ["Python"], "languages": [], "certificationsTraining": [], "awards": []}} -
create_master_resume resume_data:=@/abs/path/jobs/.work/master.json(optionallytitle=…). -
Ask the user to check it at
http://localhost:3000/resumes/<resume_id>and fix anything in the editor.
With several masters (up to 5, e.g. one per career track), list_resumes shows them; tailor from the one that fits the job, or the default.
3. Tailor (per job)
Job descriptions come pasted in chat, or as .md/.txt files in jobs/ (ignore jobs/README.md and the jobs/done/ and jobs/.work/ folders). For each job:
-
Add the job. Read it and extract the keywords, then:
add_job job_description=@/abs/path/jobs/acme.md company="Acme" role="Platform Engineer" keywords:=@/abs/path/jobs/.work/acme-keywords.jsonThe keywords object hasrequired_skills,preferred_skills,experience_requirements,education_requirements,key_responsibilitiesandkeywords(lists of short strings); company and role go in thecompanyandrolearguments. A job pasted in chat is saved tojobs/.work/<company>.mdfirst (scratch, not the batch); files the user saved injobs/are the batch. -
Read the source.
get_resume resume_id=<master id>. Start from itsresume_dataexactly as returned, includingsectionMetaandcustomSections; a copy from anywhere else fails validation. -
Write the tailored version by the rules below.
-
Save and check:
tailor_and_verify @/abs/path/jobs/.work/acme-tailor.jsonwith{"source_resume_id", "job_id", "resume_data", "title": "<Role> @ <Company>"}. It validates, saves a new resume (the master is untouched), renders the PDF, parse-checks it, scores it and adds an Applied card to the tracker. Call it once per job: every successful call adds another resume and tracker card, so fix things afterwards withupdate_resume.- The result is long. The fields you need:
saved,resume.resume_id,score.overall_score,score.missing_keywords,page_countandissues(verify_resumereturns the samescore,page_countandissues). saved: false: nothing was written. Readvalidation.violations, fix them (or adoptvalidation.repaired_resume_data) and call it again.validation.grounding_warningsare advisory: check each one against the source and fix anything unsupported.
- The result is long. The fields you need:
-
Fix
issues, then re-check withverify_resume resume_id=<id>. Stop after two or three rounds and tell the user what is left.Issue What to do injectable_keywordsWork those keywords into existing bullets or the skills list; the master supports them over_page_limitTighten the summary and bullets; do not drop roles multi_column,low_order_fidelitySuggest a single-column template such as swiss-singlegarbled_glyphs,fields_missingCheck unusual characters and empty fields render_failedThe web app is not running at the URL in render_error: start itEdit with
update_resume resume_id=<id> resume_data:=@…(it replaces the whole resume, so start fromget_resume), thenrecalculate_ats_score resume_id=<id>. -
Batch from
jobs/: after each job, move its file tojobs/done/so a rerun skips it.
Tailoring rules
These are the rules the app's own tailoring follows, and the validator enforces most of them.
- Keep
personalInfo, employers, job titles, locations, dates (years, copied exactly, months included), the number of entries and the number of bullets. - Never add a skill, tool, technology, certification, employer, metric or responsibility the source does not contain. Never raise seniority.
- Rephrase existing bullets to use the job's wording where the source already shows that experience. Reorder skills by relevance, but never remove one.
- Rewrite the summary for the role from facts already in the resume.
- Write in the resume's language. No em dashes. Avoid stock phrases such as "spearheaded", "leveraged", "orchestrated", "utilized", "synergy", "cutting-edge" and "results-driven".
- If the job needs something the user has not shown, say so; do not paper over it.
score.missing_keywordslists what the resume does not support: report those to the user as gaps they can add in the editor if they really have them. A low score from honest gaps is the right result. - The
date_consistencypart of the score is low when the source mixes date formats (Mar 2022 - Presentbeside2015 - 2019). Keep the dates as written and tell the user they can make the formats match in their master resume.
4. Hand off to the UI
When done, give the user a short table: role and company, ATS score (score.overall_score), pages, remaining issues and gaps, and the link http://localhost:3000/builder?id=<resume_id>. Then tell them:
- The dashboard lists every resume: http://localhost:3000/dashboard. Open pages update on their own within a few seconds of each save, so there is no need to reload.
- In the editor they can change any text, section order, template and formatting. Changes save automatically, and Download exports the PDF.
- The application tracker is at http://localhost:3000/tracker.
- The app's AI buttons show a prompt to paste back to you.
- If they are editing a resume while you save it, the editor asks them whether to keep their edits or take yours. Prefer to work on resumes they are not editing.
Other requests
The app's AI buttons hand these prompts to you:
| Request | Tools |
|---|---|
| Cover letter | get_resume_job resume_id=<id>, write it (100 to 150 words in 3 or 4 short paragraphs, using only facts from the resume), set_cover_letter resume_id=<id> content=@… |
| Outreach message | Same, 70 to 100 words, opening with something specific from the job, then set_outreach_message |
| Enhance a resume | Ask the user about missing results, numbers and tools; then get_resume, edit, update_resume. Add only what they told you |
| Rewrite parts | Show the user the changes first, then update_resume |
| Interview prep | Answer in the chat from get_resume and get_resume_job; the app does not store it in agent mode |
| PDF file | export_resume_pdf resume_id=<id> writes data/exports/<id>-<template>.pdf (pass output_path for elsewhere), or use Download in the editor |
| Tracker | list_applications, update_application |
Boundaries
- No tool deletes anything.
update_resume,set_*,set_job_keywordsandupdate_applicationoverwrite what they target: read it first. - Change the app's settings only to switch on agent mode, and only after the user agrees.
- The user's resume, job descriptions and exports stay out of git:
jobs/andapps/backend/data/are gitignored. Never commit them. - Prefer MCP? The same tools run as an MCP server (
resume-matcher-mcp); see SETUP.md.
レビュー
まだレビューはありません。使ってみた感想をお寄せください。