| name | job-hunt |
| description | 求职猎手主入口。上传招聘平台岗位详情页截图(Boss直聘、智联招聘、前程无忧等均可),与你的简历做 STAR 匹配分析,生成定制简历和开场白,按匹配度排序产出 shortlist。支持子命令:fetch / analyze / tailor / status / clean。 |
job-hunt 求职猎手
⚡ 全流程自动执行约束(最高优先级,全程有效)
仅适用于 /job-hunt 无参数的全流程模式。
用户提供简历 + 截图确认后,剩余所有步骤全部自动连续执行,直到输出 shortlist。
- Step 3 fetcher 返回 → Step 7 之间:严禁输出任何文字。输出文字 = turn 结束 = 等待用户 = 流程中断
- 每一步结束后,立即调用下一步所需的工具(Skill / Bash / Read / Write),不插入任何文字
- 子 skill(fetcher / analyzer / tailor)的返回结果是内部数据,不得回显、不得复述、不得向用户展开汇报,直接用于下一步
- 禁止在步骤之间询问用户「是否继续」「要不要开始下一步」
违反上述约束 = 流程中断,用户体验完全崩溃。
子命令路由
根据用户输入判断执行路径:
| 用户输入 | 执行 |
|---|
/job-hunt 无参数 | 全流程(Step 1→7) |
/job-hunt fetch | 只执行截图导入(Step 1+2+3) |
/job-hunt analyze | 只执行分析(Step 1+4) |
/job-hunt tailor | 执行排序(Step 5)+ 定制(Step 6) |
/job-hunt status | 输出当前 run 状态(Step 7b) |
/job-hunt clean | 强制清理所有缓存和产物(Step 8) |
Step 1:确定工作目录与初始化
work_dir = Claude 启动时所在的当前目录(./ 的绝对路径)。
用 Bash 获取:pwd,将结果作为 work_dir。
data_dir = <data_dir>/jobHuntSkillData(所有数据文件统一放在这一层目录下,不直接写入 work_dir)。
确保以下目录存在(用 Bash mkdir -p 创建):
<data_dir>/.work/jd-pool/
<data_dir>/output/
生成 run_id(格式:YYYY-MM-DD-HHMM,使用当前本地时间)。
创建目录 <data_dir>/output/<run_id>/。
初始化 <data_dir>/output/<run_id>/state.json:
{
"run_id": "<run_id>",
"phase": "init",
"stages": {
"fetched": [],
"analyzed": [],
"analysis_errors": [],
"tailored": []
},
"last_error": null,
"checkpoint_at": "<当前 ISO 8601 时间>"
}
后续所有步骤中凡涉及路径的地方,一律使用 data_dir 代替 work_dir。传给子 skill 的 work_dir 参数也传入 data_dir 的值。
子命令特殊处理:若当前子命令为 analyze、tailor 或 status,在生成新 run_id 之前,先扫描 <data_dir>/output/ 下已有的 run 目录(格式 YYYY-MM-DD-HHMM),若存在则复用最新一个 run_id(不创建新目录,读取已有 state.json 继续使用);若不存在,则按上述流程创建新 run_id。
Step 2:获取简历
(全流程、fetch、analyze 子命令时执行)
检查 <data_dir>/.work/resume.md 是否存在:
若已存在:告知用户:
「已检测到上次保存的简历,继续使用。
如需更换简历,直接把新简历发给我(支持文件 / 路径 / 粘贴文本),我会帮你替换并重新评估。
如果继续用当前简历,告诉我「继续」。」
停止执行,等待用户回复:
- 用户发来新简历 → 按下方「若不存在」的方式处理,覆盖保存
resume.md,进入 Step 2.5 重新评估
- 用户说「继续」或其他非简历内容 → 跳过本步骤,跳过 Step 2.5,直接进入 Step 3
若不存在:提示用户提供简历:
「请提供你的简历,支持以下两种方式:
① 发送 .md 格式简历文件,或告诉我文件的本地路径(如 /Users/xxx/resume.md)
② 直接将简历文字粘贴到消息框发送(最快最稳,从任意 PDF/Word 阅读器全选复制即可)
不支持直接上传 PDF/Word 等版式文件——这类格式跨环境解析容易失真或失败。请用方式 ② 直接贴文本。」
根据用户提供方式处理:
-
发文件(.md)/ 文件路径(.md):用 Read 工具或 Bash 读取文件内容
-
发文件 / 文件路径(其他格式,如 .pdf / .docx / .doc / .txt / .rtf 等):不要尝试任何形式的解析,直接告知用户:
「暂不支持 PDF / Word 等版式文件上传(跨环境解析容易失真)。请改用:
① 用任意 PDF/Word 阅读器打开简历,全选(Cmd/Ctrl+A)→ 复制(Cmd/Ctrl+C)→ 粘贴到这里发给我
② 或将简历另存为 .md 格式后重发」
停止执行,等待用户重新操作
-
粘贴文本:按下方「粘贴文本处理流程」执行
⛔ 伦理硬约束:无论用户提供什么格式,绝对禁止凭空编造、想象、推断简历内容。识别不了的格式就停止流程让用户重传,绝不生成假简历。
.md 文件分支处理:读取内容后直接写入 <data_dir>/.work/resume.md,告知用户「✅ 简历已保存。」,进入 Step 2.5。
粘贴文本处理流程
仅当用户走「粘贴文本」分支时执行:
步骤 1:保存原始留底
将用户粘贴的原始内容(一字不改)写入 <data_dir>/.work/resume.raw.md。这是任何后续清洗的回滚备份。
步骤 2:启发式检测格式是否已 OK
判断粘贴文本是否「已是结构化 Markdown」,必须同时满足以下条件:
- 包含 ≥ 2 处章节标记(行首是
#、## 或 1. / 2. 这类有序列表标号)
- 包含 ≥ 2 处列表标记(行首是
- 或 * 或 + 后接空格)
- 平均非空行长度 ≥ 15 个字符(说明没被一行一词强行断开)
- 不存在大量"单字孤立行"(连续 5 行以上每行只有 1-3 字符的情况)
全部满足:直接把原始内容写入 <data_dir>/.work/resume.md,告知用户「✅ 简历已保存(格式良好,直接使用)。」,进入 Step 2.5。不询问、不清洗。
任一不满足:进入步骤 3。
步骤 3:询问用户选择
关键约束:
- 必须输出用户粘贴的完整简历原文(一字不少,不是预览、不是摘要、不是前 N 字截断)
- 简历原文之后才是 A/B 问题
- A/B 问题必须是整条消息的最后一段,让用户视线最后落点就是
👉 回复 A 或 B
- 简历原文之前不要写任何说明文字(如"以下是你的简历""收到了"等开场白)
- 简历原文用代码块(``` 包裹)显示,避免 Markdown 渲染干扰原始格式
输出格式严格如下:
```
<用户粘贴的简历完整原文,一字不动>
```
---
📝 上面是你粘贴的简历内容。看起来格式有些问题——可能存在断行、缺章节标记等,常见于从 PDF/Word 复制带过来的。
两种处理方式:
A. **帮我整理一下** —— 只动格式:合并被断开的同段、还原项目符号、加章节标题;**不动一个字**
B. **保留我的原始格式** —— 我就要这样,不要改
👉 回复 A 或 B
停止执行,等待用户回复。
禁止:
- 截断简历内容(即使简历很长也要全部贴出)
- 在 A/B 问题之后再追加任何文字
- 在简历原文上方加任何标题/说明(直接代码块开始)
步骤 4:按用户选择处理
- 用户回 A(或语义等价:「整理」「清洗」「帮我弄」「随便」等)→ 进入步骤 5 做结构归一化
- 用户回 B(或语义等价:「不动」「原样」「保留」「不要改」等)→ 把原始内容写入
<data_dir>/.work/resume.md,告知用户「✅ 已按你的原始格式保存。」,进入 Step 2.5
- 用户回模糊内容(如「?」「啥意思」)→ 简短重新解释一次 A/B 含义,再等回复
- 用户直接发了新简历→ 当作重新粘贴处理,回到步骤 1
步骤 5:执行结构归一化(仅 A 路径)
严格只动格式,不动一个字。允许做和绝对禁止做的清单:
✅ 允许做:
| 操作 | 说明 |
|---|
| 合并被强行断开的同句行 | 负责抖音\n小视频\n前端开发 → 负责抖音小视频前端开发。判断标准:上一行不以句末标点结尾(。!?.!?)且下一行不像新章节/列表项的开始 |
| 合并被拆散的标题/姓名 | 张\n三 → 张三;工作经\n历 → 工作经历 |
| 移除连续空行 | 3 个及以上连续空行 → 保留 1 个 |
| 还原项目符号 | 段首孤立的 · ● ▪ ◦ ▶ → 替换为 - |
| 还原章节标题层级 | 识别"个人信息""工作经历""项目经历""项目经验""教育背景""专业技能""自我评价"等常见章节关键词,在前面加 ## |
| 规范缩进 | tab 字符 → 2 空格;行首过多空格统一为 2 空格倍数 |
| 修复编码异常 | 删除零宽字符 等不可见字符 |
| 删除明显多栏混排导致的乱序片段 | 仅当能 100% 确定是多栏问题且能正确还原时;不确定就不要动 |
❌ 绝对禁止:
- 增加、删除、改写任何文字内容(哪怕一个字)
- 修正错别字(用户写「杭洲」就保留「杭洲」)
- 翻译、总结、精简、扩写
- 根据上下文推断补齐缺失信息
- 添加用户没提的章节、技能、经历
- 改变事件顺序、时间、数字
违反任何一条 ❌ 即触发伦理硬约束告警,必须停止并告知用户。
清洗完成后:
- 把清洗结果写入
<data_dir>/.work/resume.md
- 简短告知用户清洗量:「📝 已整理简历格式:合并 N 处断行 / 还原 M 个项目符号 / 加 K 个章节标题。原始版本已留底(如不满意可说"还原原版")。」
- 进入 Step 2.5
用户事后反悔(任何阶段)
当用户在后续流程中说出「还原原版」「用原版」「用我贴的那版」「不要清洗后的」等语义等价指令时:
- 检查
<data_dir>/.work/resume.raw.md 是否存在
- 不存在 → 告知「未找到原始留底版本(可能本次简历没经过清洗)。如需更换,直接重新粘贴或发送新简历。」
- 存在 → 用 Bash 把
resume.raw.md 复制覆盖到 resume.md
- 告知用户「✅ 已切回原始版本。」
- 重新进入 Step 2.5 评估
Step 2.5:简历质量评估
(仅在用户本次会话中新提供了简历时执行;复用缓存的直接跳到 Step 3)
读取 <data_dir>/.work/resume.md,找出所有可评估单元,逐一打分,输出结果。
⛔ 必须先过滤,再评估。以下三条规则是强制先决条件,不允许跳过或绕过:
- 在任何评估行为之前,必须完成规则一→二→三的完整筛选流程
- 不得根据公司名、职位名、部门名推断该段经历的工作内容进行评估——评估对象只能是简历中白纸黑字写出的行动动词和结果描述
- 只有通过规则三的文字内容,才能出现在「逐段分析」中;未通过筛选的区块/行,一律不出现
三条判断规则,按顺序执行:
规则一:整个区块跳过(不看内容,直接略过)
下列区块不论写了什么,整体跳过,不评估:
- 个人信息 / 基本信息 / 联系方式
- 专业技能 / 技能特长 / 技术能力 / 工具使用 / 技术栈
- 教育背景 / 教育经历 / 学历
- 自我评价 / 个人简介 / 求职意向
- 证书 / 奖项 / 荣誉
区块名不限于以上文字,只要语义属于上述类型(如「我的技能」「掌握的工具」「所获奖励」),同样整体跳过。
⚠️ 合并区块的处理:如果区块名同时包含工作和教育(如「工作及教育经历」「教育与工作背景」),不整体跳过,进入规则二逐行判断。其中属于教育条目的行(含学校名、专业名、学位、在校时间)按规则二同样会被跳过。
其他所有区块(工作经历、项目经历、实习经历、创业经历、兼职经历,或任何自定义名称的经历类区块)进入规则二。
规则二:区块内的标题行跳过
经历类区块内,每一行单独判断。如果这一行同时满足以下两点,跳过:
- 没有行动动词(负责、主导、设计、推动、搭建、优化、完成、实现、带领等)
- 没有结果描述(提升、降低、增长、减少、达到、超过、节省,或具体数字/百分比)
⚠️ 重要:职位名、部门名中含有的动词性词语不算行动动词。 例如"运营组""品牌部""设计科""管理岗"——这些是组织单元的名称标签,不是对个人行为的描述,不触发评估。判断依据是:这个词是在描述「这个人做了什么」,还是在说明「这个部门/岗位叫什么名字」。
例如:
- 「字节跳动 · 产品经理 · 2021.03—2023.06」→ ❌ 跳过(无动词无结果)
- 「某文化传媒公司 2023.7~2025.11 新媒体-运营组」→ ❌ 跳过("运营"是部门名,不是行动描述)
- 「某互联网科技公司 2022.6~2023.6 市场部-品牌组」→ ❌ 跳过("品牌"是部门名,不是行动描述)
- 「xx大学 2018.9~2022.6 新闻传播专业-本科」→ ❌ 跳过(教育条目,无行动无结果)
- 「项目名称:xxx 平台 | 角色:负责人 | 2022.01—2022.06」→ ❌ 跳过(无动词无结果)
⚠️ 空区块规则(规则二执行完后立即检查)
若某经历类区块经规则二处理后,全部行均被跳过(即该区块内无任何行含有行动动词或结果描述),则该区块不进入下方三维度打分,不得为该区块生成任何评估条目,也不得从其他区块借调内容来填充。
典型场景:「工作及教育经历」区块内只有公司名+时间+部门名三行头部信息,规则二全部跳过后,该区块不参与逐段打分。
📛 但空壳的工作/实习经历不能静默消失,必须显著警示:
在跳过这类区块时,记录其中属于工作/实习经历的空壳条目(公司名 + 时间段,例如「某文化传媒公司 2023.7~2025.11」)。只要存在至少一条,就必须在评估输出最顶部输出「空壳经历警示」块(见下方输出格式)。
原因:空壳工作经历是简历最致命的短板,且 tailor 阶段无法为它做任何改写(伦理红线禁止编造内容)。若这些空壳覆盖了用户的主要工作年限,补全它们比任何简历定制都重要——必须让用户清楚看到,而不是让它默默消失。教育条目空壳不在此警示范围(教育经历本就无需行动/结果)。
规则三:剩下的内容才评估
通过前两条规则筛选后剩下的句子/条目,即为可评估单元,进入下方三维度打分。
⚠️ 标题行与描述混写在同一行时,按规则二判断:只要含有行动动词或结果描述,就评估。
- 「在字节跳动担任产品经理期间主导了 xx 项目落地,DAU 提升 40%」→ ✅ 评估(含动词+结果)
评估维度
⛔ 只有通过上方规则三筛选的内容才能进入此步骤。 若某区块(如「工作及教育经历」)内所有行均被规则二跳过,该区块整体不生成任何评估条目——即使你能判断那是一段工作经历,也不评估,因为简历里没有写任何行动或结果。
每段描述内容按以下三个维度打分(✅ 合格 / ⚠️ 薄弱 / ❌ 缺失):
| 维度 | ✅ 合格 | ⚠️ 薄弱 | ❌ 缺失 |
|---|
| 场景/问题(S/P) | 有明确业务背景或要解决的问题 | 背景模糊,一笔带过 | 无任何场景描述 |
| 行动(A) | 具体描述「我做了什么」,有方法/手段 | 只写职责,没有行动细节 | 缺失 |
| 结果(R) | 有量化数字,或明确的业务价值 | 结果模糊(如"效果不错") | 无结果描述 |
额外检查:
- 是否大量使用「负责」「参与」「协助」等被动词(减分项,建议改为主动动词)
- 是否有明显可量化但留白的指标(tailor 阶段会插入
[请填写:xxx] 占位)
输出格式
📋 简历质量评估
<【仅当检测到空壳工作/实习经历时,在最顶部输出此块;否则整块省略】
⚠️ 重要提醒:你有 <N> 段工作经历是空的
· <公司名> · <时间段>
· <公司名> · <时间段>
这几段只有公司名和时间,没写任何工作内容和成果。这是你简历最大的短板:
- 系统算匹配度时,这些经历因为没内容会被整体跳过,匹配分会明显偏低
- 定制简历时,AI 不会替你编造内容(伦理红线),这几段只能原样保留、无法优化
👉 补全这几段的「做了什么 + 拿到什么结果」,比任何简历定制都重要。强烈建议先选 A 补这部分。
>
整体:<一句话总结,如"行动描述较充分,但结果量化普遍缺失,建议优先补充">
逐段分析:
【公司名 · 职位名】
场景/问题 ✅ 行动 ⚠️ 结果 ❌
问题:<具体说明薄弱点>
建议:<一句话改写方向>
【项目名 · 角色】
场景/问题 ⚠️ 行动 ✅ 结果 ⚠️
问题:<说明>
建议:<建议>
(…其他段落)
⚡ 最值得优先改的 1-2 件事:
1. <最高优先级>
2. <次优先级>
🔧 专业技能板块诊断:
<独立于上方 STAR 评估,专项检查技能板块(语义识别板块,任意名称均适用;若无标题,按内容特征识别:连续排列的技能词/工具名/框架名)。按以下四类问题逐一检查,有问题输出具体条目,无问题省略该类;若整个技能板块无任何问题,省略「🔧 专业技能板块诊断」整节:>
- **虚浮词/空泛声称**:「精通」「熟练掌握」后面没有具体场景或工具,或「精通所有前端技术」这类大而无当的表述。
针对每条有问题的条目给出**改写示范**,例:
「精通 Python」→「熟练使用 Python(Flask/pandas,用于 xx 数据处理)」
- **缺工具名/过于宽泛**:只写了能力方向,没有写具体工具/平台/框架。例「熟悉数据分析」「了解前端开发」。
针对每条给出建议补全方向,例:
「熟悉数据分析」→「熟悉数据分析(SQL / Tableau / Power BI)」
- **无程度分层**:全部条目都是同一程度词(全是「熟悉」或全是「精通」),无法体现能力深浅。
如有此问题,提示按「熟练 / 熟悉 / 了解」或用户实际情况重新分级。
- **与目标岗位明显偏差**:<此项留空,tailor 阶段结合具体 JD 再给建议;Step 2.5 无 JD 上下文,不评估此项>
<仅当上述四类至少有一类有实质问题时,才输出「🔧 专业技能板块诊断」节;若技能板块写得合理(程度词有分层、有工具名、无大量空泛声称),整节省略,不输出任何占位文字。>
---
如何继续?
A. 我自己去改简历,改完发给你重新评估
B. 先不改,用当前简历继续
用户选择处理
选 A(修改简历):
- 告知用户:「好的,修改完后直接把新简历发给我(支持文件 / 路径 / 粘贴文本)。」
- 停止执行,等待用户重新发送简历
- 收到后按 Step 2 同样方式处理,覆盖保存
resume.md
- 重新执行 Step 2.5(循环,直到用户选 B)
选 B(继续):
Step 3:岗位收集与导入
(全流程、fetch 子命令时执行)
提示用户:
「请上传你感兴趣的岗位,支持以下方式:
【方式一】直接发岗位详情页截图(任意招聘平台,Boss/智联/猎聘/拉勾等)
一次可发多张,📌 一张截图 = 一个岗位
岗位信息长请用长截图,截图里至少要有岗位名(公司名可选)
【方式二】告诉我截图所在的目录路径(如 /Users/xxx/Desktop/jobs)
我会自动读取该目录下的所有图片,以及 .jobs.json 文件(不递归子目录)
【方式三】用浏览器插件导出 .jobs.json 文件后一键拖进来(支持 Boss直聘 / 前程无忧 / 智联招聘 / 猎聘)
👉 没装插件?查看 README 安装说明」
发出上方提示后,停止执行,等待用户发送截图或消息。不得提前进入循环。
判断用户输入类型:
| 输入 | 处理分支 |
|---|
| 图片附件(一张或多张) | 分支 A:截图解析 |
文件路径,以 .jobs.json 结尾 | 分支 C:JSON 导入 |
| 目录路径 | 分支 B:扫描目录(图片 + .jobs.json 混合) |
分支 A:截图解析
调用 Skill 工具,加载 job-hunt-fetcher skill,传入:
work_dir:<data_dir 的值>
run_id:<当前 run_id>
screenshots:<本批次截图>
fetcher 内部处理(含分组确认交互),完成后写入 jd-pool。
分支 B:扫描目录
用 Bash 验证目录存在:
ls "<目录路径>"
若不存在,告知用户「目录不存在,请确认路径后重新发送。」并重新等待。
用 Bash 列出该目录下的图片文件和 .jobs.json 文件(只读当前目录,不递归子目录):
find "<目录>" -maxdepth 1 -type f \( -iname "*.png" -o -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.webp" -o -iname "*.jobs.json" \) | sort
若结果为空,告知用户「该目录下没有找到图片或 .jobs.json 文件,请确认后重新发送。」并重新等待。
告知用户找到了哪些文件:「找到 张截图 + 个 .jobs.json 文件,开始处理。」
按文件类型分别处理:
- 图片 → 分支 A(调 fetcher)
- 每个 .jobs.json → 分支 C(调 import_jobs.py)
分支 C:JSON 导入
用 Bash 调用 import_jobs.py:
if command -v python3 >/dev/null 2>&1; then PYBIN=python3; \
elif command -v python >/dev/null 2>&1; then PYBIN=python; \
else echo "PYTHON_MISSING"; exit 1; fi
"$PYBIN" "$HOME/.claude/skills/job-hunt/import_jobs.py" "<data_dir>" "<json_path>"
预期 stdout:
OK: 已导入 N 个岗位 -> ... → 成功,继续
ERROR: ... → 告知用户「.jobs.json 处理失败:<原因>。请检查文件后重发。」并重新等待
PYTHON_MISSING → 告知用户「需要 Python 3 才能处理 .jobs.json,请安装后重试。」并停止
公共后续
不论分支 A/B/C,全部处理完成后:
用 Bash 工具扫描 <data_dir>/.work/jd-pool/ 下所有 .md 文件(排除 .analysis.md),读取 frontmatter 中 run_id 等于当前 run_id 的文件(extension-import 也包含),提取其 id 字段,作为本批次 ID 列表;将 ID 列表追加到 state.json 的 stages.fetched,更新 checkpoint_at 和 phase 为 "fetched"。
若子命令为 fetch:告知用户「✅ JD 导入完成,共 个岗位。运行 /job-hunt analyze 开始分析。」并停止。
【全流程】⚠️ 本步骤完成后到 Step 7 之间,严禁输出任何文字(包括不得回显或复述子 skill 的输出内容)。state.json 更新完毕后,下一个动作必须是 Skill 工具调用(执行 Step 4),不得有任何文字夹在中间。
Step 4:分析(job-hunt-analyzer)
(全流程、analyze 子命令时执行)
确定待分析 JD 列表:
- 扫描
<data_dir>/.work/jd-pool/ 下所有 .md 文件(排除 .analysis.md 结尾的文件)
- 读取每个文件的 frontmatter,筛选
status.analyzed: false 的文件,提取其 id 字段
- 排除
state.json.stages.analysis_errors 中已记录失败的 ID
若列表为空,告知用户「jd-pool 中没有待分析的 JD,请先上传截图。」并停止。
调用 Skill 工具,加载 job-hunt-analyzer skill,传入:
work_dir:<绝对路径>
resume_path:<data_dir>/.work/resume.md
jd_ids:<待分析 JD ID 列表>
preferences:{"soft_preferences": {"prefer_industries": [], "avoid_industries": [], "prefer_company_size": []}, "ranking": {"match_weight": 1.0, "preference_weight": 0.0}}
run_id:<当前 run_id>
analyzer 返回后,用 Bash 工具更新 state.json phase 为 "analyzed"。
【全流程】⚠️ 不得回显或复述 analyzer 的返回内容,state.json 更新完毕后立即执行 Step 5,不得有任何文字输出。
Step 5:排序
(全流程或 tailor 子命令前执行,不调用 LLM)
⚠️ 本步骤全程使用 Bash / Read 工具操作,严禁输出任何文字(包括排序过程、中间结果、排名列表)。
用 Bash 读取 <data_dir>/.work/jd-pool/*.analysis.md,提取每个文件中的 scores.total 字段,按降序排列,得到 JD ID 有序列表。所有已分析 JD 全部参与排序,不截断。
用 Bash 将排序结果写入 state.json 的 stages.sorted_ids 字段,同时保留在内存中供 Step 6 直接使用。Step 6 断点续跑时,若内存中无排序结果,从 state.json.stages.sorted_ids 读取。
【全流程】⚠️ state.json 更新完毕后立即调用 Skill 工具执行 Step 6,不得有任何文字输出。
Step 6:定制简历(job-hunt-tailor)
(全流程或 tailor 子命令时执行)
检查 <data_dir>/.work/resume.md 是否存在,若不存在则执行 Step 2 获取简历流程后再继续。
取 Step 5 排序后的完整 JD ID 列表。
排除 state.json 中已在 stages.tailored 的(断点续跑时跳过)。
调用 Skill 工具,加载 job-hunt-tailor skill,传入:
work_dir:<绝对路径>
resume_path:<data_dir>/.work/resume.md
jd_ids:<完整排序后的 JD ID 列表>
run_id:<当前 run_id>
tailor 返回后,用 Bash 工具更新 state.json phase 为 "tailored"。
【全流程】⚠️ 不得回显或复述 tailor 的返回内容,state.json 更新完毕后立即执行 Step 7,不得有任何文字输出。
Step 7:生成 shortlist.html
(全流程最后一步,只产 HTML,不产 MD 文件)
执行顺序(严格按此顺序):
- 用 Bash 工具:探测 Python,调用
build_html.py 生成 shortlist.html
- 用 Bash 工具:更新
state.json 的 phase 为 "done"
- 最后一步:在聊天里输出一条简短的完成消息(只含 HTML 链接 + 操作提示,不再输出排名 MD 概览,因为 HTML 视图就是用来看这些内容的)
执行命令:
if command -v python3 >/dev/null 2>&1; then
PYBIN=python3
elif command -v python >/dev/null 2>&1; then
PYBIN=python
else
PYBIN=""
fi
if [ -n "$PYBIN" ]; then
"$PYBIN" "$HOME/.claude/skills/job-hunt/build_html.py" "<data_dir>" "<run_id>"
else
echo "PYTHON_MISSING"
fi
Bash 输出解析规则(决定最终向用户发的完成消息):
| 脚本 stdout 内容 | 状态 |
|---|
OK: ...(无论后续 OPENED 或 OPEN_FAILED) | HTML 生成成功,提示用户复制链接到浏览器打开 |
SKIP: template not found | 模板文件缺失(极少发生,提示重装) |
PYTHON_MISSING | 系统没装 Python 3,引导用户安装(流程失败,因为现在只产 HTML) |
ERROR: ...(stderr) | 其他错误,告知用户排查 |
脚本设计原则:
- LLM 完全不构造 JSON,由脚本自己扫描 jd-pool / tailored 目录读取所有字段
- 空文件优雅处理:tailored 文件不存在 → 该字段为空字符串
- 模板缺失优雅降级:template.html 不存在 → 打印
SKIP: 退出 0,主流程不中断
更新 state.json phase 为 "done" 之后,必须在聊天里输出最终消息——根据 Bash 输出的标记选对应文案。
最终消息文案(4 种分支):
-
HTML 生成成功(Python 脚本输出 OK: ...):
✅ 全部完成!共生成 <N> 份定制简历。
🌐 HTML 视图:file://<data_dir 绝对路径>/output/<run_id>/shortlist.html
💡 复制上面的 file:// 链接到浏览器地址栏打开,即可查看完整简历视图。页面支持:
· 按匹配度排序查看所有岗位
· 在网页上直接编辑简历(自动保存到浏览器本地)
· 一键导出为 PDF(中文字体跨平台一致)
· 切换查看每个岗位的简历 / 改动 / 开场白
其中 <N> 用 state.json.stages.tailored 数组长度填充。
-
HTML 模板缺失(Python 脚本输出 SKIP: ...):
⚠️ 流程已完成,但 HTML 视图未生成。
原因:未找到 ~/.claude/skills/job-hunt/template.html。
解决:请重新安装 skill(运行 install.sh 或 npx skills add)。
各岗位定制简历已写入:<data_dir 绝对路径>/output/<run_id>/tailored/
-
Python 不可用(Bash 输出 PYTHON_MISSING):
⚠️ 流程已完成,但 HTML 视图未生成。
原因:你的系统没有 Python 3。
📦 装上 Python 3 之后即可补生成 HTML 视图:
• Mac:终端跑 `xcode-select --install`(一次性,几分钟)
• Windows:访问 https://python.org/downloads/ 下载安装
⚠️ 安装时务必勾选「Add Python to PATH」
• Linux:通常已自带;若没有 `sudo apt install python3` 或 `sudo yum install python3`
装完之后,跑这条命令补生成 HTML:
python3 ~/.claude/skills/job-hunt/build_html.py "<data_dir 绝对路径>" "<run_id>"
各岗位定制简历已写入:<data_dir 绝对路径>/output/<run_id>/tailored/
-
其他错误(脚本 stderr 输出 ERROR: ...):
⚠️ HTML 生成失败。错误信息:<stderr 内容>
各岗位定制简历已写入:<data_dir 绝对路径>/output/<run_id>/tailored/
请检查文件或重新运行。
⚠️ 关键约束:
- file:// 链接不要用反引号包——纯文本链接更容易让用户三击全选复制到浏览器
- 完成消息必须是整条回复的最后一段,不得放在中间
- 不再生成 shortlist.md,也不在聊天里输出 MD 内容概览——HTML 视图就是给用户看的,重复输出冗余且占屏
Step 7b(status 子命令):输出运行状态
扫描 <data_dir>/output/ 下所有子目录,找名字格式为 YYYY-MM-DD-HHMM 的目录,读取最新一个的 state.json,按以下格式输出:
Job-Hunt 状态报告
==================
Run ID:<run_id>
当前阶段:<phase>
工作目录:<data_dir>
进度统计:
已导入 JD:<stages.fetched 数量> 个
完成分析:<stages.analyzed 数量> 个
分析失败:<stages.analysis_errors 数量> 个
生成三件套:<stages.tailored 数量> 个
最后更新:<checkpoint_at>
若无任何 run 记录,告知用户「尚未运行过 /job-hunt,请先运行完整流程。」
Step 8(clean 子命令):强制清理
删除 <data_dir>/.work/jd-pool/ 下所有文件(含 .analysis.md)。
删除 <data_dir>/output/ 下所有 run 目录。
删除 <data_dir>/.work/resume.md(若存在)。
统计并告知用户清理了多少文件/目录。