Initial commit: Screen Leads app
Screen-capture lead tool: capture agent, Claude vision extractor with pluggable site recipes (LinkedIn), canonical funnel model, SQLite storage, FastAPI backend, dashboard, and setup/run scripts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
# Screen Leads
|
||||
|
||||
Turn a browser tab you have open on a profile into a structured lead. The tool
|
||||
screenshots the screen, scrolls, runs the images through Claude vision, and
|
||||
saves normalised leads to a database you browse and control from a dashboard.
|
||||
|
||||
Screen-capture only: it reads pixels a human already chose to display and never
|
||||
touches the target site's servers or DOM. LinkedIn is the first supported site;
|
||||
new sites drop in as recipes.
|
||||
|
||||
## How it works
|
||||
|
||||
```
|
||||
Start (dashboard) → detect front tab → [stop unless it's an enabled
|
||||
site's target page, e.g. a LinkedIn profile] → scroll + screenshot loop →
|
||||
Claude vision extraction → normalise to canonical Lead → SQLite → dashboard
|
||||
```
|
||||
|
||||
- **Guard** — runs only when the front tab is an enabled recipe's *target* page
|
||||
(a LinkedIn `/in/` profile). On anything else it stops (set
|
||||
`SCREEN_LEADS_ON_INVALID_PAGE=wait` to poll instead).
|
||||
- **Detection** — reads your own browser's URL where possible (macOS reliably),
|
||||
otherwise the AI reads the address bar from the screenshot. Both are passive.
|
||||
- **Contact info** — name/headline/company come from the profile page. Email &
|
||||
phone live behind LinkedIn's **Contact info** panel: open it yourself before
|
||||
capture and the tool will read whatever is shown. Often it simply isn't there.
|
||||
- **Funnel** — every lead is normalised to one schema and advances
|
||||
`NEW → ENRICHED → CONTACT_FOUND → EXPORTED` as data completeness grows.
|
||||
|
||||
## Setup
|
||||
|
||||
```bash
|
||||
# 1. Get the code
|
||||
git clone https://git.thecaoffice.com/OpenSource/screen-leads-app.git
|
||||
cd screen-leads-app
|
||||
|
||||
# 2. One-time setup — venv, dependencies, and prompts for your API key
|
||||
./setup.sh # Windows: setup.bat
|
||||
|
||||
# 3. Run it
|
||||
./run.sh # Windows: run.bat
|
||||
```
|
||||
|
||||
`setup.sh` creates the virtualenv, installs dependencies, and writes your
|
||||
`ANTHROPIC_API_KEY` to `.env`. `run.sh` launches the dashboard — open
|
||||
http://127.0.0.1:8000 and use **Start / Pause / Stop**.
|
||||
|
||||
<details><summary>Manual steps (no scripts)</summary>
|
||||
|
||||
```bash
|
||||
python3 -m venv .venv && source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
export ANTHROPIC_API_KEY=sk-ant-...
|
||||
python main.py
|
||||
```
|
||||
</details>
|
||||
|
||||
### OS permissions (grant once)
|
||||
|
||||
| OS | Needs |
|
||||
|----|-------|
|
||||
| macOS | System Settings → Privacy & Security → **Screen Recording** and **Accessibility** for your terminal/app. Automation permission for the browser enables exact URL detection. |
|
||||
| Windows | Usually none. `pip install uiautomation` enables native URL detection. |
|
||||
| Linux | Use an **X11** session. Wayland can't capture/scroll via `mss`/`pyautogui` — switch to X11 or use the desktop screenshot portal. |
|
||||
|
||||
## Usage
|
||||
|
||||
1. Open a LinkedIn profile in your normal browser (optionally open **Contact info**).
|
||||
2. Click **Start** on the dashboard.
|
||||
3. The tool scrolls, captures, extracts, and saves the lead; it then waits for
|
||||
you to open the next profile. Navigating away from a profile stops the run
|
||||
(default) so it never runs on non-target pages.
|
||||
|
||||
## Project layout
|
||||
|
||||
```
|
||||
screen-leads/
|
||||
agent/ capture loop pieces: screenshot, scroll, detection
|
||||
platform/ native URL helpers (mac / windows / linux)
|
||||
ai/ Claude vision extraction + per-site recipes
|
||||
recipes/ base.py, linkedin.py, registry (__init__.py)
|
||||
core/ canonical models + capture controller (state machine)
|
||||
db/ SQLite persistence (leads + runs)
|
||||
api/ FastAPI: /api/start /pause /resume /stop /status /leads
|
||||
dashboard/ single-file web UI
|
||||
config.py main.py
|
||||
```
|
||||
|
||||
## Adding a new site
|
||||
|
||||
1. Add `ai/recipes/<site>.py` implementing `SiteRecipe` (`matches`,
|
||||
`extraction_schema`, `extraction_prompt`, `to_canonical`).
|
||||
2. Register it in `ai/recipes/__init__.py`.
|
||||
|
||||
Nothing in the capture loop changes — the guard and pipeline are recipe-driven.
|
||||
|
||||
## Compliance note
|
||||
|
||||
Automated *scraping* of LinkedIn violates its Terms of Service. This tool is
|
||||
built for low-volume, human-in-the-loop use on profiles you manually open and
|
||||
are allowed to view. Keep pacing conservative and use it accordingly.
|
||||
Reference in New Issue
Block a user