Let's play a game. Have a look at this comments code and see if you can spot the bug. So, it's a query that takes a task ID. It grabs the currently authenticated user. Then, it grabs the task, then the project for that task and the assigne's name before returning all of it at the end. So, have you spotted where the bug is here? No? Well, not to worry. Neither did I. See, the bug is quite subtle and is one of those that can easily slip by when you're in the vibe coding zone. You see, I probably like most of you guys as well, have been letting the agents absolutely rip on my projects lately. And I've been quite happily just merging stuff without doing a deep evaluation of the code for potential issues. And stuff was definitely falling through the cracks. So, I decided enough was enough. I was going to try and tackle this problem by running this this particular code issue that I just showed you and nine others through a battery of code review bots to see which would catch the issue and which would not. And I have to say the results are very interesting. I won't spoil it for you just yet, but I will just say that one tool got almost everything right and one famous tool basically faceplanted [music] the whole thing. So, if you want to find out what the answer is to that problem I just showed you, and you're also like me and you want to inject a little bit more confidence into your Vive coding sessions with Convex [music] code, then this is the right video for you. We're going to take a look at some of the most popular code review bots on the market and see how they stack up against each other. And by the way, if your favorite tools missing from this list, stick around as I'm going to discuss that a little bit later. [music] So, make sure you grab yourself a lovely cup of tea, drop me a like and sub, and let's get into it. All right, so just quickly before we dive into testing the review bots, I need to quickly explain how I went about evaluating these bots. So, I started by creating this little project here. It's a realistic project that I hope I can use as a baseline. It's basically a Trello clone that uses ReactV and Convex or for authentication. So, after you log in, you can create a project. Each project can have any number of members assigned to them. Then the members create tasks on which appear on this canban style board. Each task has a few properties and each task can also have comments. There's also an activity log which we don't display [music] but basically it's keeping an audit trail of any changes behind the scenes. So it's quite basic but it has a lot of the essentials that you find in any modern SAS such as a nested related data and authentication and authorization. So I feel like this is a good starting point to evaluate from. So now I've got my baseline. I came up with 10 different scenarios I wanted to test the code review bots on. And these basically form our evals. So let's just take a quick look at one of these to get a sense of what I'm going for. So starting with what I thought would be an easy one [music] to test to see if the review bot can detect whether we are falsely using convex's dot filter when we should be using dot with index instead. Now, this recommendation to use indices instead of filter is basically plastered all over the convex docs, not to mention it being actually included inside this project in the do.cursor/ruules file uh directory. So, the bot should really have been [music] smart enough to pick this up. So, I thought this would be an easy test to check whether the review bots basic understanding of convex and to see whether they would actually go out and read the cursor rules file or not. [music] Now, I do realize that it might be a bit of a a stretch expecting the review bots to check every single IDE or tools special folder like this cursor one. And that's why I'm also working on this PR to make a change to how we inject these AI files into your convex project. So, I'll be doing a video on that once this PR lands. So, make sure you get subscribed as I'm [music] kind of excited for this one. So, with that said, I was still hoping that the review bots would be smart enough to pick up like from one of the most important AI tools out there, Cursor. But spoiler, they didn't. Actually, let's just take a quick aside to have a talk about the different review bots I chose for this series of tests. So, we have Quodo, GitHub, Copilot, Cubic, Code, Rabbit, Grapar, Codeant AI, Sorcery, Macroscope, Graphite AI. So I signed up for each of these in turn. Some required a credit card, but most gave me um some sort of full trial, which is good as this little experiment could have gotten quite expensive uh without that. Some of them had really smooth on boarding processes and a really clear and easy to understand dashboard and others not so much. Um we will talk more about that a bit later when we discuss the winners. [music] Now just note here that I intentionally did not mess with any of the settings on any of the review bots. I know some of you are probably going to complain at me for that, but I wanted a fresh out ofthe-box comparison and I'm not an expert at any of these tools. So, configuring them all to be exactly right for this project would have been a bit of a fiddly affair and likely errorprone. And while we're on the topic of addressing your complaints before they arise, I know some of you are going to complain that I'm missing some tool or other in this list. [music] And I posted that I was going to be working on this video the other day and I got a bunch of suggestions for other review bots to try out. Now, they are really good suggestions and I want to look into those, but I didn't want to crowd out this video with every bot out there, but people did mention some important ones such as Bugbot and some of the newer offerings from OpenAI and Anthropic. So, I am going to do a follow-up video in the near future to test out those guys as well. And also to explore what I think might be the ultimate solution. So, make sure you get subscribed on here and on X so you get notified when that one drops. Okay. So, now with that out of the way, let's return back to the PR we've got set up for these bots to test the dot filter versus the dot with index. So you can see here and generally throughout all of these tests I try to keep the set of changes quite minimal so that we are usually only testing one thing. So although I try and do this sometimes it's quite difficult to have the bit of work be isolated and yet the PR still be realistic. One little trick I employ to get around that is to have um the new query here where we are testing for filter versus index. I marked it as an internal query and then added this comment on top which says that we're going to execute this query via the convex dashboard which is a common thing that convex people do. So don't worry Mr. Reviewbot where this isn't actually used anywhere in the codebase but we're still going to be used from the comics dashboard. I should also just mention that I was very careful in this entire project and in the PR descriptions and everything not to add any files or anything like that would give the game away that we are evaluating the review bots. I don't want a Volkswagen [laughter] incident on my hands here. All right, so finally, Michael, stop talking. How did the bots do? All right, so if we just take a look at the review on GitHub, you'll notice that there's a lot of spam at the start here. So, up here in the user description, this part here is the bit that I added, and all the rest of this stuff is just fluff that the review bots added. I personally don't think that this like PR summary stuff is useful. Um, and I'm sure you can probably turn off in the settings. Sorcery in particular, I found to be quite verbose out of the box. add is it adds all these massive sequence diagrams in every PR which I personally don't think is that useful but whatever. So as we continue to scroll down here one thing you might be thinking because I was too is that each of these bots are they able to see each other's comments and reviews. I was actually really concerned about this because I didn't want to have to create an entirely separate repo and project for each review bot so that they could be isolated from each other. So the approach that I decided to take was to to keep a very close eye on these and see if any of them mentioned any other reviews review bots or previous reviews. And I'm thankful to report that at no instance did I ever see any review bot mention any other other bots reviews. I think this might be because I've got them all set up to start their review process is immediately as soon as the PR drops. So basically they all get triggered at the same time, grab their context, and it's at that point that they then start to do the review. So they don't have a chance to look at each other's reviews. Either way, as we continue to scroll down here, you can see that there's heaps and heaps of stuff here. Some have put stuff in some like in summary comments and some have done inline code comments. Some have done reviews, some have done checks, some have not. And I was finding it kind of annoying and errorprone to go through this manually. So, I would do what any engineer does in 2026. I had an agent do it for me. So for each of these tasks, I'm setting the review bot. I first had an agent write one of these documents where we detail what it is exactly that we're going to be testing, what we are expecting the model to say, what we want them to, and things we don't want them to [music] say. So basically, this is our grading criteria. And once again, I intentionally do not commit these files into the repo to make sure that the review bots can't see this and understand [music] that we are, you know, testing them. And I also make sure that we have a good cover story for each PR. Hi, Mike from the future here. Yes, weather's lovely. I just want to note that I have actually now committed these PR um expectation documents to the main branch. So if you want to go ahead and try and run this yourself, then you will be able to see them on the main branch or see the detailed scores or see whatever else. But these were not included in any of the branches so that the review bots didn't see any of this. Now back to Mike from the past. So for this particular PR, our cover story is new convex/reporting.ts module with a single internal query for use with the convex dashboard. Get activity for user returns recent activity for a specific user within a project. So what we want the bot to do is catch the dot filter and we want them to recommend that we should use dot with index instead. What we don't want the bot to say is anything to do with or as this is an internal query and we know that internal queries don't need or because they're going to get executed via the dashboard. All right. So finally again after all of this let's take a look at the results. So, Code Rabbit caught it. Nice. Reptile caught it. Macroscope didn't, which is a shame. It's only reported a code check. Cubit caught it. Graphite didn't. And we'll see, spoiler, will continue to perform badly. Quodto caught it. Nice. Kodan didn't. They vaguely mention indices, which might have gotten them a pass, but they also incorrectly flagged OR on the internal query. Whoops. Sorcery did a kind of halfass job by mentioning that we might need an index if not already indexed. It should have checked the schema to see whether we have an index. It shouldn't say if we already have an index. Copilot caught it and added a nice helpful inline code comment. And so I guess the takeaway is that six out of nine of the bots caught the issue which is pretty good. So, I then also had the agent, um, Claude Opus, by the way, uh, do a detailed tool review, uh, as some of the bots went the extra mile and caught some other issues or flagged other things which earned them bonus points. And I'll talk about the scoring process a little bit later. Yeah. And in this sort of details evaluation here, you might notice lines about table uh, validation agrees. So, just to give myself a little bit more confidence that this review agent is doing a good job, I um had another agent run through the entire thing again. This time using Convex 5 uh sorry, codeex 5.3 in a clean context. So, that's what this is. It's basically saying yes, I agree with the initial review. And Codeex mostly agreed. I think there was only like one or two places where it caught a couple of issues that Opus didn't catch. I also did do a few smoke tests on a few of these just to make sure 100% sure, give myself more confidence that both of them aren't messing up somewhere. So, the final thing is in each of these PR expectations documents, we have a scores table at the bottom here. So, I guess we might as well talk about scoring now. So, basically, I gave the bot three points if it passed the primary objective and zero points if they failed. And if they got a mixed result like Sorcery did here, they just get one point. Then I gave a bonus point if the review bot picked up extra good stuff. And this kind of extra good stuff is more of a judgment kind of call. So if they did a generally good job, they would get one point. However, if they had lots of false positives, then I kind of punish them by giving them minus one because in my opinion, false positives in review bots are just really annoying to deal with and I don't want to see them. So, at the end of all that, Code Rabbit, Reptile, Cubic, and Quodto, and Copilot all tied with three points. Kodand failed hard on this one by not catching the primary issue and also falsely flagging the orth issue which is not great comics knowledge at all there. But will this trend continue? What do you think? Okay, so we talked a little bit about false positives just now. So I want to take a look at this um PR PR01 which is the first one I actually tackled which deals with false positives. So I wanted to set the bots a task to see if I could catch them out. I wanted to see whether they would falsely flag something as an issue even though it isn't an issue just because of the way that convex works. So let's take a look at the code. So here we have this internal query get project overview. I'm doing that internal query trick again here so I can isolate this bit of work. And this query is supposed to take in a project and return some data that can be used to give you an overview of that project. So the first thing it does is grab a bunch of tasks. Now I'm not using doc collect here because I don't want the bots to get confused and flag unbounded reads. I have a separate test for that coming up. So I only select 50 tasks here. And when I make decisions like this, I explicitly put a comment on the top here so that the review bot knows I'm making this explicit decision. Again, I just don't I want to try and minimize the number of potential issues, side issues that get raised in here. I want the review bot to to focus on the one thing that I'm mainly testing for. But anyway, so for each task, we then also grab the assigne and all the labels before finally returning all the data at the end. Now, if you are a review bot, which is, you know, an AI model, and you've been trained on a bunch of traditional serverless code, you might look at this and go, "Oh, there's a bunch of database roundtrips here. Uh, this is not good. This is what's known as an n plus1 problem and is a pretty standard performance issue. But we all know as convex developers that this is not true in convex because in convex the database and the compute compute are collleated together. So effectively this entire query is one big transaction. So there is no n plus1 issue. Okay. Okay, so now in the markdown file we basically in this what I'll be testing section we have where the tools understand that nested uh context db calls inside of a convex query function are not an n plus1 problem. So how did they do well? Code rabbit whoops reptile nope macroscope decided not to flag anything but again it didn't flag anything either before so I've given it a pass here but I have my suspicions. Uh, Cubic saw nothing wrong uh too, which is good. Graphite, as with Macroscope, um, only did code checks here, which got a pass, but again, I'm very suspicious. Uh, Quoto falsely flagged this one. Sigh. Uh, same with Kodan, same with Sorcery. And even C-Pilot failed as well. [music] Wow. So, okay. Three out of the nine tools passed. And as we'll see, I think microscope and graphite are kind of a bit sus here. So I would say that cubic is probably the only one that honestly did a good job here. Now I'm going to skip over the details part and let's just take a look at the scores table. So microscope, cubic, and graphite all got three points, and a few of the others pick up bonus points. And Kodant and Code Rabbit, what's it with these code animal things? Anyway, they get negative points for uh false additional positives. So, super interesting results. Let's continue. All right. Now, I think you'll all agree that this is pretty interesting, but I don't want to bore you guys by just going through a list of all these in painful detail. So, instead, what I'm going to do is do the rest of these uh tests that I gave the the bots in a few little mini arcs. All right. So in the third one I wanted to test for missing or off. So you can see that this request export function here doesn't check for authentication before doing its thing. So the results are as follows. So in the fourth one I set up a chron job to run this mutation clean up old activity. [music] And while there is no issue in the handler itself, the thing that I was testing the bot for to see whether they would pick up that this should be an internal mutation, not a public mutation. And here are the results. And staying on the all authentication trip, this is the last one I did, but it's also the one that I I showed you right in the intro. So, did you spot the issue? I'll give you a few more seconds while you have a look. Okay. So, if you said it was an authorization issue, you would be correct. So, basically, even though that we check for authentication here, we grab the user's ID, we don't actually at any point in here check to see whether the past task actually belongs to this user. And thus a malicious user could use this to read tasks from any other user which is obviously not ideal and should be caught by the bots and most did indeed catch it which is nice. All right so let's take a look at some performance issues now. So in the fifth one I wanted to test for one of the big performance gotchas for agents plus convex right now and that is unbounded collects. So here we can see that even though we are using an index we are also using a collect and that could be a potential issue particularly when the table can grow in an unbounded way. [music] What I mean by unbounded is that um the number of rows here can be expected to grow larger and larger as time goes on which is the case for tasks in a project. And so this is how the bots did. The sixth task is similar to the previous one and is there because I see agents doing this one a lot wrong at the moment as well. So I've seen them using docolct as a way to count the number of documents. Basically I'm hoping that the bot will catch this and instead suggest a denormalized count process or use the aggregate component instead. And here's the results. The seventh test is again another performance one and is the first one where I made a schema change as well. So I added this checklist array to the tasks table. Then I added a couple of functions for adding and toggling a checklist item. So the test here is to see whether the bots would catch the fact that this checklist array should probably be its own table. That's because this checklist array could grow in an unbounded way, which would cause us to hit the row size limit for an individual row in a convex table. And here's how the bots did. Okay, the last one in our little mini arc here is I wanted to test for correctness basically. So in the eighth test, I wanted to test the the bot's knowledge of convex components. So, as part of the baseline, I added this aggregate that counts the number of tasks um in a given project, which is is all well and good. It's all fine. It's how you're supposed to do counts. But this PR we just added to test the bot uh is a new mutation that does something that will change the number of tasks, but we intentionally forget to make the call to update the aggregate as well. So hopefully the bot will be smart enough to catch that. And let's have a look at the results and it seems that some weren't unfortunately smart enough to catch it. Now the ninth test has the most number of changes in it and what I was thinking was going to be the most [music] complex one for bots to get. So optimistic concurrency control or OC errors and convex are a fairly complex topic. They basically happen when you try and read and write to the same value in lots of different places all at the same time. They kind of basically conflict with each [music] other. So in this PR I created a new table platform stats which has a field total mutations that I write to from every mutation in the app for every single user. So this is obviously a very bad idea. It's going to cause OCC errors. [music] Now, originally I actually had this where the I I it wasn't for every single user. I actually had this platform stats for a single project and none of the bots caught it as an OC error. And I was like, "Wow, okay. I think maybe maybe I can make this more obvious because reflecting back on it, I realized that it could be argued that maybe there wouldn't be that many OC areas depending upon how big the project is. So I decided to change this this one to make it more explicit by making it every single mutation for every single user hits the same field. And now the results yeah they seemed much more realistic of what I was expecting. All right, so at last the moment you've been waiting for the final score for all the models. Here we go. So at the top we have what I would class as gold tier. We have quoto closely followed by co-pilot. Then in silver tier we have cubic, code rabbit, and grapile. Then in bronze tier we have Kodant. And then down the bottom here we have sorcery, macroscope, and graphite which I would class in the not worth your time tier. Kodo being right at number one was a total surprise to me because I have to say his dashboard experience was absolutely the worst out of all of these tools. I mean just look at this. This is all you get. It's And like it just bugs all over the place. I mean, it says I need to connect repositories, but I've already done that several times. Look, it just refuses to show the fact that I'm already connected. I was also so frustrated and confused by this that I actually tried to exclude Quoto from my testing early on. I deleted my entire Quoto account and everything. But to my great surprise, the tool continued to submit PR's reviews for me, even though they can't have been totally deleted. Like, what? But I guess if it's going to continue to catch issues like this like a total champ and cost nothing, then now graphite I was sure I must be doing something wrong here because zeros straight across the board other than you know the false positive one at the start is just incredible result in the wrong way. But no, I logged into the dashboard, checked, double checked, triple checked all of this and just just to make sure that graphite is indeed connected and it indeed finds no issues. I just find this really hard to imagine that a tool this well known is also making this many mistakes. I guess this leads us into the next topic. So, I know that at least some of the owners behind some of these bots will be watching this. So, I just wanted to point out a couple of places that I think could be improved. So, firstly, on boarding experience varied wildly between the tools. Some required that I hand over the credit card before I could even try the tool. Please don't do that. It's just super frustrating and puts me off right away when I want when I just want to try something. The absolute worst offender for this was Aikido, which you will notice is missing from the video as I was originally going to be the 10th review bot until I realized it was going to cost me $350 per month just for this review process. So, yeah, thanks but no thanks. And while we're talking about onboarding, I really like simple wizard walkthroughs right at the start where it basically asks me what it is I'm looking to do, PR summaries, code reviews, things like that. It kind of sets up the basics for you, which eases me in. It lets me know that those other features are also available. And while we're talking about dashboards, man, just confusing UIs, I'm just again, I'm sorry to pick on your graphite, but icons for your main navbar and no text is just like, how am I supposed to know what this little down arrow thing is supposed to represent? Then where on earth are the settings that allow me to configure the review bot? Like, is it here under settings? to enable code reviews in the setting. No, no, not there. Is it this little settings icon here in the inbox that shows you reviews? No. No, not there. Ah, okay. It's this little icon here and then the settings here. Okay. Yeah, got it. I think now I know I picked on graphite here, but a number of the other bots also suffer from this kind of like dashboard nonsense. And outside of like code review and dashboard issues, I would say that I was expecting more of the bots to do to look at my project more. They should look at the cursor rules files. They may well be looking at the agents.mmd and and clawed MD files. I didn't include those with this project, but I did add cursor rules. So, I was hoping that they would check that. And if they did, I would have thought that they would have done a lot better as a result because those cursor rules files would have included much of the knowledge that many of these re review bots seem to have failed on. They could also have been a little bit more intelligent like if they detected that this is a convex project, maybe they could have um you know proactively gone out and find like our ESLint rules or something else and then stored that inside its knowledge for this particular project. and use that as part of its review process. That would have been a very intelligent way to have reviews for this project. All right, so that's about all I have for you for today. I hope you found this both useful and insightful. So, I'm not sure about you, but I found those results quite surprising. And so, I think personally for me, I will probably just start to use Copilot for my code review needs. It's built into GitHub automatically, so I don't need to mess around with anything else. Billing's already set up. And it just does seem to do a really good job on convex code, at least from what I can see. Now, as mentioned earlier, I am going to have to do a follow-up as a number of you mentioned that you would like to see other tools such as Curs's Bugbot compared here. So, please do let me know in the comments down below if there are other tools you would like me to evaluate. I am also very keen to check out GitHub's agentic workflows. I think this might be very well the ideal way to create your own project tailored review bot. But for now, I think this video is probably long enough as it is. So [music] until next time, thanks for watching. Cheerio.
Let's play a game. Here's a Convex query. See if you can spot the bug.
It takes a task ID, grabs the signed-in user, then loads the task, its project, and the assignee's name. Spotted it? No? Neither did I.
The query confirms that somebody is logged in. It never confirms that the task belongs to a project that person is a member of. So any authenticated user can read anyone else's task by guessing an ID. That's a textbook IDOR, and it's exactly the kind of hole that disappears into the noise when you're deep in the vibe coding zone.
I've been letting agents rip on my Convex projects lately, merging their work without much of a security pass. Things were falling through the cracks. So I took that bug, plus nine more I built to probe Convex-specific blind spots, and ran all ten past nine of the best AI code review tools on the market.
The results surprised me. One tool got nearly everything right. One very famous tool face-planted.
Ten tests, four points available on each, so 40 is a perfect run. Every per-test score is published in the evaluation playground repo if you want to check my working.
#
Tool
Tier
Score
Strongest showing
Weakest showing
1
Qodo
Gold
32/40
Caught nine of ten primary issues
Fell for the fake N+1
2
GitHub Copilot
Gold
31/40
Most bonus points in the field
Fell for the fake N+1
3
Cubic
Silver
26/40
Only tool to knowingly pass the N+1 trap
Missed the unbounded .collect()
4
CodeRabbit
Silver
24/40
Nailed the document size limit test
Review engine failed on one PR
5
Greptile
Silver
23/40
Full marks on the internal-function and authorization tests
Called valid array code a "critical bug"
6
CodeAnt AI
Bronze
13/40
Strong on the two auth tests
False positives on two internal queries
7
Sourcery
Skip
9/40
Caught the unbounded .collect()
Sequence diagrams on every single PR
8
Macroscope
Skip
9/40
Flagged the intro bug as Critical
Silent on six of the ten PRs
9
Graphite AI
Skip
3/40
Nothing
Zero comments on nine of ten PRs
How I tested them
I built a Trello clone on React, Vite, and Convex Auth as the baseline. You log in, create a project, assign members, and they create tasks on a kanban board. Tasks carry comments, and an activity log keeps an audit trail behind the scenes.
It's a basic app, but it has the shape of a real SaaS product: nested related data, plus genuine authentication and authorization boundaries. That's enough surface area to hide real bugs in.
From there I designed ten PRs, which are really evals for AI code review tools. Each one started as a markdown document spelling out what a correct review should catch, what it should not flag, and why. I wrote those before opening a single PR, so I couldn't grade toward whatever a bot happened to say. They never went onto the branches under test. They're on the main branch now so you can run the whole thing yourself.
Keeping each PR realistic while testing one thing at a time took some care. My main trick was to mark new queries as internal and add a comment saying they'd be run from the Convex dashboard. Convex developers do this all the time, so it let me add code that isn't wired into the UI without a bot crying dead code. I also kept the repo and the PR descriptions clean of anything that would tip a bot off. I don't want a Volkswagen emissions situation on my hands.
Every bot ran on its default configuration. I didn't tune a thing. I'm not an expert in nine separate products, and configuring them all correctly would have been fiddly and error-prone. I also watched for any bot referencing another bot's comments and never saw it happen, probably because they all trigger the moment a PR opens and grab their context at the same time.
Grading nine bots across ten PRs by hand would have taken forever, so I had an agent do the scoring. Claude Opus did the first pass. Then Codex 5.3 ran the whole thing again in a clean context as a cross-check, and it mostly agreed, catching a couple of things Opus missed.
Here's the scoring:
3 points for catching the primary issue
1 point for a mixed or partial result
0 points for missing it
+1 bonus for finding something else genuinely useful
-1 penalty for false positives
That penalty matters to me. Noisy false alarms are their own kind of cost, and I don't want to spend my week arguing with a bot.
Here's the first test, since it comes up in every entry below. It's an activity feed query that filters in memory instead of using an index:
1// Reporting queries for use via the Convex Dashboard23exportconst getActivityForUser =internalQuery({4 args:{5 projectId: v.id("projects"),6 userId: v.id("users"),7},8handler:async(ctx, args)=>{9const activity =await ctx.db
10.query("activityLog")11.order("desc")12.filter((q)=>13 q.and(14 q.eq(q.field("projectId"), args.projectId),15 q.eq(q.field("userId"), args.userId),16),17)18.take(50);1920return activity;21},22});23
That .filter() pulls the whole activityLog table through the server and throws most of it away. The right answer is an index. The guidance is plastered all over the Convex docs, and I'd also put it in the project's .cursor/rules directory. Part of the test was seeing whether any bot would go read those rules. Spoiler: none of them did.
1. Qodo
Score: 32/40. Tier: gold. Best for: raw accuracy, if you can stomach the dashboard.
Qodo topped the table. It caught the .filter() versus .withIndex() issue and nine of the ten primary issues overall, which nothing else came close to. It was also one of only two tools that caught the unbounded array test.
It wasn't flawless. It falsely flagged the N+1 pattern that Convex's collocated compute and database make a non-issue, and it hedged an auth concern on an internal query.
What makes the win remarkable is the dashboard, which was the worst of any tool here. Buggy, confusing, and repeatedly unable to show repositories I'd already connected. I got frustrated enough that I deleted my entire account, and it kept submitting PR reviews anyway. Free, accurate, and apparently impossible to get rid of.
2. GitHub Copilot
Score: 31/40. Tier: gold. Best for: most people, because you're probably already paying for it.
GitHub Copilot finished one point behind. It caught the indexing issue and attached a genuinely useful inline suggestion, and it racked up more bonus points than anything else in the lineup. It kept spotting real secondary bugs nobody asked it to look for, including a dueDate truthy check that treats zero as falsy.
It fell for the N+1 non-issue like most of the field, so it isn't immune to Convex's quirks.
What tips it into my personal pick is practical. It's already built into GitHub, so there's no new billing relationship and nothing to install.
3. Cubic
Score: 26/40. Tier: silver. Best for: teams who want the fewest false alarms.
Cubic was the standout on the test I cared about most, which was the fake N+1. Here's the bait:
1exportconst getProjectOverview =internalQuery({2 args:{ projectId: v.id("projects")},3handler:async(ctx, args)=>{4// Intentional cap: we only show up to 50 tasks5const tasks =await ctx.db
6.query("tasks")7.withIndex("by_projectId",(q)=>8 q.eq("projectId", args.projectId))9.take(50);1011const enrichedTasks =[];12for(const task of tasks){13const assignee = task.assigneeId
14?await ctx.db.get("users", task.assigneeId)15:null;16// ... labels fetched per task the same way17}18},19});20
Train a model on traditional serverless code and that loop looks like a pile of database round-trips waiting to happen. Most tools flagged it as a performance problem on sight. Cubic saw nothing wrong, because it understood that Convex runs the whole thing as one transaction rather than a chain of network calls.
Two other tools technically passed that test by saying nothing at all. Cubic passed it on purpose, which is a different thing entirely.
It also never took a single false-positive penalty across all ten PRs, and it went and read the Convex docs mid-review to confirm the OCC anti-pattern. Its blind spot was the unbounded .collect() test, which it missed completely. Of the nine, Cubic showed the clearest sign of reasoning about Convex's architecture instead of pattern-matching generic JavaScript.
4. CodeRabbit
Score: 24/40. Tier: silver. Best for: deep dives on data modeling.
CodeRabbit caught the indexing issue without trouble and was the strongest tool on the document size limit test, naming the 1MB ceiling and recommending a separate table. That's exactly the right fix.
It also fell hard for the N+1 false positive and took a scoring penalty for it, one of only two tools to go negative on that test. Its "critical" finding was that the two-argument ctx.db.get form is wrong API usage. It isn't.
Reliability bit it once too. On the internal-function PR, its review engine errored out and posted nothing at all. A broken review still counts as a miss.
5. Greptile
Score: 23/40. Tier: silver. Best for: catching what the diff implies, not just what it says.
Greptile tracked closely with CodeRabbit. It caught the indexing problem, and it was one of the few tools to name the OCC hot path directly, describing the contention precisely on a test that nothing in the field had touched in its subtler form.
Then it false-flagged the N+1 non-issue, and on the array test it described perfectly valid mutable array operations as "critical logic bugs." That one earned a penalty, because a confidently wrong critical is worse than silence.
It's a capable middle-of-the-pack reviewer that knows Convex's basics but not its deeper guarantees.
6. CodeAnt AI
Score: 13/40. Tier: bronze. Best for: nothing I'd recommend it for yet.
CodeAnt AI started badly. It missed the indexing issue, gesturing vaguely at indices without committing, and then flagged auth and data-leak problems on a query I'd explicitly marked internal and documented as dashboard-only. Internal queries don't need auth checks, because the dashboard is what runs them. It did the same thing on the N+1 test, which means it went negative on both of its first two PRs.
It recovered later. It caught the unbounded .collect() that three better-scoring tools missed, and it was solid on both authorization tests, including the intro bug.
That's the shape of it. Real capability, undermined by a weak grasp of what Convex's internal functions are for.
7. Sourcery
Score: 9/40. Tier: skip. Best for: nobody who dislikes sequence diagrams.
Sourcery had the most verbose PR summaries of anything I tried. It bolts a full sequence diagram onto every single PR, which adds noise rather than insight.
On substance it managed half credit on the indexing test, suggesting an index "if not already indexed" without ever checking the schema to see whether one existed. Then it false-flagged the N+1 like most of the field, and it repeated CodeRabbit's mistake about the two-argument ctx.db.get form, which cost it another penalty.
It missed the intro authorization bug entirely. The one issue it found on that PR was a clipboard API guard sitting in the UI code next door.
8. Macroscope
Score: 9/40. Tier: skip. Best for: teams who prefer their reviewers quiet.
Macroscope said nothing at all on six of the ten PRs. It missed the indexing test, offering a generic passing check instead of a review, then "passed" the N+1 test by not flagging anything. I gave it the points, since not flagging a non-issue is technically correct, but I doubt it reflects any understanding of Convex's execution model.
To its credit, it woke up twice late in the suite. It caught the out-of-sync aggregate, and it flagged the intro authorization bug as Critical with a proper evidence trail. Two real catches out of ten isn't enough to build a workflow on.
9. Graphite AI
Score: 3/40. Tier: skip. Best for: nothing, on this evidence.
Graphite AI has real brand recognition, which made this the most surprising result of the whole test. It scored zeros almost straight across the board. It left zero comments on nine of the ten PRs.
Its only points came from silence on the N+1 test, the same technical pass Macroscope got. Everywhere else it produced a completed check run and nothing else.
I logged back into the dashboard afterward and checked, double-checked, and triple-checked that it was properly connected. It was. It just doesn't find anything.
What the other tests showed
The indexing and N+1 tests get the most airtime because they're the cleanest signal, but the other eight are where the Convex-specific gaps show up. Here's the whole suite:
Test
What it probed
Caught it
Nested ctx.db lookups
A fake N+1. Does the bot know Convex runs the query as one transaction?
3 of 9 stayed quiet, only Cubic on purpose
.filter() over .withIndex()
Basic Convex query hygiene, documented everywhere
6 of 9, one of those only half credit
Missing authentication
An export function doing real work without checking for a signed-in user
5 of 9
Public mutation that should be internal
A cron-triggered mutation left callable by anyone
4 of 9
Unbounded .collect()
Reading a table that grows forever
4 of 9
.collect() used to count
Should be a denormalized counter or the aggregate component
7 of 9
Unbounded array on a document
A checklist field heading for the document size limit
2 of 9 clean, 3 partial
Component left out of sync
A mutation that changes the task count without updating the aggregate
7 of 9
OCC hot path
Every mutation in the app writing one shared counter row
5 of 9 clean, 3 partial
Authorization bypass
The intro bug: authentication present, membership check missing
7 of 9
A few of those deserve a note.
The authorization bug from the intro was caught by seven of the nine, which was reassuring. Authorization is a well-understood concept in every framework, so the bots have plenty to pattern-match against. Making a cron-triggered mutation internal rather than public is far more Convex-specific, and only four of nine got there.
The performance tests split the field in an odd way. Unbounded .collect() calls on a table that grows without limit tripped up five of the nine, including Cubic and CodeRabbit. But using .collect() just to count documents, where the fix is a denormalized counter or the aggregate component, was caught by seven. The difference is that the counting version was a public query wired into the UI, so the bots could see the useQuery call and reason about reactive re-execution.
The document size test was the hardest of the lot. I added a checklist array to tasks and waited to see who'd notice that an unbounded array risks Convex's per-document size limits and belongs in its own table. Only CodeRabbit and Qodo said so clearly.
Optimistic concurrency control was the test I expected nobody to pass. I added a platformStats table with a single totalMutations field, then wrote to it from every mutation in the app, for every user. That guarantees write conflicts under any real load, since Convex's OCC model retries a mutation whenever something it read gets written first.
My first attempt at this test was subtler, tracking activity per project, and it scored a clean zero across all nine bots. Making the anti-pattern blatant changed the picture: five tools named the hot document and the retry storm directly, and three more got partial credit for spotting a concurrency problem without framing it as contention. Cubic went and searched the Convex docs to confirm it. That's the gold standard for how a review bot should behave.
Tools I didn't test
Aikido was going to be the tenth bot until I found out it wanted $350 a month before I could run a single comparison. Thanks, but no thanks.
I also left out Cursor's Bugbot and the newer review tooling from OpenAI and Anthropic. People suggested all three when I posted that I was working on this, and they're good suggestions. Nine tools was already a lot for one round of testing, so those are going into a follow-up along with GitHub's agentic workflows, which I suspect might be the real answer here.
What these tools should fix
A few things came up across all nine that have nothing to do with review quality.
Onboarding varied wildly. Some tools wanted a credit card before I could try anything, which puts me off immediately. The ones I liked opened with a short wizard asking what I wanted out of it, PR summaries or code reviews or both, and set up sensible defaults from there.
Dashboards were worse. Graphite's main nav is icons with no text, and finding the settings that actually configure the review bot took me three guesses. It isn't alone in that.
The bigger miss is context. None of these bots read the .cursor/rules files sitting in the repo, and those rules contain most of the Convex knowledge the bots kept failing on. Some of them may be reading AGENTS.md or CLAUDE.md files, which this project didn't have. The smarter move would be to detect a Convex project, go find the ESLint config and the framework docs, and keep that in the project's knowledge for every future review. Nobody's doing that yet.
My pick
I'm going with Copilot for day-to-day work. It did well on Convex-specific code, it's already part of GitHub, and there's no new billing relationship to set up.
If accuracy is the only thing you're optimizing for and you can tolerate a rough dashboard, Qodo is hard to argue with, and it's free. If false positives are what you can't stand, take Cubic, which was the only tool here that never cried wolf.
The broader lesson from the exercise is that the best AI code review tools are the ones that know something about your stack. Every bot in this lineup handles generic JavaScript fine. The gap between first place and last was almost entirely about whether the tool understood how Convex actually executes your code.
All gas, no breakages
Convex is the reactive backend platform that keeps up with you and your agents. Database, functions, workflow, sync, search, file storage, and more. All TypeScript, zero glue.