career-ops 高频问题完全指南:从 Windows 安装报错到跨平台求职自动化实战
【免费下载链接】career-opsOpen-source AI job search: scan job portals, evaluate listings into a structured A-H report with a global 1-5 score, tailor your CV, track applications — runs locally in your AI coding CLI (Claude Code, Codex, OpenCode, Antigravity…)项目地址: https://gitcode.com/GitHub_Trending/ca/career-ops
导读:本文围绕开源 AI 求职工具 career-ops 的官方 FAQ 文档,逐一拆解社区最常问到的十五类问题,涵盖 Windows 技能安装修复、scan与scan:full的区别、批量运行避坑、低成本模型部署、跨公司职位重复投递(cross-listing)识别、自定义简历模板、数据可信度溯源、黑名单过滤等主题,并结合仓库源码(scaffolder/bin/skill-entrypoints.mjs、scan.mjs、scan-ats-full.mjs、fingerprint-core.mjs 等)说明底层原理。读完你既能排查日常使用中的常见故障,也能理解各功能的设计动机与实现边界。
1. Windows 上技能未加载:安装时的符号链接错误
问题现象:Windows 默认不创建符号链接(symlink),因此 Git 在检出仓库时,会把 CLI 技能入口文件(.claude/skills/、.opencode/skills/等目录下的文件)以普通指针文件而非真正的软链接形式检出。结果是技能内容不会加载,表现为"Skills aren't loading"。
官方解法:无需手动执行mklink,也无需开启 Windows 开发者模式(Developer Mode)。安装器与更新器都会自动检测这一情况:
# 已有安装,执行一次修复 node update-system.mjs apply --confirm # 全新安装 npx @santifer/career-ops init上述流程中的materializeSkillEntrypoints步骤会把指针文件替换为完整的规范技能内容。
源码佐证:scaffolder/bin/skill-entrypoints.mjs 中的materializeSkillEntrypoints(root)定义了这一机制:
- 它从规范路径读取权威技能内容(
readCanonical),遍历.claude/skills/、.opencode/skills/、.grok/skills/、.kimi/skills/等入口点; - 对每个入口执行
lstat检查:是真实符号链接则跳过(说明已正常);是普通文件且内容等于指针引用(如../../../.agents/skills/career-ops/SKILL.md)时,才把文件内容整体替换为规范技能正文; - 对应的
ensureSkillEntrypoints则负责在入口缺失时补建指针文件。
因此该修复是幂等、可重复执行的:真链接不动、坏指针被"实体化"。相关回归测试也可在 test-all.mjs 中检索materializeSkillEntrypoints找到(覆盖安装、更新、升级等场景)。
2.scan与scan:full的区别是什么?
两条命令对应两类扫描方向,核心差异在于数据源的方向:
| 维度 | npm run scan | npm run scan:full |
|---|---|---|
| 底层脚本 | scan.mjs | scan-ats-full.mjs |
| 数据来源 | 你配置在portals.yml中的公司清单,直连其 ATS API | 反方向:遍历公开 ATS 公司目录,找出与你title_filter/location_filter匹配的新职位 |
| LLM Token 消耗 | 零消耗(纯 API 抓取) | 零消耗(匹配在本地完成) |
| 适用场景 | 日常每日/每周的固定公司发现 | 更广泛的主动发现,覆盖未加入portals.yml的公司 |
package.json 中两脚本定义可直接印证:"scan": "node scan.mjs"、"scan:full": "node scan-ats-full.mjs"。
建议:把npm run scan作为日常例行;当你想跳出"已跟踪公司清单"、捕获来自新兴或尚未收录公司的职位时,运行npm run scan:full。若 ATS 供应商的列表 API 本身返回了职位描述字段(如 Lever 的descriptionPlain),scan:full还会为每条新职位做内容指纹,用于后面的跨列表检测(见第 5 节)。
3. 批量运行中如何避免触发 Token 或速率限制?
FAQ 文档给出的核心策略是分批小跑 + 断点续跑:
# 每次只处理 5 个职位,先检查输出质量 ./batch/batch-runner.sh --limit 5 # 中途被限流/网络错误打断后,从已完成任务处继续 ./batch/batch-runner.sh --resume-paused关键原则:若运行被速率限制或网络错误中断,不要从头重跑。--resume-paused会跳过已完成的工作,只接续未完成任务,避免在已成功的工作上浪费 Token。
源码佐证:查看 batch/batch-runner.sh 的 usage 帮助文本可以发现完整参数面:除--limit N与--resume-paused外,还有--parallel N(并行 worker 数,默认 1)、--dry-run(只展示待处理项)、--retry-failed(只重试失败项)、--start-from N、--max-retries N(默认 2)、--min-score N(低于该分的职位跳过 PDF/跟踪,默认关闭)、--rate-limit-sleep N(限流后等待秒数,默认 300)、--model NAME与--status/--watch进度查看等。注意该脚本依赖claude -p的--dangerously-skip-permissions与--append-system-prompt-file参数,因此目前是 Claude Code 专用。
4. 能否在更便宜或本地的模型上运行 career-ops?
可以——career-ops 对 AI 完全无绑定(AI-agnostic),可与任意 AI 编码 CLI 或独立脚本协作。
- 低成本/本地模型完整指南:见 docs/RUNNING_ON_A_BUDGET.md,覆盖 OpenCode、Qwen CLI、DeepSeek、OpenRouter、Ollama 等提供商,以及推荐的模型规格与省 Token 实践。
- 零成本方案:见 docs/FREE_TIER.md——career-ops 可在 Antigravity CLI 的免费额度上运行,无需 API Key、无需付费订阅,受 Google 每日配额限制。
- 已付费但按 Token 计费怎么办:这通常是环境中存在
ANTHROPIC_API_KEY,其优先级高于订阅。请查看预算指南中关于订阅的章节确认设置。
5. 扫描时的 "possible cross-listing" 警告是什么意思?
当扫描器显示如下警告时:
⚠ Possible cross-listing: Acme Corp / Senior AI Engineer ↔ TalentBridge / Senior AI Engineer (similarity 0.96)它表示两家不同公司的两个职位描述几乎完全一致——通常是猎头/中介把雇主直聘岗位的 JD 原样转发,只是删去或替换了雇主名。
为什么重要:如果你通过两个渠道都投递,中介和雇主会各自独立看到你的申请,形成"重复投递"(double-submission),可能损害与招聘团队的关系。
该怎么办:
- 同时阅读两份 JD,确认一份是雇主直发、一份是中介转发;
- 只选一个渠道投递。直投通常更稳妥;若中介与用人经理关系好,走中介也可能有用;
- 若两份职位其实是共享模板正文(如通用工程师模板)的不同岗位,则该警告是误报,可忽略并分别投递。
技术原理(源码级):该警告源于 JD 内容指纹,而非 URL 或公司名去重——后两者在直发+中介场景下往往不同,反而无法命中。从源码看:
- fingerprint-core.mjs 设计为"对规范化职位描述做 3-token shingle 的 64 位 SimHash"(16 个十六进制字符);
- SimHash 是局部敏感哈希:近似重复文本的指纹只差几个比特。扫描器对不同公司之间指纹相似度 ≥ 92%(即 64 比特中至多 5 位不同)且出现于 90 天时间窗内的两条记录发出警告;
- 指纹在本地根据 ATS API 已返回的文本计算,不产生额外网络请求;没有可用描述体的职位永远不会被赋指纹、也永远不会被标记;
- 指纹写入 data/scan-history.tsv 的第 8 列(
jd_fingerprint),第 9 列为原始发布日期。完整列说明见 docs/SCRIPTS.md,数据结构约定亦可参考 DATA_CONTRACT.md 中关于scan-history.tsv的描述。
6. 能否使用自己的简历(CV)模板?
可以。在 config/profile.yml 中设置cv.template(以及可选的cover_letter.template),值为templates/目录下模板文件的 kebab-case 名称:
cv: template: modern # 解析到 templates/cv-template.modern.html cover_letter: template: modern # 解析到 templates/cover-letter-template.modern.html规则细节:
- 名字
modern解析为templates/cv-template.modern.html;求职信用templates/cover-letter-template.<name>.html; - 留空则回退到内置默认模板
templates/cv-template.html(求职信为templates/cover-letter-template.html); - 也可以按次选择:在对话中直接要求"use the modern template"即可,无需改配置。
完整字段参考(含注释)见 config/profile.example.yml:cv.template注释说明它默认取templates/下cv-template.<name>.html,并给出了modern与zh-minimal(中文极简简历)示例;cover_letter.template同理。仓库中实际已交付的模板不止一套(见第 10 节),templates/sections/还提供可复用的段落片段。
7. 为什么 career-ops 拒绝使用我故事库(story bank)里的数字?
一句话原因:可信的数字 ≠ 已核实的数字。面试准备的文档往往为了匹配某个 JD 而草拟,其措辞可能被后续吸收进interview-prep/story-bank.md。若无溯源检查,一次准备中编造的数值会在下一次被复用,逐渐"洗"成看似的事实。
career-ops 采用两级信任模型:
- 一级:用户撰写的原始来源——如
cv.md、article-digest.md、config/profile.yml、modes/_profile.md、writing-samples/等,是事实主张的地面真相(ground truth); - 二级:累积/派生来源——如故事库、特定公司的面试准备,可提供叙述与措辞,但量化主张必须能追溯到一级来源,或携带受支持的标记:
- 视为已核实:
**Provenance:** user-stated YYYY-MM-DD或**Provenance:** source: cv.md; - 不视为已核实:
**Provenance:** derived-unverified、**Provenance:** user-cannot-confirm以及任意裸数值。
- 视为已核实:
本地审计命令(无需调用 LLM):
node story-provenance-check.mjs --summary源码佐证:story-provenance-check.mjs 头注释把每条数值主张归类为四种:existing(数值本身可在 cv.md 等一级来源找到)、supportedByResume(数值不在 cv.md 但 cv.md 的陈述间接支撑)、derived-unverified(仅出现在 story-bank.md 且无 Provenance 字段,是安全默认)、user-cannot-confirm(Provenance 字段被显式标为该值)。脚本只读:对标记的主张,你应当对一级来源核实并修正数字、删除数字只保留叙述,或者直接回答"我不知道"——最后一种回答被刻意设计为"一等公民":user-cannot-confirm标记能保证该数字在后续扫描中永不被当作已验证,诚实的不确定永远不会通过重复被"洗白"成自信的事实。
8. 如何阻止某家公司出现在扫描结果中?
三步启用公司黑名单:
- 复制模板:templates/blacklist.example.md →
data/blacklist.md; - 每行列出一家公司(可附带 Since / Scope / Reason 表格列作为你自选的记录);
- 保存即可生效。
行为契约(来自 templates/blacklist.example.md 与 docs/SCRIPTS.md):
scan.mjs会跳过黑名单公司的职位——匹配是大小写与标点不敏感的(与跟踪脚本共享的公司名规范化逻辑一致);- 跳过从不静默:运行摘要会报告
N skipped (blacklist),并把计数写入data/scan-runs.tsv的filtered_blacklist列; - 需要审计时可
--include-blacklisted放行:命中的职位会带note: blacklisted: {reason}注释流入data/pipeline.md; auto-pipeline、oferta、apply模式遇到命中会停下、引用你记录的原因,并要求显式确认后才继续——你的决定始终优先;- 黑名单只是闸门而非评分信号:它绝不改动任何分数;
- 默认不存在黑名单文件 = 不过滤;系统永远不会自动把公司加入列表。
scan-ats-full.mjs同样遵循此规则。
9.Discarded与SKIP有什么区别?
二者都是终态,语义差异在于你对待这家公司的态度阶段:
Discarded(已放弃):description定义为 "discarded by candidate or offer closed"——你评估过、考虑过,后来因候选人决定或职位关闭而停止推进;SKIP(跳过):定义为 "doesn't fit, don't apply"——从来就不是候选人,根本不适合投递。
漏斗含义:二者落在 dashboard 的不同分组,因此在漏斗中统计口径不同——SKIP 属于筛选(filtering),Discarded 属于中途退出(dropping out)。追踪漏斗时请勿混用。
源码佐证:templates/states.yml 是状态机事实源,同时被 writer(career-ops)与 dashboard(reader)消费。两个状态都是terminal: true,且各自带大量多语言别名(如discarded的西班牙语descartado/descartada、cerrada、cancelada;skip的no_aplicar、geo blocker等),便于多语言流水线写入精确状态。
10. 只有一个简历模板吗?
不。templates/目录包含(均可在仓库根下确认存在):
- templates/cv-template.html(内置默认 HTML)
- templates/cv-template.tex(LaTeX / Overleaf)
- templates/cv-template.zh-minimal.html(中文极简风格,配置
cv.template: zh-minimal) - templates/resume-template.html
- templates/cover-letter-template.html
- 以及
templates/sections/段落片段库
此外可参考第 6 节"能否用自己的简历模板"。想深入了解 LaTeX 工作流的读者可继续阅读 docs/latex.md 相关模式文档,但模板扩展的入口始终是config/profile.yml中的cv.template/cover_letter.template。
11. 为什么某些扫描会打开 Chrome,另一些不会?
Chromium 浏览器只在带--verify参数时启动。
- 普通扫描读取公开 ATS API,是纯文本请求,不需要浏览器;
--verify用于核对某条职位是否真的仍然在线(live),这需要真实的页面加载,因而启动 Chromium。
如果验证失败,报错会提示你运行npx playwright install chromium补齐浏览器二进制。
12. 能在 Docker 或自托管环境中运行吗?
可以。仓库根目录下有 Dockerfile 与 docker-compose.yml。不过请注意边界:career-ops 是local-first 且 human-in-the-loop(本地优先、人在环上)的,因此 Docker 只负责封装运行环境,它不会把 career-ops 变成一个自主常驻的服务,也不会替你去投递职位。每次决策仍需你亲自确认。
13. career-ops 支持多设备同步吗?
不支持。所有数据都是检出目录(checkout)里的文件,没有任何云组件。需要多设备同步的用户,做法是把整个目录放进某个同步盘/同步文件夹中。这与 docs/SETUP.md 描述的文件型数据契约一致(参考 DATA_CONTRACT.md 中的数据文件清单)。
14. 如何让一个问题分配给我处理?
直接在对应 issue 下评论,维护者会把 issue 分配给你(该规则也写在 CONTRIBUTING.md 中)。
对 PR 而言,无前置 issue 的贡献在以下范围内是受欢迎的:bug 修复、零鉴权(zero-auth)的扫描器 provider、文档与翻译。只有新功能、新模式与架构变更才需要先提 issue、issue-first 流程。
15. 不用终端能使用 career-ops 吗?
可以。官方在 docs/COWORK.md 中专门介绍了在 Claude Cowork 中运行的方式,并已完成端到端验证。常见踩坑点:Cowork 的 shell 没有 npm 网络访问权限,所以必须先在一个普通终端里完成git clone与npm install,再打开该文件夹——否则依赖安装会失败。
附:FAQ 速查表
| # | 问题 | 一句话答案 | 依据文件 |
|---|---|---|---|
| 1 | Windows 技能不加载 | 运行node update-system.mjs apply --confirm,materializeSkillEntrypoints自动实体化技能文件 | scaffolder/bin/skill-entrypoints.mjs |
| 2 | scan vs scan:full | scan 扫你配置的公司;scan:full 扫公开 ATS 目录里的新职位 | scan.mjs / scan-ats-full.mjs |
| 3 | 批量限流 | --limit 5小跑验证,中断后--resume-paused续跑 | batch/batch-runner.sh |
| 4 | 便宜/本地模型 | 完全 AI 无关,见 docs/RUNNING_ON_A_BUDGET.md 与 docs/FREE_TIER.md | — |
| 5 | cross-listing 警告 | 64 位 SimHash JD 指纹相似度 ≥92% 且公司不同 → 疑似中介转投 | fingerprint-core.mjs |
| 6 | 自定义简历模板 | cv.template: modern→templates/cv-template.modern.html | config/profile.example.yml |
| 7 | 故事库数字被拒 | 派生来源的量化主张必须带Provenance且可溯源;user-cannot-confirm永不升级 | story-provenance-check.mjs |
| 8 | 屏蔽公司 | 复制 templates/blacklist.example.md 到data/blacklist.md | docs/SCRIPTS.md |
| 9 | Discarded vs SKIP | 前者评估后放弃/关闭,后者根本不合适;漏斗口径不同 | templates/states.yml |
| 10 | 模板数量 | 不止一套:HTML/LaTeX/zh-minimal/resume/cover-letter + sections | templates/ |
| 11 | Chrome 随机打开 | 只有--verify活体校验才启动 Chromium | docs/SCRIPTS.md |
| 12 | Docker/自托管 | 可封装环境,但不是自主服务、不会替你投递 | Dockerfile / docker-compose.yml |
| 13 | 多设备同步 | 不支持云端;自建目录同步即可 | docs/SETUP.md |
| 14 | 领取 issue | 评论即可;bug/文档/翻译可免 issue 直接提 PR | CONTRIBUTING.md |
| 15 | 不用终端 | Claude Cowork 可用,但 clone +npm install须先在终端完成 | docs/COWORK.md |
以上就是 docs/FAQ.md 中全部高频问题的展开解答。若仍有疑问,建议先查阅安装细节文档 docs/SETUP.md 及各功能对应的 SCRIPTS 文档;新场景下请以本仓库当前版本的实际文件与命令为准。
【免费下载链接】career-opsOpen-source AI job search: scan job portals, evaluate listings into a structured A-H report with a global 1-5 score, tailor your CV, track applications — runs locally in your AI coding CLI (Claude Code, Codex, OpenCode, Antigravity…)项目地址: https://gitcode.com/GitHub_Trending/ca/career-ops
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考