开源框架用Claude Code实现职位评估、简历定制、求职信撰写、模拟面试全流程,求职者本地运行,数据不上传。

在你本地机器上运行的求职工具。
一个基于 Claude Code 构建的 AI 驱动求职框架。Fork 它,填写你的个人资料,让 Claude 评估招聘帖子、定制简历、撰写求职信,并为你准备面试。
注意:这是一个独立的开源项目,与 Anthropic 没有关联、未被其认可、未被其赞助或维护。提及 Anthropic 和 Claude Code 仅用于描述此工作流使用的工具链。
本项目没有任何关联的加密货币、代币或付费赞助计划。任何此类声明均未经授权,应被视为骗局。支持本项目的唯一方式是下方提供的 Ko-fi 链接以及在 GitHub 上贡献。
它真的有效吗?
我原本是地球物理学家出身。2025 年底我所在的岗位被裁撤后,我用这个框架来运行自己的求职——就是本仓库中相同的 /scrape、/apply 和 /interview 工作流,每周都用在自己的职业生涯上。我对每一位沟通过的雇主都坦诚相告,而它非但没有成为阻碍,反而通常会引发一场真正的技术交流。
六十九份定制申请,二十场初面,一份已签署的合同——2026 年 6 月,我以 AI 工程师的身份入职了。人们一直在问这玩意儿到底有没有用。是它让我找到了工作。现在它是你的了。
更详细的版本,包括完整的申请漏斗数据,已发布在 LinkedIn 上。
这是否为你节省了一个周日的求职信撰写时间?请我喝杯咖啡。它是否帮你拿下了那份工作?或许可以请两杯。☕
一个结构化工作流,将 Claude Code 转变为全栈求职申请助手。核心工作流(自我画像、匹配度评估以及审核人-撰写人的申请流水线)是语言和地区无关的。职位门户搜索技能是为丹麦市场构建的(Jobindex、Jobnet、Akademikernes Jobbank 等),但其模式设计为可替换为你当地招聘平台。
/setup /scrape /apply <url>
| | |
v v v
Fill in Search job Evaluate fit
your profile portals Score & recommend
| | |
v v v
Profile Present matches Draft CV + Cover Letter
files ready with fit ratings (LaTeX, tailored)
| |
v v
Pick a match Reviewer agent critiques
-> /apply -> Revise -> Final output
该框架编码了职业指导的最佳实践,包括结构化评估标准、前瞻性求职信框架以及可选的薪资基准对比。
Claude Code (CLI)。如果你使用的是其他 Agent 工具(Codex、Antigravity、Gemini CLI)?从 AGENTS.md 开始——门户搜索技能开箱即用,社区分支则适配了完整工作流。
Bun(用于求职搜索 CLI 工具)
带有 lualatex 和 xelatex 的 LaTeX 发行版:TeX Live、MacTeX、TinyTeX 或 MiKTeX。简历使用 lualatex 编译(pdflatex 在现代 MiKTeX 安装上常因 fontawesome5 字体扩展错误而失败);求职信使用 xelatex 编译,因为 cover.cls 需要 fontspec。如果你使用的是最小化 TeX 安装(如 TinyTeX 或 BasicTeX),请安装 SETUP.md 中列出的额外包。
可选:poppler 的 pdftotext(macOS: brew install poppler,Debian/Ubuntu: apt install poppler-utils,Windows: choco install poppler)——用于 /apply 对编译后简历的 ATS 可解析性检查。如果缺失,该检查会优雅降级为可视化关键词审查。
🎥 想先看实际效果?Next New Thing 对工作流的实际使用方式做了手把手的演示,从安装配置到完成一份申请(录制于 2026 年 8 月——命令可能已过时)。
gh repo fork MadsLorentzen/ai-job-search --clone
cd ai-job-search
此仓库的 Fork 始终是公开的——GitHub 不允许对公开仓库进行私有 Fork——而 /setup(下方第 3 步)会将你的个人数据(姓名、联系方式、工作经历、薪资期望)写入被追踪的文件。如果你是为了自己的求职而非为贡献代码而 Fork,请使用私有仓库并将本仓库作为上游——两分钟操作指南在 SETUP.md 第 8 节,每次更新工作流都完全相同。只有在为社区贡献时才 Fork。
$tools = @("jobbank-search", "jobdanmark-search", "jobindex-search", "jobnet-search", "linkedin-search", "freehire-search")
foreach ($tool in $tools) {
Push-Location ".agents/skills/$tool/cli"
bun install
Pop-Location
}
Bash / zsh / Git Bash:
for tool in jobbank-search jobdanmark-search jobindex-search jobnet-search linkedin-search freehire-search; do
(cd .agents/skills/$tool/cli && bun install)
done
对于 linkedin-search 和 freehire-search,install 是可选的:两者零运行时依赖,直接用 bun 运行即可;bun install 仅拉取 TypeScript 开发类型。
claude
# 然后在 Claude Code 内:
/setup
/setup 提供三条路径:如果你的 documents/ 文件夹已有内容(简历 PDF、LinkedIn 导出、学历证书、推荐信、过往申请)则读取之,导入聊天时粘贴的一份简历,或者通过对话走一遍面试流程。它会自动检测你有什么并做出询问。documents 文件夹模式是幂等的,安全地支持你添加更多材料时重复运行;详见 documents/README.md 的布局。
/scrape
这会在多个招聘门户搜索与你简历匹配职位,对结果去重,并按匹配度排序展示。选择一个职位直接对其运行 /apply——或者,当一次抓取返回的职位多到你不想逐个浏览时,先运行 /rank 对所有职位按匹配度框架批量评分,得到排序后的候选清单后再处理。
/apply https://jobindex.dk/job/1234567
如果 URL 无法获取(某些招聘门户屏蔽了自动化访问),你也可以直接粘贴职位描述:
/apply <在此粘贴完整职位描述>
这将运行完整工作流:评估匹配度、起草简历和求职信、用第二个 Agent 审核、修改并呈现最终输出。
招聘帖子被视为不受信任的输入(工作流不会遵循其中嵌入的任何指令,也不会从其正文中获取任何链接),但 Agent 层面的防御是指令级的,而非沙箱——在陌生的招聘平台上,在你点击发送之前快速浏览一下已获取并撰写的内容。详见 SECURITY.md。
/setup、/scrape 和 /apply 构成核心工作流。一旦你的资料到位,十条额外的命令将扩展其功能:
/interview 为你跟踪的申请中已安排的面试做准备。它根据该申请的档案(原始招聘帖子、面试官实际看到的简历和求职信、以及从早期轮次记录的反馈)构建针对特定阶段的准备包,用验证后使用的规则研究公司和面试官,将可能的问题对应到你的 STAR 案例,并按照 07-interview-prep.md 中的角色扮演协议提供模拟面试。空档会得到诚实的过渡性回答,绝不编造经验。
/outcome 记录一个申请的结果——面试阶段、录用、拒绝、无声无息。它将提交的简历、求职信和帖子原文归档到 documents/applications/<公司>_<职位>/ 中,用 /setup Path A 解析的格式保留 outcome.md,并更新追踪器。它还拥有在有结果可记录之前的那段延伸时间:/outcome followup 找出已陷入沉默的活跃申请(默认 10 天),使用你已提交材料中的内容以你的写作风格起草一封简短且渠道恰当的跟进邮件(仅起草,不发送;每个申请最多两次),并在同一轮面试阶段被记录时提供一封感谢信。一旦有一些申请有了结果,它会引导你回到 /setup 从实际获得面试的情况来校准匹配度框架。
/notion-sync 通过官方 Notion MCP 服务器(OAuth,无需 API 密钥)将流水线单向发布为 Notion 数据库中的只读视图——每个排名的职位一行,每个跟踪的申请也一行,每行有一个一次性写入的简报页面。仓库文件仍是系统真相:没有任何内容同步回来,文档仅以文件名同步。这是 /html-report 的补充:那个是你在桌面前重新生成的深度离线仪表板;这个则是 Notion 运行之处(桌面端、Web 端、手机端)随时可瞥见的实时视图。
/gmail-sync 读取你的 Gmail(通过 Gmail connector)中的状态信号——面试邀请、测评链接、录用通知、拒绝通知——并以批处理方式将它们列为待审批项,在写入 tracker 或 outcome.md 之前必须经过你的确认,每条拟议变更都会附上原始邮件来源。录用通知不会自动提议 hired/offer_declined,因为那是你的决定;冲突或无法匹配的信 号则标记为需要手动执行 /outcome 处理,而不是靠猜测。
/rank 桥接 /scrape 和 /apply:它将所有新抓取的职位按匹配框架进行批量评分(并行 agent 各自获取一个职位并从五个维度评分),返回一份有排名的候选清单,诚实列出每个职位的优势与不足。致命缺陷直接否决,截止日期打上紧急标记,已失效的职位标记为过期。选定一个数字后交由完整的 /apply 工作流处理。
/expand 通过扫描你在个人资料中已关联的公开来源(GitHub 仓库、作品集网站、Kaggle、Google Scholar)并查询命名课程和认证的syllabus 来丰富你的简历。发现的技能会附带来源标签后加入个人资料。建议在 /setup 之后立即运行,以挖掘出文档本身无法明确体现的技能。
/upskill 分析你的个人资料、你追踪的职位帖子以及已排名但未追踪的帖子(/rank 在 seen_jobs.json 中记录的差距)之间的技能缺口——或者通过 /upskill <URL> 针对单个职位。生成一份按优先级排列的技能缺口热力图,以及一份包含网页搜索学习资源和时间估算的学习计划。适合在两次申请之间做职业规划。
/html-report 根据 job_search_tracker.csv 和申请档案生成一个自包含的 HTML 仪表板——统计卡片、状态/行业/渠道/漏斗图表(内联 SVG,无外部依赖),以及可筛选的申请表。可直接在浏览器中打开,完全离线运行。在 /apply 或 /outcome 新增条目后随时重新运行。
/add-template 用你自己的简历或求职信模板(LaTeX、Typst 或其他工具链)替换现有模板。它捕获模板的说明(源文件扩展名、编译命令、字体、样式规则、页数限制),运行强制性的测试编译,然后将模板接入 /apply。详见下方的自定义模板部分。
/add-portal 为你所在市场的招聘网站生成一个职位搜索 skill。它调查该招聘网站(搜索 URL 模式、结果结构、访问规则),从与已内置模板相同的结构脚手架化 CLI skill,并在注册前对实时查询进行测试运行。详见下方的职位搜索工具部分。
/reset 也可用,详见下方的重新开始部分。
ai-job-search/
├── CLAUDE.md # 主候选人资料 + 工作流规则
├── .claude/
│ ├── commands/
│ │ ├── apply.md # /apply 工作流(起草-审核模式)
│ │ ├── setup.md # /setup 入门(文档文件夹、简历导入或面试)
│ │ ├── expand.md # /expand 从文档和在线状态丰富技能
│ │ ├── add-template.md # /add-template 注册自定义模板(LaTeX、Typst……)
│ │ ├── add-portal.md # /add-portal 为你所在市场生成招聘网站搜索 skill
│ │ ├── rank.md # /rank 将抓取的职位分类为有排名的候选清单
│ │ ├── outcome.md # /outcome 记录申请结果、归档材料
│ │ ├── gmail-sync.md # /gmail-sync 从 Gmail 自动检测申请状态
│ │ ├── interview.md # /interview 阶段特定的准备包 + 模拟面试
│ │ ├── html-report.md # /html-report 生成申请追踪仪表板
│ │ ├── notion-sync.md # /notion-sync 单向流水线视图存入 Notion 数据库
│ │ └── reset.md # /reset 清除个人资料数据或文档文件夹
│ ├── skills/
│ │ ├── job-application-assistant/ # 核心申请 skill
│ │ │ ├── SKILL.md # Skill 定义
│ │ │ ├── 01-candidate-profile.md # 你的教育、经历、技能
│ │ │ ├── 02-behavioral-profile.md# PI/DISC/人格评估
│ │ │ ├── 03-writing-style.md # 语气、结构、宜忌
│ │ │ ├── 04-job-evaluation.md # 职位匹配评分框架
│ │ │ ├── 05-cv-templates.md # LaTeX 简历结构 + 定制规则
│ │ │ ├── 06-cover-letter-templates.md # LaTeX 求职信模板
│ │ │ └── 07-interview-prep.md # STAR 示例 + 面试框架
│ │ ├── job-scraper/ # 职位搜索编排
│ │ └── upskill/ # /upskill 技能缺口分析与学习计划
│ └── settings.json # Claude Code 权限(共享、作用域限定)
├── .agents/skills/ # 招聘网站 CLI 工具
│ ├── jobbank-search/ # Akademikernes Jobbank(丹麦)
│ ├── jobdanmark-search/ # Jobdanmark.dk(丹麦)
│ ├── jobindex-search/ # Jobindex.dk(丹麦)
│ ├── jobnet-search/ # Jobnet.dk(丹麦,政府门户)
│ ├── linkedin-search/ # LinkedIn 公开职位列表(跨国通用)
│ └── freehire-search/ # freehire.me 科技职位聚合(多市场、REST API)
├── cv/
│ └── main_example.tex # moderncv LaTeX 模板
├── cover_letters/
│ ├── cover.cls # 自定义求职信 LaTeX 类
│ ├── cover_example.tex # 求职信示例(结构参考 + CI 冒烟测试)
│ └── OpenFonts/ # Lato + Raleway 字体
├── templates/ # 通过 /add-template 注册的自定义模板
│ └── README.md # 文件夹布局说明
├── documents/ # /setup 路径 A 和 /expand 的职业源材料
│ ├── README.md # 文件夹布局说明
│ ├── cv/ # 主简历(PDF 或 .tex)
│ ├── linkedin/ # LinkedIn 主页导出(PDF)
│ ├── diplomas/ # 学位证书和成绩单
│ ├── references/ # 推荐信
│ └── applications/ # 历史申请记录(<公司>_<职位>/)
├── .github/workflows/ci.yml # CI:LaTeX 冒烟编译、skill 检查、CLI 类型检查
├── salary_lookup.py # 薪资基准查询工具(自带数据)
├── tools/
│ ├── convert_salary_excel.py # 将薪资 Excel 转换为 JSON
│ ├── lint_skills.py # CI l
/apply 命令以起草-审核工作流运行,包含强制性的 PDF 编译:
解析职位描述(URL 或文本) 根据你的个人资料评估匹配度(技能、经验、文化、地点、职业发展规划) 用 LaTeX 起草定制化的简历和求职信 生成一个审核 agent,研究公司情况并批评草稿 根据审核反馈进行修订 编译并检查两份 PDF:简历用 lualatex,求职信用 xelatex。Claude 阅读渲染后的页面并迭代 LaTeX,直到简历恰好两页且没有孤立的条目标题,求职信恰好一页且签名可见、字体一致。 对简历进行 ATS 检查:用 pdftotext(可选依赖)提取 PDF 的文本层,验证 ATS 解析器看到的方式——联系详情是否为原文文本、无乱码字符、阅读顺序正常——然后对照提取结果对职位描述的关键词覆盖进行评分。简历真实支持的关键词会被添加;真实的缺口保持可见,绝不塞入。 用验证清单展示最终输出
简历和求职信中的所有陈述都会根据你的真实个人资料进行核实。系统绝不杜撰技能或经历。
什么让这个工作流与众不同
PDF 验证循环。大多数 LaTeX 简历模板产生的输出"在 .tex 里看起来没问题"但在 PDF 中会出问题:职位标题孤立地跳到下一页、求职信溢出到第 2 页、项目符号字体静默回退到正文字体。/apply 命令在每次申请时都会自动编译并目视检查每份 PDF,应用针对性修复(\needspace、\enlargethispage、列表项的字体匹配包装器),直到布局干净整洁。
ATS 文本层验证。ATS 读取的是 PDF 嵌入的文本,而不是渲染后的页面——LaTeX 可能静默产生文本提取出来是乱码的 PDF(应该是邮箱的地方是图标字形、多栏布局的行交错)。/apply 用 pdftotext 提取编译后简历的文本层,验证联系详情、阅读顺序,以及解析器实际看到的职位关键词覆盖。诚信规则强制执行:个人资料不支持的关键词被承认为缺口,绝不塞入。
Relevance-weighted CV cutting. 当 CV 超过 2 页时,工作流不会机械地从"最旧"部分开始裁剪。它按以下三项对每条候选内容打分:(a) 与目标岗位的相关性,(b) 在文档中的独特性,(c) 求职信是否依赖它,然后优先裁剪总分最低的行。一条命中岗位关键词的旧职位条目,会排在不命中关键词的新职位条目之前保留下来。
Drafter-reviewer separation. 起草者负责撰写;第二个 Claude 智能体在全新上下文中被唤起,负责研究公司并批评草稿。起草者随后进行修订。这能捕获遗漏的关键词、乏力的表达,以及单次通过常会留下的套话。
Token-efficient reviewer dispatch. 审阅者智能体以内联方式接收草稿,而非重新阅读;验证检查清单在工作流末尾统一执行一次,而非两个智能体各自重复一遍。注意:第 5 步中新的编译与检查步骤将省下的部分 token 消耗花在了 PDF 渲染和排版迭代上——工作流用一定的端到端 token 成本,换取了到达用户手中的损坏 PDF 真实减少。
Which files to edit manually
如果你更倾向于直接编辑文件而非使用 /setup:
Updating your search queries
随着你的优先级变化,你可以只重新配置职位搜索,而无需重新运行完整的个人资料设置:
/setup --section search
这会重新运行搜索配置访谈:目标岗位类型、搜索技能列表、工作地点以及招聘门户。它还会根据你的个人资料建议你可能未考虑到的岗位类型。
简历使用 moderncv(银行业风格)。求职信使用自定义 cover.cls,配备 Lato/Raleway 字体。两者均为 LaTeX——这是本仓库默认附带和维护的参考引擎。
要使用你自己的模板——无论是 LaTeX、Typst,还是任何其他可通过命令行编译为 PDF 的工具链——请运行:
/add-template
指向你的源文件(一个 .tex 文件加任意 .cls/.sty 文件或捆绑字体;一个 .typ 文件加任意本地包;或其他工具链的等价物)。该命令会引导你填写模板说明——源文件扩展名、编译命令、字体及其位置、需要保留的样式规则、硬性页数限制——将一切存储在 templates/ 下,执行强制测试编译,然后激活模板,使 /apply 草稿和编译均使用该模板。模板以 [PLACEHOLDER] 令牌存储个人数据,因此可以安全地提交和共享。
/add-template --list 查看已注册的模板
/add-template --use <name> 在不同模板间切换
/add-template --use default 还原为 stock moderncv / cover.cls 模板
如果你更倾向于手动操作,传统方式依然可行:更新 05-cv-templates.md 和 06-cover-letter-templates.md 中的指南。
.agents/skills/ 中的四个丹麦 CLI 工具(Jobbank、Jobdanmark、Jobindex、Jobnet)展示了为特定市场构建招聘门户集成的模式。如果你身处其他国家,请运行:
/add-portal
提供你当地招聘网站的 URL。该命令会调查该门户(搜索 URL 模式、结果页结构、robots.txt/访问规则),用相同的结构、命令和输出契约脚手架一个 CLI 技能,并在注册任何内容前对实时查询进行测试运行。需要认证的门户会被拒绝,条款严格的门户会在生成的技能中附带醒目的"仅限个人使用"警告。生成的技能是市场特定的,位于你的 fork 中;生成器本身是通用的。
在为你的市场或语言维护一个适配的 fork?请将其添加到 Community forks & adaptations 话题中,以便他人发现。
对于丹麦以外的地域无关起点,仓库随丹麦演示一起附带了两个门户技能:
linkedin-search —— 构建于 LinkedIn 公开的、未认证的 jobs-guest 端点。领域无关,零运行时依赖(仅需 bun 即可运行),将搜索位置作为显式标志接收,因此开箱即用地适用于任何市场(-l "Berlin, Germany"、-l "Mumbai, Maharashtra, India"、-l "Remote"……)。仅供个人使用——自动化访问违反 LinkedIn 服务条款,请保持低频率。见 .agents/skills/linkedin-search/SKILL.md。
freehire-search —— 查询 freehire.me 聚合器的公开 REST API(JSON,无需 API 密钥)。聚焦技术领域(软件、数据、工程、DevOps、远程),通过方面标志(--region、--country、--remote)支持多市场,且结果以结构化形式返回(技能、资历、类别)。后端采用 MIT 许可证并可自托管——如果需要可将 FREEHIRE_API_URL 指向你自己的实例。见 .agents/skills/freehire-search/SKILL.md。
Extending the framework: portals, templates, criteria - and borrowing from other forks
以上所有内容共同构成了一种扩展模型,所以在此明确陈述。框架有三个扩展点,且均无需触碰上游:
Portal skills —— 招聘网站模块系统。每个 *-search 技能都是一个自包含的文件夹,位于 .agents/skills/ 下,具有相同契约(搜索/详情 CLI、--format json|table|plain 输出、SKILL.md 中的 enabled: 标志、独立的测试)。/scrape 自动发现任何遵循契约的已安装技能——无需注册,无需接线。/add-portal 生成新的;社区 portal 索引编目其他 fork 构建的那些。
Document templates —— /add-template 注册任何可通过命令行编译为 PDF 的简历或求职信工具链,无论 LaTeX 或其他。
Evaluation criteria —— 你个人资料中的 deal-breakers 和偏好是自由格式的,评估量表会针对你设定的内容打分。"强育儿假条款"、"按工会标准最低薪资 X"、"无需值班"——每条都是一条个人资料,无需代码,在 /rank 和 /apply 的匹配度评估中具有真实权重。语言是唯一有专门、结构化处理 deal-breaker 类型:/setup 捕获你工作的每种语言及你的水平(直接询问,或从 CV/LinkedIn 导出推断),存入 Languages 表,Language Gate(04-job-evaluation.md)会硬性拒绝要求你未声明语言的岗位,同时——而非自动拒绝——对要求你声明但水平不足的语言进行标记。