Automation

Daily competitor price change alert emailer

Python agent that checks competitor pricing pages daily, diffs prices against stored history, and emails only when a price changes.

pythonsqlitehttpxselectolaxpydantic-settingspytest

Built 1 time, downloaded 0 times.

Install from your terminal

Run this in your project folder. It signs you in, shows what changes and asks before it overwrites a file.

npx claude-lab add daily-competitor-price-change-alert-emailer-2e1b75
CLAUDE.md
# Competitor price watcher

## Purpose

Daily monitor of competitor pricing pages. It emails the owner only when a tracked price changes.

Behavior is defined in SPEC.md. The current phase is in PLAN.md.

## Stack

- Python 3.12
- uv for dependencies and running commands
- httpx for fetching
- selectolax for HTML parsing
- SQLite for history (`data/watcher.db`)
- pydantic-settings for config
- pytest and ruff for tests and lint

## Commands

- `uv sync`: install dependencies
- `uv run pytest -q`: run tests (no network)
- `uv run ruff check .`: lint
- `uv run python -m watcher init-db`: create the observations table
- `uv run python -m watcher run --dry-run --fixtures tests/fixtures`: smoke run, no network, no email
- `uv run python -m watcher run`: real daily run (cron or launchd)

## Layout

- `src/watcher/fetch.py`: httpx fetcher, robots.txt check, timeouts, retries
- `src/watcher/extract.py`: selectolax price extraction
- `src/watcher/store.py`: SQLite reads and writes
- `src/watcher/diff.py`: change and failure rules
- `src/watcher/notify.py`: SMTP email
- `src/watcher/cli.py`: command entry points
- `config/targets.yaml`: competitor URLs and CSS selectors
- `tests/fixtures/`: saved HTML snapshots, one per target
- `data/`: SQLite database, gitignored
- `.env`: secrets, gitignored; `.env.example` has placeholders only

## Conventions

- Store prices as integer minor units plus an ISO currency code.
- Store no raw HTML. Keep only a short snippet and its hash.
- Use UTC timestamps. No naive datetimes.
- Log errors with the target id, never with full page content.
- Keep CLAUDE.md under 200 lines. Put detail in SPEC.md or PLAN.md.

## Fetch rules

- One request per domain per run.
- Send an identifying User-Agent.
- Honor robots.txt.
- Timeout is 15 seconds.
- At most 2 retries, with backoff.
- No login, no CAPTCHA bypass, no checkout pages.

## Gotchas

- A failed parse is an error row, never a price of zero.
- Alert only when the new ok price differs from the last ok price. Ignore error rows when comparing.
- Secrets live in `.env` only. Never put real SMTP credentials in code, tests or fixtures.
- Use placeholders such as YOUR_SMTP_PASSWORD in `.env.example`.
- Do not edit SPEC.md unless the owner asks.

## Working rules

- Read SPEC.md and PLAN.md before writing code.
- Follow REVIEW.md before calling work done.
- Run the verify skill before claiming any change works.
- Use the test-runner subagent for test output so the main context stays small.
- Do not edit tests to make them pass. Report the mismatch.

## Review rules

@REVIEW.md
Use for my project