JobClaw
by @weixijia
AI-powered automated job search skill. Searches LinkedIn and Indeed daily, scores jobs against the user's profile, and saves results to a local CSV. Use when...
clawhub install job-clawπ About This Skill
name: jobclaw description: | AI-powered automated job search skill. Searches LinkedIn and Indeed daily, scores jobs against the user's profile, and saves results to a local CSV. Use when: - User says "run job search", "find jobs", "search for jobs", "start daily job search" - User types "/newjob URL" to analyse a specific job posting - User asks to set up automated daily job searching - User asks to show job stats, top matches, or update a job status - User asks to configure or set up job search preferences - User asks for "job tracker", "JobClaw", or "job search automation" First-time setup: guide the user through conversational onboarding (see Conversational Setup below). After setup: search.py handles all searching; run_daily.sh for the full automated pipeline. Install via ClawHub: clawhub install job-claw
JobClaw
AI-powered job search automation. Searches multiple platforms, scores results against the user's profile, and maintains a local CSV tracker. No backend server or web dashboard required.
Quick Reference
See references/commands.md for all CLI commands and chat commands.
See references/screening_guide.md for scoring logic and interview type classification.
See references/keywords.md for keyword lists and search strategy.
Conversational Setup (First Run)
When a user first activates JobClaw, do not run setup.py directly. Instead, guide them through a natural conversation to collect all config values, then write config.json yourself at the end.
Check first:
test -f ~/Documents/JobClaw/config.json && echo "exists" || echo "not found"
If config doesn't exist, start the conversational flow below. Ask one topic at a time β never dump all questions at once.
Conversation Flow
Step 1 β Greeting
Hey! Let's get JobClaw set up. I'll ask you a few quick questions and have you searching for jobs in minutes.First β what's your name?
Step 2 β Background (after they give name)
Nice to meet you, [name]! Tell me a bit about your background β what kind of work do you do or want to do?
(e.g. "software engineer with Python/ML experience", "data scientist at a fintech", "researcher in NLP")
This helps me score jobs that actually fit you.
Step 3 β Skills (after background)
Got it. What are your key technical skills or tools? List whatever feels most relevant β I'll use these to boost scoring for matching jobs.(e.g. pytorch, python, sql, docker, react, java β whatever fits you)
Step 4 β Target roles (after skills)
What kinds of roles are you looking for? You can be specific or broad.(e.g. "ML engineer or data scientist", "backend engineer", "product manager", "research scientist")
Step 5 β Locations (after roles)
Where are you looking? List cities or regions β I'll search each one separately.(e.g. "London, UK", "Remote", "Berlin, DE and Amsterdam, NL", "New York, NY")
Step 6 β Search preferences (after locations)
A couple of quick settings:How recently posted should jobs be? (default: 48 hours)
Minimum match score to save a job? (default: 70 out of 100 β higher = fewer but better results) Hit enter to keep defaults, or tell me what you'd prefer.
Step 7 β Daily schedule (after preferences)
Do you want a daily automated search? I can run it every weekday morning and notify you of new matches.If yes β what time? (e.g. "7:30am", default is 07:30)
And your timezone? (e.g. Europe/London, America/New_York)
Step 8 β Notifications (after schedule)
Last one β how do you want to be notified when new jobs are found?1. Telegram Bot (you'll need a bot token from @BotFather)
2. Through OpenClaw (if you're using another channel like Signal or WhatsApp)
3. No notifications β I'll just save to CSV
Which works for you?
For option 1, ask for: bot token + chat ID (tell them to message @userinfobot to get their chat ID).
For option 2, ask for: channel name (e.g. telegram) and their chat/user ID.
For option 3, set notifications.enabled: false.
Step 9 β Write config and confirm
Once all answers collected, write ~/Documents/JobClaw/config.json using the template from assets/config.example.json, populated with the user's answers. Then confirm:
All set! Here's your config summary:π€ Name: [name]
π Skills: [skills]
π Locations: [locations]
β° Daily search: [time], [timezone]
π Notifications: [method]
Want me to run your first search now? (takes ~1-2 minutes)
If they say yes, run: python3
Daily Automated Search Workflow
Triggered by cron or the user saying "run job search":
# Reads: ~/Documents/JobClaw/config.json
Writes: ~/Documents/JobClaw/data/jobs.csv
Logs: ~/Documents/JobClaw/logs/daily.log
./run_daily.sh # both coding + noncoding
./run_daily.sh --mode coding
./run_daily.sh --mode noncoding
Or directly:
python3 scripts/search.py --mode all
python3 scripts/search.py --mode coding --dry-run
The search pipeline:
1. Reads config.json for keywords, locations, min_score, platforms
2. Searches LinkedIn + Indeed via python-jobspy
3. Scores each job (keyword-based, 0-100) using user.skill_keywords as boosters
4. Filters by min_score (default 70), deduplicates by company+role and URL
5. Appends qualified jobs to data/jobs.csv
6. Sends notification via OpenClaw/Telegram (if configured)
/newjob Command
When user says /newjob :
1. Fetch the JD: browser(action="navigate", url= then browser(action="snapshot")
2. Analyse against references/screening_guide.md:
- Company, Role, Location, Work Mode, Salary
- Match Score 0-100 with reasoning
- Interview Type estimate
- ML Direction, Seniority
3. Add to CSV:
import sys; sys.path.insert(0, "/scripts")
from tracker import JobTracker
t = JobTracker()
t.add_jobs([{...job dict...}])
4. Reply with score, match reasons, interview type, apply angleArchive Management
When user says "archive expired jobs", "clean up old jobs", "auto-archive":
# Dry-run (see what would be archived, no changes)
python3 scripts/archiver.pyApply archiving
python3 scripts/archiver.py --commitView archive stats
python3 scripts/archiver.py --statsRestore a job (by company name, role, or URL fragment)
python3 scripts/archiver.py --restore "DeepMind"
Archive rules (same as the web dashboard):
expired_30d β status New/Interested with no update for 30+ daysauto_rejected β status Rejected/Passed for 60+ daysurl_dead β non-LinkedIn URL returns 404/410 or contains "job has expired" etc.Archived jobs move from data/jobs.csv β data/jobs_archive.csv.
Auto-archive runs automatically at the end of every daily search (run_daily.sh).
Showing Stats
When user asks "show job stats", "how many jobs", "top jobs":
import sys; sys.path.insert(0, "/scripts")
from tracker import JobTracker
t = JobTracker()
t.print_summary()
top = t.top_jobs(10)
Setting Up Daily Automation (OpenClaw Cron)
1. Confirm daily time and timezone from config.json
2. Register an OpenClaw cron job:
Schedule: daily at , weekdays only
Command: JOBCLAW_DIR=~/Documents/JobClaw /scripts/run_daily.sh
Updating Config Mid-Conversation
When user says things like "also search in Berlin", "add React to my skills", "change time to 8am":
1. Load ~/Documents/JobClaw/config.json
2. Edit the relevant field
3. Save back
4. Confirm the change: "Done β I've added Berlin, DE to your search locations."
Environment
~/Documents/JobClaw/config.json (override with JOBCLAW_DIR env var)~/Documents/JobClaw/data/jobs.csv~/Documents/JobClaw/logs/daily.logpython-jobspy β install with pip install python-jobspy