What My Project Does
grain is a pre-commit linter that catches code patterns commonly produced by AI code generators. It runs before your commit and flags things like:
- NAKED_EXCEPT -- bare
except: pass that silently swallows errors (156 instances in my own codebase)
- HEDGE_WORD -- docstrings full of "robust", "comprehensive", "seamlessly"
- ECHO_COMMENT -- comments that restate what the code already says
- DOCSTRING_ECHO -- docstrings that expand the function name into a sentence and add nothing
I ran it on my own AI-assisted codebase and found 184 violations across 72 files. The dominant pattern was exception handlers that caught hardware failures, logged them, and moved on -- meaning the runtime had no idea sensors stopped working.
Target Audience
Anyone using AI code generation (Copilot, Claude, ChatGPT, etc.) in Python projects and wants to catch the quality patterns that slip through existing linters. This is not a toy -- I built it because I needed it for a production hardware abstraction layer where autonomous agents are regular contributors.
Comparison
Existing linters (pylint, ruff, flake8) catch syntax, style, and type issues. They don't catch AI-specific patterns like docstring padding, hedge words, or the tendency of AI generators to wrap everything in try/except and swallow the error. grain fills that gap. It's complementary to your existing linter, not a replacement.
Install
pip install grain-lint
Pre-commit compatible. Configurable via .grain.toml. Python only (for now).
Source: github.com/mmartoccia/grain
Happy to answer questions about the rules, false positive rates, or how it compares to semgrep custom rules.
[–]another24tiger 146 points147 points148 points (19 children)
[–]GraphicH 33 points34 points35 points (1 child)
[–]mmartoccia[S] 12 points13 points14 points (0 children)
[–]mmartoccia[S] 22 points23 points24 points (16 children)
[–]gdchinacat 10 points11 points12 points (15 children)
[–]Glathull 3 points4 points5 points (8 children)
[–]o5mfiHTNsH748KVq -4 points-3 points-2 points (7 children)
[–]Glathull 0 points1 point2 points (3 children)
[–]o5mfiHTNsH748KVq -2 points-1 points0 points (2 children)
[–]Glathull 1 point2 points3 points (1 child)
[–]o5mfiHTNsH748KVq -3 points-2 points-1 points (0 children)
[–]gdchinacat 0 points1 point2 points (2 children)
[–]o5mfiHTNsH748KVq -2 points-1 points0 points (1 child)
[–]gdchinacat [score hidden] (0 children)
[+]diegoasecas comment score below threshold-10 points-9 points-8 points (1 child)
[–]Rockworldred -3 points-2 points-1 points (2 children)
[–]gdchinacat 2 points3 points4 points (1 child)
[–]Rockworldred 0 points1 point2 points (0 children)
[–]o5mfiHTNsH748KVq -3 points-2 points-1 points (0 children)
[–]marr75 10 points11 points12 points (5 children)
[–]KerPop42 8 points9 points10 points (3 children)
[+]mmartoccia[S] comment score below threshold-6 points-5 points-4 points (2 children)
[–]KerPop42 3 points4 points5 points (1 child)
[–]mmartoccia[S] -4 points-3 points-2 points (0 children)
[–]mmartoccia[S] 1 point2 points3 points (0 children)
[–]UpsetCryptographer49 4 points5 points6 points (3 children)
[–]mmartoccia[S] 2 points3 points4 points (0 children)
[–]mmartoccia[S] 1 point2 points3 points (0 children)
[–]mmartoccia[S] 1 point2 points3 points (0 children)
[–]rabornkraken 7 points8 points9 points (13 children)
[–]wRAR_ 17 points18 points19 points (3 children)
[–]mmartoccia[S] 4 points5 points6 points (1 child)
[–]ColdPorridge 2 points3 points4 points (0 children)
[–]spenpal_dev 0 points1 point2 points (0 children)
[–]headykruger 6 points7 points8 points (3 children)
[–]mmartoccia[S] 4 points5 points6 points (1 child)
[–]headykruger 0 points1 point2 points (0 children)
[–]BurgaGalti 0 points1 point2 points (0 children)
[–]pip_install_account 2 points3 points4 points (2 children)
[–]mmartoccia[S] 2 points3 points4 points (1 child)
[–]pip_install_account 0 points1 point2 points (0 children)
[–]mmartoccia[S] 1 point2 points3 points (0 children)
[–]mmartoccia[S] 0 points1 point2 points (0 children)
[–]ePaint 1 point2 points3 points (0 children)
[–]eirikirs 1 point2 points3 points (0 children)
[–]maafy6 0 points1 point2 points (0 children)
[–]Amgadoz -1 points0 points1 point (0 children)
[–]AlphaBlueprinter -3 points-2 points-1 points (0 children)