Tired of losing track of jobs you saw in an email three days ago? This pulls every LinkedIn and Indeed job alert from your Gmail, parses out the role, company, and location, and drops it into an Airtable dashboard where you can mark each one as Open, Applied, or Not Relevant — without touching a spreadsheet or copy-pasting a single link.
Runs automatically every 5 hours in the background. No browser tab to keep open, no SaaS subscription, no monthly fee.
Your Airtable base ends up as a clean grid of every job that hit your inbox:
| Title | Company | Location | Source | Status | Job URL |
|---|---|---|---|---|---|
| Senior Security Engineer | Ericsson | Bengaluru | Open | [link] | |
| AI GRC Director | EC-Council | Remote | Indeed | Applied | [link] |
| Security Analyst III | Avaya | Bengaluru | Not Relevant | [link] |
From there you can filter by status, sort by date, or switch to a Kanban view grouped by status if that's more your thing.
Gmail (job-alerts label)
│
▼
gmail_reader.py ← OAuth2, fetches emails from last N days
│
├── parsers/linkedin.py ← extracts jobs from LinkedIn alert emails
└── parsers/indeed.py ← extracts jobs from Indeed alert emails
│
▼
airtable_client.py ← deduplicates, batch-pushes to Airtable
│
▼
Airtable dashboard ← you mark: Open / Applied / Not Relevant
Three layers of deduplication so the same job never shows up twice — within an email, across emails in the same sync, and across all historical syncs.
git clone https://github.com/pranayesse/job-alert-tracker.git
cd job-alert-tracker
pip3 install -r requirements.txtIn Gmail, create a filter that applies a label called job-alerts to emails from:
jobalerts-noreply@linkedin.comdonotreply@jobalert.indeed.com
Then set up OAuth credentials to read your Gmail:
- Go to console.cloud.google.com → create a project
- Enable the Gmail API
- Create an OAuth client ID (Desktop app) → download as
credentials.jsoninto this folder - Add your Gmail address as a test user under OAuth consent screen
- First run opens a browser tab to authorize — after that it's token-based
- New base → name it Job Tracker
- Rename the default table to Jobs
- Add these fields:
| Field | Type |
|---|---|
| Title | Single line text |
| Company | Single line text |
| Location | Single line text |
| Remote | Checkbox |
| Source | Single select → LinkedIn, Indeed |
| Job URL | URL |
| Email Date | Date |
| Status | Single select → Open, Applied, Not Relevant |
- Get your API token at airtable.com/create/tokens — scopes:
data.records:read,data.records:write - Your base ID is in the URL:
airtable.com/appXXXXXXXXXXXXXX/...
cp .env.example .env
# fill in your Airtable token and base IDpython3 main.py 30 # pull the last 30 days of alerts# Runs every 5 hours. Fires on wake if your Mac was sleeping.
launchctl load ~/Library/LaunchAgents/com.pranay.job-tracker.plistTo create the plist, copy this into ~/Library/LaunchAgents/com.pranay.job-tracker.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.pranay.job-tracker</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/python3</string>
<string>/path/to/job-alert-tracker/main.py</string>
</array>
<key>WorkingDirectory</key>
<string>/path/to/job-alert-tracker</string>
<key>StartInterval</key>
<integer>18000</integer>
<key>RunAtLoad</key>
<true/>
<key>StandardOutPath</key>
<string>/path/to/job-alert-tracker/job_tracker.log</string>
<key>StandardErrorPath</key>
<string>/path/to/job-alert-tracker/job_tracker.log</string>
<key>KeepAlive</key>
<false/>
</dict>
</plist>Check the log anytime:
tail -f job_tracker.logThe parser directory is intentionally modular. To add Naukri, Glassdoor, or any other source:
- Add their sender to your Gmail
job-alertsfilter - Create
parsers/naukri.pywith aparse(text_body, email_date)function that returns a list of job dicts - Add the source detection in
main.py
No changes needed to the Gmail fetcher, deduplication logic, or Airtable client.
- Python 3.10+
- Gmail API (read-only OAuth scope)
- Airtable API via pyairtable
- macOS
launchdfor scheduling (no cron, no server)
Most of them show you everything. This only shows you jobs that landed in your alerts — roles that already match your saved search criteria. The Airtable layer is just a persistent, sortable memory on top of what Gmail already delivers.
MIT