Comment by hannofcart
20 days ago
The post touches very briefly on linting in 7. For me, setting up a large number of static code analysis checks has had the highest impact on code quality.
My hierarchy of static analysis looks like this (hierarchy below is Typescript focused but in principle translatable to other languages):
1. Typesafe compiler (tsc)
2. Basic lint rules (eslint)
3. Cyclomatic complexity rules (eslint, sonarjs)
4. Max line length enforcement (via eslint)
5. Max file length enforcement (via eslint)
6. Unused code/export analyser (knip)
7. Code duplication analyser (jscpd)
8. Modularisation enforcement (dependency-cruiser)
9. Custom script to ensure shared/util directories are not over stuffed (built this using dependency-cruiser as a library rather than an exec)
10. Security check (semgrep)
I stitch all the above in a single `pnpm check` command and defined an agent rule to run this before marking task as complete.
Finally, I make sure `pnpm check` is run as part of a pre-commit hook to make sure that the agent has indeed addressed all the issues.
This makes a dramatic improvement in code quality to the point where I'm able to jump in and manually modify the code easily when the LLM slot machine gets stuck every now and then.
(Edit: added mention of pre-commit hook which I missed mention of in initial comment)
this is close to what i've landed on too. the pre-commit hook is non-negotiable. i've had Claude Code report "all checks pass" when there were 14 failing eslint rules. beyond the static analysis though, i keep hitting a harder problem: code that passes every lint rule, compiles clean, and greens the test suite but implements a subtly wrong interpretation of the spec. like an API handler that returns 200 with an empty array instead of 404, technically valid but semantically wrong. evaluating behavioural correctness against intent, not just syntax or type safety, is the gap nobody's really cracked yet. property-based testing helps but it still requires you to formalize the invariants upfront, which is often the hard part.
Not a catch all to fix issues agree with linting. Being very strict with linters has become very cheap with coding agents and it keeps you up to date with code standards and keeps code style homogenous which is very nice when you are reviewing professional code, regardless of who wrote it.
It’s also tricky otherwise if you have to occasionally review lazily written manual code mixed with syntactically formal/clean but functionally incorrect AI code.
My setup has some of the things mentioned and I found that occasionally the LLM will lie that something passes, when it doesn't.
Yup I have run into the same.
I use a pre-commit hook to run `pnpm check`. I missed mentioning it in the original comment. Your reply reminded me of it and I have now added it. Thanks.
That's something I find to be incredibly frustrating. I have to keep reminding it that we're not done, no matter how much I enforce that the lints must pass before we're done.
Make the error message much more dramatic and it will be less likely to miss it. Create a wrapper if you can't change the error message.
Remember these are still fundamentally trained on human communication and Dale Carnegie had some good advice that also applies to language generators.
If you're using Claude try the hookify plugin and ask if to block commits unless the rules pass.
These kinda things aren’t really the issues I run into. Lack of clarity of thought, overly verbose code, needlessly defensive programming - the stuff that really rots a codebase. Honestly some of the above rules you have I’d want the LLM to ignore at the times if we’re going for maximum maintainability.
Very nice.
BUT, what is the point of max line length enforcement, just to see if there are crazy ternary operators going on?
It makes diff split view nicer to use.
At least this is the reason why I do use it
I see. That makes sense, but sometimes is makes code harder to read.
Except for dependency cruiser which I hadn't heard of, this is almost exactly what I've built up over the past few weeks.
For the pre-commit hook, I assume you run it on just the files changed?
> Custom script to ensure shared/util directories are not over stuffed (built this using dependency-cruiser as a library rather than an exec)
Would you share this?