Your first scan¶
From an empty pipeline to a paste-ready application in one Claude conversation. This assumes you finished Install: config.yaml written, profile.yaml and company_list.yaml filled in, and the MCP server registered.
How to scan the companies you care about¶
- List the companies. In
company_list.yaml, put each company under its ATS (greenhouse,lever,ashby,workable,recruitee,smartrecruiters,inhire) and a phase (phase1,phase2,phase3); a plain list with no phases is scanned in every phase. The slug is the company's identifier in its job-board URL: forhttps://boards.greenhouse.io/acmeit isacme. - Try one company first. Ask Claude "what's open at acme on Greenhouse?". That runs
scan_company, which scans one board without touching your list — a wrong slug shows up here, not in the middle of a full scan. - Scan your list. Ask "scan my companies". That runs
scan_and_evaluate, which fetches every posting from the companies underphase1and scores the new ones. Ask for phaseall(orphase2,phase3) to cover more. - Scan without spending LLM calls (optional). From a shell,
moonlighter-scan --no-evaldiscovers and stores postings unscored, asneeds_review; score one later withverify_job. See Command line.
You: scan my companies
moonlighter: 3 sources scanned — 41 postings, 38 already known, 3 new
✓ NEW — Acme Robotics / Senior Backend Engineer
Score: 8.1/10 (threshold: 6.5)
✓ NEW — Nimbus Health / Staff Engineer
Score: 7.4/10
✗ Vandelay Industries / .NET Architect — 3.2/10, archived (hard filter: .NET)
The conversation is illustrative: Claude relays the tool's output in its own words. The tool itself reports how many jobs were processed, how many passed the threshold (with a table of them), and how many were filtered by title, archived for location, or scored below the threshold.
How to read the scores¶
- Each score is 0–10, from the LLM comparing the posting against your
profile.yaml, including the hard and soft filters undercriteria. - Below the threshold, the job is archived automatically. The threshold is
score_thresholdinconfig.yaml, 6.5 by default. A posting that breaks one of your hard filters (".NET" above) scores low and is archived with the reason. - Some jobs are archived before any LLM call. A title matching
title_blocklistinconfig.yamlis saved asarchivedwith a note, unscored. So is an onsite or hybrid posting outside the city you set ascriteria.home_cityinprofile.yaml; without that key, nothing is archived by location. A remote posting, or one whose location doesn't settle the question, goes on to be scored. - An empty description can't be scored. Those jobs wait as
needs_review: ask forlist_jobswith statusneeds_review, open the posting, copy the whole page, and pass it toverify_jobto score it. - Browse what passed with
list_jobs(statusnewby default) and open one withget_jobfor its full details and history.
How to prepare your first application¶
- Ask for the sheet. "Prepare the application for the Acme one" runs
prepare_application. Where the ATS API publishes the form's questions (Greenhouse, Recruitee), moonlighter reads them from there. - No API? Paste the page. When the questions aren't published, it asks you to open the application page, select all, copy, and hand the text over — that runs
prepare_application_from_paste. - Review the whole sheet. Every question gets an answer drafted from your profile, or a flag saying why it needs you. This excerpt is in the tool's real format; the model is told to answer UNKNOWN when your profile gives it no basis, and that comes back as a gap:
[5/9] How many years have you run Elixir in production? (required)
!! I DON'T KNOW — no basis in your profile to answer
1 of 9 need you
Answer the flagged ones yourself, and read the drafted ones too — the model can still get an answer wrong.
4. Paste and send it yourself. Copy the answers into the employer's form and submit it there. moonlighter never opens the form and never clicks submit.
5. Record that you sent it. Tell Claude "mark job 42 as submitted" — that runs update_status. With Gmail tracking on, the sheet's email field already carries a tracking alias, and the recruiter's reply finds this application by itself.