Skip to content

avnath13/crowdcheck

Repository files navigation

crowdcheck

license python interface status built on last30days

The contestation layer for last30days. Community Notes for AI agents.

last30days tells you what people are saying about a topic right now, scored by real engagement. crowdcheck turns that into something an agent can act on: it maps who agrees, who disputes, and how sure the signal is. Not a true/false verdict. A contestation map.

crowdcheck is a companion to last30days by @mvanhorn. last30days does the genuinely hard part: reaching Reddit, X, YouTube, TikTok, Hacker News, and real-money prediction markets, and ranking everything by what people actually engaged with. crowdcheck adds a thin, deterministic layer on top: stance classification, a two-axis calibration (consensus and confidence), and a typed contract your agent calls. It can run without last30days too (a keyless Hacker News plus prediction-market fallback), but it is built to sit on top of the full engine.

Status: experimental (v0.1). The quality of the map depends on the quality of the evidence, so crowdcheck shines with last30days behind it (or with an agent doing the reasoning). The standalone keyless fallback is intentionally light. See Status and honest limits.

crowdcheck CLI output: a claim mapped to consensus and confidence with weighted positions

A contestation map (shown in --demo). This is what a last30days-backed run looks like.

The one idea

Most tools collapse "do people agree?" and "do we have enough signal?" into a single fuzzy score. crowdcheck keeps them separate, because "confidently contested" is a completely different, and far more useful, answer than "we're not sure."

Two-axis model: consensus versus confidence

How the two fit together

   last30days                         crowdcheck                     your agent
   ----------                         ----------                     ----------
   reach Reddit, X, YouTube,   ->     classify stance,        ->     branch on a typed
   TikTok, HN, prediction             calibrate consensus +          contract instead of
   markets; rank by engagement        confidence; emit a map         guessing from prose

last30days is the retrieval and engagement layer. crowdcheck is the judgment layer: it reads that ranked evidence and produces consensus, confidence, weighted positions, and a market signal, as a machine-readable contract.

Pipeline: normalize the claim, search, classify stance, calibrate

Quickstart

Get started in 3 steps: try it offline, go live, use it in your agent

pip install "crowdcheck[mcp]"      # pre-release: see the install note below

Recommended - with last30days (the full experience):

git clone https://github.com/mvanhorn/last30days-skill ~/.claude/skills/last30days
export CROWDCHECK_LAST30DAYS_DIR=~/.claude/skills/last30days

crowdcheck "AI agents will replace most junior developer jobs by 2027"

No setup at all - offline demo:

crowdcheck "AI agents will replace most junior developer jobs by 2027" --demo

Without last30days, crowdcheck falls back to a keyless Hacker News plus prediction-market search. That runs with zero setup but gives lighter coverage (Reddit blocks keyless access; see Troubleshooting).

Pre-release: not on PyPI yet. Until the first release, install from source: pip install "git+https://github.com/avnath13/crowdcheck". On macOS, add the [native] extra (pip install "crowdcheck[native]") for a working CA bundle.

You get back a contestation map, not a thumbs-up or thumbs-down:

  • consensus 0.06 - the crowd is deeply split.
  • confidence 0.85 - but there is plenty of signal, so we are sure it is split.
  • positions - 40% dispute / 34% support / 25% "it depends", each with the top quote and where it came from.
  • market - a real-money prediction market puts the related bet at 34%.

What crowdcheck adds

last30days crowdcheck on top
Answers what are people saying, and what did they engage with do they agree, and can we trust the signal
Output a brief for a human to read a typed contract an agent branches on
New fields engagement-ranked evidence consensus, confidence, positions[], leaning
For research, catching up agents deciding whether to assert a claim

If you just want the human-readable brief, use last30days directly. crowdcheck is for when an agent (or a pipeline) needs a structured, uncertainty-calibrated read in the loop.

Works anywhere you do (MCP)

crowdcheck ships a standard stdio MCP server, so it drops into any MCP-compatible tool. Install once, then point your client at the crowdcheck-mcp command.

Claude Code

claude mcp add crowdcheck -- crowdcheck-mcp

Or add to .mcp.json (project) or ~/.claude.json (global), then verify with /mcp:

{ "mcpServers": { "crowdcheck": { "command": "crowdcheck-mcp" } } }

Cursor, Claude Desktop, Windsurf, Cline (the common mcpServers shape)

Add to ~/.cursor/mcp.json (Cursor global) or .cursor/mcp.json (project). Claude Desktop uses claude_desktop_config.json; Windsurf uses ~/.codeium/windsurf/mcp_config.json:

{ "mcpServers": { "crowdcheck": { "command": "crowdcheck-mcp", "args": [] } } }

VS Code (Copilot agent mode) - note the key is servers, not mcpServers. Add to .vscode/mcp.json:

{ "servers": { "crowdcheck": { "type": "stdio", "command": "crowdcheck-mcp" } } }

Codex CLI - codex mcp add crowdcheck -- crowdcheck-mcp, or add to ~/.codex/config.toml:

[mcp_servers.crowdcheck]
command = "crowdcheck-mcp"

Not on your PATH? Use the module form anywhere crowdcheck-mcp appears (use an absolute path to python if the client does not inherit your shell PATH):

{ "mcpServers": { "crowdcheck": { "command": "python", "args": ["-m", "crowdcheck.mcp_server"] } } }

Once connected, your agent has one tool, crowd_check, and the built-in reflex:

high confidence + high consensus  -> state it plainly
high confidence + low consensus   -> say it is contested; show both sides
low confidence (thin)             -> do not overclaim; flag the uncertainty

The agent calls it on its own, gets the JSON contract back, and acts deterministically instead of guessing from prose. This is where crowdcheck is strongest: the agent supplies the reasoning over the returned quotes on its own plan, so you do not need a separate model or key.

An agent calls crowd_check, gets consensus and confidence, and hedges its answer instead of hallucinating

The output contract

{
  "claim": "AI agents will replace most junior developer jobs by 2027",
  "mode": "live",             // "live" | "demo"
  "consensus": 0.06,          // 0 = evenly split, 1 = one-sided agreement
  "confidence": 0.85,         // 0 = insufficient signal, 1 = strong signal
  "leaning": "split",         // "supported" | "disputed" | "split"
  "read": "Highly contested, no clear side; market puts it at 34%. Signal: strong.",
  "positions": [
    { "stance": "dispute", "weight": 0.40, "count": 3, "top_quote": "...agents can't own context...", "who": "reddit (2,600), hackernews (1,240)", "sources": ["https://..."] },
    { "stance": "support", "weight": 0.34, "count": 3, "top_quote": "...we stopped backfilling junior roles...", "who": "reddit (1,980), youtube (51,000)", "sources": ["https://..."] },
    { "stance": "qualify", "weight": 0.25, "count": 2, "top_quote": "...reshaping junior work, not deleting it...", "who": "x (910)", "sources": ["https://..."] }
  ],
  "market_signal": { "question": "Will entry-level dev postings fall >30% by end of 2027?", "probability": 0.34, "source": "prediction market" },
  "coverage": { "sources_hit": ["reddit","x","hackernews","youtube"], "item_count": 8, "distinct_authors": 8, "thin": false }
}

From Python:

from crowdcheck import crowd_check

cmap = crowd_check("React Server Components are production ready", demo=True)
if cmap.confidence < 0.35:
    print("thin signal, do not rely on this")
elif cmap.consensus < 0.5:
    print("contested:", [p.stance for p in cmap.positions])
else:
    print("settled:", cmap.leaning)

Evidence sources

crowdcheck owns the judgment layer and treats retrieval as a pluggable provider. Pick the source with a one-flag toggle - same run, no code changes:

Where With last30days (recommended) Keyless fallback
CLI crowdcheck "your claim" --source last30days crowdcheck "your claim" --source native
Python crowd_check("your claim", source="last30days") crowd_check("your claim", source="native")
Agent (MCP) call crowd_check with source: "last30days" tool default

auto (the default) uses last30days when CROWDCHECK_LAST30DAYS_DIR (or --last30days-dir PATH) is set, and otherwise falls back to the native keyless provider. Valid sources: auto, last30days, native, demo.

  • LastThirtyDaysProvider (recommended) - the full engine: Reddit, X, YouTube, TikTok, Hacker News, prediction markets, and more, ranked by engagement. Keyless for Reddit, HN, markets, and GitHub; bring your own keys or browser sessions for X, YouTube, and TikTok.
  • NativeProvider (zero-setup fallback) - keyless Hacker News (stories and comments) plus a prediction market (Manifold), and Reddit on a best-effort basis (Reddit blocks keyless access on many networks). Claims are reduced to keywords before searching for better recall; sources fail independently and print a one-line notice rather than crashing.
  • DemoProvider - bundled offline sample evidence for --demo and the tests.

Bring your own provider by implementing fetch(claim) -> (list[Evidence], MarketSignal | None).

For LLM-grade stance labels (the built-in heuristic is intentionally simple), pass a classifier - no crowdcheck key required, you supply the model:

from crowdcheck import crowd_check, PromptedLLMClassifier, openai_compatible_complete

complete = openai_compatible_complete(model="gpt-4o-mini", api_key="sk-...")  # or any local/other endpoint
cmap = crowd_check("AI agents will replace junior devs by 2027",
                   classifier=PromptedLLMClassifier(complete))

Viral is not true, and here is how crowdcheck handles it

People upvote things that are wrong. A confident falsehood can go viral while the correct, boring correction gets ignored. The design accounts for that in four concrete ways, and stays honest about the one thing it cannot fix:

  • It never says "true" or "false". consensus measures whether people agree, not whether they are right. There is no verdict field, on purpose. Read high consensus as "widely believed," never as "correct."
  • One loud voice cannot dominate. confidence includes an independence term, so a single viral post reposted a hundred times does not manufacture strong signal.
  • The dissent is always shown. positions surfaces the dispute and qualify camps with their strongest quotes, right beside the popular view.
  • Money as a check on vibes. For predictive claims, market_signal pulls in real-money prediction-market odds.

What it cannot do: catch a genuine, widely-held misconception where almost nobody pushes back. That reads as high consensus, and crowdcheck reports it as such. For settled-fact questions, pair it with an authoritative source. crowdcheck maps the conversation; it does not verify facts.

Status and honest limits

  • Experimental (v0.1). APIs and output shape may change.
  • The map is only as good as the evidence. With last30days behind it you get Reddit, X, YouTube, TikTok, and more. The standalone keyless fallback is intentionally light: reliable Hacker News and prediction markets, best-effort Reddit.
  • Stance labeling is heuristic by default. Titles rarely trip a keyword lexicon, so a keyless run often shows solid confidence but low consensus. Wire an LLM classifier, or run crowdcheck inside an agent, where the model reasons over the returned quotes itself.

Troubleshooting

  • Live search returns 0 items or "thin" on macOS. Almost always an SSL certificate problem (CERTIFICATE_VERIFY_FAILED) with a python.org interpreter. Fix: pip install "crowdcheck[native]" (bundles a CA store via certifi), or run your Python's Install Certificates.command.
  • 'reddit' source unavailable (HTTPError: 403: Blocked). Reddit blocks keyless access on many networks. This is expected, not a bug; use last30days (--source last30days) for reliable Reddit.
  • Confidence is solid but consensus is ~0 with no positions. The built-in heuristic classifier only keyword-matches. Wire an LLM classifier, or run crowdcheck inside an agent.

Roadmap

  • Smarter query expansion and entity resolution for the native fallback
  • LLM stance classifier presets (OpenAI, Anthropic, local)
  • Compound-claim decomposition (split "A and B" into separate checks)
  • Batch mode: contestation-check every claim in a document
  • crowd_check_batch MCP tool

Contributions welcome, especially stance classifiers and evidence providers. See CONTRIBUTING.md.

Credits and acknowledgments

crowdcheck is built on and powered by last30days by @mvanhorn, which does the hard work of reaching a dozen walled-garden platforms and ranking by real engagement. If you find crowdcheck useful, star last30days first. last30days is MIT licensed; crowdcheck uses it as an optional external provider and is not a fork of it.

crowdcheck is MIT licensed (see LICENSE). It is an independent project and is not affiliated with last30days, its author, or any of the platforms it reads.

About

An MCP server that gives AI agents Community Notes: built on last30days, it maps who agrees, who disputes, and how sure the signal is - a contestation map, not a true/false verdict.

Topics

Resources

License

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages