Install
openclaw skills install job-search-skillSearches LinkedIn, Poslovi Infostud, and HelloWorld.rs for jobs matching your target roles. Scores each listing against your resume PDF (1-10 with justification) using your configured LLM. Results in chat, optional email digest, optional daily cron. No auto-applying. Cover letters on demand. Use when the user says: - "Run the job search" - "Find jobs for me" / "Search for jobs" - "Set up daily job search" / "Schedule the job search" - "Enable email for job results" - "Write a cover letter for [job title / company]" - "Generate a cover letter for [pasted job description]"
openclaw skills install job-search-skillThree modes:
| File | Purpose |
|---|---|
workspace/resume.pdf | Resume PDF. User replaces to update CV. |
workspace/roles.txt | Target job titles, one per line. |
workspace/config.json | Search, email, and cron settings. |
data/seen_jobs.db | SQLite — deduplication across runs. Auto-created. |
scripts/scrape.py | Fetches jobs from LinkedIn, Infostud, HelloWorld.rs. |
scripts/extract_resume.py | Extracts text from resume.pdf. Prints to stdout. |
scripts/mark_seen.py | Marks shown jobs as seen. Run after output. |
scripts/send_email.py | Sends HTML email digest. Only if email.enabled=true. |
python scripts/scrape.py
Writes new unseen jobs to data/raw_jobs.json.
python scripts/extract_resume.py
Read the printed resume text carefully — you need it for scoring.
Read data/raw_jobs.json. For each job score the fit against the resume 1–10.
Scoring guide:
Be specific. Reference actual skills/experience from the resume against actual
requirements in the job. Use the tags field where descriptions are absent.
Only include jobs at or above config.json → search.min_score_to_include.
Sort by score descending, grouped by source. Format each job as:
🟢 [9/10] Strong fit
Senior .NET Developer
Luxoft Serbia · Belgrade
Tags: .NET, Azure, SQL
🔗 https://...
↳ [your 2-3 sentence justification]
🟢 = score 8–10 · 🟡 = 6–7 · 🔴 = below 6
Top summary line: "Found X jobs — Y 🟢 strong · Z 🟡 good · W 🔴 moderate"
Always run after outputting results:
python scripts/mark_seen.py
Then check config for email:
python scripts/send_email.py
If email.enabled is false in config.json, the email script prints "Email disabled"
and exits cleanly — no error, nothing to do.
If email is enabled, it sends the HTML digest automatically.
When the user says "set up daily job search" or "schedule this" or "run it every day at [time]":
Read workspace/config.json to get the preferred time and timezone.
Default is 09:00 Europe/Belgrade unless the user specifies otherwise.
Update config.json to set cron.enabled = true and the user's preferred time.
Register the cron job with OpenClaw:
openclaw cron add \
--name "Daily Job Search" \
--cron "0 9 * * *" \
--tz "Europe/Belgrade" \
--session isolated \
--message "Run the job search"
Adjust the hour (0 9 = 9am) to match the user's chosen time.
To cancel: openclaw cron list to find the job ID, then openclaw cron delete <id>
When the user says "enable email" or "also send results by email":
Ask for: Gmail address, Gmail App Password (16-char, from myaccount.google.com/apppasswords), and recipient email (can be the same address).
Update workspace/config.json:
email.enabled to truesmtp_user, smtp_pass, recipientConfirm: "Email enabled. Results will be sent to [address] after each job search."
Note: Gmail requires an App Password (not the regular login password). Generate one at: myaccount.google.com/apppasswords
When the user asks for a cover letter for a specific job:
python scripts/extract_resume.py and read the output.Rules — non-negotiable:
Output the letter in chat. The user copies and edits it themselves.
workspace/resume.pdf is missing: stop and tell the user.workspace/roles.txt is empty: stop and tell the user.