Scan a snippet, a repo, or your own code
The exact same 100 checks as the CLI, running in a real CPython build compiled to WebAssembly. Nothing you paste or point it at leaves your machine.
codehound hunts subtle correctness and async-safety bugs — the ones that pass code review and only bite in production. Every rule below was distilled from a real bug, found and fixed in a real open-source project. Scan a snippet, a whole GitHub repo, or a local folder further down. Nothing is uploaded: it runs on your machine, in codehound's own Python, compiled to WebAssembly.
codehound isn't a demo — these are real defects it found in widely-used open-source projects, each fixed with a regression test verified to fail before the fix and pass after it.
agno 41k★The project's original proof point. codehound pointed at agno's own source found requests.get() sitting inside the async Discord on_message handler — freezing the event loop on every attachment, and able to 403 on authenticated URLs. Not a bug anyone was looking for; the scan found it.
accelerate 9k★In distributed-training parameter sync, a list of callbacks — one per model chunk — each captured model_index by reference. Whichever chunk's callback fired last reported the same, wrong index for every chunk. Used across the PyTorch training ecosystem.
huggingface/accelerate #4273 →
optuna 12k★Seven node-lookup methods on _FanovaTree were @lru_cache'd directly on the class. Every tree built for a single get_param_importances() call — one per random-forest estimator — stayed reachable through the cache forever, instead of being freed the moment it was done.
llama_index 40k★Same class-level cache mistake, with a compounding twist: VectaraIndex._get_corpus_key's leak meant the class's own __del__ — written specifically to close its HTTP session — never ran. One bug quietly broke a second, unrelated cleanup path nobody had connected to it.
litellm 30k★Router._cached_get_model_group_info leaked every Router that ever served a request — and survived even a correctly-called Router.discard(), the class's own documented cleanup method. Proved it independently by testing all four combinations before trusting the fix.
agno 41k★A fire-and-forget asyncio.create_task() in the tracing exporter's async path — the event loop only holds a weak reference to a task, so with nothing else referencing it, traces could be silently dropped mid-run.
Most tools only show you what shipped. Eight fully-built checks were corpus-scanned and thrown out this year because the real hits turned out to be correct code, not bugs — the same discipline applied to codehound's own rules that its rules apply to yours.
The exact same 100 checks as the CLI, running in a real CPython build compiled to WebAssembly. Nothing you paste or point it at leaves your machine.
Pyodide runs a full CPython build in your browser tab. On load, it installs the real, currently-published codehound wheel straight from PyPI with micropip — the exact same package pip install codehound gives you.
A snippet is scanned in memory. A GitHub repo is fetched file-by-file from GitHub's own CDN straight into the browser tab. A local folder never leaves your machine at all — there's no server behind this page to send it to.
This isn't a demo subset — it's codehound.get_checks() and scan_files(), the identical code path codehound scan runs locally. What you see here is what you'd get from the real tool.
A finding means the shape looks dangerous, not that it definitely is. Read the message, check the context — some flagged code is genuinely fine, and the findings log above documents real examples of exactly that, checked and cleared.