ai-job-search
基于 Claude Code 的全自动求职框架,从简历定制、求职信撰写到面试准备一站式完成。亮点:作者亲身使用并成功找到工作,69份申请换来20次面试并签约,可信度高;采用 drafter-reviewer 双 agent 协作与 PDF 编译验证,确保输出质量;支持多国职位搜索与自定义模板。独立开源项目,无加密货币关联。
README
AI Job Search
运行在你机器上的求职助手。
一个基于 Claude Code 构建的 AI 驱动求职申请框架。Fork 它,填写你的个人资料,让 Claude 评估招聘信息、定制你的简历、撰写求职信,并为面试做好准备。
注意:这是一个独立的开源项目,与 Anthropic 无关联、未获得其认可、赞助或维护。提及 Anthropic 和 Claude Code 仅用于描述此工作流所使用的工具链。
本项目没有关联的加密货币、代币或付费赞助计划。任何声称相反的表述均未经授权,应视为诈骗。支持本项目的唯一途径是下方的 Ko-fi 链接以及在 GitHub 上贡献代码。
它真的有效吗?
我原本是一名地球物理学家。当我的职位在 2025 年底被裁撤后,我构建了这个框架来管理自己的求职——也就是这个仓库中每周使用一次的 /scrape、/apply 和 /interview 工作流,用于我自己的职业生涯。我与每位面试官都坦诚相告,结果这非但没有成为减分项,反而常常引发一场真正的技术讨论。
69 份定制申请、20 次初面、一份签署合同之后,我于 2026 年 6 月成为了一名 AI 工程师。人们不断追问这是否真的有效。它确实帮我找到了工作。现在,它属于你了。
包含完整申请漏斗的详细版本,请参见 LinkedIn。
如果这为你省下了一个写求职信的周日,不妨请杯咖啡。
如果它帮你拿到了工作,或许两杯。 ☕
这是什么
一个结构化的工作流,将 Claude Code 转变为全栈求职申请助手。核心工作流(自我描述、匹配度评估、起草-审核申请流水线)是与语言和国家无关的。职位门户搜索技能是为丹麦市场(Jobindex、Jobnet、Akademikernes Jobbank 等)构建的,但该模式设计为可替换为你本地的招聘网站。
/setup /scrape /apply <url>
| | |
v v v
填写 搜索职位 评估匹配度
个人资料 职位门户 评分 & 推荐
| | |
v v v
个人资料 展示匹配结果 起草简历 + 求职信
文件就绪 带匹配度评级 (LaTeX, 定制)
| |
v v
选择一个匹配项 审核 agent 进行批评
-> /apply -> 修改 -> 最终输出
该框架编码了职业指导的最佳实践,包括结构化评估标准、前瞻性求职信框架以及可选的薪资基准比较。
前提条件
- Claude Code(命令行界面)
- Python 3.10+
- Bun(用于求职搜索 CLI 工具)
- 支持
lualatex和xelatex的 LaTeX 发行版:TeX Live、MacTeX、TinyTeX 或 MiKTeX。简历使用lualatex编译(在较新的 MiKTeX 安装上,pdflatex 常因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 可解析性检查。如果缺失,该检查会优雅降级为视觉关键词审查。
快速开始
1. Fork 并克隆
gh repo fork MadsLorentzen/ai-job-search --clone
cd ai-job-search
2. 安装求职搜索工具
PowerShell:
$tools = @("jobbank-search", "jobdanmark-search", "jobindex-search", "jobnet-search", "linkedin-search", "freehire-search")
foreach ($tool in $tools) {
Set-Location ".agents/skills/$tool/cli"
bun install
Set-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 && cd ../../../..
done
对于 linkedin-search 和 freehire-search,安装是可选的:两者都为零运行时依赖,直接使用 bun 即可运行;bun install 仅拉取 TypeScript 开发类型声明。
3. 设置个人资料
claude
# 然后在 Claude Code 中:
/setup
/setup 提供三种方式:读取你的 documents/ 文件夹(如果你已填充了简历 PDF、LinkedIn 导出文件、学位证书、推荐信、过往申请),导入粘贴到聊天中的单份简历,或者通过访谈逐步填写。它会自动检测你已有的内容并询问。文档文件夹模式是幂等的,可以安全地重复运行,以添加更多材料;布局请参见 documents/README.md。
4. 搜索职位
/scrape
这会搜索多个职位门户,寻找与你的个人资料匹配的职位,去重结果,并按匹配度排序显示。选择一个匹配项,直接对其运行 /apply——或者,当抓取结果过多时,先运行 /rank 对所有结果进行批量评分,获取一个排序后的短名单。
5. 申请职位
/apply https://jobindex.dk/job/1234567
如果无法获取该 URL(某些招聘网站会阻止自动化访问),你可以直接粘贴职位描述:
/apply <在此处粘贴完整的职位描述>
这会运行完整的工作流:评估匹配度、起草简历 + 求职信、由第二个 agent 进行审核、修改,并呈现最终输出。
其他命令
/setup、/scrape 和 /apply 构成了核心工作流。一旦你的个人资料就绪,还有七个扩展命令:
/interview针对已追踪申请中已安排的面试,为你提供准备。它会根据该申请的存档(确切的招聘信息、面试官实际看到的简历和求职信、之前轮次记录的反馈)构建一个针对特定阶段的准备包,研究公司和面试官(遵循“核实后再使用”规则),将可能的问题映射到你的 STAR 示例,并提供遵循07-interview-prep.md中角色扮演协议的模拟面试。对于差距,会给出诚实的过渡性回答,绝不编造经历。/outcome记录申请的结果——面试阶段、录用、拒绝、无回应。它会将提交的简历、求职信和招聘信息文本归档到documents/applications/<公司>_<职位>/中,以/setup路径 A 可解析的格式保存outcome.md,并更新追踪器。当一些申请得到结果后,它会指引你回到/setup,根据实际获得面试的申请来校准匹配度框架。/rank连接/scrape和/apply:对所有新抓取的招聘信息进行批量评分(并行 agent 获取每则招聘信息并评分五个评估维度),返回一个排序后的短名单,并针对每个职位诚实地列出优势和差距。一票否决项会被否决,截止日期会被标记紧急标志,已过期的招聘信息会被标记为失效。选择一个编号即可进入完整的/apply工作流。/expand通过扫描你在个人资料中已链接的公开来源(GitHub 仓库、作品集网站、Kaggle、Google Scholar)并查找命名的课程和认证的教学大纲,来丰富你的个人资料。发现的能力会以来源标签添加到你的个人资料中。在/setup之后立即运行此命令很有用,可以挖掘文档本身未明确列出的技能。/upskill分析你的个人资料与你追踪的招聘信息(或通过/upskill <URL>分析的单个招聘信息)之间的差距。生成一个优先级排序的技能差距热图,以及包含通过网络搜索到的学习资源和时间估计的学习计划。对于在申请之间进行职业规划很有用。/add-template注册你自己的 LaTeX 简历或求职信模板,替换默认模板。它会捕获模板的指令(编译引擎、字体、样式规则、页数限制),运行强制测试编译,并将模板接入到/apply中。参见下面的 LaTeX 模板。/add-portal为你所在市场的招聘网站生成一个职位搜索技能。它会调查该门户(搜索 URL 模式、结果结构、访问规则),按照与已提供技能相同的结构搭建 CLI 技能,并在注册前进行实时查询测试运行。参见下面的 求职搜索工具。
/reset 也可用,参见下面的 重新开始。
文件结构
ai-job-search/
├── CLAUDE.md # 主要候选人资料 + 工作流规则
├── .claude/
│ ├── commands/
│ │ ├── apply.md # /apply 工作流(起草者-审核者)
│ │ ├── setup.md # /setup 入职指导(文档文件夹、简历导入或访谈)
│ │ ├── expand.md # /expand 从文档和在线形象进行能力丰富
│ │ ├── add-template.md # /add-template 注册自定义 LaTeX 模板
│ │ ├── add-portal.md # /add-portal 为你所在市场生成职位搜索技能
│ │ ├── rank.md # /rank 将抓取的职位分类为排序短名单
│ │ ├── outcome.md # /outcome 记录申请结果,归档材料
│ │ ├── interview.md # /interview 针对特定阶段的准备包 + 模拟面试
│ │ └── reset.md # /reset 清除个人资料数据或文档文件夹
│ ├── skills/
│ │ ├── job-application-assistant/ # 核心申请技能
│ │ │ ├── SKILL.md # 技能定义
│ │ │ ├── 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.dev 技术职位聚合器(多市场,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 冒烟编译、技能 lint、CLI 类型检查
├── salary_lookup.py # 薪资基准比较工具(自带数据)
├── tools/
│ ├── convert_salary_excel.py # 将薪资 Excel 转换为 JSON
│ ├── lint_skills.py # CI 对 skills、commands、settings.json 进行 lint
│ ├── security_guards.py # CI 守卫:权限白名单、gitignore 规则、清单
│ └── README_SALARY_TOOL.md # 薪资工具设置说明
├── job_scraper/ # 爬虫状态(已见职位、结果)
├── upskill/ # /upskill 报告输出(每次运行的 markdown 报告)
├── job_search_tracker.csv # 申请追踪电子表格
└── SETUP.md # 详细设置指南
/apply 如何工作
/apply 命令运行一个起草者-审核者工作流,并强制进行 PDF 编译:
- 解析 职位信息(URL 或文本)
- 评估匹配度 与你的个人资料对比(技能、经验、文化、地点、职业一致性)
- 起草 一份定制的 LaTeX 简历和求职信
- 生成一个审核 agent,研究公司并批评草稿
- 根据审核者的反馈进行修改
- 编译并检查两个 PDF:简历使用 lualatex,求职信使用 xelatex。Claude 读取渲染后的页面,并迭代修改 LaTeX,直到简历正好 2 页,没有孤立的条目标题;求职信正好 1 页,签名可见且字体一致。
- 对简历进行 ATS 检查:提取 PDF 的文本层(
pdftotext,可选依赖),并验证 ATS 解析器看到的内容——联系方式作为文字存在、无乱码字符、阅读顺序正常——然后根据提取结果对招聘信息的关键词覆盖率进行评分。个人资料真正支持的关键词才会被添加;真正的差距会保持可见,绝不强行填充。 - 呈现 最终输出,并附带验证检查清单。
简历和求职信中的所有声明都会根据你的实际个人资料进行验证。系统永远不会虚构技能或经验。
这个工作流有何不同
- PDF 验证循环。 大多数 LaTeX 简历模板会生成“在 .tex 中看起来不错”但在 PDF 中出问题的输出:职位标题孤立到下一页、求职信溢出到第 2 页、项目符号字体静默回退到正文字体。
/apply命令会编译并视觉检查每个 PDF,并应用有针对性的修复(\needspace、\enlargethispage、用于列表项的字体匹配包装器),直到布局干净。这会在每次申请时自动运行。 - 在 PDF 文本层上进行 ATS 验证。 ATS 读取的是 PDF 中嵌入的文本,而不是渲染后的页面——而 LaTeX 可能会静默生成文本提取为垃圾的 PDF(图标字形代替了电子邮件、多列布局导致行交错)。
/apply使用pdftotext提取编译后简历的文本层,并验证联系方式、阅读顺序以及解析器实际看到的关键词覆盖率。强制执行诚实规则:个人资料不支持的关键词被承认为差距,绝不强行填充。 - 相关性加权简历裁剪。 当简历超出 2 页时,工作流不会机械地从“最旧”部分开始裁剪。它会根据(a)与目标职位的相关性、(b)在文档中的唯一性,以及(c)求职信是否依赖它,对每个候选条目进行评分,并首先裁剪总分最低的条目。较旧职位中与招聘信息关键词匹配的条目,会比较新职位中不匹配的条目更优先保留。
- 起草者与审核者分离。 起草者撰写;第二个 Claude agent 以全新上下文生成,研究公司并批评草稿。然后起草者进行修改。这能捕捉到单次通读时容易遗漏的关键词缺失、薄弱表述和通用语言。
- Token 高效的审核者调度。 审核 agent 直接接收内联草稿,无需重新读取,验证检查清单在工作流结束时只运行一次,而不是被两个 agent 重复执行。注意:第 5 步中新增的编译-检查步骤会消耗部分节省的 token 用于 PDF 渲染和布局迭代——工作流以端到端 token 成本的一点增加,换取了实际送达用户的中断 PDF 数量减少。
自定义
哪些文件需要手动编辑
如果你更倾向于直接编辑文件而不是使用 /setup:
| 文件 | 需要修改的内容 |
|---|---|
CLAUDE.md |
你的完整个人资料(姓名、教育、经验、技能、目标) |
01-candidate-profile.md |
简历数据的结构化版本 |
02-behavioral-profile.md |
你的行为评估或自我评估 |
04-job-evaluation.md |
技能匹配领域、职业目标、动机筛选条件 |
05-cv-templates.md |
针对不同职位类型的个人简介模板 |
07-interview-prep.md |
你实际经历中的 STAR 示例 |
search-queries.md |
针对你的技能和地点的职位搜索查询 |
更新搜索查询
随着你的优先级变化,你可以仅重新配置职位搜索,而无需重新运行完整的个人资料设置:
/setup --section search
这会重新运行搜索配置访谈:目标职位、搜索哪些技能、哪些地点、哪些门户。它还会根据你的个人资料,建议你可能未考虑过的职位类型。
LaTeX 模板
简历使用 moderncv(banking 样式)。求职信使用自定义的 cover.cls,包含 Lato/Raleway 字体。
要使用你自己的模板,运行:
/add-template
将其指向你的 .tex 文件(以及任何 .cls/.sty 文件或捆绑字体)。该命令会询问你模板的指令——编译引擎、字体及其位置、要保留的样式规则、硬性页数限制——将所有内容存储在 templates/ 下,运行强制测试编译,并激活模板,使 /apply 使用它进行起草。模板中的个人数据以 [PLACEHOLDER] 标记存储,因此可以安全地提交和共享。
/add-template --list显示已注册的模板/add-template --use <name>在它们之间切换/add-template --use default恢复到默认的 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?请将其添加到 社区 Fork 与适配 讨论帖中,以便其他人找到。
对于丹麦以外的国家无关的起点,该仓库除了丹麦演示工具外,还提供了两个门户技能:
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.dev 聚合器的公开 REST API(JSON,无需 API 密钥)。专注于技术岗位(软件、数据、工程、DevOps、远程),通过分面标志支持多市场(--region、--country、--remote),零运行时依赖。与使用 HTML 抓取的丹麦门户不同,结果以结构化形式返回(技能、资历、类别)。后端是 MIT 许可的,可自行托管——如果愿意,可以将FREEHIRE_API_URL指向你自己的实例。参见.agents/skills/freehire-search/SKILL.md。
薪资基准比较
薪资工具可与任何你提供的薪资数据一起使用(工会统计数据、Glassdoor 导出、个人研究等)。有关预期格式和设置,请参见 tools/README_SALARY_TOOL.md。如果你没有薪资数据,薪资步骤会被跳过。
重新开始
要清除个人资料数据并重新开始:
/reset profile # 清除技能文件,保留框架规则
/reset documents # 删除 documents/ 文件夹中的文件
/reset all # 两者都做
/reset 会精确显示将要删除的内容,并要求你输入 RESET 确认。在你确认之前,不会删除任何内容。
获得更好结果的小贴士
个人资料的深度至关重要
影响输出质量的最大因素是你在个人资料中投入的细节量。单薄的资料会产生通用的申请;详细的资料才能带来真正定制的结果。
- 职位描述: 不要只列出职位头衔。描述你在每个职位中实际做了什么:具体项目、使用的工具、职责和可衡量的成就。你提供的材料越多,系统就能越精确地针对不同职位重新定位你的经验。
- 上下文中的技能: 不要只列出“Python”或“项目管理”,描述你如何以及在何处应用了它们。“使用 Python 和 scikit-learn 构建了用于客户流失预测的机器学习管道”比“Python,机器学习”提供了多得多的信息。
- 所有入职路径都有效: 无论你让
/setup读取你的documents/文件夹、粘贴一份简历,还是通过访谈逐步填写,原则都是一样的:更丰富的输入产生更精准的输出。
职业路径发现
该框架支持两种不同的求职模式:
- 明确目标: 你知道自己想要什么职位或行业。系统帮助根据匹配度进行优化和优先级排序。
- 潜在机会发现: 通过分析你的完整经历(不仅仅是职位头衔,还有你实际做过的工作),系统可以发现你未曾考虑过的职业路径。可迁移技能映射到意想不到的行业、你在工作中享受或擅长的模式,或者将你的领域专业知识与新技术相结合的新兴职位。
要充分利用这一点,请在 /setup 期间投入时间描述不仅仅是你的经验,还有哪些工作让你充满活力、哪些让你疲惫,以及你希望获得更多什么。这些上下文直接塑造了系统评估匹配度的方式,以及 /scrape 期间会浮现哪些职位。
贡献
考虑提交 PR?请先阅读 CONTRIBUTING.md——它说明了什么会被合并、什么存在于 fork 中,以及原因。
致谢
- Mikkel Krogholm (skills 仓库) 提供了求职搜索 CLI 技能
- 由 Anthropic 的 Claude Code 构建
许可证
MIT