Job Hunt — Daily
Daily automation: search → score → tailor outputs for high-match jobs → digest.
What it does
profile.json + resume.txt (cached by jobhunt-setup)
│
▼ extract-keywords → "python,kubernetes,senior,…"
▼ job-search → ~50 listings across 4 boards
▼ score-listings → per-listing {url, score 0-10, rationale}
▼ generate-outputs → for each score ≥ 7: tailored resume + cover letter
▼ send-digest → "5 new matches today" message to the user
Per-job output folder structure:
/home/me/jobhunt/2026-05-13/
├── acme-corp-senior-backend-engineer/
│ ├── listing.md ← original posting + match score + rationale
│ ├── resume.md ← Claude-tailored, emphasizing matching experience
│ └── cover-letter.md ← personalized to this listing
├── …
└── DIGEST.md ← one-line summary per match
Setup before first run
- Run jobhunt-setup first. It produces the two files this workflow
depends on (
profile.json+resume.txt). - Credentials:
-
ollama— pointed at your local Ollama server. Used for cheap, private scoring. -claude-api— Anthropic API key. Used for tailored resume + cover letter. - Adzuna (optional). For broader board coverage (Indeed/LinkedIn
via aggregation), sign up free at developer.adzuna.com and paste your
app_id+app_keyinto thesearch-jobstask properties. Without it, the workflow still uses Remotive, We Work Remotely, and HN Who-is-hiring. - Schedule it. Use InTouch's Workflows view to attach a daily schedule (e.g. weekdays at 8 AM). Or run on-demand whenever you want a refresh.
Tunable knobs (in the YAML)
| Where | What | Default | Why change |
|---|---|---|---|
score-listings.model |
Ollama model for scoring | llama3.2 |
Use llama3.1 (8B) or mistral for better JSON adherence. |
generate-outputs.SCORE_THRESHOLD |
Min score to generate outputs | 7 |
Raise to 8 for stricter; lower to 5 to see more. |
generate-outputs.MAX_OUTPUTS |
Cap on tailored outputs per run | 5 |
Each tailored output is 2 Claude calls (~$0.02 each). |
generate-outputs.MODEL |
Claude model | claude-sonnet-4-6 |
claude-haiku-4-5 is cheaper if you'd rather spread across more listings. |
search-jobs.maxPerSource |
Listings per source | 30 |
Lower if scoring runs slow on your machine. |
search-jobs.country |
Adzuna country code | us |
gb, ca, au, de, fr, in, etc. |
Cost rough estimate per daily run
| Step | Provider | Calls | Approximate cost |
|---|---|---|---|
score-listings |
Ollama (local) | 1 | $0 — local compute |
generate-outputs |
Anthropic (claude-sonnet-4-6) | 2 × MAX_OUTPUTS (default 10) | $0.10-0.30 |
search-jobs |
HTTP only | 3-4 | $0 |
Adzuna's free tier is 100 calls/day — well above a daily run's needs.
Failure modes worth knowing
- Ollama returns malformed JSON for scoring → the python step strips
markdown fences but if the model goes off-script entirely, the JSON
parse will fail. Fix: change
score-listings.modelto a larger model. - No matches at threshold → script exits 0 with "No matches at
score >= 7" and
send-digestsends an empty-ish message. Lower the threshold or broaden keywords. - Anthropic 429 / overload → script raises and the task fails. Re-run.
- User has no email channel →
send-digestfalls back to whatever channels the user has (in-app inbox if nothing else configured). Set up SMTP / a contact's email for a real digest email.
Manual inspection helpers
After a run:
ls /home/me/jobhunt/$(date +%Y-%m-%d)/
cat /home/me/jobhunt/$(date +%Y-%m-%d)/DIGEST.md
Listings + scores from the latest run:
cat /tmp/jobhunt-listings.json | jq '. | length'
cat /tmp/jobhunt-scored.json | jq '.[] | select(.score >= 7)'