career-ops 技能路由全解析:一份 SKILL.md 如何驱动多 CLI 求职命令中心
本篇基于 .opencode/skills/career-ops/SKILL.md 展开,解析 career-ops 项目如何用一个「路由器技能文件」把 40 余个求职子模式(评估 JD、扫描招聘门户、生成 CV/PDF、跟踪申请进度等)统一暴露给 Claude Code、OpenCode、Codex、Cursor 等多种 AI 编码 CLI。读完你可以掌握:技能前置元数据的写法、项目根目录哨兵解析机制、模式路由表与自动流水线触发规则、按模式分级加载上下文的策略,以及子代理(subagent)委派的具体调用形式。
技能文件的定位与多 CLI 分发
SKILL.md 是 career-ops 的「Router」(路由器):它本身不执行任何业务逻辑,只负责把用户输入解析成某个具体模式,并规定该模式执行前必须加载哪些文件。文档开篇即声明:
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.
同一份路由逻辑被分发到不同 CLI 的技能/命令目录,仓库中可以确认三处镜像副本:
.opencode/skills/career-ops/SKILL.md(OpenCode 技能).claude/skills/career-ops/SKILL.md(Claude Code 技能).cursor/skills/career-ops/SKILL.md(Cursor 技能)
此外,.opencode/commands/career-ops.md 提供了一层 OpenCode 斜杠命令包装,其全部正文只做了两件事:把 $ARGUMENTS 展开,并调用 skill({ name: "career-ops" }) 加载技能——也就是说斜杠命令与技能入口最终汇入同一套路由语义。各 CLI 的入口文件与调用方式在 docs/SUPPORTED_CLIS.md 中有完整对照表,例如 OpenCode 的入口是 OPENCODE.md(内部通过 @AGENTS.md 引入核心规则,交互式 opencode、批量 opencode run "prompt"),Codex 无斜杠命令保证时用 codex exec "prompt" 无头执行。
前置元数据(frontmatter)
技能文件头部采用 YAML frontmatter 声明注册信息,逐字段含义如下:
| 字段 | 取值 | 作用 |
|---|---|---|
name |
career-ops |
技能唯一名,供 skill({ name }) 加载 |
description |
多行描述 | 描述触发场景:粘贴 JD/URL、扫描门户、生成 CV/PDF、跟踪申请、面试准备、起草外联邮件等 |
arguments |
mode |
声明该技能接收一个 mode 参数,即路由表的输入 $mode |
user_invocable / user-invocable |
true |
允许用户直接调用(两种键名并列,兼容不同 CLI 的解析约定) |
argument-hint |
[scan | discover | deep | pdf | ...] |
补全提示,列出全部可输入子命令 |
license |
MIT |
许可证声明 |
argument-hint 与下文路由表的 Input 列一一对应,是命令中心全部能力的索引。
项目根解析:哨兵目录法
路由器规定,在读取任何仓库相对路径之前,必须先解析 PROJECT_ROOT:
- 从已加载的
SKILL.md所在目录出发,向上逐级寻找同时包含AGENTS.md和modes/的最近目录——这两个文件/目录即「哨兵(sentinels)」; - 本路由器中出现的一切路径(
modes/、config/、data/、脚本、模板、输出路径)一律相对PROJECT_ROOT解析,绝不相对进程当前工作目录; - 若找不到哨兵,立即停止,先定位 career-ops 检出目录,再继续读写字节。
这条规则针对的是两类真实部署形态:检出目录本身嵌套在其他项目下(如 Development\career-ops),或用户从子目录启动命令。它还与项目根 AGENTS.md 的数据契约(Data Contract)相配合:AGENTS.md 定义了 User Layer(cv.md、config/profile.yml、data/* 等个性化文件,永不自动更新)与 System Layer(modes/_shared.md、脚本、模板等,可自动更新),并给出数据根解析优先级(CAREER_OPS_ROOT / CAREER_OPS_DATA_DIR 环境变量 → .career-ops-data 标记文件 → 仓库根)。哨兵法保证「技能文件在哪里被加载」与「数据在哪里」解耦,路由层稳定,数据层可迁移。
多 CLI 调用方式与等价语义
SKILL.md 用一节 Invocation Notes 说明不同入口如何映射到同一套路由:
- 支持斜杠命令注册的 CLI 可把路由器暴露为
/career-ops; - Cursor 中技能位于
.cursor/skills/career-ops/,被自动发现,可以直接按名字要模式,或粘贴 JD/URL 触发自动流水线; - 交互式 Codex 会话在仓库根执行
codex;斜杠命令在 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.
Discovery 菜单部分还给出更完整的对照关系,例如 /career-ops {JD} ↔ “Evaluate this JD with career-ops auto-pipeline: {JD or URL}”、/career-ops scan ↔ “Run the career-ops scan mode and summarize new matches.” 等。核心结论写在文档里:无论入口是斜杠命令还是自然语言提示,下述路由语义保持一致——这正是「AI 无关(AI-agnostic)」设计的关键:业务规则只存在于 modes/*.md 与 AGENTS.md,入口包装保持极薄。
模式路由表与自动流水线检测
路由器的核心是一张「输入 → 模式」映射表。$mode 的解析规则如下(完整表格):
| 输入 | 路由到 |
|---|---|
| (空 / 无参数) | 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 |
映射表之外还有两条判定规则:
- 自动流水线检测:若
$mode不是已知子命令,且包含 JD 文本特征词("responsibilities"、"requirements"、"qualifications"、"about the role"、"we're looking for",或「公司名 + 职位」)或指向 JD 的 URL,则执行auto-pipeline; - 若既不是子命令、也不像 JD,则回落到
discovery菜单。
以路由表中最重的目标 auto-pipeline 为例,其实现位于 modes/auto-pipeline.md,流程为:Step 0 提取 JD(优先 Playwright 渲染 SPA,可配置 scan.extractor: cli 走 browser-extract.mjs 返回紧凑 JSON,静默回退)、Step 0.5 存活性门禁(拒绝评估 404/已关闭岗位)、Step 0.6 黑名单门禁、Step 1 A–G 评估(复用 oferta 模式的评估块)、Step 2 保存报告、Step 3 按 cv.output_format 分派到 latex / text / 默认 pdf 流水线。这印证了 SKILL.md 的设计:路由器只做分诊,重活全部委托给 modes/ 下的模式文件。
输出语言指令:市场词汇与行文语言解耦
路由器规定:在执行任何模式之前,若 config/profile.yml 存在,须先读取并解析两个键(参考示例 config/profile.example.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.output 对行文语言具有最高权威;modes_dir 只注入市场上下文(例如用 modes/de 的 DACH 市场词汇仍可以英文行文)。示例配置中注释也明确了二者区别:output 选择散文语言,modes_dir 选择市场词汇/规则。这一设计使项目支持的多语言模式目录(modes/de/、modes/zh/ 等 20 余个本地化目录)与用户输出语言正交组合。
Discovery 菜单:命令中心的完整能力清单
无参数调用时,CLI 会展示如下菜单(SKILL.md 原文菜单,Codex 中以纯文本呈现相同选项):
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 走全流水线。从源码结构看,oferta/ofertas/contacto 等西语命名的模式对应 modes/ 下的同名文件(如 modes/oferta.md),而菜单中的能力描述与路由表 Input 列完全对齐——菜单本质上就是路由表的人类可读渲染。
按模式加载上下文:三级文件与子代理委派
确定模式后,路由器规定了严格的上下文加载顺序,其中若 modes/_custom.md 存在,须在读完 modes/_profile.md 之后、加载所选模式文件之前读取——它承载用户的「家规」与流程偏好,可覆盖工作流/风格默认值,但永远不引入关于候选人的事实性声明(与 AGENTS.md 中 Source-of-Truth 边界一致)。加载分三类:
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。这些都是重评估/重生成路径,需要共享评估规则(_shared.md 中也包含 spend_tier 模型档位解析:缺省 standard,非法值回退 standard 并提示一次)。
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。当前仓库 modes/regional/ 目录中包含 eu-swe.md,与路由表中 eu-swe → regional/eu-swe 的映射对应(regional/eu-fintech 为路由表声明的目标模式)。
3. 委派给子代理的模式
对于 scan、apply(使用 Playwright 时)、pipeline(3 个及以上 URL)这类长时任务,路由器要求以 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}"
)
最后一步是执行已加载模式文件中的指令。这个「路由—加载—委派」三段式保证了:主会话上下文不被大规模扫描占满(重活进 worker),而所有 worker 拿到的指令集与交互式运行完全一致——批量与交互路径对同一份 JD 的处理语义相同。
小结:单文件路由带来的工程收益
从 SKILL.md 的实现可以归纳出三条可复用的设计:
- 薄入口、厚模式:技能文件只做解析与加载编排,全部业务规则下沉到
modes/与AGENTS.md,使同一套语义能同时服务斜杠命令、自然语言提示与无头批处理(对照 docs/SUPPORTED_CLIS.md 的十种 CLI 入口); - 哨兵式根解析 + 分层数据契约:
AGENTS.md+modes/双哨兵定位PROJECT_ROOT,再叠加 User Layer / System Layer 划分,使嵌套检出与子目录启动都不破坏路径解析,且系统更新不会覆盖用户个性化数据; - 正交配置轴:输出语言(
language.output)、市场词汇(language.modes_dir)、模型档位(spend_tier)相互独立,一个 frontmatter 驱动的mode参数即可路由到 40 余个行为确定的模式。
若要在自己的 Agent CLI 项目里复刻这套结构,起点就是:写一个带 arguments/user_invocable 元数据的路由器 SKILL.md,用哨兵文件锚定项目根,用一张「输入→模式」表加两条兜底规则(内容特征检测、菜单回落)完成分诊,再按模式声明上下文加载清单——career-ops 的 .opencode/skills/career-ops/SKILL.md 可直接作为参照实现。
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