Skip to main content

halfbaked

Find the mistakes AI leaves behind in your code.

Your ai assistant writes code that imports cleanly, reads well, and looks finished. Some of it does nothing. halfbaked runs over a Python project like a test suite and reports every place the model invented an API, left a function unwritten, swallowed an error, or produced a test that cannot fail.

halfbaked finding 25 problems in an AI-written project

In full (not --quiet) it shows the offending line and what to do about it:

$ halfbaked examples/vibe_coded_app

  app.py
      3  x  GHOST IMPORT      `fastjson` does not exist: not in the standard library, not
                              installed, not part of this project, and not in your dependencies
         |  import fastjson
         -> Check the real package name before installing anything with this name -
            attackers register hallucinated package names on PyPI.

     13  x  GHOST FUNCTION    `sanitize_input()` is not defined anywhere in this project
         |  clean_order = sanitize_input(order)

     27  x  LOST AWAIT        send_email() is async, but it is called without `await`,
                              so its body never runs
         |  services.send_email(
         -> Write `await send_email(...)`.

  tests/test_orders.py
     14  x  TEST THEATER      test_truncate_long_text() runs code but never asserts anything,
                              so it can only fail if the code crashes
     21  x  FAKE ASSERT       `assert 1 == 1` is true no matter what the code does

  ────────────────────────────────────────────────────────────
  25 flops  ·  15 critical  ·  10 warning  ·  5 of 5 files affected
  checked in 0.18s

Why this is not just another linter

Existing linters check style and syntax — things a human gets wrong. Generated code fails differently. It is syntactically perfect and semantically hollow.

Nothing else catches these, because until recently nothing wrote them at scale:

  • A test that sets up an elaborate scenario and then asserts nothing.
  • A function with a thorough docstring describing behaviour it does not have.
  • client.send_json() — a method name so plausible you never think to check it exists.
  • # In a real implementation, you would validate the token here — shipped to production.

Install

pip install halfbaked

Zero dependencies. Python 3.9+. Windows, macOS and Linux. It never runs, imports, or evaluates the code it analyses — everything is read from the syntax tree.

If pip or halfbaked isn't found

macOS / Linux — the system Python has no pip command, only the module, and installed scripts land somewhere not on PATH:

python3 -m pip install --user halfbaked
python3 -m halfbaked .                     # always works

To type halfbaked directly, add the script directory to your shell:

echo 'export PATH="$HOME/Library/Python/3.9/bin:$PATH"' >> ~/.zshrc   # macOS

Windows — use the launcher if pip isn't on PATH:

py -m pip install halfbaked
py -m halfbaked .

python -m halfbaked is equivalent to the halfbaked command everywhere, so it is the reliable form when PATH is uncooperative.

Use

halfbaked                   # check the current directory
halfbaked src/              # check one directory
halfbaked app.py            # check a single file

halfbaked --only VC040      # only test-theater findings
halfbaked --ignore VC030    # hide a rule you disagree with
halfbaked --json            # machine-readable, for CI
halfbaked --list            # describe every check

Silence a single line:

result = risky()  # halfbaked: ignore
result = risky()  # noqa: VC030

Exit codes: 0 clean, 1 findings at or above --fail-on (default warning), 2 usage error.

What it catches

Code Check What it means
VC001 GHOST IMPORT Package does not exist anywhere — not stdlib, not installed, not declared, not local
VC002 GHOST FUNCTION A call to a function that was never written
VC003 GHOST METHOD A method that does not exist on the module it is called on
VC010 PLACEHOLDER A function with a docstring and no implementation
VC011 MODEL CONFESSION A comment where the model admits the code is not real
VC020 FAKE VALUE Placeholder credentials wired into live code
VC021 FAKE ENDPOINT example.com used as a real service
VC022 FAKE FALLBACK os.getenv("KEY", "your-key-here") — fails silently in production
VC030 SILENT FAIL Errors caught and discarded
VC031 SWALLOWED RETURN return inside finally, which throws away the exception
VC040 TEST THEATER A test that asserts nothing and cannot fail
VC041 FAKE ASSERT assert True — true regardless of the code
VC042 MOCK TAUTOLOGY A test that only asserts on values it mocked itself
VC050 LOST AWAIT An async function called without await, so it never runs
VC051 BLOCKING ASYNC time.sleep() inside async def, freezing the event loop

It stays quiet on good code

A linter that cries wolf gets uninstalled. Every rule is calibrated against real, mature, human-written code rather than tuned only to catch things.

Across 241 files of pip and setuptools source, halfbaked reports 2 critical findings. Nearly all of the remaining output is VC030 — real error-swallowing that is genuinely there.

Getting to that number meant teaching the checks about how Python is actually written:

  • raise NotImplementedError in a base class is informal abstract, not an unfinished job.
  • except KeyboardInterrupt: with a real handler body is correct; only discarding it is a bug.
  • try: import tomllib / except ImportError: import tomli is a compatibility shim, not a hallucination.
  • A package in requirements.txt but not installed is your setup, not the model's invention.
  • Vendored directories are somebody else's code and are skipped.

Speed

The whole Python standard library - 680 files, 306,000 lines - takes about 27 seconds on a laptop, or roughly 11,000 lines a second. A normal project is a fraction of that: a few thousand lines finishes before you lift your hand off the keyboard.

Each file is parsed once and its nodes bucketed by type, so adding a sixteenth check costs almost nothing - the tree is already walked.

In CI

- name: halfbaked
  run: |
    pip install halfbaked
    halfbaked . --fail-on critical

How it works

  1. Index — parse every file and record what the project genuinely defines: functions, classes, methods, class hierarchies, async definitions.
  2. Check — walk each file once, bucket the nodes by type, and run all fifteen rules against that shared view.
  3. Report — group findings by file, ranked by severity, each with the offending line and a concrete fix.

The index is what makes ghost detection possible: no single file can tell you whether helpers.format_date() is real, but the whole project can.

Roadmap

  • JavaScript / TypeScript. The flops are identical in every language — only the parser is Python-specific, and the checks are deliberately separated from parsing.
  • Editor integration, so findings appear as you accept a suggestion rather than afterwards.
  • Config file for per-project severity overrides.

Contributing

A new rule is one Check subclass and one line in the registry. The bar for merging: it must fire on generated code and stay silent on pip and setuptools.

git clone <repo> && cd halfbaked
pip install -e ".[dev]"
python -m pytest tests/ -q
halfbaked examples/vibe_coded_app     # should report 25 flops

The README demo and the social card are both generated from the tool's real output, so they cannot drift from what it actually prints:

python3 tools/make_demo.py      # -> demo.svg
python3 tools/make_social.py    # -> social-preview.png  (macOS)

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

halfbaked-0.4.0.tar.gz (64.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

halfbaked-0.4.0-py3-none-any.whl (55.2 kB view details)

Uploaded Python 3

File details

Details for the file halfbaked-0.4.0.tar.gz.

File metadata

  • Download URL: halfbaked-0.4.0.tar.gz
  • Upload date:
  • Size: 64.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for halfbaked-0.4.0.tar.gz
Algorithm Hash digest
SHA256 1d3b8d479d68e339734ce6470a995e93111043d2e6f7773e8a6fb78f8ad8bc43
MD5 4593dc07e70ff819ebf37b1b09e2e7da
BLAKE2b-256 d611fbab297e3173973e501c3a6224777d2b9c618906560b388b63070f18d831

See more details on using hashes here.

File details

Details for the file halfbaked-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: halfbaked-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 55.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for halfbaked-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8647fb1e761aec7420af9e67b0c9e5f253c55f41324afc0fa6e4855ff509d0fc
MD5 3f5b965eced653c6402da998efa12de5
BLAKE2b-256 0f38146257679651b543625ed36ef7e2341bc946ada564e0655b84e554613f46

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page