honest-cv

io.github.JesusCabreraReveles由 GitHub 帳號 JesusCabreraReveles 發布v0.3.3更新於 Nov 5, 2026

Honest, ATS-safe CVs and cover letters from a skill inventory you confirm yourself.

概覽

AI 產生的概覽

依據本機保存、有證據佐證的技能清單,產出誠實且對 ATS 友善的履歷、求職信與 LinkedIn 文案,並依職務類型分版本。

可以做什麼
  • 建立與匯入個人檔案:初始化檔案資料夾,匯入 JSON Resume 或 LinkedIn 匯出資料,編輯聯絡方式、工作經歷、學歷、著作與證照
  • 管理技能清單:依等級讀取技能,單筆或批次設定技能,用內建或自訂清單逐項標註並附上證據
  • 撰寫成就與履歷版本:新增成就條目,儲存針對不同職務的履歷版本,檢視各版本包含的內容
  • 產出並檢查文件:將履歷與求職信輸出為 PDF 與 DOCX,檢查任何 PDF 的 ATS 相容性,並核對文字中的說法是否與檔案相符
  • 依職缺客製:評估各版本對關鍵字的涵蓋程度,並依誠實可行的處理方式歸類落差
  • 追蹤投遞與面試:記錄投遞與狀態,列出久無回音的申請,依關鍵字準備面試資料
適用情境
適合希望借助 AI 助理撰寫或客製履歷與求職信、又不願憑空捏造經歷的人,也適合需要履歷能被招募系統正確解析的情境。同樣適用於求職進度追蹤與根據本人真實成就的面試準備。
執行需求
透過 uvx 以 stdio 在本機執行,需先安裝 uv;Typst 與字型已隨套件提供。支援 Linux glibc 的 x86_64 與 ARM64、macOS 的 Intel 與 Apple Silicon、Windows x64;不支援 Alpine Linux 與 Windows ARM。需要一個檔案資料夾,以 HONEST_CV_PROFILE 環境變數或 profile 參數指定。不需 API 金鑰或帳號。
安裝前請注意
檔案中包含聯絡方式、工作經歷與成就等個人資料,應避免放在公開儲存庫中。助理透過工具讀取的內容會傳送給 AI 用戶端所用的模型供應商,部分用戶端可能要求把檔案資料夾複製到雲端。刪除類工具會永久刪除技能、成就條目、工作經歷與著作,並影響所有版本。提升技能等級需要本人確認,部分用戶端只能透過終端機指令完成。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 honest-cv,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

honest-cv

[CI] [License: MIT] [PyPI] [Listed on mcpservers.org]

Honest, ATS-safe CVs tailored to each role, generated by your AI agent. honest-cv is an MCP server, a CLI and a Claude Code skill. It keeps one source of truth about your experience and turns it into a PDF and DOCX for each type of role. It never claims a skill you don't have.

Leer en español

[Demo: skill checklists including your own, scoring a job post, a verified build, a cover letter that refuses a skill the person lacks, LinkedIn texts and logging the application]

Why

Many CVs that get no callbacks don't fail on design. They fail on targeting, and on details that quietly break text extraction. AI makes the opposite problem easy: a model will happily stuff a CV with keywords you can't defend in an interview. honest-cv is built around three ideas:

  • The code enforces honesty, not a prompt. Every skill has a level. A skill at familiarity level is always labeled as such, and a skill you don't have is never printed. Raising a level takes written evidence and your confirmation, which the server asks you for directly. The model can't confirm on your behalf.
  • Gaps are measured against your own inventory. For each keyword a job post asks for, honest-cv tells you which of three cases it is:
    • you have it, but this CV doesn't show it;
    • you only know it at familiarity level;
    • you don't have it.
  • ATS safety is checked on every build. Every PDF goes through two text extractors (pypdf and pdfminer.six). The build checks that the text is one column, has no ligatures, keeps each date on its role's line, follows the right reading order and includes every bullet.

The server is deterministic and needs no API key. Your MCP client's model runs the conversation; honest-cv validates, builds, verifies and measures. It keeps your profile in a folder on your machine and never sends it anywhere: see Privacy for what your AI client does with it.

[A generated one-page CV for the fictional Ada Example]

Quick start

honest-cv needs uv. Typst and the fonts ship inside the package, so there is nothing else to install. It runs on Linux (glibc) on x86_64 and ARM64, macOS on Intel and Apple Silicon, and Windows on x64. Alpine Linux and Windows on ARM aren't supported, because the typst package doesn't publish wheels for them.

Claude Code

bash
claude mcp add honest-cv -- uvx honest-cv serve --profile ~/cv-profile

To install the skill as well, which guides the interview and the tailoring:

bash
mkdir -p ~/.claude/skills/honest-cvcurl -fsSL https://raw.githubusercontent.com/JesusCabreraReveles/honest-cv/master/skills/honest-cv/SKILL.md \  -o ~/.claude/skills/honest-cv/SKILL.md

Then follow Your first CV, step by step.

Cursor

Add this to ~/.cursor/mcp.json, or to .cursor/mcp.json in a project:

json
{  "mcpServers": {    "honest-cv": {      "command": "uvx",      "args": ["honest-cv", "serve", "--profile", "/absolute/path/to/cv-profile"]    }  }}

Claude Desktop

Edit claude_desktop_config.json:

  • on macOS, ~/Library/Application Support/Claude/;
  • on Windows, %APPDATA%\Claude\.

Add the same mcpServers block as in the Cursor example and restart the app. If the app can't find uvx, use its absolute path (which uvx).

How each client confirms a skill upgrade

Raising a skill's level needs your own confirmation, which the server asks for through MCP elicitation. Not every client supports it yet:

ClientWhere you confirm
Claude CodeIn the chat: a form with one "no / sí" field per upgrade, up to 10 at a time. Only the ones you answer "sí" are saved; Decline saves nothing.
Claude DesktopIn a terminal. The server refuses the change and gives you the command to run: uvx honest-cv skill <profile> "<name>" <level> --evidence "...".
Other clientsIn the chat if they support elicitation, otherwise in a terminal as above.

Your first CV, step by step

This walkthrough uses Claude Code; any MCP client works the same way, only the setup differs.

1. Install uv and add honest-cv. One time only. On macOS or Linux:

bash
curl -LsSf https://astral.sh/uv/install.sh | sh        # Windows: see docs.astral.sh/uvclaude mcp add honest-cv -- uvx honest-cv serve --profile ~/cv-profile

~/cv-profile is the folder where your profile will live. It doesn't have to exist yet, and it should not be inside a public repository. Install the skill too (Claude Code above).

2. Start the interview. Open Claude Code in any folder (claude) and write, in your own language, "Interview me for my CV", or run /mcp__honest-cv__interview. The assistant keeps your language for the whole conversation. You can answer by voice with your system's dictation (on macOS: System Settings → Keyboard → Dictation): it reads names and numbers back to you before saving them, since dictation mishears them. It goes like this:

You: Interview me for my CV.

Assistant: The folder ~/cv-profile doesn't exist yet. Shall I create it? … The whole interview can take a few hours, but everything is saved as we go. A first session with your contact details, your two most recent roles and the skills checklist is enough for a first CV. Do you have a LinkedIn data export or a JSON Resume to start from?

  • Import, if you can (optional). Download LinkedIn's data export (see Import) and give the assistant the path to the ZIP. Your roles, education and achievements come in, and skills arrive without a level for you to mark.
  • Contact, roles and education. It asks a few at a time and reads names and numbers back before saving. Then it asks once about certifications, courses and anything you wrote.
  • Achievements, role by role. For each role: what the team did, what you did, and what changed, with numbers. It drafts a bullet and saves it only after you approve the wording.
  • Skills. It offers a checklist, e.g. backend-jvm + engineering-lead, or your own for any profession. Open ~/cv-profile/checklist.md in your editor, put P, L, F or X on each line, add where you used it after " — ", save, and tell the assistant "done". It asks for the evidence it is missing, in groups. Then a form asks you to confirm the upgrades: only what you answer "sí" is saved.
  • Your biggest achievements. One achievement usually covers several skills. It then asks about your main P skills that no achievement shows yet; the rest can wait for a job post.

3. Build your first CV. The assistant proposes one variant per kind of role you apply to (for example "platform" or "engineering manager"): title, summary and which bullets to show. Once you approve it:

You: Build my platform CV in English and Spanish.

The PDF and DOCX land in ~/cv-profile/out/, already checked for ATS safety. Without an AI client, the same is uvx honest-cv build ~/cv-profile -v platform -l en.

4. Tailor it to a job post. Paste the post, or run /mcp__honest-cv__tailor_for_job:

You: Here is a job post: (paste it). How well do I fit, and what should I change?

You get the coverage of each variant, the missing keywords split into you have it but this CV doesn't show it, familiarity only and you don't have it, plus the ones you marked in your checklist but haven't backed with evidence yet (it asks where you used them), a tailored variant to approve, and the build. Then it can draft a cover letter, which check_claims checks before it is built, and log the application with the post's text and what to prepare for the interview. When you get the interview, "help me prepare the interview" drafts likely questions with answers from your own achievements.

5. Come back any day. Say "let's continue my CV interview": it starts from what is missing. When you need to update your LinkedIn profile, say "update my LinkedIn".

Your profile

A profile is a folder with four YAML files. Create one with honest-cv init ~/cv-profile, or let the interview prompt fill it in with you. Keep it out of public repositories.

FileWhat it holds
profile.yamlContact details, roles, education, certifications, publications, courses and languages.
bullets.yamlA pool of achievements, each with an id, a role and tags.
skills.yamlYour skill inventory, with levels and evidence.
variants.yamlOne CV plan per type of role. A variant can inherit from another with extends:.

Any text can be a single string or one string per language: {en: ..., es: ...}. CVs can be built in English and in Spanish.

LevelMeaningOn the CV
PUsed in production at a jobShown
LYour own project or labShown
FFamiliarityOnly on the line labeled "Familiarity"
XYou don't have itNever shown, but recorded so gap reports are honest

Skill checklists

Recording dozens of skills one question at a time is slow. A checklist is a Markdown file you mark in your editor, one letter per line:

markdown
## Messaging and streamingevidence: Payments platform at Acme, 2020–2026- [P] Kafka — reconciliation flow, 2M events a day · years: 6 · last year: 2026- [F] RabbitMQ — a workshop and the official tutorials- [X] NATS

Text after " — " is the evidence, and an evidence: line under a heading covers that section. Lines without evidence are never saved: they come back as pending, and your assistant asks you about them in groups. Upgrades are confirmed once for the whole file.

Checklists come in English and Spanish (--lang es): the Spanish names are synonyms of the English ones, so a skill you mark in Spanish still matches a job post in English.

bash
honest-cv checklist list                                     # backend-jvm, platform-sre, ...honest-cv checklist new ~/cv-profile backend-jvm engineering-leadhonest-cv checklist apply ~/cv-profile ~/cv-profile/checklist.md

Any profession works. The built-in checklists cover software (backend, frontend, mobile, data, platform/SRE, QA, security, ML/AI, embedded, game development, architecture, engineering leadership) and data analysis/BI, product and project management, UX design, marketing, sales, customer support, finance and accounting, human resources, supply chain, nursing and teaching. A template is just a Markdown list in this format: save your own (or one someone shared) in ~/cv-profile/checklists/ and it shows up in checklist list and combines with the others in checklist new, which also takes a path. A template can declare synonyms, such as same: Work Breakdown Structure = WBS, and the job score, the gaps and the letter check use them, along with its skill names. Start from examples/checklists/event-planning.md. You can also apply a file you marked yourself, in English or Spanish (años, último uso). When you're done, honest-cv names the P and L skills that no achievement shows, and your assistant asks you for one real example of each.

bash
honest-cv checklist list ~/cv-profile                        # yours too, e.g. accountinghonest-cv checklist new ~/cv-profile accounting engineering-lead

New checklists for other kinds of roles are welcome: see CONTRIBUTING.md.

See examples/ada/ for a complete, fictional profile with three variants, a job post and its keywords.

Privacy

  • honest-cv itself makes no network calls. No accounts, no telemetry, no API keys. Your profile is a folder of YAML files on your machine, and the PDF engine and fonts run locally. You can check it: every command works with the network turned off.
  • Your AI client is a different matter. Whatever the client's model reads through the tools goes to that model's provider, under the provider's terms, like anything else you share in a chat. That includes your skills, bullets and the text of your CVs.
  • Some clients copy files to the cloud. To edit files directly, Claude Desktop may ask for access to the profile folder and say that the files leave your device. honest-cv's editing tools make that unnecessary: decline the request and ask the assistant to use the tools.
  • Running it on a hosted service takes it off your machine. Directories such as Glama offer to deploy honest-cv on their servers or try it in the browser. It works, but then your profile and your CVs live on that service, under its terms. For your real data, run it on your own computer with uvx honest-cv.
  • If you want nothing to leave your machine, use only the CLI (build, verify, score, skill) and edit the YAML files yourself.

Import what you already have

honest-cv import reads a JSON Resume file or LinkedIn's data export (Settings → Data privacy → Download your data, a ZIP of CSVs, or its folder if your browser unzipped it). Ask for the full archive: the basic one, offered when you pick files, has only your headline and summary, without roles. Contact, roles, education, certifications, languages and each role's achievements go into your profile; with a headline and a summary it also creates a first variant, so build works right away.

  • It only adds what your profile lacks and never overwrites. Try --dry-run first.
  • Imported achievements are tagged imported: review their wording.
  • Skills arrive without a level, because neither format says whether you used a skill in production. They go to imported-skills.md, a checklist for you to mark.

LinkedIn's "Save to PDF" profile changes layout without notice, so it isn't parsed: with an MCP client, the import_linkedin_pdf prompt reads its text and proposes each section for you to approve.

Track your applications

honest-cv apps keeps a log in applications.yaml, inside your profile folder: which variant and files went to which company, and each status with its date (draft, applied, interview, offer, rejected, withdrawn). Logging the same company and role again updates it. With an MCP client, your assistant offers to log an application after building the CV or letter, and list_applications points out the ones with no news for two weeks. It keeps a copy of each file you sent in sent/, since the next build overwrites out/, and the job post's text in posts/, since links expire, and what to prepare for the interview: ask your assistant "what did I need to prepare for Acme?".

When you get the interview, say "help me prepare the Acme interview" (or run the interview_prep prompt). For each keyword of the saved post, honest-cv lays out your level, your evidence and the bullets that back it, starting with the ones in the CV you sent. Your assistant drafts the likely questions with STAR answers taken only from those bullets, honest answers for what you only know at familiarity level or don't have, and questions to ask them. The notes you approve are saved in prep/. Without an AI client: honest-cv apps prep ~/cv-profile acme_sre -k "Kafka,Scala".

LinkedIn

honest-cv linkedin turns a variant into LinkedIn's texts, each within its limit: the headline (your title and up to five production skills), About (the summary and impact bullets), one description per position from its bullets, and the skills list. It writes them to a Markdown file to copy from. The skills are P and L only: LinkedIn can't label familiarity, so F skills stay out, and X skills never appear. With an MCP client, the linkedin_profile prompt polishes the wording and checks it with check_claims.

Export

To go the other way, honest-cv export writes a variant as JSON Resume for other CV tools and sites, with the same rules as the CV: X skills never appear, and F skills only in a "Familiarity" group with that level.

Cover letters

The cover_letter prompt drafts a one-page letter for a job post from your own bullets. Before it is built, check_claims reads the text against your profile:

  • Problems block the build: a skill you marked X, or a familiarity skill presented as experience ("I use Rust in production" when Rust is F; "I am familiar with Rust" is fine).
  • Warnings are for you to review: a technology neither your inventory nor your bullets show, or a number that appears nowhere in your profile. If it is true, record it first; if not, it comes out of the letter.

The letter uses the CV's fonts and passes the same ATS checks. Without an AI client, write it in a text file (paragraphs separated by blank lines) and use honest-cv letter check and letter build.

CLI

Run any command with uvx honest-cv ..., or install it once with uv tool install honest-cv to type just honest-cv.

bash
honest-cv init ~/cv-profile                        # create the profile templateshonest-cv build ~/cv-profile -v backend -l en -l es # PDF + DOCX, verified on every buildhonest-cv verify any-cv.pdf --text                  # check any PDF, even one made elsewherehonest-cv score ~/cv-profile -k "Kubernetes,Go" -p "Rust"   # coverage per variant, with gapshonest-cv skill ~/cv-profile "Rust" L --evidence "CLI tool on GitHub"  # asks you to confirmhonest-cv import ~/cv-profile linkedin-export.zip --dry-run         # or resume.jsonhonest-cv export ~/cv-profile -v backend -l en                       # JSON Resumehonest-cv apps log ~/cv-profile --company Acme --role "SRE" -s applied -v platformhonest-cv apps list ~/cv-profile                                     # latest first, with countshonest-cv apps prep ~/cv-profile acme_sre -k "Kafka,Scala"           # what backs each keyword, for the interviewhonest-cv linkedin ~/cv-profile -v platform -l en                    # texts to paste into LinkedInhonest-cv remove skill ~/cv-profile "Kafka"                          # asks you to confirmhonest-cv letter check ~/cv-profile letter.txt -k "Kubernetes,Go"     # claims your profile doesn't supporthonest-cv letter build ~/cv-profile letter.txt --company Acme --role "Platform Engineer" -l enhonest-cv serve --profile ~/cv-profile              # the MCP server, over stdio

verify works on any PDF. Use --text to see exactly what a parser extracts. Its single_column check also catches a common defect: a date aligned to the right, which parsers split away from its role.

MCP tools and prompts

NameWhat it does
init_profileCreates a profile folder with commented templates.
get_inventoryReturns your skills, grouped by level, with years and evidence.
set_skillAdds or changes a skill. To raise its level it needs evidence and asks you to confirm.
set_skillsAdds or changes several skills at once. Upgrades are confirmed with one question that lists each change.
checklist_listLists the built-in checklists.
checklist_newMerges built-in checklists into one file, prefilled from your inventory.
checklist_applySaves the skills marked in a checklist and returns the lines that still need evidence.
add_bulletAdds an achievement to the pool.
remove_skill, remove_bullet, remove_role, remove_publicationDelete for good, and remove every use in the variants. A role with bullets needs with_bullets. Clients ask before running them.
set_contactChanges contact details: name, email, phone, location, links.
set_profile_detailsReplaces the certifications list, the courses list and the spoken-languages line.
upsert_roleAdds a role in date order, or changes fields of an existing one.
upsert_educationAdds or changes an education entry.
upsert_publicationAdds or changes a book, article or paper the person wrote. Each variant shows all of them, or the ones it lists.
save_variantAdds or replaces a variant. Every reference is checked before saving.
list_variantsLists the variants after inheritance, with their bullet texts and the bullets no variant uses.
build_cvRenders a PDF and/or DOCX and verifies it.
verify_pdfRuns the ATS checks on any PDF and returns its extracted text.
score_jobMeasures the keyword coverage of each variant. The client extracts the keywords.
gap_reportGroups missing keywords by what you can honestly do about each one.
prompt interviewFills your inventory and bullet pool, one question at a time.
check_claimsChecks any text against your profile: blocks X skills and familiarity sold as experience, flags what the profile doesn't show.
build_letterRenders a cover letter to PDF and DOCX, one page, with the CV's ATS checks. Refuses while check_claims finds problems.
prompt tailor_for_jobScores the variants, explains the gaps, adapts a variant and rebuilds.
prompt cover_letterDrafts a letter for a job post from your bullets, checks its claims and builds it.
import_profileImports JSON Resume or a LinkedIn data export, adding only what is missing. For a LinkedIn PDF it returns the text.
export_json_resumeExports a variant as JSON Resume; X skills never appear and F skills keep their label.
log_applicationRecords an application (company, role, CV variant, files sent, the post's text, what to prepare) or a new status, with its date.
linkedin_profileLinkedIn headline, About, position descriptions and skills (P and L only) from a variant, within LinkedIn's limits.
list_applicationsLists applications, latest first, with a count per status and the ones with no news for 14+ days.
interview_prepFor an application: the saved post and, per keyword, your level, evidence and the bullets that back it. Saves the prep notes.
prompt import_linkedin_pdfTurns the PDF from LinkedIn's "Save to PDF" into a profile, section by section, with your approval.
prompt linkedin_profilePolishes the LinkedIn texts of a variant without adding claims, checked with check_claims.
prompt interview_prepPrepares an interview: likely questions, STAR answers from your own bullets, honest answers for the gaps.

ATS guarantees

The template enforces these. verify checks them on every build, and the test suite runs in CI on Linux, macOS and Windows:

  • One column. No layout tables, images, icons, headers or footers.
  • Ligatures and kerning off, no hyphenation, and terms like "CI/CD", URLs and emails never split across lines.
  • Reading order equals source order. Dates sit on the same line as their role.
  • Text is extractable by both pypdf and pdfminer.six, and the two agree.
  • The fonts (Carlito, metric-compatible with Calibri) are embedded and identical on every machine.

Development

bash
uv syncuv run pytestuv run honest-cv build examples/ada -l en -l es

The repository's .mcp.json registers honest-cv-dev with the fictional profile, so Claude Code in this folder can use your working copy. See CONTRIBUTING.md.

License

MIT. The bundled Carlito font is under the SIL Open Font License; see src/honest_cv/render/fonts/OFL.txt.

來源:README.md,提交 51bcc81

工具

31

init_profile

Create a new profile folder with empty, commented YAML templates (profile, bullets, skills, variants). Use it once, before anything else, when the person has no profile; to start from LinkedIn or a JSON Resume, call import_profile afterwards. Refuses an existing profile and overwrites nothing. Returns `created`: the files written.

輸入參數profile必填

get_inventory

Read the person's skill inventory. Use it at the start of a session and before proposing skill changes; for CV content (roles, bullets, variants) use list_variants instead. Returns `levels` (what P, L, F and X mean) and `skills` grouped by level, each with its years, last_used_year, evidence, aliases and notes. Read-only.

輸入參數profile

set_skill

Add or change one skill in the inventory. Use it for a single skill; for several at once use set_skills, and for a whole marked list use checklist_apply. Raising a level (a new skill counts as rising from X) needs `evidence`, and the server asks the person to confirm before saving; lowering is always allowed. Returns `saved` (the stored skill) and `previous_level`.

輸入參數name必填level必填notesyearsaliasesprofileevidencelast_used_year

set_skills

Add or change several skills in one call, for example a group the person just told you about. Use set_skill for one skill and checklist_apply for a marked checklist. Every upgrade needs `evidence`; the person confirms upgrades in a form, up to 10 per call, and only those they answer "sí" are saved. Returns `saved`, `upgrades_confirmed`, `upgrades_refused` and `upgrades_not_asked_yet`: when that list is not empty, call set_skills again with those skills.

輸入參數skills必填profile

import_profile

Import an existing CV into the profile: a JSON Resume (.json), a LinkedIn data export (.zip or its unzipped folder) or a LinkedIn profile PDF. Use it at the start, right after init_profile, instead of typing everything; run it first with `dry_run`. Adds contact, roles with their achievements, education, certifications, courses, publications and languages; only what the profile lacks, never overwriting. Skills arrive without a level, so they go to <profile>/imported-skills.md for the person to mark, never to the inventory. Imported bullets are tagged `imported`: review them with the person. Returns what was added and an optional `note` to pass on. For a PDF nothing is written: it returns the `text`, to organize with the editing tools (see the import_linkedin_pdf prompt).

輸入參數path必填dry_runprofile

checklist_list

List the skill checklist templates the person can combine. Use it before checklist_new, to let the person pick the ones that fit their profession. Returns `checklists`: each with its `id`, `title`, `description`, number of `skills` and `origin` ("built-in", or "yours" for templates in <profile>/checklists/). Any profession works. Pass `lang` in the person's language to get the translated templates. Read-only.

輸入參數langprofile

checklist_new

Write a checklist file for the person to mark in their editor, merged from the templates picked in checklist_list, without duplicates and prefilled from the inventory. Use it when the person has many skills: it is much faster than asking one by one. Next step: once they have marked it, call checklist_apply. Refuses to replace an existing file unless `overwrite`. `lists` may be empty when `extra` names the skills. Returns the file's `path` and its number of `skills`.

輸入參數langpathextralists必填profileoverwrite

checklist_apply

Save the skills the person marked in a checklist file. Use it after checklist_new, once the person says they are done, and again to resume. Lines that keep or lower a level are saved at once; upgrades with evidence are confirmed in a form, up to 10 per call: call again while `upgrades_not_asked_yet` is not empty. Returns the counts saved, `pending_evidence` (marked lines without evidence: ask where they used them, in groups, and save with set_skills), `skills_without_achievements` and `key_skills_without_achievements`. Ask about nothing else: unmarked lines are for the person to mark in the file. After the checklist, ask for the person's biggest achievements first, since one usually covers several skills, then for the key skills still without one; save each with add_bullet. The rest wait for a job post that asks for them (gap_report → `no_achievement`). Never write an achievement for them.

輸入參數path必填profile

add_bullet

Add one achievement to the bullet pool, the material every CV variant picks from. Use it after the person approves the wording, one bullet per call; to change which bullets a CV shows, use save_variant. `role` is a role id from upsert_role; leave it out for bullets used only in Selected Impact. Use only facts the person stated, never invented numbers. Returns `saved`.

輸入參數id必填roletagsmetricsprofiletext_en必填text_es

set_contact

Update the person's contact details on the CV. Use it for name, email, phone, location and links; roles, education and the rest have their own tools. Only the fields given change; pass "clear" to remove an optional one. `links` replaces the whole list. Returns the `contact` as saved in profile.yaml.

輸入參數nameemaillinksphoneprofilelocation

set_profile_details

Replace the certifications, courses or spoken-languages line of the profile. Use it for those three lists only; roles, education and publications have their own tools. Each list you pass replaces the current one in full; leave a field out to keep it. A course or training without an exam goes in `courses`, never in `certifications`. Returns the saved values.

輸入參數coursesprofilelanguagescertifications

upsert_role

Add a job role, or change some fields of an existing one by its `id`. Use it while interviewing the person about their work history; their achievements go in with add_bullet, pointing to this id. A new role needs `title`, `company` and `start`; roles stay in date order, newest first. Keep the person's real title. Returns the `role` as saved.

輸入參數id必填endstarttitlecompanycontextprofilelocation

upsert_education

Add an education entry, or change the one with the same institution and degree. Use it for degrees and formal studies; courses and certifications go in set_profile_details. Say honestly whether the degree was completed, e.g. "B.Sc. (unfinished)". Returns the `education` entry as saved.

輸入參數endstartdegreeprofileinstitution必填

upsert_publication

Add a book, article or paper the person wrote, or change some fields of the one with this `id`. Use it when the person mentions something they published; courses and certifications go in set_profile_details. Every variant shows all publications unless it lists the ones it wants (save_variant → `publications`). Returns the `publication` as saved.

輸入參數id必填urlyeartitlevenueprofile

save_variant

Create or replace a CV variant: the plan for one kind of role (title, summary, which bullets and skills to show). Use it to set up a variant or tailor one to a job post; read the current ones with list_variants first. It replaces the variant whole, so pass every field it should define (list_variants → `own` shows them). A variant without `extends` needs `title` and `summary`. Every reference is checked before saving. Returns `saved` and the `variant`.

輸入參數id必填rolestitleimpactskillsextendsprofilesummarymax_pagescompetenciespublications

remove_skill

Delete a skill from the inventory, e.g. a duplicate or a misspelling, and from the variants' skill groups and competencies. Use it only for mistakes: to record that the person doesn't have a skill, use set_skill with level X instead, which keeps gap reports honest. Ask the person first; it cannot be undone. Returns what was removed and `variants_updated`.

輸入參數name必填profile

remove_bullet

Delete an achievement from the pool and from every variant that uses it. Use it when the person wants it gone; to stop showing it in one CV, change that variant with save_variant instead. Ask the person first; it cannot be undone. Returns what was removed and `variants_updated`.

輸入參數id必填profile

remove_publication

Delete a publication from the profile and from every variant that lists it. To hide it from one CV only, change that variant's `publications` with save_variant instead. Ask the person first; it cannot be undone. Returns what was removed and `variants_updated`.

輸入參數id必填profile

remove_role

Delete a role from the profile and from every variant. A role that still has bullets is refused unless `with_bullets` is true, which deletes them too. To hide a role from one CV, edit that variant with save_variant instead. Ask the person first; it cannot be undone. Returns what was removed and `variants_updated`.

輸入參數id必填profilewith_bullets

list_variants

Read every CV variant, with `extends` already applied and the text of each bullet it uses. Use it before save_variant, build_cv or score_job, to know what each CV contains. Returns `variants` (with `own`: the fields each one defines itself) and `unused_bullets`: achievements no variant shows yet. Read-only.

輸入參數profile

build_cv

Render a CV variant to PDF and/or DOCX, then verify the PDF for ATS safety. Use it when the person wants the files; for a cover letter use build_letter, and to check a PDF made elsewhere use verify_pdf. Files go to `out_dir`, default <profile>/out, replacing earlier builds of the same variant and language. Returns the `files`, each PDF with its pages, `ats_ok` and failed checks. A failed check is probably a bug in honest-cv: report it, never reword the person's text to pass it.

輸入參數langformatsout_dirprofilevariant必填

verify_pdf

Check whether any PDF is ATS-safe: one column, no ligatures, dates on their role's line, text extractable, and the page count. Use it on a CV from any tool, e.g. the person's current one; build_cv already runs it on the CVs it renders. Returns `ok`, `pages`, `checks` (each with `name`, `ok`, `detail`) and `text`: what an ATS reads. Read-only.

輸入參數path必填max_pages

check_claims

Check any text about the person against their profile before it goes anywhere: a cover letter, a summary, a LinkedIn text. build_letter and linkedin_profile run it too. Returns `problems`, which must be fixed (a skill marked X, or a familiarity skill not called familiarity in its sentence), and `warnings` for the person (a technology the profile doesn't show, or a number found nowhere in it). Fix them by removing or qualifying the claim, never by adding skills. Read-only.

輸入參數text必填profilekeywords

build_letter

Render an approved cover letter to a one-page PDF and/or DOCX with the CV's ATS checks. Use it after drafting the letter with the person and running check_claims; for the CV itself use build_cv. It runs check_claims again and refuses while there are problems. Returns the `files` and any `warnings` to show the person.

輸入參數langrole必填closingcompany必填formatsout_dirprofilegreetingkeywordsrecipientparagraphs必填

export_json_resume

Export a CV variant as a JSON Resume file, for other CV tools and sites that import that format. Use build_cv for a PDF or DOCX instead. Same honesty rules as the CV: X skills never appear, and F skills only in a "Familiarity" group. Writes to `out_dir`, default <profile>/out, and returns its `path`.

輸入參數langout_dirprofilevariant必填

linkedin_profile

Write the LinkedIn texts for a variant, each within LinkedIn's limit: headline, About, one description per position from its bullets, and the skills (P and L only, since LinkedIn can't label familiarity). Use it when the person updates their LinkedIn profile. Writes them to a Markdown file to copy from and returns them with their `path`, plus `left_out`: bullets that didn't fit. After the person approves a polished headline or About, call it again with them: they are checked like a letter and saved in that file.

輸入參數langaboutout_dirprofilevariant必填headline

log_application

Record a job application, or update the one for the same company and role. Use it when the person sends a CV or letter, and whenever they tell you what happened (interview, offer, rejection); list_applications reads them back. Fields not given keep their value. Save the post's full text in `post`, since links expire, and your interview advice in `prep`. Each file in `files` is copied to <profile>/sent/<id>/, so the record keeps what was sent. Returns the `application` and `not_found`: paths it could not copy.

輸入參數urldatelangpostpreprole必填filesnotesstatuscompany必填profilevariant

list_applications

List the person's job applications, most recently updated first. Use it when they ask how their search is going or which application to follow up; log_application records changes. Returns `applications` (each with its id, status and `days_since_update`), a count per status and `waiting`: open applications with no news for 14 days or more. Read-only.

輸入參數statusprofile

interview_prep

Prepare the interview for one logged application from what the person can honestly back up. Call it first with only `application` to get the saved job post (`post_text`), then again with the post's keywords. For each keyword it returns their level, evidence, `stories` (the bullets that show it, those in the CV they sent first) and a `standing`: strong (tell a story from those bullets), no_achievement (ask for a real example), marked_pending (ask for evidence), familiarity (say it is familiarity) or lacking (say so honestly). Every story must come from `stories`. With `notes`, saves the approved prep to <profile>/prep/<id>.md.

輸入參數notesprofilekeywordspreferredapplication必填

score_job

Measure how well each CV variant covers a job post's keywords, best first. Use it first when the person shares a post, to pick a variant; then call gap_report on that variant to see what is missing and why. Extract the keywords yourself in the post's own wording: `keywords` are the required ones, `preferred` the nice-to-haves. Returns `scores`: per variant, the required and overall coverage and each keyword found, found only as familiarity, or missing. Read-only.

輸入參數langprofilekeywords必填variantspreferred

gap_report

Explain the keywords a job post asks for that one variant doesn't show, grouped by what can honestly be done. Use it after score_job picked the variant, before editing it with save_variant. Returns: `in_inventory_not_in_cv` (the person has it: add it, using `unused_bullets`, or name it in the summary or competencies), `familiarity_only` (only as familiarity), `not_in_inventory` (do not claim it), `no_achievement` (P or L skills no bullet shows: ask for one real achievement each) and `marked_in_checklist` (marked in their checklist, still without evidence: ask where they used it). Read-only.

輸入參數langprofilevariant必填keywords必填preferred

版本歷史

3
  1. v0.3.3最新Oct 21, 2026
  2. v0.3.2Oct 16, 2026
  3. v0.2.0Oct 16, 2026

評分

已滿足適用檢查項的 90%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分
  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具必需15 分
  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分