Query Chinese big-tech campus + social recruiting from your terminal — job.ha7ch.com
npx @ha7ch/job-pro@latest tencent search "后台开发"
npx @ha7ch/job-pro@latest bytedance search "后台开发" --scope socialNo signup, no token, no proxy server. 50 companies, all live. The CLI talks
straight to each company's public API (e.g. join.qq.com for Tencent) and
prints JSON. Pipe it into jq, Claude Code, anything.
Every adapter accepts a unified --scope flag:
job-pro bytedance search "后台开发" --scope social --page-size 5
job-pro xiaohongshu all --scope campus
job-pro find "AI infra" --scope social --text--scope works on search, all, match, and the cross-company find
verb. Default (flag omitted) preserves each adapter's 1.0.93 behaviour
bit-for-bit — usually campus or a mixed feed. Adapters that can't query
the requested channel (Tencent / JD / Cainiao / WeBank / Hikvision / CICC /
Unitree have no public social-hire API) refuse fast with a useful message
instead of silently returning empty. On find, those companies are
silently skipped and reported under companies_skipped_by_scope.
Run job-pro help for the full company list, or see the roadmap matrix at
job.ha7ch.com. Per-release notes:
CHANGELOG.md.
Drop the prompt from job.ha7ch.com into Claude Code, attach your resume, and let the agent drive the CLI end-to-end.
1. It pulls the city's intern list and shortlists roles against your resume.
2. It pulls multiple JDs in parallel and grades each one line-by-line.
3. It hands you a final verdict — apply, fall back, or skip.
npm i -g @ha7ch/job-pro
job-pro --version
job-pro selftest # 3-stage end-to-end check; ~3sOr one-shot via npx:
npx @ha7ch/job-pro@latest help# search & inspect jobs
job-pro tencent search "数据科学" --page-size 10
job-pro tencent detail 1200791473415778304
job-pro tencent all --page-size 100 # drain every open post
# announcements
job-pro tencent notices
job-pro tencent notice 284
job-pro tencent flow "腾讯2026实习什么时候开始" --question-time 2026-05-13
# resume tooling (all offline)
echo "..." | job-pro tencent match -
job-pro tencent resume-check resume.md
# local memory for tracking your hunt
job-pro tencent memory set "stack=Go,Python" "target_city=深圳"
job-pro tencent memory event applied "腾讯后台 1200791473415778304"
job-pro tencent memory list
# list / browse adapters
job-pro list # human-readable, grouped by ATS family
job-pro list --compact # JSON for piping
# cross-company parallel search
job-pro find "intern" --text # scan all 50 in parallel
job-pro find "AI" --apply-ready --text # only show buckets you can fire today
job-pro find "前端" --companies tencent,bytedance,alibaba --limit 5Add --compact to any command for a single-line JSON output (pipe-friendly).
Submit applications from the CLI. 50 / 50 adapters expose an application schema; 45 / 50 have an executor wired (3 anon Greenhouse/Lever
- 42 session-required); 45 / 50 have endpoint-verified status. The 5 external adapters (Liepin × 4 + Unitree WeChat) are structurally IM-mediated and intentionally stay browser / chat handoff only.
# 1. Set up your profile (one-time)
job-pro profile init --interactive # prompts for the 5 essential fields (validates each)
job-pro profile lint # check format of every field (exit 1 on fail)
# or: job-pro profile init && $EDITOR ~/.jobpro/profile.json
# 2. Inspect a job's schema (no profile required)
job-pro xpeng apply 8548990002 --schema
# 3. Dry-run an application (no network)
job-pro xpeng apply 8548990002 # stage + preview the POST
job-pro xpeng apply 8548990002 --interactive --remember # fills answers, persists to profile
# 4. Verify the wire format against an echo server (no upstream impact)
job-pro xpeng apply 8548990002 --debug-submit-to https://httpbin.org/post
# 5. Actually submit
job-pro xpeng apply 8548990002 --confirm-submit
# Script mode still exists when you intentionally do not want a prompt:
JOB_PRO_I_UNDERSTAND_REAL_SUBMIT=yes \
job-pro xpeng apply 8548990002 --really-submitGreenhouse / Lever boards (xpeng / hoyoverse / weride) submit
anonymously. Every other family needs a captured session — run
job-pro extension for the path + install walkthrough, log into the
careers site once, click Export, then drop
~/Downloads/jobpro/<adapter>.session.json under ~/.jobpro/.
# After capturing nio's session via the extension:
job-pro nio apply 7639693860494543167 --confirm-submitThe CLI gates real submission behind four layers (refuses with a clear JSON mode at the first that fails):
- User consent: either
--confirm-submitinteractive confirmation, orJOB_PRO_I_UNDERSTAND_REAL_SUBMIT=yeswith--really-submitfor scripts. staged.ready— every required field is filled.endpoint_verified === true(URL probe-confirmed or end-to-end smoked) — bypass withJOB_PRO_ALLOW_SPECULATIVE_ENDPOINT=yes.- For non-anon families: captured
~/.jobpro/<co>.session.jsonAND <30 days old — bypass staleness with--allow-stale-session.
Bulk-stage with apply --batch <file|- (newline-separated post_ids;
- reads stdin); pairs with --form-file for uniform answers. Batch
intentionally refuses real submission — verify wire format with
--debug-submit-to, then submit jobs individually with --confirm-submit.
Five adapters (hikvision / cicc / cainiao / webank / unitree) are
intentionally external — recruiting is mediated through Liepin
recruiter chat or WeChat mini-programs; no API submission exists.
For those, apply surfaces the apply_url to open in browser.
See docs/auto-apply.md for the full per-adapter submission flow matrix.
Phase 1 — Read jobs: 50 / 50 companies, all live. See the full live matrix
with per-company status icons at job.ha7ch.com, or run
job-pro help for the canonical list.
Coverage by source family:
| Source family | Companies | Notes |
|---|---|---|
| Bespoke per-company API | 23 | Tencent, ByteDance, Alibaba, Meituan, Xiaohongshu, JD, … |
| Feishu Recruiting (ATSX) | 9 | Xiaomi, NIO, MiniMax, Zhipu, iQIYI, Agibot, Lilith via CDP, 01.AI, Baichuan |
| Moka (app.mokahr.com) | 7 | Moonshot, Megvii, DeepSeek, GalaxyUniversal, StepFun, Cambricon, Geely |
| Beisen Wecruit | 2 | SenseTime, Horizon Robotics |
| Beisen iTalent (zhiye) | 2 | vivo, iFlytek |
| Greenhouse / Lever | 3 | XPeng, WeRide, HoYoverse — international/US arms |
| Liepin third-party feed | 4 | Hikvision, CICC, Cainiao, WeBank (no canonical public feed exists) |
23 + 9 + 7 + 2 + 2 + 3 + 4 = 50.
Phase 2 — Auto-apply is live: 45 / 50 adapters have a submitter
wired (3 anon Greenhouse/Lever, 42 via captured browser session); the
remaining 5 are intentionally external (Liepin recruiter chat × 4 +
Unitree WeChat QR × 1 — IM-mediated, no API submission exists).
- Greenhouse / Lever boards (XPeng / WeRide / HoYoverse) only carry the international arm's postings (US AI center, Singapore game-dev, etc.). The China-side campus boards for these companies aren't publicly reachable from outside their networks; when they become accessible a sibling adapter will land.
- Lilith uses a Feishu tenant gated by a ByteDance Tengine
_signatureanti-bot token. The CLI cracks it viapuppeteer-coredriving the user's local Chrome. If Chrome isn't installed, this one adapter returns a helpfulok:falsewith the install hint — the other 49 are unaffected. - Hikvision / CICC / Cainiao / WeBank have no canonical anonymous public
feed (the first three are geo-fenced or DNS-internal; WeBank is WeChat-
mini-program-only). For these four the CLI surfaces real currently-open
positions through Liepin and clearly labels the
result with
source: "api-c.liepin.com"andattribution: "via Liepin (third-party aggregator) — official portal not publicly accessible". See docs/stub-unblock.md for the reasoning.
cli/— the npm package (TypeScript, Node 18+). Single runtime dep:puppeteer-core(used only by thelilithadapter, see above).cli/src/<company>.ts— one thin adapter per company.cli/src/{feishu,greenhouse,lever,moka,wecruit,liepin}.ts— generic SaaS-ATS factories. Adding a new tenant on an existing ATS is a ~30-line wrapper.cli/src/cdp.ts— singleton headless-Chrome helper for anti-bot upstreams. Reads$JOB_PRO_HTTPS_PROXYfor a CN-egress proxy when needed.cli/src/adapter.ts— the explicitCompanyAdaptercontract every adapter must satisfy.cli/test/smoke.ts— strict gate: any live adapter regressing took:falseFAILs the suite.KNOWN_LIMITEDis currently the empty set.src/— the job.ha7ch.com landing page (Next.js).python-reference/— the original Python port forjoin.qq.com.docs/— endpoint inventories per company, plusstub-unblock.mdwith the full recon history.extension/— manifest v3 Chrome extension that captures careers-site session cookies + CSRF headers for Phase 2 auto-apply. Load it viachrome://extensions/ → Developer mode → Load unpacked. Seeextension/README.md.
The data is public. We don't store anything on a server, don't see your queries, don't rate-limit you, can't go down. The flipside: you get the upstream's quirks (typos in field names, etc.) — we paper over them in the client, but if the upstream changes, the CLI may need a release.
The endpoint inventory for join.qq.com was recovered by inspecting the
official Tencent WorkBuddy skill bundle. We re-implemented the client in
both Python and TypeScript with our own structure, naming, and matching
heuristics. No prompt copy, no documentation copy, no skill body is reused.
Adding a new company is mechanical:
- Find its public listing/detail API. DevTools → Network on the careers
site is the fast path, but for SPAs with anti-bot challenges
(Tengine
_signature, EdgeOne JS cookies, etc.) you may needcli/probe/<company>-network.tsrunning puppeteer-core to intercept the real XHR — see existing probes for templates. - Identify the SaaS ATS family. If it's already supported
(
feishu/greenhouse/lever/moka/wecruit/liepin), add a ~30-line wrapper that callscreateAdapter({ … }). Otherwise write a bespoke adapter mirroringtencent.ts. - Wire it into
cli/src/index.tsADAPTERSandcli/test/smoke.ts. Thesatisfies CompanyAdapterclause will refuse to compile if any of the 9 required verbs is missing. - Add an entry to
src/app/page.tsx'sCOMPANIESarray. - Run
pnpm test. The smoke gate runs every adapter in parallel and FAILs onok:falsefor non-KNOWN_LIMITEDadapters. - Open a PR.
The auto-apply phase needs more thought — see the roadmap doc.
MIT — see LICENSE.


