关于 freehire-search
freehire-search 是用于搜索 freehire.me 技术职位的命令行技能;该聚合平台会统一多个 ATS 平台的职位数据。它支持结构化地点和职位筛选,搜索结果包含完整描述。
主要功能
- 01搜索技术类职位
- 02按地区、国家、城市和工作模式筛选
- 03按资历、类别和技能筛选
- 04搜索结果包含完整描述
- 05通过 slug 查询职位
适用场景
- 01查找欧盟地区的远程 React 职位
- 02按地区搜索高级后端职位
- 03查看已保存或已关闭职位的详情
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ madslorentzen/ ai-job-search --skill freehire-search安装后在 Claude Code 中输入/freehire-search确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
url-reference.mdcli/package.jsonREADME.mdtsconfig.jsoncli/src/cli.tshelpers.tscli/src/commands/detail.tssearch.tscli/tests/cli-flag-validation.test.tscommands.test.tshelpers.tsparsing.test.tsrequest-timeout.test.tsrequired-search-values.test.tsretry-backoff.test.ts详细介绍
freehire 搜索 Skill
从 freehire.me 职位聚合器搜索实时职位列表 —— 这是一个开源的 IT 职位板,将来自多个国家约 50 个 ATS 平台的职位统一为同一种数据结构。无需身份验证,无需 API key,且零运行时依赖 —— 仅用 bun 即可运行。市场通过 facet 标志(--region、--country)按查询选择,因此同一个 skill 对任何市场的 fork 者都能开箱即用。
这是本仓库职位门户 skill 模式的一个与国别无关的完整示例,类似
linkedin-search。与那些抓取 HTML 的门户不同,它查询 freehire 的公开 JSON API,因此结果是结构化的(技能、资历、地区 facet),而非从标记中解析而来。
⚠️ 适用范围:以技术为主
freehire 的语料库已包含一些非技术职位(它会抓取整个公司的招聘页面),但其分面筛选 —— 技能、类别和资历词典 —— 目前是以技术为先调优的,因此本 skill 将触发范围限定在软件 / 数据 / 工程 / 技术类职位,这些职位的筛选效果最强。非技术类覆盖虽然存在,但仍在成熟中;目前尚不能依赖本 skill 来覆盖一般(非技术)职位。
ℹ️ 托管服务依赖(尽力而为,无 SLA)
本 skill 依赖第三方托管服务 freehire.me。读取操作是公开且无需身份验证的 —— 与 linkedin-search 一样无需注册。
freehire.me 是一个个人项目,但仍在积极维护;它以尽力而为的方式运行(无正式 SLA)。 如果 API 无法访问,CLI 会优雅失败 —— 以非零退出并给出清晰的错误信息 —— 因此服务中断只会降低此来源的可用性,而不会破坏整个工作流。
可自托管 / 可替换的 base URL。 freehire 后端是一个独立的 MIT 许可仓库 —— strelov1/freehire(Go + PostgreSQL + Meilisearch)—— 通过 Docker Compose 一条命令即可启动(make up → API 位于 :8080,相同的 /api/v1/... 路径)。本 skill 支持一个 base-URL 环境变量 FREEHIRE_API_URL(默认 https://freehire.me),因此将其指向本地实例只需改一行:
FREEHIRE_API_URL=http://localhost:8080 bun run .agents/skills/freehire-search/cli/src/cli.ts search -q "go"
注意事项:启动 API 很轻量,但维护一个完整、持续更新的镜像(约 50 个平台上的数百万条职位)则资源消耗很大 —— 自托管者要么抓取限定范围的来源子集,要么将环境变量指回托管 API。
何时使用本 skill
- 按关键词搜索某个地区/国家或远程的技术职位 —— 每条结果都会返回其完整描述,无需逐条跟进
- 按资历、类别、技能或时效(发布于 N 天内)进行筛选
- 通过 slug 查找某条 freehire 职位(包括已关闭的职位)
命令
搜索职位列表
bun run .agents/skills/freehire-search/cli/src/cli.ts search [-q "<keywords>"] [facet flags]
关键标志:
--query <text>/-q <text>— 关键词搜索(标题、技能、角色)。全文搜索;可选。--jobage <days>— 在 N 天内发布(映射到posted_within_days)。--page <n>— 从 1 开始的页码。默认 1。--limit <n>/-n <n>— 每页结果数(API 限制)。默认 25。--format json|table|plain— 默认json。--description-format markdown|text|html— 每条结果的完整描述如何 呈现。默认markdown,这会保留职位发布的标题和要求 列表的完整性。仅适用于json输出。
搜索结果已经带有完整描述。 此技能查询 freehire 的
agent 搜索端点,该端点会用每个
职位发布的完整文本替换索引中的截断预览,因此搜索 20 个角色只需 1 次请求,而不是 1 + 20 次。
不要对搜索结果循环调用 detail 来读取它们的描述 — 只有在
按 slug 查找单个职位时才使用 detail(例如,从跟踪器中,或某个已关闭因此不在搜索结果中的职位)。
完整描述很冗长:
保持 --limit 适中,并在阅读正文之前按标题/公司预过滤 -
或者传入 --no-description 进行一次低成本发现遍历,保留所有其他
字段并完全去掉正文(用
detail 获取入围职位的正文,或者在不带该标志的情况下重新运行搜索)。
分面过滤器(值来自 freehire 的受控词表;同一分面内用逗号分隔表示 OR):
--region <codes>— 宏观区域,例如global、eu、us、apac、latam、cis。--region eu,us。使用none匹配区域无法解析的职位(见下文“部分数据”)。--country <codes>— ISO-3166 alpha-2,例如--country DE,GB--city <names>— 城市名称,例如--city Berlin--seniority <levels>—junior、middle、senior、staff、principal、lead、……--category <cats>—backend、frontend、fullstack、devops、ml_ai、qa、……--skill <names>— 规范技能,例如--skill go,kubernetes--company <slug>— 公司 slug(来自结果的company_slug)--remote <mode>—remote|hybrid|onsite(work_mode分面)--facet <key=value>— 任何其他分面参数(可重复),例如--facet salary_min=100000
位置是一个分面,不是自由文本。 不同于
linkedin-search的--location, freehire 通过结构化的--region/--country/--city分面来过滤地理信息。可在/api/v1/jobs/facets查看某个市场的实时值 (追加?q=<role>来限定范围)— 绝不要凭空编造分面值。
获取完整职位详情
bun run .agents/skills/freehire-search/cli/src/cli.ts detail <slug|url> [--format json|plain]
slug 是来自 search 结果的 id(例如 golang-zensar-2bxu6dxm)。你也可以
传入完整的 https://freehire.me/jobs/<slug> URL。返回完整(已去除 HTML)
的描述、技能、区域/国家,以及 — 当职位发布已丰富时 — 资历、
类别、雇佣类型和薪资。当 freehire 记录了薪资周期时,salary 会保留该周期
(INR 300000–300000/year、INR 12000/month);只能在同一周期内比较薪酬。
当你已经有一个职位的 slug 时使用它 — 例如已跟踪的申请、共享
链接,或搜索不再列出的已关闭职位。重新获取 search
刚刚返回的命中项只会重新读取你已经拥有的描述。
使用示例
# Senior backend roles, table view
bun run .agents/skills/freehire-search/cli/src/cli.ts search -q "backend engineer" --seniority senior --limit 10 --format table
# Remote React roles in the EU
bun run .agents/skills/freehire-search/cli/src/cli.ts search -q "react" --remote remote --region eu --format table
# DevOps roles in Germany posted in the last 14 days
bun run .agents/skills/freehire-search/cli/src/cli.ts search --category devops --country DE --jobage 14 --format table
# ML/AI roles anywhere, fully remote
bun run .agents/skills/freehire-search/cli/src/cli.ts search -q "machine learning" --category ml_ai --remote remote --format table
# Descriptions as plain text instead of Markdown
bun run .agents/skills/freehire-search/cli/src/cli.ts search -q "platform engineer" --limit 5 --description-format text
# Full details for a specific job
bun run .agents/skills/freehire-search/cli/src/cli.ts detail golang-zensar-2bxu6dxm --format plain
输出格式
| 格式 | 适用场景 |
|---|---|
json | 默认格式——适用于程序处理;唯一包含每条结果描述的格式 |
table | 快速浏览,便于人类阅读 |
plain | 查看单个职位的完整详情(detail 命令) |
搜索结果的 JSON 结构为 { "meta": { "count", "page", "total" }, "results": [...] };每条结果至少包含 id(freehire slug)、title、company、location、date、url 和 description(缺失值为 null)。table 和 plain 格式不包含描述——描述会让列表难以浏览。所有错误都会以 { "error": "...", "code": "..." } 的形式写入 stderr,进程以代码 1 退出。
部分数据
筛选项按职位生成,数据可能不完整,尤其是地理信息。
职位可能已解析出 work_mode(例如 remote),但因来源中的地点文本含糊而无法确定地区或国家/地区(freehire 的字典不会进行猜测)。因此:
- 缺少地区/国家/地区表示“未解析”,而不是“不适用”——使用
--region eu筛选时,未解析出地区的职位会被静默排除,即使它们实际上位于欧盟也是如此。若要找回这些职位,请扩大筛选范围或移除该筛选项。 - 有一个专门用于未解析类别的筛选值:
--region none可匹配没有已解析地区的职位——适合筛选出从未明确标注地理位置的远程职位。它可以与实际地区使用 OR 逻辑组合,例如--region eu,none。 - 出于相同原因,
result.regions/countries/cities可能是空数组;应将空数组视为未知,而不是“以上均不符合”。
说明
- 数据来自 freehire.me 的公共 API——无需凭据。只有按用户追踪(申请/保存)需要密钥,而此技能有意不使用该功能:它仅支持搜索和查看详情。
- 搜索结果中的
id是 freehire 的public_slug——将其原样传给detail。 date是职位发布的日期,格式为YYYY-MM-DD(取自 API 的posted_at时间戳中的日期部分,这是所有招聘门户 CLI 都会输出的格式);未注明日期的职位可能为null。- 筛选值属于受控词表。筛选前,可使用
/api/v1/jobs/facets查看查询对应的实时值(及其数量)。 - API 会在遇到 429/5xx 错误时采用指数退避重试;若 API 无法访问,进程会以非零状态退出并显示明确消息(尽力提供服务,参见上文的依赖说明)。
search会调用/api/v1/agent/jobs/search(与其他接口一样公开);--no-description会调用较轻量的/api/v1/jobs/search,该接口不提供完整正文。比该接口更旧的可自托管实例会返回 404,CLI 会报告错误并注明接口名称——绝不会将其当作空结果集。