Skip to content

Commit 783511a

Browse files
committed
Draft Custom Check blogpost
1 parent a90f5fb commit 783511a

1 file changed

Lines changed: 160 additions & 0 deletions

File tree

content/posts/rules.md

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
---
2+
title: "Custom Semantic Code Checks for PRs"
3+
date: 2025-06-26T17:16:50+01:00
4+
draft: true
5+
toc: false
6+
images:
7+
tags:
8+
- untagged
9+
---
10+
11+
# Custom Semantic Code Checks for PRs
12+
13+
<!-- TODO: add a Recurse screenshot as a header here -->
14+
15+
Maintaining consistent code quality while scaling the team is difficult.
16+
Well-intentioned Notion style guides are time-consuming to write and are often disregarded as soon as they're written.
17+
In this post I'll describe how you can use Recurse ML's new Custom Rules Feature to put the code style guide inside of your PR process.
18+
19+
Recurse ML is a GitHub App that identifies bugs introduced in PRs.
20+
It focuses on semantic issues that slip past static analysers.
21+
22+
We realised that every team's "source of paranoia" is different.
23+
While some universal bugs exist, the most valuable catches are often team-specific.
24+
That's why we built custom rules - a way to teach Recurse ML about your codebase's unique requirements.
25+
26+
## Quickstart
27+
28+
First off, install Recurse ML [GitHub app](https://github.com/apps/recurseml/) if you haven't already.
29+
30+
Then, create a `.recurseml.yaml` file (you can place it anywhere in your project):
31+
32+
```yaml
33+
# put this in .recurseml.yaml anywhere in your repo
34+
custom_rules:
35+
- name: "Effective Code Comments" # https://blog.codinghorror.com/code-tells-you-how-comments-tell-you-why/
36+
applicable_files:
37+
- "**/*.js"
38+
- "**/*.ts"
39+
- "**/*.py"
40+
- "**/*.go"
41+
- "**/*.java"
42+
- "**/*.rb"
43+
- "**/*.cs"
44+
description: "Explain WHY not WHAT the code does. Document complex business logic, clarify non-obvious implementations, warn about gotchas, and provide context for maintainers. Use proper documentation comment format for functions/methods. Keep TODO comments specific with assignees. Update comments when code changes."
45+
```
46+
47+
The full docs for custom rules can be found [here](https://recurse-ml.notion.site/Custom-Rules-21106defaa718059beabfb583f2ad066).
48+
49+
Now, every time a PR is submitted in your repo, a check will run, that verifies whether comments in the newly introduced code adhere to these guidelines.
50+
If they don't, Recurse ML will leave a review comment.
51+
52+
53+
For tips on how to write high quality rules, I recommend reading [bdougie's](https://x.com/bdougieYO) excellent blogpost [The Anatomy of Rules](https://blog.continue.dev/the-anatomy-of-rules-writing-effective-boundaries-for-ai-agents-in-ruby/).
54+
Even though his examples are in Ruby, the principles are universal.
55+
56+
## Inspiration Gallery
57+
58+
If you're still wondering what custom rules to introduce into your repo, I've gathered some examples.
59+
60+
### Performance & Scaling
61+
62+
These rules catch the performance killers that don't show up until you're under real load.
63+
For most applications, they're probably overkill - but if you're one of the lucky few startups with actual users, these patterns become critical.
64+
They're designed to prevent issues that work fine in development but can bring down your entire API when traffic picks up.
65+
66+
```yaml
67+
custom_rules:
68+
- name: "Avoid Blocking Operations in Request Handlers"
69+
applicable_files:
70+
- "routes/**/*.js"
71+
- "api/**/*.js"
72+
- "**/*handler*.js"
73+
description: "Don't use synchronous operations (fs.readFileSync, crypto.pbkdf2Sync) in request handlers as they block the event loop and kill performance under load. Use async alternatives or move to worker threads. One blocking operation can take down your entire API response time."
74+
```
75+
76+
77+
```yaml
78+
custom_rules:
79+
- name: "Avoid Blocking Operations in Request Handlers"
80+
applicable_files:
81+
- "routes/**/*.js"
82+
- "api/**/*.js"
83+
- "**/*handler*.js"
84+
description: "Don't use synchronous operations (fs.readFileSync, crypto.pbkdf2Sync) in request handlers as they block the event loop and kill performance under load. Use async alternatives or move to worker threads. One blocking operation can take down your entire API response time."
85+
```
86+
87+
```yaml
88+
custom_rules:
89+
- name: "Database Query Optimisation"
90+
applicable_files:
91+
- "**/*.js"
92+
- "**/*.ts"
93+
description: "Avoid N+1 queries and missing database indexes. Use eager loading, batch queries, or data loaders. Flag loops that contain database queries or ORM calls. These issues don't show up in development but will crash production performance as data grows."
94+
```
95+
96+
## Operational Reliability
97+
98+
99+
Production systems have a way of failing in the most inconvenient moments.
100+
These rules focus on the defensive coding practices that make the difference between a system that gracefully handles errors and one that silently loses data or crashes under pressure.
101+
Most codebases won't need this level of rigour, but when reliability matters to your users (and your sleep schedule), these patterns become essential.
102+
103+
```yaml
104+
custom_rules:
105+
- name: "Proper Error Handling in Critical Paths"
106+
applicable_files:
107+
- "**/*.js"
108+
- "**/*.ts"
109+
description: "Critical operations (payments, user registration, data processing) must have comprehensive error handling with logging, monitoring, and graceful degradation. Avoid silent failures that could lose revenue or corrupt user data. Include error context for debugging production issues."
110+
```
111+
112+
```yaml
113+
custom_rules:
114+
- name: "Memory Leak Prevention"
115+
applicable_files:
116+
- "**/*.js"
117+
- "**/*.ts"
118+
description: "Clean up event listeners, timers, and streams to prevent memory leaks. Use weak references for caches, clear intervals/timeouts, and properly close database connections. Memory leaks in Node.js can silently kill server performance and require expensive restarts."
119+
```
120+
121+
### Wisdom from the Elders
122+
123+
What if instead of sending a link-dump of classic blogposts to new-hires, we could encode the knowledge right inside of the repo?
124+
Wonder no more.
125+
As you probably noticed, the example rule in Quickstart session was inspired by [Jeff Atwood's](https://blog.codinghorror.com/about-me/) [classic](https://blog.codinghorror.com/code-tells-you-how-comments-tell-you-why/).
126+
I decided to distil some more classic software engineering blogposts into rules.
127+
128+
```yaml
129+
custom_rules:
130+
- name: "Don't DRY Your Code Prematurely" # https://testing.googleblog.com/2024/05/dont-dry-your-code-prematurely.html
131+
applicable_files:
132+
- "**/*.js"
133+
- "**/*.ts"
134+
- "**/*.py"
135+
- "**/*.go"
136+
- "**/*.java"
137+
- "**/*.rb"
138+
- "**/*.cs"
139+
description: "Consider carefully if code duplication is truly redundant or just superficially similar before applying DRY principles. Functions or classes may look the same but serve different contexts and business requirements that evolve differently over time. Avoid premature abstractions that couple behaviours which may need to evolve separately. When in doubt, keep behaviours separate until enough common patterns emerge over time that justify the coupling. Think about long-term evolution, not just making code shorter. Apply YAGNI principle - tolerate a little duplication in early development stages and wait to abstract until clear patterns emerge."
140+
```
141+
142+
```yaml
143+
custom_rules:
144+
- name: "Make Wrong Code Look Wrong" # https://www.joelonsoftware.com/2005/05/11/making-wrong-code-look-wrong/
145+
applicable_files:
146+
- "**/*.js"
147+
description: "Use naming conventions that make security vulnerabilities and type mismatches immediately visible. For web applications, prefix all user-supplied strings with 'unsafe_' or 'us' and all sanitized strings with 'safe_' or 's'. For coordinate systems, use prefixes like 'window_x' vs 'layout_x' to distinguish semantic differences. Apply Apps Hungarian notation principles - use prefixes that indicate the semantic meaning or origin of data, not just the data type. Make code self-documenting by ensuring that dangerous or incorrect operations look obviously wrong at the point of use. Collocate all information needed to verify correctness in the same line of code."
148+
```
149+
150+
Now, the rules act as a JIT learning tool for new-joiners, too!
151+
152+
153+
## Your Usecase Here
154+
155+
Do you have a pet peeve that you fight for like it's the Battle of Verdun?
156+
Is there part of your project that requires extra care during every PR?
157+
Maybe you just found a weird and wacky way to use this feature?
158+
I'd like to hear all about it.
159+
My email's my name at recurse.ml.
160+
And for higher bandwidth comms, you can find our team on Discord: https://discord.gg/qEjHQk64Z9

0 commit comments

Comments
 (0)