A thesis-driven sourcing engine for early-stage VC. Describe an investment thesis in plain English; Scout searches X, GitHub, Hacker News and arXiv for companies that match it, scores them against the thesis, and drafts the investment memo.
Every figure it reports traces to something it actually read. Where it has no evidence it says so rather than estimating — that constraint is enforced in code, not just asked for in a prompt.
| Startups in the database | 942 across 13 runs |
| Classified with a thesis-fit score | 643 |
| Strong fit (≥ 70%) | 28 |
| Adversarially audited | 43 — every one returned corrections |
| Funding rounds tagged | 17, all evidence-cited |
| Theses tracked in parallel | 4, with version history |
| X API spend | $3.21 of a $25 grant |
git clone https://github.com/alantgoff/Scout.git scout && cd scout
./startNo API keys needed to look around — ./start seeds a sample dataset and opens
the workspace at localhost:8501. On macOS, double-click Scout.command
in Finder instead.
Thesis — the control room. Write your thesis in plain language and the strategy agent generates the whole sourcing configuration: X query bank, bio searches, GitHub topics, an investor watchlist (handles are existence-checked; fabrications are dropped), and scoring weights. You review before anything saves. This page also holds the thesis library — switch between theses without losing either, and see how many startups each one found. Runs launch from here, with a worst-case cost estimate and an explicit confirmation before any paid run.
Startups — everything sourcing found, newest run or all runs, as a triage cockpit: a dense scannable list on the left, full dossier on the right. Each row shows thesis fit, score, funding round and B2B/B2C at a glance. The dossier gives you the product summary, the sector line, "How it scored" with every point attributed, and one-click Longlist / Pass. Filter by round, stage, customer type, fit or score. A Database view of the same data adds editable CRM columns (vertical, use case, priority, your own custom fields) with AI auto-categorisation.
Longlist — companies you've marked worth a closer look. Same cockpit, narrower set, with the next action being shortlist or pass.
Shortlist — the ones you're seriously considering. This is where memos get written and outreach gets drafted.
Memos — a 12-section first-draft investment memo per company: Overview · Why now · Team · Product & differentiation · Technology & architecture · Traction & metrics · Competitive landscape · Market sizing · Strategic capital & acquisition dynamics · Deal terms & ownership · Risks · Recommendation, opening with a TL;DR and closing with a VERDICT: PURSUE / TRACK / PASS, tripwires, and first-call questions. Deep research is the default: it finds the real company site, researches founders by name, verifies funding, and cites its sources. Memos are editable in place and export as Markdown or styled PDF. AI-drafted outreach sits below each one.
Activity — the firm's shared memory. Every vote, comment, triage move and memo edit, newest first, filterable by member and kind, with an unread count in the nav. With partners in different timezones this is the first thing you open: what happened while you were asleep.
Graph — the database sideways. A live force-directed map of everything
the pipeline knows about who connects to whom: companies, their backers,
founders and the labs they left, acquirers, and the smart money watching —
every edge derived from cited evidence, never from vibes. Click a node to
trace its connections with their evidence; focus on one company to see its
two-hop neighborhood; hub tables underneath answer the standing questions
(which backer keeps showing up, which lab the founders come from, what else
an acquirer bought). The same graph answers in the terminal via scout graph.
Evidence — whether any of this actually works. A backtest scores companies using only evidence that was public on a past date, then checks where the ones that went on to raise actually ranked. Three views: Results (recall, separation, lead time, and every company plotted against the controls), Signals (which individual signals carried the information, with confidence intervals and a check for two signals measuring the same thing), and Over time (whether a signal is wearing out as the world catches on). Every report carries its own limitations — including the ones that undercut it.
Automation — schedules, the job queue, and whether the worker is alive.
Momentum signals decay in days, so the run that matters is the one nobody had
to remember. Sourcing runs, digests and memos can all be scheduled or queued.
scout worker --bootstrap sets up the daily rhythm: a sourcing run at 06:00,
an unlinked-lead resolve at 06:30 (turns the headlines and launches the run
could not key to a company into scored leads), a tracked-company refresh at
06:45 (re-researches the longlisted+ companies whose facts are oldest —
raises, acquisitions, shutdowns land in the feed), and the digest at 07:30. The whole day is bounded by one spend envelope
(DAILY_SPEND_CAP_USD, default $1): heuristics, caches and free scraping
always run; paid Claude/X calls stop when the envelope is spent and resume
tomorrow.
Settings — API keys, the X spend ledger, Slack notifications, your own taste profile, and firm-wide defaults.
DISCOVER SCORE DECIDE
X search queries 11 deterministic signals Longlist / Shortlist / Pass
bio search → + Claude classification → Memo
GitHub topics + adversarial audit Outreach
Hacker News + thesis fit
arXiv papers
RSS / Atom feeds
SEC Form D filings
YC directory
investor follows
A run sources candidate accounts, folds a founder and their company account
into one entry — and lands every source's sighting of one company on one row,
whatever key it arrived under (an X handle from search, a domain from a feed
or a Show HN, a GitHub org), so a company seen three ways is one lead with
three corroborating sources, not three leads. Signals with no company key at
all — a funding headline on a publisher's site — are resolved into leads the
same morning (scout resolve). And every US private raise files an SEC Form
D within 15 days — issuer, amount sold, first-sale date, named officers — so
the sec source reads new filings daily: one that names a company already
tracked attaches to it (feed, digest, card, and a real round date for the
backtest); a startup-shaped one nobody has heard of goes to the resolver.
YC's directory (a public static mirror, rebuilt daily) supplies every
new-batch company with its domain and one-liner — launched and seed-funded
by definition, on-thesis ones become leads the day the batch starts.
Each lead is then scored on three components:
- Quality — a readiness scorecard (B2B or B2C rubric), criteria scored 1–3 from cited evidence only, rolled up 0–100
- Fit — how squarely the product matches your thesis, 0–1
- Signal — momentum: investor follow-graph convergence, bio changes, departure language, launch traction, GitHub star velocity (stars the discovery repo gained this week — the launch that landed), and a change of published affiliation — a researcher whose next paper carries a different lab has usually left months before any bio says so
These blend (currently 35 / 50 / 15 — fit outweighs quality deliberately, so a well-built off-thesis company can't outrank an on-thesis one), then pass through multipliers for classifier confidence, evidence grounding, and stage match. A second adversarial pass audits the top verdicts against their own evidence and corrects what the first pass overstated.
Runs are incremental: everything fetched is cached, and accounts scored within the last 7 days are skipped, so re-running while you tune a thesis is fast and mostly free.
Evidence or nothing. An LLM asked for a competitor's funding round will produce one — plausible, specific, often a year stale, and indistinguishable from a real one. A live run tagged Perplexity "Series C+" off a bio reading "Everything is Computer." Rounds without a cited source are now discarded by a model validator, and the memo prompt bans recalled figures and citation-shaped phrases ("per analyst estimates") at every research depth.
A thesis is an object, not a config file. Identity is kept separate from version, so editing weights bumps the version while the thesis stays itself. Scores name their origin ("Scored against Novel Architectures · v3"), changing a thesis marks old scores stale rather than silently reinterpreting them, and previous verdicts are archived — so "0.20 under Edge AI, 0.75 under Novel Architectures" stays answerable.
Cost is a correctness problem. The X API is pay-per-use against a fixed grant. The guard pre-checks worst-case cost before each request, never retries anything that may already have been billed, and buys breadth through many narrow queries rather than one deep page — worst case per run fell from $30 to $3.60, measured actual $1.55.
Two files, both editable in the UI:
thesis.yaml— the thesis statement, target stages, keywords, sectors, disqualifiers, signal weights, scorecard weights, and scoring parametersseeds.yaml— the X query bank (departure / stealth-intent / hiring / launch), bio searches, investor watchlist, GitHub topics
Optional keys in .env: ANTHROPIC_API_KEY (classification and memos —
without it, heuristics-only), TW_COOKIES (free X scraping),
X_BEARER_TOKEN + XAPI_SPEND_CAP_USD (paid X API), GITHUB_TOKEN
(raises GitHub's rate limit from 60/hr to 5,000).
run Full pipeline → out/leads_*.csv + report_*.md
--source twscrape|xapi free scraping (default) or the paid X API
--max-accounts N · --min-score N · --ttl-days N
reclassify Re-score without discovery — no X spend, cache-first
--all every startup in the ledger
--stale-only only those scored under an older thesis version
refresh Re-research the tracked companies whose facts are oldest —
the daily watch on longlisted+ companies for raises,
acquisitions and shutdowns. A newly-cited round is captured as
a backtest OUTCOME automatically (see hindsight) and alerted
in the digest. Rotating and budget-gated: a fixed
daily allowance (SCAN_REFRESH_PER_DAY) sweeps the whole
tracked list on a cycle, and the pass stops mid-list when
today's spend envelope (DAILY_SPEND_CAP_USD) runs out.
--limit N · --handle <one company now>
add <domain> Add ONE company by domain; the system fills in the rest.
Crawls the site, then researches the company live — name, X
handle, GitHub org, founders, HQ, founding year, funding, and
whether it is still independent — and runs the SAME classifier
and scorer every discovered lead goes through.
--status longlisted where to track it (default: longlisted)
--url · --name · --bio · --note
--no-research skip the live research
--no-classify record only what you typed, grounded "manual"
--force add it even if no company is found at the domain
resolve Turn the signals discovery could not key to a company — a
funding headline on a publisher's site, a Show HN linking to a
demo video, an SEC Form D issuer — into scored leads. Free move first (the article's
own outbound links, matched against the name), then one small
web-search call; then the SAME path `add <domain>` takes. A
headline about a company already tracked lands on that row and
its cited round is captured as an outcome. Each unlinked lead
is attempted once and stamped with what it became. Budget-gated
(SCAN_RESOLVE_PER_DAY, DAILY_SPEND_CAP_USD); runs daily at 06:30.
--limit N
merge <dup> <keep> Fold one company's records into another's — the manual
fix for a duplicate (the same company keyed by its X handle and
by a slug from its domain). Every table follows; where both hold
one unique thing (a status, a person's vote) the kept row wins.
thesis list · show <id> · new <name> · use <id> · clone <id> <name> · archive <id>
source Discovery preview — raw accounts per strategy, no scoring or cost
inspect <handle> Score one account, print the per-signal breakdown
verify Hydrate the shortlist with fresh paid X data and re-score
graph The knowledge graph: cross-links derived from evidence the
pipeline already collected. Summary view (top investors by
portfolio-in-database, labs by founder alumni, acquirers,
watchers) or `scout graph <name>` for one node's connections
and the companies it shares a backer with.
publish Render docs/ as a read-only phone app — Startups (search/sort/
filters), Funnel, Graph, Alerts, offline via a service worker.
Lead data only; never notes, votes, spend, secrets or config.
The worker runs it every morning at 07:45 (--auto).
--push commit docs/ and push to DIGEST_REPO (GitHub Pages)
--vercel deploy docs/ to Vercel — password-protected via
the bundled middleware (DIGEST_PASSWORD)
--auto push and/or deploy wherever configured
budget Today's spend envelope + Claude and X API ledgers
demo $0 offline end-to-end test
ui Launch the workspace
migrate Adopt a single-user database into the multi-member schema
--owner [email protected] attribute existing judgments, snapshot memos,
import past triage as votes. Idempotent.
worker Run the background worker: schedules fire, queued jobs execute
--bootstrap create the default daily schedules: sourcing run
(06:00), unlinked-lead resolve (06:30), tracked
refresh (06:45), digest (07:30), phone app
publish (07:45)
--once drain the queue and exit (for cron)
jobs Queue state · --enqueue <kind> · --cancel <id>
schedule --list · --add <kind> --at 06:00 --weekdays --tz Europe/London
digest Post the Slack digest now (the scheduled one runs via the worker)
memo <handle> Write one memo headlessly · --depth quick|standard|deep
hindsight Backtest the scorer against companies that went on to raise.
Auto-captured rounds from `scout refresh` merge in by
themselves (curated YAML wins collisions); controls stay
hand-curated — automation can't prove a negative.
--outcomes outcomes.yaml companies that raised, plus controls that did not
--cutoff 2025-02-01 score only evidence public on that date
--sweep 3 three cutoffs six months apart, for signal decay
--suggest-weights propose weights from the measured predictive power
--blinded re-score with names redacted, to measure how much
the model is recognising rather than judging
Use ./scout-cli <cmd>. On macOS, uv marks .venv hidden and CPython then
skips the editable-install .pth, which breaks the bare scout command;
./scout-cli runs python -m scout.cli and is immune.
Scout is one shared instance, not a copy per person: partners sign in with Google, vote and comment on the same startups, and a worker sources on a schedule so momentum signals get caught while they are still fresh.
scout migrate --owner [email protected] # adopt an existing single-user database
scout worker --bootstrap --once # create the default schedules
scout worker # run them (systemd unit in deploy/)deploy/ has the whole kit — systemd units, Caddy for TLS, and
litestream for continuous backup to object storage. One small VM is enough;
SQLite in WAL mode handles a firm's concurrency comfortably, and the database
is a single file you can copy.
The workspace (Streamlit, the worker, SQLite) is a long-running process and
belongs on that VM. The phone app scout publish renders is static, and
Vercel is the better host for it than GitHub Pages: a custom domain, and —
the part that matters for a deal-flow digest — a password. scout publish
writes the Vercel files into docs/ alongside the app (vercel.json,
middleware.js, robots.txt; inert on Pages), so:
npm i -g vercel
scout publish # render docs/
cd docs && vercel link # once: create/attach the Vercel project
cd .. && scout publish --vercelThen in the Vercel project → Settings → Environment Variables set
DIGEST_PASSWORD. Until it is set the app is open; once set, every request
except the manifest and icon needs the password (HTTP Basic auth, in the
Edge Middleware — the files are never served without it). For the worker
to deploy every morning, set VERCEL_TOKEN in scout.env; publish --auto
deploys to whatever is configured and only renders when nothing is.
Alternatively connect the DIGEST_REPO checkout to Vercel's Git integration
(framework: Other, no build command) and --push deploys by itself.
To run the backtest, describe the companies you want to test against in an
outcomes file — see outcomes.example.yaml. It needs
both companies that raised and controls that did not: recall on its own
proves nothing, because a scorer that rates everyone 90 recalls everything.
The most persuasive version is a firm's own history — the ones you passed on,
and a few you correctly skipped.
- ToS risk: scraping X via twscrape violates X's Terms of Service. Use a burner account.
- arXiv affiliation coverage is partial.
lab_departurereads an author's stated affiliation across papers, but arXiv makes that field optional and it is often absent. A gap is treated as unknown, so the signal under-fires: real departures are missed, but the ones it reports are evidenced. - Paper authors are matched by name, the only identifier arXiv gives. The key deliberately under-merges, so a researcher who changes how their name is written splits into two records rather than two people fusing into one. The signal quotes its evidence so either case is visible.
- The follow-graph signal is twscrape-only — via the official API it always
scores 0, as engagement operators (
min_faves:) are also unsupported there and get stripped. - Confidence is biased against stealth. Classifier confidence multiplies the
score, and stealth companies are inherently less legible (0.57 average vs
0.83–0.93) despite carrying the highest thesis fit. Flooring it was tried and
reverted — it also lifts companies whose product claims never traced to
evidence. Documented in
AGENTS.mdas an open thread. - X API cost constants are unverified. Spend figures derive from hardcoded per-read prices, never reconciled against X's actual rate card.
- Without
ANTHROPIC_API_KEYyou get heuristics-only ranking: no stage/sector/summary enrichment, and memos fall back to a data-only skeleton. - The backtest cannot prove what people will read it as proving. Evidence is rewound to the cutoff, but the thesis and weights applied are today's — written by people who already know which companies raised. So it supports "would today's thesis have ranked these highly given only past evidence", not "would Scout have caught them at the time". Only running a frozen thesis forward settles the second. Outcomes and controls are also chosen by hand, and X history cannot be reconstructed at all, so every figure is a floor with a selection bias on top. Each report states all of this itself; the Evidence page will not show a number without them.
Working on the code?
AGENTS.mdis the map — architecture, data flow, invariants, and the gotchas that will bite you.