Skip to main content

Sweepy developer reference

Sweepy runs as a small Python project with a flat engine. This page maps each pipeline stage to the module that runs it, so you know where to make a change.

Audience​

Read this page if you plan to change Sweepy's code or add a job source. Reviewers can use it to orient a pull request. It covers internals only: modules, dependencies, and Python versions.

tip

Skip this page if you want to run sweeps. Start with Installation.

Pipeline stages and modules​

swee.py runs five stages in order. The terminal prints each stage as [1/5] through [5/5].

StageModuleWhat it does
1. Loading profileengine/config.pyLoads and validates your YAML profile. The wizard in the same module writes one.
2. Discovering rolesengine/discovery.pyQueries aggregator feeds through python-jobspy and classifies each platform.
2. Discovering rolesengine/sources/Fetches Greenhouse, Ashby, Lever, Workable, and Built In NYC boards from public endpoints.
2. Deduplicatingswee.pyMerges aggregator and source results into one card per job link.
3. Validating URLsengine/validator.pyChecks every link with an HTTP HEAD request and a GET fallback. It prunes dead postings.
4. Scoring against resumeengine/scorer.pyExtracts posting and resume terms, then scores overlap on requirements and keywords. It tags postings that demand written answers.
5. Routing resume tracksengine/enrich.pyPicks the track with the highest term overlap and assigns the matching badge color.
5. Enriching cardsengine/enrich.pyBuilds card summaries, compensation lines, and tailored tip text.
5. Default card PDFengine/report.pyRenders the card layout, six cards per page by default, and returns the page count.
5. Legacy table PDFengine/pdf_builder.pyRenders the table layout when your profile sets report.style: legacy.
5. Data exportsengine/exporter.pyWrites CSV and JSON files. It rasterizes PNG page images on request.
5. Job trackingengine/tracking.pyAdds the tracking columns and reads earlier exports so the values you enter come back.

engine/session.py holds the card store for the stateful Model Context Protocol (MCP) flow. It keeps cards in a thread-safe map indexed by a stable hash of each job link.

Where to make a change​

You want to changeStart in
A job source or its endpointengine/sources/, plus a seed list in data/sources/
How matches scoreengine/scorer.py
What a card showsengine/enrich.py, then engine/report.py
How links get checkedengine/validator.py
A command-line flagswee.py
An MCP toolserver.py
tip

server.py imports the same engine modules as the command-line tool. Test the MCP path after any engine change, because one fix affects both entry points.

Module reference​

Entry points​

ModulePurpose
swee.pyPrimary orchestrator and argparse command-line entry point for the five-stage pipeline.
server.pyModel Context Protocol (stdio) server that exposes engine tools to AI assistants.

Engine modules​

ModulePurpose
engine/config.pyInteractive wizard plus YAML loading and validation.
engine/discovery.pyScraper orchestration for python-jobspy and the deterministic sources, Applicant Tracking System (ATS) detection, and deduplication.
engine/validator.pyLink uptime checks with soft-404 detection. Unverifiable links stay in the run.
engine/scorer.pyResume term extraction, percentage matching, tagging, and per-track scoring.
engine/enrich.pyCard enrichment for summaries, compensation, track routing, and tailored tips.
engine/session.pyThread-safe card store with stable IDs for the stateful MCP flow.
engine/report.pyDefault card-layout PDF.
engine/pdf_builder.pyLegacy table-layout PDF for report.style: legacy.
engine/exporter.pyCSV and JSON exports, plus PNG rasterization of report PDFs.
engine/tracking.pyTracking columns and the carry-over read of earlier exports.
engine/docx.pyDOCX to PDF conversion with python-docx and reportlab, plus a Microsoft Word fallback.
engine/documents.pyDocument dispatch for --convert and the MCP converter, covering DOCX, DOC, text, Markdown, and PDF.
engine/logging.pyOpt-in debug logs under logs/.
engine/cache.pySQLite scrape cache keyed by query and engine set, with a one-hour time to live.
engine/circuit_breaker.pyCounts consecutive source errors and pauses calls during a cooldown.
engine/engine_defaults.pyShared default site lists and engine settings, kept import-free to avoid cycles.
engine/engines.pyAdapter registry and installer for the optional hirehunt, openroles, apify, and jobdrop engines.
engine/history.pyPersistent record of postings already reported. A daily sweep reports only new roles.
engine/normalize.pyNormalizes raw engine rows into the shared posting columns.
engine/salary.pyPay extraction from posting text when a board omits structured pay.
engine/sweep_config.pyApplies the shared engine defaults to profile settings.
engine/updater.pyGit-based update check and dependency reinstall for the checkout.

Deterministic sources​

ModulePurpose
engine/sources/__init__.pyFetcher exports and seed-list loading from data/sources/.
engine/sources/_common.pyShared helpers for HTTP headers, title pre-filtering, and HTML-to-text conversion.
engine/sources/greenhouse.pyGreenhouse job board fetcher.
engine/sources/ashby.pyAshby job board fetcher.
engine/sources/lever.pyLever postings fetcher.
engine/sources/workable.pyWorkable widget API fetcher.
engine/sources/builtinnyc.pyBuilt In NYC category scraper.

Engine adapters​

ModulePurpose
engine/adapters/__init__.pyRegistry that maps each engine name to its adapter.
engine/adapters/base.pyScraperAdapter base class, shared User-Agent header, and result-shape helpers.
engine/adapters/jobspy_adapter.pypython-jobspy aggregator adapter for LinkedIn, Indeed, Glassdoor, and ZipRecruiter.
engine/adapters/ats_adapter.pyAdapter over the deterministic ATS fetchers in engine/sources/.
engine/adapters/hirehunt_adapter.pyOptional hirehunt engine adapter.
engine/adapters/openroles_adapter.pyOptional openroles engine adapter.
engine/adapters/apify_adapter.pyOptional Apify actor adapter.
engine/adapters/jobdrop_adapter.pyOptional jobdrop engine adapter.

Data, scripts, and tests​

PathPurpose
data/sources/*.txtSeed lists for boards, companies, organizations, and categories.
scripts/make_sample.pyBuilder for the sample report stored in docs/.
tests/pytest suite with a file per area: adapters, config, documents, docx, engines, enrich, history, logging, and report. Further files cover salary, scorer, server, session, sources, swee, tracking, updater, and validator.
note

Add a dedicated test file when you change discovery.py, exporter.py, or pdf_builder.py. Put the file in tests/.

Dependencies​

Runtime packages come from requirements.txt. Versions below match that file.

PackageVersionWhat it does for Sweepy
reportlab5.0.1Builds the styled PDF report with clickable links.
pymupdf1.28.2Extracts text from resume PDFs and rasterizes PNG exports.
python-docx1.2.0Reads .docx resumes and rebuilds DOCX text as a PDF without Word.
requests2.32.5Reaches the ATS endpoints and checks each job link for a live response.
beautifulsoup44.15.0Parses HTML from the Greenhouse, Lever, Workable, and Built In NYC sources.
pyyaml6.0.3Reads and writes YAML profiles.
questionary2.1.1Drives the interactive wizard questions.
prompt-toolkit3.0.53Drives the wizard's interactive text input.
python-jobspy1.2.0Scrapes LinkedIn, Indeed, Glassdoor, and ZipRecruiter with no API credentials.
pandas2.2.3Structures postings and builds the CSV and JSON exports.
mcp1.30.0Runs the Model Context Protocol server.
anyio4.12.1Runs the asynchronous MCP transport.

requirements.txt lists one optional package too. Uncomment docx2pdf when Word should build the PDF.

  • docx2pdf (0.5.2, optional) renders DOCX to PDF through Microsoft Word on Windows. Sweepy calls it whenever Microsoft Word exists on the machine.
note

mcp stays on 1.x on purpose. The 2.x SDK serves only the 2026-07-28 protocol era. A client that probes server/discover and then falls back to the initialize handshake gets a -32022 error. VS Code Copilot follows that fallback.

tip

pandas stays on 2.x on purpose. Pandas 3.x requires Python 3.11 or newer, and the CI matrix still tests Python 3.10.

Development packages (requirements-dev.txt)​

PackageVersionWhat it does
pytest9.1.1Runs the test suite in tests/.
pytest-cov7.1.0Reports coverage for swee.py, server.py, and engine/scorer.py.
ruff0.17.0Lints the code and sorts imports.
tomli2.2.1Supplies tomllib for the Python 3.10 test runs.
Terminal
pip install -r requirements.txt
pip install -r requirements-dev.txt
ruff check .
pytest -q

Requirements and supported Python versions​

ItemDetail
Python floorSweepy requires Python 3.10 or newer and targets 3.10 syntax in every module.
Tested rangeThe CI workflow in .github/workflows/ci.yml runs Python 3.10, 3.11, and 3.12 on Ubuntu.
Lint targetpyproject.toml sets ruff target-version = "py310". A newer-only construct fails the lint job.
Line lengthRuff enforces a 100-character line limit and ignores E501.
CI stepsThe job installs both requirements files and runs ruff check . before pytest.
note

pyproject.toml declares requires-python = ">=3.10", so pip refuses an older interpreter at install time. The CI matrix and the ruff target define the tested range. Python 3.13 works in practice but stays outside that range.

Python 3.13

The pymupdf package may compile from source when no pre-built wheel exists. Install the Microsoft C++ Build Tools and select the "Desktop development with C++" workload before you install dependencies.

Repository layout​

Repository layout
swee.py CLI entry point and sweep orchestrator
server.py MCP server over stdio
engine/ Pipeline modules
engine/sources/ Deterministic ATS fetchers
engine/adapters/ Aggregator and optional engine adapters
data/sources/ Seed lists for each fetcher
profiles/ YAML search profiles
results/ Generated PDF, CSV, JSON, and PNG files
logs/ Opt-in debug logs
styles/ Vale style rules for the docs
tests/ pytest suite

When you change a tool signature in server.py, update the MCP tool reference in the same commit.