⚡ Full-process automatic execution constraints (highest priority, effective throughout)
Only applies to /job-hunt the no-argument full-process mode.
After the user provides a resume + says "start analysis",all remaining steps are executed automatically and continuously until the shortlist is output。
- Between Step 4 and Step 7: strictly no text output. Outputting text = turn ends = waiting for user = process interrupted
- After each step ends, immediately call the tool required for the next step (Skill / Bash / Read / Write), without inserting any text
- The return results of sub-skills (fetcher / analyzer / tailor) are internal data,not reported to the user in detail, and used directly for the next step
- Prohibitedto ask the user between steps "whether to continue" or "do you want to start the next step"
Violating the above constraints = process interrupted, user experience completely broken.
Subcommand routing
Determine the execution path based on user input:
| User input | Execution |
|---|---|
/job-hunt no arguments |
Full process (Step 1→7) |
/job-hunt fetch |
Only execute screenshot import (Step 1+2+3) |
/job-hunt analyze |
Only execute analysis (Step 1+4) |
/job-hunt tailor |
Execute ranking (Step 5) + tailoring (Step 6) |
/job-hunt status |
Output the current run status (Step 7b) |
/job-hunt clean |
Force clean all caches and artifacts (Step 8) |
Step 1: Determine the working directory and initialize
work_dir = the current directory where Claude was started (./ absolute path).
Get it with Bash:pwd, use the result as work_dir。
Ensure the following directories exist (create with Bash mkdir -p ):
<work_dir>/.work/jd-pool/
<work_dir>/output/
Generate run_id(format:YYYY-MM-DD-HHMM, using the current local time).
Create directory <work_dir>/output/<run_id>/。
Initialize <work_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 时间>"
}
Special handling for subcommands: if the current subcommand is analyze、tailor or status, before generating a new run_id, first scan <work_dir>/output/ for existing run directories (format YYYY-MM-DD-HHMM), and if any exist,reuse the latest run_id(do not create a new directory, read the existing state.json and continue using it); if none exist, create a new run_id according to the above process.
Step 2: Obtain the resume
(executed for the full-process, fetch, and analyze subcommands)
Check whether <work_dir>/.work/resume.md exists:
If it already exists: inform the user:
"The previously saved resume has been detected, continuing to use it. If you want to change the resume, just send me the new resume (file / path / pasted text supported), and I will help you replace it and re-evaluate. If you want to continue using the current resume, tell me "continue"."
Stop execution and wait for the user's reply:
- User sends a new resume → handle it as in "if it does not exist" below, overwrite and save
resume.md,Proceed to Step 2.5 to re-evaluate - User says "continue" or other non-resume content → skip this step, skip Step 2.5, and go directly to Step 3
If it does not exist: prompt the user to provide a resume:
"Please provide your resume. The following three methods are supported: ① Send a resume file (.md or .docx) ② Tell me the local path of the file (e.g., /Users/xxx/resume.md) ③ Paste the resume text directly into the message box and send it"
Process according to the method provided by the user:
- Send a file (.docx): call the Skill tool to load the
docxskill to parse it and convert it to Markdown text - Send a file (.md): read the file content directly
- File path (.docx): after using Bash to confirm the path exists, call the
docxskill to parse it - File path (.md): use Bash to read the file content
- Paste text: use the text content directly
Write the final Markdown content to <work_dir>/.work/resume.md.
Tell the user: "✅ Resume saved."
Proceed to Step 2.5.
Step 2.5: Resume quality assessment
(Only execute when the user provides a new resume in this session; if reusing the cache, skip directly to Step 3)
Read <work_dir>/.work/resume.md, find allassessable units, score them one by one, and output the results.
Rules for determining assessable units (strictly follow):
✅ Needs assessment: sentences or entries that describe "what was done / what was responsible for / what the result was", for example:
- "Responsible for requirements planning and implementation of the user growth module"
- "Led the refactoring of the payment process, increasing the conversion rate from 12% to 18%"
- "Designed and promoted the A/B testing system, covering xx pages across the entire site"
❌ Skip, do not assess: title lines that only describe "where / when / what position was held", for example:
- "ByteDance · Product Manager · 2021.03—2023.06"
- "Company A, Senior Operations, 2019 to 2021"
- "Project name: xxx platform | Role: Lead"
Such lines are only factual resume annotations,there are no actions and results to assess, and forcibly splitting them into S/A/R is wrong, so skip them directly.
⚠️ Edge case: title and description mixed on the same line
The basis for judgment iscontent, not format. If a line contains not only a project name/company name but also a description of actions or results, treat it as a description line and assess it. For example:
- "Project name: xxx platform, responsible for building the growth system from 0 to 1, DAU increased by 40%" → ✅ Needs assessment (contains actions and results)
- "During my time as a product manager at ByteDance, I led the implementation of the xx project" → ✅ Needs assessment (contains action description)
- "Project name: xxx platform | Role: Product Lead | Time: 2022.01—2022.06" → ❌ Skip (pure annotation, no description)
Assessment dimensions
Score each description according to the following three dimensions (✅ Qualified / ⚠️ Weak / ❌ Missing):
| Dimension | ✅ Qualified | ⚠️ Weak | ❌ Missing |
|---|---|---|---|
| Scenario/Problem(S/P) | Has a clear business context or problem to be solved | Vague background, mentioned only in passing | No scenario description at all |
| Action(A) | Specifically describes "what I did", with methods/means | Only lists responsibilities, no action details | Missing |
| Result(R) | Has quantified numbers, or clear business value | Vague result (e.g., "worked well") | No result description |
Additional checks:
- Whether passive verbs such as "responsible for", "participated in", "assisted with" are used heavily (a deduction item; recommend changing to active verbs)
- Whether there are obvious quantifiable but left-blank metrics (the tailor stage will insert
[请填写:xxx]placeholder)
Output format
📋 简历质量评估
整体:<一句话总结,如"行动描述较充分,但结果量化普遍缺失,建议优先补充">
逐段分析:
【公司名 · 职位名】
场景/问题 ✅ 行动 ⚠️ 结果 ❌
问题:<具体说明薄弱点>
建议:<一句话改写方向>
【项目名 · 角色】
场景/问题 ⚠️ 行动 ✅ 结果 ⚠️
问题:<说明>
建议:<建议>
(…其他段落)
⚡ 最值得优先改的 1-2 件事:
1. <最高优先级>
2. <次优先级>
---
如何继续?
A. 我自己去改简历,改完发给你重新评估
B. 先不改,用当前简历继续
User chooses how to proceed
Choose A (revise resume):
- Tell the user: "Okay, after revising, send the new resume directly to me (files / paths / pasted text are all supported)."
- Stop execution and wait for the user to resend the resume
- After receiving it, process it in the same way as Step 2, overwrite and save
resume.md - Re-execute Step 2.5(loop until the user chooses B)
Choose B (continue):
- Tell the user: "Okay, continue."
- Execute Step 3
Step 3: Screenshot collection and import
(executed for the full workflow and the fetch subcommand)
Prompt the user:
"Please upload screenshots of the job detail pages you are interested in (Boss直聘, 智联招聘, 前程无忧, 猎聘, 拉勾, etc. are all fine); you can send them all at once."
After sending the prompt above, stop execution and wait for the user to send screenshots.
After receiving the screenshots:
- Call the Skill tool, load the
job-hunt-fetcherskill, and pass in:work_dir: <parsed absolute path>run_id: <current run_id>screenshots: <screenshots in this batch>
- fetcher handles it internally (including the grouping confirmation interaction), and when done returns the list of written JD file IDs
- Append the ID list to
state.jsonofstages.fetched, updatecheckpoint_atandphaseto"fetched"
If the subcommand is fetch: Tell the user "✅ JD import complete, total positions. Run /job-hunt analyze to start analysis." and stop.
[Full workflow] Do not output any text; immediately call the Skill tool to execute Step 4.
Step 4: Analysis (job-hunt-analyzer)
(executed for the full workflow and the analyze subcommand)
Determine the list of JDs to analyze:
- Scan all
<work_dir>/.work/jd-pool/files under.md(excluding files ending with.analysis.md) - Read each file's frontmatter, filter files with
status.analyzed: false, and extract theiridfield - Exclude
state.json.stages.analysis_errorsIDs already recorded as failed in
If the list is empty, tell the user "There are no JDs to analyze in jd-pool, please upload screenshots first." and stop.
Call the Skill tool, load the job-hunt-analyzer skill, and pass in:
work_dir: <absolute path>resume_path:<work_dir>/.work/resume.mdjd_ids: <list of JD IDs to analyze>preferences:{"soft_preferences": {"prefer_industries": [], "avoid_industries": [], "prefer_company_size": []}, "ranking": {"match_weight": 1.0, "preference_weight": 0.0}}run_id: <current run_id>
After analyzer returns, update state.json phase to "analyzed"。
[Full workflow] Do not output any text; immediately execute Step 5.
Step 5: Sorting
(Executed before the full workflow or the tailor subcommand; does not call the LLM)
Read all analysis files (<work_dir>/.work/jd-pool/*.analysis.md), extract from each file the scores.total field, and sort in descending order.
All analyzed JDs all participate in sorting, with no truncation.
Write the sorting result (ordered list of JD IDs) to state.json 's stages.sorted_ids field, while also keeping it in memory for direct use by Step 6. When Step 6 resumes from a checkpoint, if there is no sorting result in memory, read it from state.json.stages.sorted_ids .
[Full workflow] After sorting is complete, immediately execute Step 6 without waiting for the user.
Step 6: Tailor resume (job-hunt-tailor)
(Executed during the full workflow or the tailor subcommand)
Check whether <work_dir>/.work/resume.md exists; if it does not exist, execute the Step 2 resume acquisition process before continuing.
Take the complete JD ID list sorted in Step 5.
Exclude those already in stages.tailored in state.json (skip them when resuming from a checkpoint).
Call the Skill tool, load the job-hunt-tailor skill, and pass in:
work_dir: <absolute path>resume_path:<work_dir>/.work/resume.mdjd_ids: <complete sorted JD ID list>run_id: <current run_id>
After tailor returns, update state.json phase to "tailored"。
[Full workflow] Do not output any text; immediately execute Step 7.
Step 7: Generate shortlist.md
(Final step of the full workflow)
Read all analysis files and the corresponding JD frontmatter, and generate <work_dir>/output/<run_id>/shortlist.md,At the same time, output the complete content in the chat message:
# 求职 Shortlist · <run_id>
## 概况
- 导入岗位:<stages.fetched 数量> 个
- 完成分析:<stages.analyzed 数量> 个
- 已生成定制简历:<stages.tailored 数量> 个
## 推荐排名(按匹配度)
### 🥇 1. <company.name> · <title> · 匹配度 <match_score> 分
- 💰 <salary.range><若 monthly_count 不为 null 追加"·<monthly_count>薪"> | 📍 <location.city>·<location.district>
- 👤 HR <hr.name>(<hr.active_status>)
- 📊 分项:硬技能 <scores.hard_skills> / 经验 <scores.experience_depth> / 行业 <scores.domain_fit> / 软性 <scores.soft_fit>
- 💡 <analysis 文件中的「一句话评估」>
- 📄 [定制简历](tailored/<id>/resume.md) · 💬 [开场白](tailored/<id>/opener.md) · 📋 [改动](tailored/<id>/changelog.md)
- ⚠️ 投递前:<从 tailored/<id>/changelog.md 的「⚠️ 需用户回填」节提取第一条;若该节不存在则省略此行>
<重复以上格式直到最后一名>
Update state.json phase to "done".
Tell the user: "✅ All done! The shortlist has been saved to <work_dir>/output/<run_id>/shortlist.md and displayed above."
Step 7b (status subcommand): Output run status
Scan <work_dir>/output/ for all subdirectories, find directories whose names are in the format YYYY-MM-DD-HHMM , read the state.jsonof the latest one, and output in the following format:
Job-Hunt 状态报告
==================
Run ID:<run_id>
当前阶段:<phase>
工作目录:<work_dir>
进度统计:
已导入 JD:<stages.fetched 数量> 个
完成分析:<stages.analyzed 数量> 个
分析失败:<stages.analysis_errors 数量> 个
生成三件套:<stages.tailored 数量> 个
最后更新:<checkpoint_at>
If there is no run record at all, tell the user: "You have not run /job-hunt yet. Please run the full workflow first."
Step 8 (clean subcommand): Force cleanup
Delete all files under <work_dir>/.work/jd-pool/ (including .analysis.md).
Delete all run directories under <work_dir>/output/ .
Delete <work_dir>/.work/resume.md(if it exists).
Count and tell the user how many files/directories were cleaned up.