π Contributing Β· β Get Help
Stop refreshing LinkedIn. This pipeline scrapes new job listings based on your settings, uses AI agents to summarize each one and score it against your CV, then delivers only the best matches straight to your inbox π¬ β so you're always first to apply π
- The Problem
- How It Works
- Tech Stack
- Pipeline Architecture
- AI Output Fields
- Setup
- Project Structure
- Roadmap v2
- Contributing
- License
Job hunting on LinkedIn is a full-time job in itself. New listings appear daily, most are irrelevant, and by the time you spot a good one, 200 people have already applied.
SnapplAI flips the game: it runs on a schedule, scrapes fresh listings, lets AI read and score every single one against your CV, and emails you only the top matches β before the crowd even sees them.
The pipeline runs in 4 sequential steps, fully automated:
1. Scrape β job_scraper() pulls fresh listings from LinkedIn based on your search settings (role, location, filters) using python-jobspy.
2. Summarize β agentic_summarize() sends each job description to Gemini, which extracts structured fields (title, seniority, skills, salary, etc.) as clean JSON.
3. Analyze β agentic_analyze() reads your CV and scores each listing on how well it matches your profile. Chain-of-thought enforced: the model writes analysis before score in the JSON schema, so reasoning comes before judgment.
4. Deliver β send_email() builds an email with the top-scored jobs and sends it to your inbox via SMTP.
5. Apply and analytics β Two attachments complete the report: top match, a filtered Excel with all scraped jobs, and an analytics .txt summarizing the batch.
--
Resilience: each Gemini call retries with exponential backoff on transient errors (429/500/503) and falls back through a fixed chain (gemini-3.5-flash-lite β gemini-3.1-flash-lite), so a temporarily overloaded model no longer crashes the whole pipeline.
Key principle: AI reads and evaluates. Python orchestrates and delivers. No frameworks, no agents-calling-agents β just a clean data pipeline with LLM calls where they matter.
| Component | Technology |
|---|---|
| LLM | Google GenAI SDK β gemini-3.5-flash-lite (primary), gemini-3.1-flash-lite (fallback) |
| Resilience | Retry with exponential backoff + fixed model fallback chain (src/llm.py) |
| Scraping | python-jobspy (LinkedIn) |
| Data | pandas, PyPDF / PyMuPDF |
| Parsing | BeautifulSoup4 |
| smtplib (SMTP) β provider-agnostic (Gmail, Outlook/Office365, ...) | |
| Config | python-dotenv |
The entire pipeline operates on a single pandas DataFrame that gets enriched at each step. No intermediate files, no database β everything flows through memory.
Each job in the email is ranked by fit score and includes:
- city, company, role, and work mode
- a one-line AI summary explaining the match
- a direct apply link to the LinkedIn listing
Two attachments complete the report: a filtered Excel with all scraped jobs, and an analytics .txt summarizing the batch.
- Get a free API key from Google AI Studio
- Generate an app password for your email (e.g. Gmail App Password). For non-Gmail providers, set
SMTP_HOST/SMTP_PORTin.envβ e.g. Outlook/Office365 usessmtp.office365.comon port587(STARTTLS); Gmail defaults tosmtp.gmail.comon465(SSL). - Place your CV (PDF) in
your_cv_config/ - Configure search settings: config your
file_config.env - Create your
.envfrom the template:cp example_env.txt .env
git clone https://github.com/TDK-99/SnapplAI.git && cd SnapplAI
pip install -r requirements.txt
# complete setup steps above
python main.pygit clone https://github.com/TDK-99/SnapplAI.git && cd SnapplAI
# complete setup steps above
docker build -t snapplai .
docker run --env-file .env snapplai- Fork this repo (or create a private copy)
- Complete setup steps 1-4 above in your fork
- Delete the # on schedule and -cron for action auto start
- Add credentials as repository secrets (Settings β Secrets β Actions):
GOOGLE_API_KEY,GMAIL_USER,GMAIL_APP_PASSWORD - Actions tab β enable workflows β Run workflow (for manual)
SnapplAI/
βββ main.py # Entry point β runs the 4-step pipeline
βββ src/
β βββ daily_scraper.py # LinkedIn scraping with python-jobspy
β βββ ai_agents.py # Gemini calls: summarize + analyze
β βββ llm.py # Resilient Gemini wrapper: retry/backoff + model fallback
β βββ smtp.py # Email builder and SMTP sender
β βββ pydantic.py # pydantic class for force ai output
βββ tests/
β βββ test_ai_analyze.py # Unit test for AI analysis agent
β βββ test_job_scraper.py # Unit test for the LinkedIn scraper
β βββ test_ai_summarize.py # Unit test for AI summarize agent
β βββ test_pydantic.py # Unit test for pydantic validation
β βββ test_smtp.py # Unit test for SMTP email sending
βββ your_cv_config/
β βββ .gitkeep # Keeps folder tracked in git
β βββ file_config.env # Your settings (role, location, filters)
β βββ file_config.txt # Additional config parameters
β βββ Your_CV.pdf # Your CV goes here (PDF)
βββ assets/ # Output screenshots and docs images
βββ .github/
β βββ workflows/
β βββ snapplai.yml # GitHub Actions workflow (scheduled + manual)
β βββ ci.yml # CI pipeline β runs tests on push/PR
β βββ yml.example # Template for GitHub Actions workflow
βββ Dockerfile # Run anywhere with Docker
βββ .env # API keys and SMTP credentials (git-ignored)
βββ .gitignore
βββ example_env.txt # Template for .env variables
βββ requirements.txt # Dependencies
βββ CONTRIBUTING.md # Contribution guidelines
βββ SUPPORT.md # Support and contact info
βββ CLAUDE.md # Repo workflow standards for Claude Code
βββ LICENSE # MIT
βββ README.md
- β Multi-country scraping β search across 2+ countries in a single run (custom feature, not supported by python-jobspy out of the box)
- Excel/DB deduplication β persistent storage to compare runs and filter out already-seen listings, so you never score the same job twice
- Scoring calibration β benchmark AI scores against known good/bad matches to improve match quality
- β Output redesign β better visual formatting for the email report (job cards, readability, direct links)
- β Fix issue β fix main issue: fallback model e smtp for non @gmail user
Contributions are welcome β bug fixes, new features, or docs improvements.
- Issues β Report bugs or suggest features
- Pull Requests β Fork, build, submit
MIT β see LICENSE

