career-ops SKILL.md 路由机制深度解析:一份共享 Router 如何让多个 AI 编程 CLI 复用同一套求职命令中心
在 career-ops 项目中,.antigravitycli/skills/career-ops/SKILL.md 是一份以开放技能标准编写的"路由器"文档:它不直接实现任何求职功能,而是负责把用户输入(一个模式名、一段 JD 文本、一个职位 URL)解析为正确的执行路径,并按模式按需加载 modes/ 下的指令文件。读完本文,你将掌握 Skill Router 的 frontmatter 声明、PROJECT_ROOT 哨兵解析、38 种模式的完整路由表、输出语言指令的注入时机,以及多 CLI 入口文件如何通过 symlink/指针机制保持单源同步的设计。
一、SKILL.md 是什么:多 CLI 共享的求职命令中心入口
career-ops 是一个"AI 无关"(AI-agnostic)的求职搜索工作台:扫描招聘门户、把职位评估为带全局 1–5 分的 A–H 结构化报告、定制 CV、跟踪申请状态,全部运行在你本地的 AI 编程 CLI 中。docs/SUPPORTED_CLIS.md 列出了它支持的 CLI 矩阵:
| CLI | 入口文件 | 调用方式 |
|---|---|---|
| Claude Code | CLAUDE.md |
交互式 claude(然后 /career-ops);无头 claude -p "prompt" |
| Cursor | AGENTS.md |
在 Cursor 中打开项目请求 career-ops(技能入口在 .cursor/skills/career-ops/SKILL.md) |
| Codex | CODEX.md |
交互式 codex(纯文本);无头 codex exec "prompt" |
| OpenCode | OPENCODE.md |
交互式 opencode(然后 /career-ops);无头 opencode run "prompt" |
| Antigravity CLI | AGENTS.md |
交互式 agy(然后 /career-ops);无头 agy -p "prompt" |
| Grok Build CLI | AGENTS.md |
交互式 grok(然后 /career-ops);无头 grok -p "prompt" |
| Qwen | AGENTS.md |
交互式 qwen;无头 qwen -p "prompt" |
| Kimi | KIMI.md |
交互式 kimi |
| GitHub Copilot CLI | AGENTS.md |
无头 copilot -p "prompt" |
| Gemini | GEMINI.md |
遗留封装,重定向到 AGENTS.md |
核心逻辑共享在 AGENTS.md,而各 CLI 的技能入口(Claude Code 的 .claude/skills/、Cursor 的 .cursor/skills/、Antigravity CLI 的 .antigravitycli/skills/ 等)最终都指向同一份 Router 文档。.antigravitycli/skills/career-ops/SKILL.md 就是其中面向 Antigravity CLI 的入口副本,其正文字首声明:
career-ops is a multi-CLI job-search command center. The routing below is shared across supported agent CLIs even when the invocation surface differs.
(career-ops 是一个多 CLI 求职搜索命令中心。下面的路由在所有受支持的 agent CLI 之间共享,即使各自的调用表面不同。)
1.1 Frontmatter:技能声明头
文件开头的 YAML frontmatter 是开放技能标准的元数据声明,决定了这个技能如何被发现、能否被用户直接调用:
---
name: career-ops
description: >-
AI job search command center -- evaluate offers, generate CVs, scan portals,
track applications. Use when the user pastes a job URL or JD, asks to scan
portals, generate a CV/PDF, track applications, prepare for interviews, draft
outreach/emails, or run any career-ops mode.
arguments: mode
user_invocable: true
user-invocable: true
argument-hint: "[scan | discover | deep | pdf | text | latex | latex-tex | cover | email | add | expand | eu-swe | oferta | ofertas | apply | batch | tracker | agent-inbox | pipeline | contacto | training | project | interview-prep | interview | interview/plan | interview/practice | interview/debrief | interview-redflag | patterns | offer-prep | titles | upskill | followup | reply-watch | outcome | update]"
license: MIT
---
各字段的作用:
name:技能标识,与目录名skills/career-ops/一致;description:给 LLM 的触发描述——何时该加载本技能(粘贴 JD/URL、扫描门户、生成 CV/PDF、跟踪申请、面试准备、起草外联邮件等);arguments: mode:声明该技能接受一个位置参数mode,后文所有路由逻辑都围绕解析这个变量展开;user_invocable: true(同时写出user-invocable双下划线/连字符两种写法):允许用户以/career-ops形式直接调用,而不只是被 agent 自动触发;argument-hint:CLI 交互提示中展示的可选模式列表,覆盖 scan、pdf、tracker、pipeline 等全部子命令;license: MIT:技能本身的许可证声明。
需要区分的是:argument-hint 是"建议输入",真正的模式判定表在正文的 Mode Routing 一节,二者允许存在差异(例如 hint 中出现的 discover 在路由表中对应 discover 模式)。
二、PROJECT_ROOT 解析:用哨兵文件定位仓库根目录
Router 中所有路径(modes/、config/、data/、脚本、模板、输出路径)都必须相对"项目根目录"解析,而不是相对进程当前工作目录。SKILL.md 给出了一套哨兵文件(sentinel)算法:
- 从当前加载的这份
SKILL.md所在目录出发; - 逐级向上走,直到找到同时包含
AGENTS.md和modes/的最近目录,该目录即PROJECT_ROOT; - 之后本路由中的所有相对路径一律对
PROJECT_ROOT解析; - 若两个哨兵都找不到,则停止一切读写操作,先定位 career-ops 的 checkout。
原文强调这是硬性要求:
This is required even when the checkout itself is nested (for example
Development\career-ops) or the command starts from a subdirectory.(即使 checkout 本身是嵌套的,或者命令从某个子目录启动,也必须执行该解析。)
从源码结构看,这套算法的健壮性设计针对的是真实使用场景:用户可能在深层嵌套目录克隆仓库,或在子目录里启动 CLI 会话,此时 CWD 解析会拿到错误路径,而"从 SKILL.md 位置向上找双哨兵"与 CWD 完全解耦。哨兵选择 AGENTS.md + modes/ 而非 package.json 这类通用文件,也避免了误匹配嵌套 monorepo 中其他子项目。
三、调用方式:斜杠命令与自然语言两条入口
SKILL.md 的 Invocation Notes 一节明确了不同 CLI 的调用表面,但强调路由语义与入口无关:
- 支持斜杠命令注册的 CLI 可以暴露
/career-ops; - Cursor 中技能位于
.cursor/skills/career-ops/,会被自动发现——直接按名字要一个模式,或粘贴 JD/URL 触发 auto-pipeline; - Codex 交互会话在仓库根目录运行
codex。由于 Codex 不保证支持斜杠命令,/career-ops不可用时,让 Codex 按名字运行同一个模式即可; - Codex 无头 worker 使用
codex exec "prompt"; - 无论入口是斜杠命令还是自然语言提示,下面的路由语义保持一致。
文档给出了等价的 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.
这五条示例恰好覆盖了四种输入形态:JD URL(auto-pipeline)、纯模式名(scan)、模式 + 数据文件(pipeline + data/pipeline.md)、针对最近评估角色的 pdf、以及状态汇总(tracker)。
四、Mode Routing:完整的模式判定表
模式判定规则是:从 $mode(即 arguments: mode 传入的值)确定执行模式。SKILL.md 内置的完整路由表如下(这是本文件的核心资产,必须完整理解):
| 输入 | 模式 |
|---|---|
| (空 / 无参数) | discovery — 显示命令菜单 |
| JD 文本或 URL(无子命令) | auto-pipeline |
oferta |
oferta |
ofertas |
ofertas |
contacto |
contacto |
deep |
deep |
interview-prep |
interview-prep |
interview |
interview |
eu-swe |
regional/eu-swe |
eu-fintech |
regional/eu-fintech |
interview/plan |
interview/plan |
interview/practice |
interview/practice |
interview/debrief |
interview/debrief |
pdf |
pdf |
text |
text |
latex |
latex |
latex-tex |
latex-tex |
email |
email |
add |
add |
expand |
expand |
training |
training |
project |
project |
tracker |
tracker |
agent-inbox |
agent-inbox |
inbox |
agent-inbox(别名) |
pipeline |
pipeline |
apply |
apply |
scan |
scan |
discover |
discover |
batch |
batch |
patterns |
patterns |
offer-prep |
offer-prep |
titles |
titles |
upskill |
upskill |
followup |
followup |
reply-watch |
reply-watch |
outcome |
outcome |
interview-redflag |
interview-redflag |
update |
update |
cover |
cover |
表中值得注意的路由细节:
- 子路径模式:
interview/plan、interview/practice、interview/debrief与regional/eu-swe、regional/eu-fintech指向modes/下的子目录文件,说明模式名即文件路径; - 别名归并:
inbox归并到agent-inbox,两者读取同一 data/agent-inbox.md 队列; - 空输入兜底:无参数进入
discovery(显示菜单); - auto-pipeline 兜底:见下节。
每个模式在 modes/ 目录中都有对应的指令文件(如 modes/tracker.md、modes/scan.md、modes/pdf.md、modes/latex.md、modes/cover.md),Router 只负责"选哪份文件",具体执行语义由各模式文件定义。
4.1 Auto-pipeline 自动检测
当 $mode 不是已知子命令时,Router 还要判断它是否"长得像一份 JD":
Auto-pipeline detection: If
$modeis not a known sub-command AND contains JD text (keywords: "responsibilities", "requirements", "qualifications", "about the role", "we're looking for", company name + role) or a URL to a JD, executeauto-pipeline.若
$mode既不是子命令,也不像 JD,则显示 discovery 菜单。
即三段式判定:已知子命令 → 对应模式;未知但含 JD 特征(六个关键词或职位 URL)→ auto-pipeline;其余 → discovery。这条规则让"粘贴一段 JD 就自动跑完整流程"成为零配置行为。auto-pipeline 本身的执行步骤定义在 modes/auto-pipeline.md:提取 JD → 存活检查(Liveness gate)→ 黑名单检查 → A–G 评估 → 保存报告到 reports/ → 按 cv.output_format 生成 PDF/文本/LaTeX → 分数 ≥ 4.5 时起草申请表答案 → 更新 data/applications.md 跟踪表,任何一步失败都会继续后续步骤并在跟踪表中标记 pending。
五、Output Language Directive:输出语言指令的注入时机
Router 在执行任何模式之前读取 config/profile.yml(若存在),解析两个键:
language.output→ 面向人类输出的 ISO 语言码,默认en;language.modes_dir→ 可选的市场模式目录,只控制市场词汇与本地评估规则,不控制行文语言。
然后在加载完模式指令文件之后、产出任何用户可见内容之前,注入如下指令:
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. Iflanguage.modes_dirsupplies market-specific vocabulary, keep the market logic but explain terms in{language.output}when needed.
关键设计是两者的权限划分:
language.outputis authoritative for prose.modes_diris market context; it must not force the prose language.
即 output 对行文语言有最终决定权;modes_dir 只是市场语境(例如 modes/de 提供 DACH 市场词汇),不得强行改变行文语言。这一点在 config/profile.example.yml 中有完整注释佐证:
language:
# Human-facing output language for reports, tracker notes, PDFs, cover
# letters, outreach, and form answers. Use an ISO language code such as
# `en` or `zh-CN`; `zh-CN` also enables Chinese PDF typography rules.
# This is separate from language.modes_dir: modes_dir selects market
# vocabulary/rules, while output selects the prose language.
output: en
# modes_dir: modes/de # optional: use DACH market vocabulary while still writing in English
项目还有可执行的实现层印证这条指令。profile-language.mjs 提供了 parseOutputLanguage() 与 outputLanguageInstruction() 两个函数:前者从 profile YAML 中解析 language.output,对非字符串、空值、超长(>64 字符)或含控制字符的取值一律回退到默认 en;后者生成注入模型提示词的规范语言规则,核心断言与 SKILL.md 一致——"配置的 language.output 始终优先于职位描述的语言"。测试 tests/output-language.test.mjs 对该行为做了回归验证。
六、Discovery Mode:无参数时的命令菜单
当 CLI 支持 /career-ops 且用户不带参数时,Router 要求展示完整命令菜单;在 Codex 等无斜杠命令的环境中,则以纯文本列出同样选项,并按同一套语义映射模式名。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.
这份菜单与第四节的路由表逐条对应,同时为每个模式补充了"用户视角"的一句话说明(例如 email 强调 draft-only、绝不发送/提交/点击;offer-prep 明确"不构成法律建议")。它也是 Discovery 模式的行为规范:Router 在此场景下只输出菜单、不执行任何有副作用的操作。
七、Context Loading by Mode:三类上下文加载策略
模式确定后,Router 规定了执行前的文件加载顺序。这里的关键是 _shared.md、_profile.md、_custom.md 三个基础文件与模式文件的组合方式:
前置规则(适用于所有模式):若 modes/_custom.md 存在,须在 modes/_profile.md 之后、所选模式文件之前读取。它承载用户的"家规"与流程偏好,可以覆盖流程/风格默认值,但永远不允许为候选人添加事实性声明(factual claims)。
7.1 需要 _shared.md 的模式
加载顺序:modes/_shared.md + modes/_profile.md(若存在)+ modes/_custom.md(若存在)+ modes/{mode}.md。
适用模式:auto-pipeline、oferta、ofertas、pdf、text、contacto、apply、pipeline、scan、batch。
这些是"重"模式——评估、报告、PDF、扫描等需要共享评估规则与候选人画像的场景,modes/_shared.md 中的 A–G 评估块、查询预算(bounded research budget)等规则在此被统一注入。
7.2 独立的 Profile/Custom 模式
加载顺序:modes/_profile.md(若存在)+ modes/_custom.md(若存在)+ modes/{mode}.md,不加载 _shared.md。
适用模式:tracker、agent-inbox、deep、interview-prep、interview、regional/eu-swe、interview/plan、interview/practice、interview/debrief、latex、latex-tex、training、project、patterns、titles、upskill、followup、reply-watch、outcome、cover、email、add、offer-prep、discover。
这一组多为"读数据 + 生成产物"的轻量模式(跟踪表查询、邮件/信草稿、技能差距聚合等),不需要完整评估上下文,减少无关 token 注入。
7.3 委派给 subagent 的模式
对于 scan、apply(配合 Playwright)、pipeline(3 个以上 URL)三种长任务模式,Router 要求将其作为 worker/subagent 启动,并把 _shared.md + _profile.md(若存在)+ _custom.md(若存在)+ modes/{mode}.md 的内容注入 worker 的提示词。若 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}"
)
注意注入顺序中 output language directive 排在最前——这与第五节"注入指令必须先于任何用户可见内容"的规则一致。从源码结构看,主会话把长任务整体外包给 subagent 是为了隔离 token 预算:modes/auto-pipeline.md 明确要求评估继承 oferta 的有界研究预算,不得升级成开放式 deep-research;AGENTS.md 中还规定了并行 fan-out 前先用 node reserve-report-num.mjs --count N 预留报告编号区间,避免并行 worker 各自计算 max+1 造成编号竞争。最后一步指令是"Execute the instructions from the loaded mode file"——Router 的职责到"把正确文件装进正确上下文"为止。
八、单源多入口:SKILL.md 的同步机制
.antigravitycli/skills/career-ops/SKILL.md 并非独立维护的副本。项目以 .agents/skills/career-ops/SKILL.md 为唯一正源(canonical path),为各 CLI 生成入口文件。scaffolder/bin/skill-entrypoints.mjs 定义了全部七个入口及其指针目标:
export const CANONICAL_SKILL_PATH = '.agents/skills/career-ops/SKILL.md';
export const SKILL_ENTRYPOINTS = [
{ path: '.claude/skills/career-ops/SKILL.md',
pointer: '../../../.agents/skills/career-ops/SKILL.md' },
{ path: '.cursor/skills/career-ops/SKILL.md',
pointer: '../../../.agents/skills/career-ops/SKILL.md' },
{ path: '.opencode/skills/career-ops/SKILL.md',
pointer: '../../../.agents/skills/career-ops/SKILL.md' },
{ path: '.qwen/skills/career-ops/SKILL.md',
pointer: '../../../.agents/skills/career-ops/SKILL.md' },
{ path: '.antigravitycli/skills/career-ops/SKILL.md',
pointer: '../../../.agents/skills/career-ops/SKILL.md' },
{ path: '.grok/skills/career-ops/SKILL.md',
pointer: '../../../.agents/skills/career-ops/SKILL.md' },
{ path: '.kimi/skills/career-ops/SKILL.md',
pointer: '../../../.agents/skills/career-ops/SKILL.md' },
];
该模块提供两个函数,覆盖了两种文件系统能力:
ensureSkillEntrypoints(root):初始化(npx init)时为缺失的 CLI 创建目录与指针文件,并把"内容为指针路径"的普通文件物化为正源全文(materialize)——用于不支持 symlink 的文件系统;materializeSkillEntrypoints(root):更新(update-system)时遍历已存在的入口,跳过真实 symlink,把指针文件替换为正源内容。
物化逻辑的判定条件是"文件内容恰好等于指针字符串"(content !== entry.pointer 则跳过),既保证幂等,也避免误改用户自定义过的文件。test-all.mjs 中则把七个入口路径列为必须存在的文件清单,纳入全量测试回归,确保任何一个 CLI 的入口丢失都会在测试中暴露。
由此可以推断出该设计的目标:修改路由语义只需改一份文件,其余 CLI 入口由初始化/更新工具与测试共同保障同步,这正是 README 中"skill 以开放标准定义在 .agents/skills/career-ops/SKILL.md,并为每个受支持的 CLI 建立 symlink 或引用"的机制落地。
九、如何阅读与验证这份 Router
如果你想在自己的 checkout 中验证本文描述的行为,建议按以下路径阅读:
- 入口与正源:对比 .antigravitycli/skills/career-ops/SKILL.md 与 .agents/skills/career-ops/SKILL.md,确认入口是正源的 symlink/指针;
- 路由落点:挑一个路由表中的模式(如
tracker),打开 modes/tracker.md 看 Router 选中的文件如何定义实际执行语义; - 上下文文件:阅读 modes/_shared.md、modes/_profile.md、modes/_custom.md(后两者为可选项),理解 7.1/7.2 两类加载差异;
- 语言指令:对照 config/profile.example.yml 的
language段与 profile-language.mjs 的实现,验证 SKILL.md 中的指令与代码行为一致; - 多入口同步:查看 scaffolder/bin/skill-entrypoints.mjs 与 test-all.mjs 中的入口清单;
- 端到端示例:从 modes/auto-pipeline.md 走一遍"粘贴 JD → A–G 评估 → 报告 → PDF → 跟踪表"的完整链路,这是整条路由最终服务的核心工作流。
这套 Router 的价值在于把"多 CLI × 数十种模式"的组合复杂度压缩成一张声明式表格加三条加载规则:哨兵算法解决路径解析,路由表 + auto-pipeline 检测解决输入判定,三类上下文加载策略解决 token 预算,而单源多入口机制保证所有 CLI 看到的永远是同一套语义。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00