首页
/ career-ops 多 CLI 求职技能路由详解:SKILL.md 的 Mode 路由、项目根解析与上下文加载机制

career-ops 多 CLI 求职技能路由详解:SKILL.md 的 Mode 路由、项目根解析与上下文加载机制

2026-09-03 15:37:46作者:齐添朝

career-ops 是一个运行在 AI 编码 CLI(Claude Code、Codex、OpenCode、Antigravity、Grok、Cursor、Qwen、Kimi 等)中的开源求职指挥中心。它的统一入口是一个名为 SKILL.md 的技能路由文件:用户粘贴一段 JD(职位描述)文本或 URL,或者输入一个模式名(如 scanpdftracker),路由就会把请求分发到对应的求职工作流模式。本文以 .grok/skills/career-ops/SKILL.md 为主体,完整讲解它的 frontmatter 元数据、Mode 路由表、auto-pipeline 自动检测、输出语言指令、Discovery 命令菜单和分层上下文加载规则,并结合 scaffolder/ 的引导代码与测试文件,说明这套路由如何做到跨 CLI、跨工作目录的确定性行为。

一、SKILL.md:一份被多 CLI 共享的技能定义

.grok/skills/career-ops/SKILL.md 并不是独立的一份副本,而是指向 canonical 定义 SKILL.md 的符号链接。这一设计来自仓库的开放标准约定:技能在 .agents/skills/career-ops/SKILL.md 中定义一次,然后为每个受支持的 CLI 各建一份 symlink(.claude/.cursor/.opencode/.qwen/.antigravitycli/.grok/.kimi/)。因此无论 Agent 从哪个 CLI 加载技能,读到的路由语义都完全一致——这也是 SKILL.md 开篇所说的 "The routing below is shared across supported agent CLIs even when the invocation surface differs"。

文件以 YAML frontmatter 开头,声明了 CLI 自动发现所需的元数据:

字段 取值 作用
name career-ops 技能名,slash command 注册名
description AI job search command center — evaluate offers, generate CVs, scan portals, track applications… 供 Agent 判断"何时触发本技能"的自然语言描述:粘贴 JD/URL、要求扫描门户、生成 CV/PDF、跟踪申请、面试准备、起草外联邮件时均应命中
arguments mode 唯一参数名,路由的输入来源(即 $mode
user_invocable / user-invocable true 允许用户主动调用(两种写法并存以兼容不同 CLI 的解析器)
argument-hint [scan | discover | deep | pdf | text | … | update] 交互界面中展示的候选模式提示,共 33 个模式名
license MIT 许可证声明

关于 symlink 的健壮性,仓库有两层保障:

  • 引导物化(materialize)skill-entrypoints.mjs 定义了 SKILL_ENTRYPOINTS 注册表,canonical 路径为 .agents/skills/career-ops/SKILL.md,其余 7 个 CLI 目录的入口都是指向它的指针。对不支持 symlink 的文件系统,ensureSkillEntrypoints() 会写入指针文件;当检测到某个入口是"内容为指针字符串的普通文件"(而非真正的 symlink)时,materializeSkillEntrypoints() 会把 canonical 的完整内容直接落盘,保证旧版本 clone 或特殊文件系统上技能依然可用。测试 test-all.mjs 中"SKILL SYMLINK INTEGRITY"一节会用 realpathSync 逐一验证 6 个 symlink 入口都解析到同一 canonical 文件,并断言引导测试中 ensureSkillEntrypoints 物化的 .grok 入口内容与 canonical 完全一致。
  • CLI 支持面:各 CLI 的加载方式记录在 SUPPORTED_CLIS.md,例如 Grok Build CLI 通过 AGENTS.md 加载、交互式命令为 grok 然后 /career-ops,无头批处理为 grok -p "prompt";Claude Code 为 claude 然后 /career-ops,无头为 claude -p "prompt";OpenCode 为 opencode / opencode run "prompt"

二、Project Root Resolution:用哨兵文件定位仓库根,而不是 cwd

SKILL.md 在读取任何仓库相对路径之前,要求先推导 PROJECT_ROOT,规则是:

从本 SKILL.md 所在目录开始向上逐层走,直到找到同时包含 AGENTS.mdmodes/ 两个哨兵的最近目录。此后路由中出现的每一个路径(modes/config/data/、脚本、模板、输出路径)都必须相对 PROJECT_ROOT 解析,永远不要相对进程当前的工作目录(cwd)解析。

这条规则针对的是两类真实场景:checkout 本身嵌套在更深的路径下(例如 Development\career-ops),或用户从仓库某个子目录启动命令。只要哨兵缺失(既没有 AGENTS.md 也没有 modes/),技能应停下来先定位 career-ops 的 checkout,再继续读写文件。

仓库为这条规则配备了回归测试 skill-project-root.test.mjs(对应 issue #3332):

  • 测试内实现的 findProjectRoot() 与 SKILL.md 的语义一一对应:从技能文件目录向上找,直到某目录同时存在 AGENTS.mdmodes/
  • 断言 8 个入口(.agents.antigravitycli.claude.cursor.grok.kimi.opencode.qwen 下的 skills/career-ops/SKILL.md)都能解析到同一个 checkout 根;
  • hasRoutingRule() 断言技能文本必须同时包含 "Resolve every path in this router" 和 "never against the process's current working directory" 两条关键语句,防止未来编辑删掉路由不变量;
  • 针对"Git index 中 mode 为 120000(symlink)但工作区物化成普通文件"的情况,测试构造了一个 fixture,验证通过 Git index mode 仍能把指针文件解析回 canonical 内容。

三、Invocation Notes:slash command 与自然语言是同一套路由的两种表面

SKILL.md 对不同 CLI 的调用面做了显式归一:

  • 支持 slash command 注册的 CLI 把本技能暴露为 /career-ops
  • Cursor 中技能位于 .cursor/skills/career-ops/ 并被自动发现——可以直接按名字要某个模式,或粘贴 JD/URL 触发 auto-pipeline;
  • Codex 的交互式会话在仓库根运行 codex 启动。Codex 不保证提供 slash command,因此在 /career-ops 不可用时,用自然语言让 Codex 按名字运行同一模式;无头 Codex worker 使用 codex exec "prompt"
  • 无论入口是 slash command 还是自然语言提示,路由语义保持不变。

文档给出了与 slash command 等价的 Codex 提示词示例,这是把"命令面差异"落到"提示词层面"的关键映射:

Evaluate this JD with career-ops auto-pipeline: https://company.com/jobs/123
Run the career-ops scan mode and summarize new matches.
Run the career-ops pipeline mode for data/pipeline.md.
Run the career-ops pdf mode for the latest evaluated role.
Run the career-ops tracker mode and summarize the current statuses.

四、Mode Routing:从 $mode 到模式的完整路由表

路由的核心逻辑:从 $mode 判定模式。SKILL.md 给出的完整映射如下(左列输入,右列模式):

输入 模式
(空 / 无参数) discovery — 显示命令菜单
JD 文本或 URL(无子命令) auto-pipeline
oferta / ofertas / contacto / deep 同名模式
interview-prep / interview / interview/plan / interview/practice / interview/debrief / interview-redflag 同名模式
eu-swe / eu-fintech regional/eu-swe / regional/eu-fintech
pdf / text / latex / latex-tex / cover / email 同名模式
add / expand / training / project 同名模式
tracker / agent-inbox / inbox trackeragent-inboxinbox 是别名)
pipeline / apply / scan / discover / batch 同名模式
patterns / offer-prep / titles / upskill 同名模式
followup / reply-watch / outcome / update 同名模式

两个判定细节:

  1. auto-pipeline 检测:当 $mode 不是已知子命令,且内容包含 JD 特征关键词("responsibilities"、"requirements"、"qualifications"、"about the role"、"we're looking for",或"公司名 + 职位"),或直接是 JD 的 URL 时,执行 auto-pipeline
  2. 兜底:当 $mode 既不是子命令、也不像 JD 时,回落到 Discovery(显示菜单),而不是报错。

这意味着用户最常见的"把 JD 原文直接粘进来"这一动作,不需要任何模式前缀即可进入完整评估流水线——路由表把"意图识别"内建进了技能本身。

五、Output Language Directive:执行任何模式前的语言归一

在执行任何模式之前,路由要求先读取 config/profile.yml(若存在),解析两个键:

  • language.output → 面向人类输出的 ISO 语言代码,默认 en
  • language.modes_dir → 可选的"市场模式目录",只控制市场词汇与本地评估规则(例如用 DACH 市场术语但仍用英文写作)。

随后在加载模式指令之后、产出任何用户可见内容之前,注入以下指令:

Write all human-facing output in {language.output} regardless of the language of these instructions or of the job description. This includes reports, tracker notes, PDFs, cover letters, outreach, interview prep, form answers, and summaries. If language.modes_dir supplies market-specific vocabulary, keep the market logic but explain terms in {language.output} when needed.

不变量是:language.output 对行文语言拥有最终决定权;modes_dir 只是市场上下文,不能强行改变行文语言。仓库中的 profile.example.yml 对这一设计有配套注释:language.output 用于报告、tracker 备注、PDF、求职信、外联与表单答案(zh-CN 还会启用中文 PDF 排版规则),而 language.modes_dir(如 modes/de)用于选择市场词汇/规则,两者相互独立。

六、Discovery Mode(无参数):完整的命令菜单

无参数调用时,CLI 展示命令菜单(Codex 等无 slash command 的场景则以纯文本列出同样选项,并按同样的方式映射模式)。SKILL.md 内置的菜单如下:

career-ops -- Command Center

Available commands:
  /career-ops {JD}      → AUTO-PIPELINE: evaluate + report + PDF + tracker (paste text or URL)
  /career-ops pipeline  → Process pending URLs from inbox (data/pipeline.md)
  /career-ops oferta    → Evaluation only A-F (no auto PDF)
  /career-ops ofertas   → Compare and rank multiple offers
  /career-ops contacto  → LinkedIn power move: find contacts + draft message
  /career-ops deep      → Deep research prompt about company
  /career-ops interview-prep → Generate company-specific interview prep doc
  /career-ops interview    → Interactive profile/CV onboarding interview
  /career-ops eu-swe    → Calibrate a European SWE application before CV/apply/interview
  /career-ops eu-fintech → Scan 21 EU fintech portals for Product Manager roles (zero-token)
  /career-ops interview/plan → Time-blocked prep plan for an upcoming interview
  /career-ops interview/practice → Practice interview, one question at a time with feedback
  /career-ops interview/debrief → Post-interview debrief: close gaps, predict next round
  /career-ops pdf       → PDF only, ATS-optimized CV
  /career-ops text      → Tailored markdown CV (mirrors cv.md, no PDF)
  /career-ops latex     → Export CV as LaTeX/Overleaf .tex
  /career-ops latex-tex → Tailor your own resume.tex in place (opt-in; cv.md stays default)
  /career-ops cover     → Cover letter: standalone JD paste or /career-ops cover {slug}
  /career-ops email     → Formal application email draft (draft-only; never sends, submits, or clicks)
  /career-ops add       → Add a project/paper/role to your CV (fetch + preview + confirm)
  /career-ops expand    → Auto-discover and add missing competencies from profile links
  /career-ops training  → Evaluate course/cert against North Star
  /career-ops project   → Evaluate portfolio project idea
  /career-ops tracker   → Application status overview
  /career-ops agent-inbox → Queue/drain requests for the next session (data/agent-inbox.md)
  /career-ops apply     → Live application assistant (reads form + generates answers)
  /career-ops scan      → Scan portals and discover new offers
  /career-ops discover  → Resolve a company list to scannable ATS boards + append to portals.yml (zero-token)
  /career-ops batch     → Batch processing with parallel workers
  /career-ops patterns  → Analyze rejection patterns and improve targeting
  /career-ops offer-prep → Read a received offer/contract with the candidate: clause walk + lawyer questions (not legal advice)
  /career-ops titles    → Suggest adjacent job titles from your CV to broaden the search
  /career-ops upskill   → Aggregate skill-gap analysis from your evaluated reports
  /career-ops followup  → Follow-up cadence tracker: flag overdue, generate drafts
  /career-ops outcome   → Record application outcome & archive artifacts
  /career-ops update    → Update career-ops system files with diff preview + compat check

Inbox: add URLs to data/pipeline.md → /career-ops pipeline
Or paste a JD directly to run the full pipeline.

菜单尾部给出了"收件箱"用法:把 URL 追加到 data/pipeline.md,再用 pipeline 模式批量处理;或者直接粘贴 JD 触发全流水线。

七、Context Loading by Mode:三层上下文 + 子代理委托

模式判定后、执行前,路由规定了精确的文件加载顺序。整个上下文体系分为三类模式加载策略:

1. 需要 _shared.md + 模式文件的模式

读取顺序:modes/_shared.md + modes/_profile.md(若存在)+ modes/_custom.md(若存在)+ modes/{mode}.md。适用于:auto-pipelineofertaofertaspdftextcontactoapplypipelinescanbatch

2. 带 profile 与 custom 上下文的独立模式

读取顺序:modes/_profile.md(若存在)+ modes/_custom.md(若存在)+ modes/{mode}.md。适用于:trackeragent-inboxdeepinterview-prepinterviewregional/eu-sweinterview/planinterview/practiceinterview/debrieflatexlatex-textrainingprojectpatternstitlesupskillfollowupreply-watchoutcomecoveremailaddoffer-prepdiscover

3. 委托给子代理(subagent)的模式

scanapply(使用 Playwright 时)以及 pipeline(3 个及以上 URL):以 worker/subagent 形式启动,把 _shared.md + _profile.md + _custom.md + modes/{mode}.md 的内容注入 worker prompt。如果 CLI 提供 Agent(...) 原语,调用形如:

Agent(
  subagent_type="general-purpose",
  prompt="[output language directive]\n\n[content of modes/_shared.md]\n\n[content of modes/_profile.md if exists]\n\n[content of modes/_custom.md if exists]\n\n[content of modes/{mode}.md]\n\n[invocation-specific data]",
  description="career-ops {mode}"
)

两个文件在加载顺序上有明确的语义边界:

  • modes/_custom.mdmodes/_profile.md 之后、模式文件之前读取。它承载用户自定义的流程规则与偏好,可以覆盖工作流/风格默认值,但永远不得引入关于候选人的事实性声明
  • 加载完成后,执行从模式文件中读取到的指令。

这一分层与 AGENTS.md 中的数据契约(User Layer 与 System Layer,完整清单见 DATA_CONTRACT.md)一致:用户个性化事实写进 modes/_profile.mdconfig/profile.yml 等用户层文件,程序性规则写进 modes/_custom.md(可从 modes/_custom.template.md 复制),而 modes/_shared.md 属于系统层、不可写入用户特定内容——这样系统更新不会覆盖用户定制。_grok/.claude 等技能入口目录也在数据契约中被归为技能定义文件,如 DATA_CONTRACT.md 中记录的 .grok/skills/*(Grok Build CLI 的技能定义)。

八、测试视角下的路由完整性

除前面提到的 project-root 测试外,仓库的总测试入口 test-all.mjs 还对 SKILL.md 做了两类断言:

  1. 系统文件存在性.claude/skills/career-ops/SKILL.md.cursor/….opencode/….qwen/….antigravitycli/….grok/….kimi/… 全部列在 systemFiles 检查清单中,与 CLAUDE.mdCODEX.mdmodes/_shared.mdmodes/oferta.md 等系统文件一并验证存在;
  2. symlink 完整性:逐一 realpathSync 各 CLI 入口并断言解析结果等于 canonical 的 .agents/skills/career-ops/SKILL.md;对"物化指针"(文件内容为单行 ../.. 指针)的情况,测试还会从指针字符串手动解析目标后再验证。

这套"canonical 单份 + symlink 多入口 + 引导物化 + 双重测试断言"的结构,让 SKILL.md 的路由表、语言指令和加载顺序只需维护一处,即可在所有受支持的 CLI 上保持行为一致。

九、小结:把 SKILL.md 当作路由契约来读

.grok/skills/career-ops/SKILL.md 本质上是一份可执行的路由契约,它约束了四件事:

  1. 路径基准:所有仓库路径相对哨兵文件推导出的 PROJECT_ROOT 解析,与 cwd 无关;
  2. 模式解析:33 个具名模式 + auto-pipeline 意图检测 + discovery 兜底,slash command 与自然语言提示映射到同一语义;
  3. 语言归一config/profile.ymllanguage.output 对所有面向人类的输出拥有最终决定权,modes_dir 仅承载市场上下文;
  4. 上下文装配_shared.md / _profile.md / _custom.md / modes/{mode}.md 的加载顺序按模式分三类,重负载模式(scan、Playwright 版 apply、多 URL pipeline)委托给子代理执行。

对维护者而言,改动任何模式名、加载规则或语言指令时,需要同步检查 skill-project-root.test.mjs 的路由不变量断言与 test-all.mjs 的入口清单;对使用者而言,只需记住入口行为:粘贴 JD 走 auto-pipeline,输入模式名走具名路由,什么都不输就看 Discovery 菜单。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
982
502
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384