ai-job-agent
CLAUDE.md61 starsChanged 6 months agoMITView on GitHub
This is a job application automation toolkit. It automates filling and submitting applications on LinkedIn Easy Apply, Greenhouse, Lever, Jobvite, and Ashby, plus email triage and Google Sheets tracking. Two ways to drive it: Installed by bash skills/install.sh (symlinks them into ~/.claude/skills/). Each skill's prompt lives at skills/<name>/SKILL.md — read it to see exactly what the agent does. First-run flow (gstack-style): open Claude Code anywhere and paste this one message: Install ai-job-agent: run git clone --single-branch --depth 1 https://github.com/AkbarDevop/ai-job-agent ~/.claude/skills/ai-job-agent…
- Installs packages
We split this CLAUDE.md into the rules it gives an agent
13 rules. About 0 are common, 9 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈9
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 75
All personal details are in the config/ directory:
- Distinctive: line 86
Legacy (raw scripts): Search → Apply → Track → Triage.
- Very specific: line 90
Use /job-search or python-jobspy to find matching roles.
- Distinctive: line 121
After each successful submission:
- Distinctive: line 129
Use the Outlook scripts to search for confirmation and rejection emails:
- Distinctive: line 144
When you receive rejections, interviews, or other updates:
- Distinctive: line 152
Truthfulness first: Prefer truthful, submittable applications over aggressive volume.
- Distinctive: line 154
Resume selection: Use the appropriate resume variant for each role type (see candidate-profile.md for the mapping).
- Distinctive: line 155
Captcha honesty: If a form stalls behind CAPTCHA, log it as "blocked" -- never inflate submitted counts.
- Distinctive: line 156
Headless default: Use headless browser by default.
- Distinctive: line 179
All application scripts use consistent exit codes:
- Very specific: line 218
Web browsing: use /browse for all web browsing.
- Very specific: line 225
If gstack isn't installed, those skills are optional — this repo's 13 bundled skills (/job-coach, /job-setup, /job-evaluate, /job-apply, …
≈ “Common” is an estimate: at least 1 in 5 of the 25,680 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
AI Job Application Agent - Claude Code Instructions
Overview
This is a job application automation toolkit. It automates filling and submitting applications on LinkedIn Easy Apply, Greenhouse, Lever, Jobvite, and Ashby, plus email triage and Google Sheets tracking.
Two ways to drive it:
- Bundled skills (recommended) — type
/job-coach,/job-apply,/job-evaluate,/job-cv,/job-track,/job-triage,/job-status,/job-outreach,/job-followup,/job-dashboard,/job-interview,/job-patterns, or/job-setupin any Claude Code session. Each skill wraps the scripts below and renders results as a markdown table. Install once withbash skills/install.sh. - Raw scripts — call the Node.js / Python scripts in
scripts/directly from your terminal (documented below).
Bundled Skills
Installed by bash skills/install.sh (symlinks them into ~/.claude/skills/). Each skill's prompt lives at skills/<name>/SKILL.md — read it to see exactly what the agent does.
| Skill | Wraps | Output |
/job-coach | the persona — intake, research, slate, dispatch | target-role slate + next-move suggestions; persists to config/search-plan.md |
/job-setup | wizard.sh equivalent — but in chat | conversational onboarding, auto-reads user files, writes configs, registers skills |
/job-apply <url> [--submit] | 5 ATS fillers (auto-routed by URL host) | result table: platform, outcome, exit code |
/job-track [sync] | local CSV + google-sheet-sync.py | counts-by-status table + recent activity |
/job-triage [query] | outlook-triage.js | classified-email counts + preview table, step-through extract/mark-read |
/job-status <updates.json> | tracker-status-update.py | before/after diff, confirmation prompt, result summary |
/job-outreach <target> | send-cold-email.js + Claude (the agent drafts) | research → draft preview → dry-run → send → log to outreach-log.csv |
/job-followup [send] | outreach-log.csv + send-cold-email.js | urgency table (overdue/due/soon/waiting) + optional step-through send |
/job-dashboard [live] | job-dashboard.mjs (zero deps) | ANSI tables: applications + outreach + follow-ups. Snapshot in chat or npm run dashboard for live TUI |
/job-evaluate <url> | WebFetch + 7-block A-G rubric + /job-cv chain + tracker append | structured eval report at reports/<date>-<company>-<role>.md + tailored PDF + tracker row |
/job-cv <jd> | scripts/generate-tailored-cv.mjs (Playwright Chromium → PDF) | Claude rewrites base CV (no invention) → ATS-friendly PDF at output/cv-<company>-<date>.pdf |
/job-interview <company> | application-tracker.csv + WebSearch + WebFetch | company snapshot + 10-15 likely Qs + 5-8 STAR stories from real projects + 5 smart asks + 3 red flags |
/job-patterns | application-tracker.csv + outreach-log.csv | rejection diagnostics (by ATS / time-to-rej / geography / role-type / day-of-week) + 3 actionable fixes |
First-run flow (gstack-style): open Claude Code anywhere and paste this one message:
Install ai-job-agent: run
git clone --single-branch --depth 1 https://github.com/AkbarDevop/ai-job-agent ~/.claude/skills/ai-job-agent && cd ~/.claude/skills/ai-job-agent && bash skills/install.shthen add an "ai-job-agent" section to my CLAUDE.md telling you to treat me like a career-coaching client — open-ended job-search talk →/job-coach(intake + research + slate), job URL alone →/job-apply, "evaluate this URL" →/job-evaluate(rubric + report + tailored CV), "tailor my CV" →/job-cv, "prep me for X interview" →/job-interview, "what's working / why am I getting rejected" →/job-patterns, reaching out to a person →/job-outreach, follow-ups →/job-followup, "how am I doing" →/job-dashboard, tracker →/job-track, status updates →/job-status, Outlook →/job-triage, first-time setup →/job-setup. Never answer job-search questions conversationally — always dispatch. Tell me when done, then run /job-setup and chain into /job-coach intake.
Claude clones into ~/.claude/skills/ai-job-agent/, registers all 13 skills as symlinks under ~/.claude/skills/, writes the coach-first routing block into CLAUDE.md, runs /job-setup (identity + resume + optional msmtp), and chains into /job-coach intake (target roles + companies + timeline → live market research → ranked slate of next moves). After that, the user talks naturally — "I want to apply to this url", "email the VP at X", "evaluate this posting", "tailor my CV for this JD", "prep me for my interview at Y", "what's working" → diagnostics, "how am I doing" — and Claude dispatches to the right skill. No cd required ever; skills work from any directory in any session. bash wizard.sh and bash setup.sh still exist for non-Claude-Code users.
Skills find this repo via $AI_JOB_AGENT_ROOT → ~/.claude/skills/ai-job-agent/REPO_PATH → ~/ai-job-agent. Set the env var or rerun install.sh from a non-default clone location.
Unified mode — npm run agent
Daily driver. Opens Claude Code chat (top pane) + live TUI dashboard (bottom pane) in one terminal window via tmux. They auto-sync via fs.watch — anything Claude does in chat that touches application-tracker.csv or outreach-log.csv re-renders the dashboard within ~200ms.
Launcher: bin/job-agent.sh. If tmux isn't installed it offers to brew install tmux (macOS) or apt install tmux (Linux) with a one-key confirmation. On decline, falls back to opening two Terminal/iTerm tabs (macOS) or printing manual instructions (Linux).
NPM scripts
| Command | Purpose |
npm run agent | Unified mode — Claude Code + live TUI dashboard, split-pane via tmux |
npm run dashboard | Interactive 5-tab TUI dashboard (Applications · Outreach · Follow-ups · Pipeline · Reports) |
npm run dashboard:snapshot | One-shot ANSI snapshot to stdout (used by /job-dashboard skill) |
npm run mirror | Generate data/applications.md + data/outreach.md from CSVs (markdown twin) |
npm run mirror:watch | Same, but rerun on every CSV change via fs.watch |
npm run smoke | Fresh-install smoke test in a sandboxed $HOME (CI-safe) |
npm run doctor | Health check on the real environment (toolchain, configs, msmtp, gcloud, skill files) |
npm run linkedin / greenhouse / lever / jobvite / ashby | Direct ATS form-fillers (legacy CLI surface, wrapped by /job-apply) |
npm run triage / send | Outlook search + send via CDP (legacy CLI surface, wrapped by /job-triage) |
Output locations (all gitignored)
| Path | Owner | Contents |
application-tracker.csv | source of truth | every applied / evaluated / interview / offer / rejected row |
outreach-log.csv | source of truth | every cold email sent + replies + follow-up cadence |
data/applications.md | npm run mirror | markdown twin of application-tracker.csv |
data/outreach.md | npm run mirror | markdown twin of outreach-log.csv |
reports/<date>-<co>-<role>.md | /job-evaluate | per-JD rubric report (A-G blocks + sources + recommended move) |
output/cv-<co>-<date>.pdf | /job-cv | tailored ATS-friendly PDF resume |
interview-prep/<date>-<co>-<role>.md | /job-interview | STAR prep doc + smart Qs + red flags |
config/search-plan.md | /job-coach | the live job-search plan (intake outputs, target tiers, log) |
Configuration
All personal details are in the config/ directory:
config/candidate-profile.md-- Full candidate profile, application rules, session state, and agent handoff context. Read this first in every session.config/answer-bank.md-- Pre-written answers for common application questions.config/linkedin-config.json-- LinkedIn Easy Apply config with identity, resume path, and Chrome cookie path.config/example-config.json-- Reference example showing all available fields.
Workflow
Recommended (skill-driven): /job-coach (intake + slate) → for each row: /job-evaluate <url> (deep-dive + rubric) → if fit ≥ 4.0, automatically chains into /job-cv (tailored PDF) and offers /job-apply → after applying, run /job-followup weekly → /job-triage to log replies → /job-status to flip rows → /job-patterns once a month for diagnostics → /job-interview whenever an interview shows up.
Legacy (raw scripts): Search → Apply → Track → Triage.
1. Search for jobs
Use /job-search or python-jobspy to find matching roles. Filter by:
- Role fit (match resume variants to role types)
- Work authorization eligibility
- Location preferences
- Recency (prefer jobs posted in the last 72 hours)
2. Apply to jobs
Choose the right script based on the ATS platform:
# LinkedIn Easy Apply
node scripts/linkedin-easy-apply.js <jobUrl> config/linkedin-config.json
# Lever
node scripts/lever-apply.js <jobUrl> <configPath>
# Greenhouse
node scripts/greenhouse-apply.js <jobUrl> <configPath>
# Jobvite
node scripts/jobvite-apply.js <jobUrl> <configPath>
# Ashby
node scripts/ashby-apply.js <jobUrl> <configPath>For Lever, Greenhouse, Jobvite, and Ashby, you need to inspect the form first to build the config with the correct field IDs and values.
3. Track applications
After each successful submission:
- Append a row to the local
application-tracker.csv - Append an entry to the daily log
submitted-applications-YYYY-MM-DD.md - Sync to Google Sheets:
python3 scripts/google-sheet-sync.py application-tracker.csv
4. Triage emails
Use the Outlook scripts to search for confirmation and rejection emails:
# Search for job-related emails
node scripts/outlook-triage.js search "application confirmation"
# Read a specific email
node scripts/outlook-triage.js extract 0
# Mark as read after processing
node scripts/outlook-triage.js mark-read 05. Update statuses
When you receive rejections, interviews, or other updates:
python3 scripts/tracker-status-update.py updates.jsonApplication Rules
- Truthfulness first: Prefer truthful, submittable applications over aggressive volume.
- Work authorization: Skip hard citizen/green-card gated roles unless the form provides a truthful path for the candidate's actual status.
- Resume selection: Use the appropriate resume variant for each role type (see candidate-profile.md for the mapping).
- Captcha honesty: If a form stalls behind CAPTCHA, log it as "blocked" -- never inflate submitted counts.
- Headless default: Use headless browser by default. Only open visible windows when manual intervention (e.g., CAPTCHA solving) is required.
- Email triage: Mark confirmation emails as read after logging. Leave interviews, assessments, and recruiter outreach unread.
Available Scripts
| Script | Purpose | Input |
scripts/linkedin-easy-apply.js | LinkedIn Easy Apply | Job URL + LinkedIn config JSON |
scripts/lever-apply.js | Lever ATS | Job URL + form config JSON |
scripts/greenhouse-apply.js | Greenhouse ATS | Job URL + form config JSON |
scripts/jobvite-apply.js | Jobvite ATS | Job URL + form config JSON |
scripts/ashby-apply.js | Ashby ATS | Job URL + form config JSON |
scripts/outlook-triage.js | Email search/read/mark | Command + query/index |
scripts/outlook-send.js | Send email (Outlook Web via CDP) | To + subject + body file |
scripts/send-cold-email.js | Send cold email (Gmail via msmtp) | JSON payload on stdin or path |
scripts/job-dashboard.mjs | Terminal dashboard (5-tab TUI + snapshot) | Reads CSVs; --snapshot for one-shot |
scripts/generate-tailored-cv.mjs | Render approved markdown CV → ATS-friendly PDF (headless Chromium) | JSON payload on stdin (cv, outputPath, title, format) |
scripts/mirror-tracker.mjs | CSV → markdown mirror (data/applications.md, data/outreach.md) | Reads CSVs; --watch for fs.watch live mirror |
scripts/google-sheet-sync.py | Append to Google Sheet | CSV file path |
scripts/tracker-status-update.py | Batch status update | JSON file path |
Exit Codes
All application scripts use consistent exit codes:
0-- Success (submitted or ready in dry-run mode)1-- Crash or unexpected error2-- Blocked on unknown required field3-- Captcha or submission timeout4-- Step limit exceeded (LinkedIn only)
Environment Variables
| Variable | Default | Purpose |
CDP_URL | (none) | Connect to existing Chrome via CDP |
HEADLESS | 1 | Set to 0 for visible browser |
PW_CHANNEL | (none) | Playwright browser channel (e.g., chrome) |
KEEP_OPEN_ON_BLOCK | 0 | Set to 1 to keep browser open when blocked |
CHROME_COOKIE_PATH | (none) | Path to Chrome Cookies file |
SPREADSHEET_ID | (none) | Google Sheet ID for tracking |
SHEET_NAME | Job Tracker | Google Sheet tab name |
LOCAL_TRACKER | application-tracker.csv | Path to local CSV tracker |
OUTLOOK_PORT | 9224 | Chrome debug port for Outlook |
Recommended Companion Skills
The skills below are community-built and complement the 13 bundled skills above:
/job-search-- Multi-board job search/tailor-resume-- Resume customization per posting/apply-- AI-assisted ATS form filling (different from bundled/job-apply, which wraps this repo's scripts directly)/interview-prep-generator-- STAR stories and practice questions/resume-ats-optimizer-- ATS keyword optimization/salary-negotiation-prep-- Market rate research
See skills/README.md for the full list and install commands.
gstack
This repo pairs well with gstack — a general-purpose Claude Code skill pack for shipping code. Install gstack once (git clone --single-branch --depth 1 https://github.com/garrytan/gstack.git ~/.claude/skills/gstack && cd ~/.claude/skills/gstack && ./setup) and these gstack skills become useful in this repo's workflow:
- Web browsing: use
/browsefor all web browsing. Never usemcp__claude-in-chrome__*tools./connect-chrome+/setup-browser-cookiesfor authenticated pages (useful for LinkedIn / Outlook flows). - Shipping code:
/shipto sync main + run tests + push + open PR (this repo pushes direct to main by convention, but/shipstill handles the rest)./reviewfor pre-landing paranoid review./codexfor a second-opinion code review. - Testing:
/qa//qa-onlyfor systematic QA + fix loops./browsefor one-off dogfooding. - Debugging:
/investigatefor root-cause debugging./careful//freeze//guard//unfreezefor safety during destructive ops on the trackers / config files. - Dev-experience:
/devex-reviewafter shipping a new skill — it actually runs the install + first-skill-invocation and scores the onboarding./plan-devex-reviewbefore adding new skills. - Post-ship:
/document-releaseto syncREADME.md/CLAUDE.md/skills/README.mdafter a skill lands./retrofor the weekly "what did we ship" log.
If gstack isn't installed, those skills are optional — this repo's 13 bundled skills (/job-coach, /job-setup, /job-evaluate, /job-apply, /job-track, /job-triage, /job-status, /job-outreach, /job-followup, /job-dashboard, /job-cv, /job-interview, /job-patterns) work standalone.
File Locations
- Config templates:
config/*.template.* - Active configs:
config/linkedin-config.json,config/candidate-profile.md,config/answer-bank.md - Scripts:
scripts/ - Templates:
templates/ - Documentation:
docs/ - Local tracker:
application-tracker.csv(created by setup.sh) - Daily logs:
submitted-applications-YYYY-MM-DD.md(created per session)
In this repository14 other files it gives its agents.
- job-applySkill
- job-coachSkill
- job-cvSkill
- job-dashboardSkill
- job-evaluateSkill
- job-followupSkill
- job-interviewSkill
- job-outreachSkill
- job-patternsSkill
- job-recapSkill
- job-setupSkill
- job-statusSkill
- job-trackSkill
- job-triageSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

